From 8aae8284fece2b8fc404ccd40b7a30aa96f317b5 Mon Sep 17 00:00:00 2001 From: Jacob Shin Date: Mon, 21 Nov 2005 07:23:08 -0800 Subject: [CPUFREQ] Improve Error reporting in powernow-k8 This patch cleans up some error messages in the powernow-k8 driver and makes them more understandable. Signed-off-by: Jacob Shin Signed-off-by: Mark Langsdorf Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 31 +++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index 68a1fc87f4c..34978273680 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -45,7 +45,7 @@ #define PFX "powernow-k8: " #define BFX PFX "BIOS error: " -#define VERSION "version 1.50.4" +#define VERSION "version 1.50.5" #include "powernow-k8.h" /* serialize freq changes */ @@ -464,7 +464,7 @@ static int check_supported_cpu(unsigned int cpu) set_cpus_allowed(current, cpumask_of_cpu(cpu)); if (smp_processor_id() != cpu) { - printk(KERN_ERR "limiting to cpu %u failed\n", cpu); + printk(KERN_ERR PFX "limiting to cpu %u failed\n", cpu); goto out; } @@ -517,22 +517,28 @@ static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst, u8 printk(KERN_ERR BFX "maxvid exceeded with pstate %d\n", j); return -ENODEV; } - if ((pst[j].fid > MAX_FID) - || (pst[j].fid & 1) - || (j && (pst[j].fid < HI_FID_TABLE_BOTTOM))) { + if (pst[j].fid > MAX_FID) { + printk(KERN_ERR BFX "maxfid exceeded with pstate %d\n", j); + return -ENODEV; + } + if (pst[j].fid & 1) { + printk(KERN_ERR BFX "fid invalid - %d : 0x%x\n", j, pst[j].fid); + return -EINVAL; + } + if (j && (pst[j].fid < HI_FID_TABLE_BOTTOM)) { /* Only first fid is allowed to be in "low" range */ - printk(KERN_ERR PFX "two low fids - %d : 0x%x\n", j, pst[j].fid); + printk(KERN_ERR BFX "two low fids - %d : 0x%x\n", j, pst[j].fid); return -EINVAL; } if (pst[j].fid < lastfid) lastfid = pst[j].fid; } if (lastfid & 1) { - printk(KERN_ERR PFX "lastfid invalid\n"); + printk(KERN_ERR BFX "lastfid invalid\n"); return -EINVAL; } if (lastfid > LO_FID_TABLE_TOP) - printk(KERN_INFO PFX "first fid not from lo freq table\n"); + printk(KERN_INFO BFX "first fid not from lo freq table\n"); return 0; } @@ -912,7 +918,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi set_cpus_allowed(current, cpumask_of_cpu(pol->cpu)); if (smp_processor_id() != pol->cpu) { - printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu); + printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu); goto err_out; } @@ -982,6 +988,9 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) cpumask_t oldmask = CPU_MASK_ALL; int rc, i; + if (!cpu_online(pol->cpu)) + return -ENODEV; + if (!check_supported_cpu(pol->cpu)) return -ENODEV; @@ -1021,7 +1030,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) set_cpus_allowed(current, cpumask_of_cpu(pol->cpu)); if (smp_processor_id() != pol->cpu) { - printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu); + printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu); goto err_out; } @@ -1162,7 +1171,7 @@ static void __exit powernowk8_exit(void) cpufreq_unregister_driver(&cpufreq_amd64_driver); } -MODULE_AUTHOR("Paul Devriendt and Mark Langsdorf and Mark Langsdorf "); MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver."); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 019a61b99338d0ac05de25317b85da88e7ec4b35 Mon Sep 17 00:00:00 2001 From: "Langsdorf, Mark" Date: Tue, 29 Nov 2005 14:18:03 -0600 Subject: [PATCH] Support 100 MHz frequency transitions Future versions of the Opteron processor may support frequency transitions of 100 MHz, instead of the=20 current 200 MHz. This patch enables the powernow-k8 driver to transition to an odd FID code, indicating a multiple of 100 MHz frequency. Signed-off-by: Jacob Shin Signed-off-by: Mark Langsdorf Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 17 +++++++---------- arch/i386/kernel/cpu/cpufreq/powernow-k8.h | 9 +++++---- 2 files changed, 12 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index 34978273680..a342b32c084 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -45,7 +45,7 @@ #define PFX "powernow-k8: " #define BFX PFX "BIOS error: " -#define VERSION "version 1.50.5" +#define VERSION "version 1.60.0" #include "powernow-k8.h" /* serialize freq changes */ @@ -336,7 +336,7 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid /* Phase 2 - core frequency transition */ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid) { - u32 vcoreqfid, vcocurrfid, vcofiddiff, savevid = data->currvid; + u32 vcoreqfid, vcocurrfid, vcofiddiff, fid_interval, savevid = data->currvid; if ((reqfid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) { printk(KERN_ERR PFX "ph2: illegal lo-lo transition 0x%x 0x%x\n", @@ -359,9 +359,11 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid) : vcoreqfid - vcocurrfid; while (vcofiddiff > 2) { + (data->currfid & 1) ? (fid_interval = 1) : (fid_interval = 2); + if (reqfid > data->currfid) { if (data->currfid > LO_FID_TABLE_TOP) { - if (write_new_fid(data, data->currfid + 2)) { + if (write_new_fid(data, data->currfid + fid_interval)) { return 1; } } else { @@ -371,7 +373,7 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid) } } } else { - if (write_new_fid(data, data->currfid - 2)) + if (write_new_fid(data, data->currfid - fid_interval)) return 1; } @@ -474,7 +476,7 @@ static int check_supported_cpu(unsigned int cpu) eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) || ((eax & CPUID_XFAM) != CPUID_XFAM_K8) || - ((eax & CPUID_XMOD) > CPUID_XMOD_REV_F)) { + ((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) { printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax); goto out; } @@ -521,10 +523,6 @@ static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst, u8 printk(KERN_ERR BFX "maxfid exceeded with pstate %d\n", j); return -ENODEV; } - if (pst[j].fid & 1) { - printk(KERN_ERR BFX "fid invalid - %d : 0x%x\n", j, pst[j].fid); - return -EINVAL; - } if (j && (pst[j].fid < HI_FID_TABLE_BOTTOM)) { /* Only first fid is allowed to be in "low" range */ printk(KERN_ERR BFX "two low fids - %d : 0x%x\n", j, pst[j].fid); @@ -1177,4 +1175,3 @@ MODULE_LICENSE("GPL"); late_initcall(powernowk8_init); module_exit(powernowk8_exit); - diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h index b1e85bb3639..d0de37d58e9 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h @@ -42,7 +42,7 @@ struct powernow_k8_data { #define CPUID_XFAM 0x0ff00000 /* extended family */ #define CPUID_XFAM_K8 0 #define CPUID_XMOD 0x000f0000 /* extended model */ -#define CPUID_XMOD_REV_F 0x00040000 +#define CPUID_XMOD_REV_G 0x00060000 #define CPUID_USE_XFAM_XMOD 0x00000f00 #define CPUID_GET_MAX_CAPABILITIES 0x80000000 #define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007 @@ -86,13 +86,14 @@ struct powernow_k8_data { * low fid table * - lowest entry in the high fid table must be a <= 200MHz + 2 * the entry * in the low fid table - * - the parts can only step at 200 MHz intervals, so 1.9 GHz is never valid + * - the parts can only step at <= 200 MHz intervals, odd fid values are + * supported in revision G and later revisions. * - lowest frequency must be >= interprocessor hypertransport link speed * (only applies to MP systems obviously) */ /* fids (frequency identifiers) are arranged in 2 tables - lo and hi */ -#define LO_FID_TABLE_TOP 6 /* fid values marking the boundary */ +#define LO_FID_TABLE_TOP 7 /* fid values marking the boundary */ #define HI_FID_TABLE_BOTTOM 8 /* between the low and high tables */ #define LO_VCOFREQ_TABLE_TOP 1400 /* corresponding vco frequency values */ @@ -106,7 +107,7 @@ struct powernow_k8_data { #define MIN_FREQ 800 /* Min and max freqs, per spec */ #define MAX_FREQ 5000 -#define INVALID_FID_MASK 0xffffffc1 /* not a valid fid if these bits are set */ +#define INVALID_FID_MASK 0xffffffc0 /* not a valid fid if these bits are set */ #define INVALID_VID_MASK 0xffffffc0 /* not a valid vid if these bits are set */ #define VID_OFF 0x3f -- cgit v1.2.3 From 6df8900676c3f5c133328332fb8ad889fd0cc9e3 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 30 Nov 2005 13:33:30 -0800 Subject: [CPUFREQ] Fix indentation in powernow-k8 Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index a342b32c084..f44c1b1b04e 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -216,10 +216,10 @@ static int write_new_vid(struct powernow_k8_data *data, u32 vid) do { wrmsr(MSR_FIDVID_CTL, lo, STOP_GRANT_5NS); - if (i++ > 100) { - printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n"); - return 1; - } + if (i++ > 100) { + printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n"); + return 1; + } } while (query_current_values_with_pending_wait(data)); if (savefid != data->currfid) { -- cgit v1.2.3 From d4921914de19339d7cd987d2ed6d48754821f41a Mon Sep 17 00:00:00 2001 From: "Gabriel A. Devenyi" Date: Thu, 1 Dec 2005 01:09:22 -0800 Subject: [PATCH] cpufreq-nforce2.c fix u32<0 test Thanks to LinuxICC (http://linuxicc.sf.net), a comparison of a u32 less than 0 was found, this patch changes the variable to a signed int so that comparison is meaningful. Signed-off-by: Gabriel A. Devenyi Signed-off-by: Andrew Morton Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c index 04a40534520..2b62dee35c6 100644 --- a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c +++ b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c @@ -177,9 +177,10 @@ static unsigned int nforce2_fsb_read(int bootfsb) */ static int nforce2_set_fsb(unsigned int fsb) { - u32 pll, temp = 0; + u32 temp = 0; unsigned int tfsb; int diff; + int pll = 0; if ((fsb > max_fsb) || (fsb < NFORCE2_MIN_FSB)) { printk(KERN_ERR "cpufreq: FSB %d is out of range!\n", fsb); -- cgit v1.2.3 From cc6e8de8f0fab61760bb7091fb19eef1406e17be Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 6 Dec 2005 15:03:55 -0800 Subject: [CPUFREQ] Change loglevels on powernow-k8 bios error printk's. If a user has booted with 'quiet', some important messages don't get displayed which really should. We've seen at least one case where powernow-k8 stopped working, and the user needed a BIOS update that they didn't know about. Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index f44c1b1b04e..0fbbd4c1072 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -635,7 +635,7 @@ static int find_psb_table(struct powernow_k8_data *data) dprintk("table vers: 0x%x\n", psb->tableversion); if (psb->tableversion != PSB_VERSION_1_4) { - printk(KERN_INFO BFX "PSB table is not v1.4\n"); + printk(KERN_ERR BFX "PSB table is not v1.4\n"); return -ENODEV; } @@ -693,7 +693,7 @@ static int find_psb_table(struct powernow_k8_data *data) * BIOS and Kernel Developer's Guide, which is available on * www.amd.com */ - printk(KERN_INFO PFX "BIOS error - no PSB or ACPI _PSS objects\n"); + printk(KERN_ERR PFX "BIOS error - no PSB or ACPI _PSS objects\n"); return -ENODEV; } -- cgit v1.2.3 From 1a10760c91c394dfe4adfefeeaf85cd8098c4894 Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Fri, 2 Dec 2005 21:59:41 +0100 Subject: [CPUFREQ] Measure transition latency at driver initialization The attached patch introduces runtime latency measurement for ICH[234] based chipsets instead of using CPUFREQ_ETERNAL. It includes some sanity checks in case the measured value is out of range and assigns a safe value of 500uSec that should still be enough on problematics chipsets (current testing report values ~200uSec). The measurement is currently done in speedstep_get_freqs in order to avoid further unnecessary transitions and in the hope it'll come handy for SMI also. Signed-off-by: Mattia Dongili Acked-by: Dominik Brodowski Signed-off-by: Dave Jones speedstep-ich.c | 4 ++-- speedstep-lib.c | 32 +++++++++++++++++++++++++++++++- speedstep-lib.h | 1 + speedstep-smi.c | 1 + 4 files changed, 35 insertions(+), 3 deletions(-) --- arch/i386/kernel/cpu/cpufreq/speedstep-ich.c | 4 ++-- arch/i386/kernel/cpu/cpufreq/speedstep-lib.c | 32 +++++++++++++++++++++++++++- arch/i386/kernel/cpu/cpufreq/speedstep-lib.h | 1 + arch/i386/kernel/cpu/cpufreq/speedstep-smi.c | 1 + 4 files changed, 35 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c index 5b7d18a06af..862e0b5656b 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c @@ -315,10 +315,11 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) cpus_allowed = current->cpus_allowed; set_cpus_allowed(current, policy->cpus); - /* detect low and high frequency */ + /* detect low and high frequency and transition latency */ result = speedstep_get_freqs(speedstep_processor, &speedstep_freqs[SPEEDSTEP_LOW].frequency, &speedstep_freqs[SPEEDSTEP_HIGH].frequency, + &policy->cpuinfo.transition_latency, &speedstep_set_state); set_cpus_allowed(current, cpus_allowed); if (result) @@ -335,7 +336,6 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) /* cpuinfo and default policy values */ policy->governor = CPUFREQ_DEFAULT_GOVERNOR; - policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = speed; result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs); diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c index d368b3f5fce..7c47005a180 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c @@ -320,11 +320,13 @@ EXPORT_SYMBOL_GPL(speedstep_detect_processor); unsigned int speedstep_get_freqs(unsigned int processor, unsigned int *low_speed, unsigned int *high_speed, + unsigned int *transition_latency, void (*set_state) (unsigned int state)) { unsigned int prev_speed; unsigned int ret = 0; unsigned long flags; + struct timeval tv1, tv2; if ((!processor) || (!low_speed) || (!high_speed) || (!set_state)) return -EINVAL; @@ -337,7 +339,7 @@ unsigned int speedstep_get_freqs(unsigned int processor, return -EIO; dprintk("previous speed is %u\n", prev_speed); - + local_irq_save(flags); /* switch to low state */ @@ -350,8 +352,17 @@ unsigned int speedstep_get_freqs(unsigned int processor, dprintk("low speed is %u\n", *low_speed); + /* start latency measurement */ + if (transition_latency) + do_gettimeofday(&tv1); + /* switch to high state */ set_state(SPEEDSTEP_HIGH); + + /* end latency measurement */ + if (transition_latency) + do_gettimeofday(&tv2); + *high_speed = speedstep_get_processor_frequency(processor); if (!*high_speed) { ret = -EIO; @@ -369,6 +380,25 @@ unsigned int speedstep_get_freqs(unsigned int processor, if (*high_speed != prev_speed) set_state(SPEEDSTEP_LOW); + if (transition_latency) { + *transition_latency = (tv2.tv_sec - tv1.tv_sec) * USEC_PER_SEC + + tv2.tv_usec - tv1.tv_usec; + dprintk("transition latency is %u uSec\n", *transition_latency); + + /* convert uSec to nSec and add 20% for safety reasons */ + *transition_latency *= 1200; + + /* check if the latency measurement is too high or too low + * and set it to a safe value (500uSec) in that case + */ + if (*transition_latency > 10000000 || *transition_latency < 50000) { + printk (KERN_WARNING "speedstep: frequency transition measured seems out of " + "range (%u nSec), falling back to a safe one of %u nSec.\n", + *transition_latency, 500000); + *transition_latency = 500000; + } + } + out: local_irq_restore(flags); return (ret); diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h index 261a2c9b7f6..6a727fd3a77 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h @@ -44,4 +44,5 @@ extern unsigned int speedstep_get_processor_frequency(unsigned int processor); extern unsigned int speedstep_get_freqs(unsigned int processor, unsigned int *low_speed, unsigned int *high_speed, + unsigned int *transition_latency, void (*set_state) (unsigned int state)); diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c index 2718fb6f6ab..28cc5d524af 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c @@ -269,6 +269,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) result = speedstep_get_freqs(speedstep_processor, &speedstep_freqs[SPEEDSTEP_LOW].frequency, &speedstep_freqs[SPEEDSTEP_HIGH].frequency, + NULL, &speedstep_set_state); if (result) { -- cgit v1.2.3 From 9a7d82a89a8bf55b112f2a5c3b3f405eb95a4303 Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Wed, 30 Nov 2005 22:00:59 +0100 Subject: [CPUFREQ] Move PMBASE reading away and do it only once at initialization time This patch moves away PMBASE reading and only performs it at cpufreq_register_driver time by exiting with -ENODEV if unable to read the value. Signed-off-by: Mattia Dongili Acked-by: Dominik Brodowski Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/speedstep-ich.c | 43 +++++++++++++++++++--------- 1 file changed, 30 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c index 862e0b5656b..b425cd3d183 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c @@ -40,6 +40,7 @@ static struct pci_dev *speedstep_chipset_dev; */ static unsigned int speedstep_processor = 0; +static u32 pmbase; /* * There are only two frequency states for each processor. Values @@ -56,34 +57,47 @@ static struct cpufreq_frequency_table speedstep_freqs[] = { /** - * speedstep_set_state - set the SpeedStep state - * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) + * speedstep_find_register - read the PMBASE address * - * Tries to change the SpeedStep state. + * Returns: -ENODEV if no register could be found */ -static void speedstep_set_state (unsigned int state) +static int speedstep_find_register (void) { - u32 pmbase; - u8 pm2_blk; - u8 value; - unsigned long flags; - - if (!speedstep_chipset_dev || (state > 0x1)) - return; + if (!speedstep_chipset_dev) + return -ENODEV; /* get PMBASE */ pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); if (!(pmbase & 0x01)) { printk(KERN_ERR "speedstep-ich: could not find speedstep register\n"); - return; + return -ENODEV; } pmbase &= 0xFFFFFFFE; if (!pmbase) { printk(KERN_ERR "speedstep-ich: could not find speedstep register\n"); - return; + return -ENODEV; } + dprintk("pmbase is 0x%x\n", pmbase); + return 0; +} + +/** + * speedstep_set_state - set the SpeedStep state + * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) + * + * Tries to change the SpeedStep state. + */ +static void speedstep_set_state (unsigned int state) +{ + u8 pm2_blk; + u8 value; + unsigned long flags; + + if (state > 0x1) + return; + /* Disable IRQs */ local_irq_save(flags); @@ -400,6 +414,9 @@ static int __init speedstep_init(void) return -EINVAL; } + if (speedstep_find_register()) + return -ENODEV; + return cpufreq_register_driver(&speedstep_driver); } -- cgit v1.2.3 From 95235ca2c20ac0b31a8eb39e2d599bcc3e9c9a10 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Fri, 2 Dec 2005 10:43:20 -0800 Subject: [CPUFREQ] CPU frequency display in /proc/cpuinfo What is the value shown in "cpu MHz" of /proc/cpuinfo when CPUs are capable of changing frequency? Today the answer is: It depends. On i386: SMP kernel - It is always the boot frequency UP kernel - Scales with the frequency change and shows that was last set. On x86_64: There is one single variable cpu_khz that gets written by all the CPUs. So, the frequency set by last CPU will be seen on /proc/cpuinfo of all the CPUs in the system. What you see also depends on whether you have constant_tsc capable CPU or not. On ia64: It is always boot time frequency of a particular CPU that gets displayed. The patch below changes this to: Show the last known frequency of the particular CPU, when cpufreq is present. If cpu doesnot support changing of frequency through cpufreq, then boot frequency will be shown. The patch affects i386, x86_64 and ia64 architectures. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/proc.c | 6 +++++- arch/ia64/kernel/setup.c | 8 +++++++- arch/x86_64/kernel/setup.c | 6 +++++- 3 files changed, 17 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c index e7921315ae9..6d91b274589 100644 --- a/arch/i386/kernel/cpu/proc.c +++ b/arch/i386/kernel/cpu/proc.c @@ -3,6 +3,7 @@ #include #include #include +#include /* * Get CPU information for use by the procfs. @@ -86,8 +87,11 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "stepping\t: unknown\n"); if ( cpu_has(c, X86_FEATURE_TSC) ) { + unsigned int freq = cpufreq_quick_get(n); + if (!freq) + freq = cpu_khz; seq_printf(m, "cpu MHz\t\t: %u.%03u\n", - cpu_khz / 1000, (cpu_khz % 1000)); + freq / 1000, (freq % 1000)); } /* Cache size */ diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 5add0bcf87a..088e5dded8d 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -517,6 +518,7 @@ show_cpuinfo (struct seq_file *m, void *v) char family[32], features[128], *cp, sep; struct cpuinfo_ia64 *c = v; unsigned long mask; + unsigned int proc_freq; int i; mask = c->features; @@ -549,6 +551,10 @@ show_cpuinfo (struct seq_file *m, void *v) sprintf(cp, " 0x%lx", mask); } + proc_freq = cpufreq_quick_get(cpunum); + if (!proc_freq) + proc_freq = c->proc_freq / 1000; + seq_printf(m, "processor : %d\n" "vendor : %s\n" @@ -565,7 +571,7 @@ show_cpuinfo (struct seq_file *m, void *v) "BogoMIPS : %lu.%02lu\n", cpunum, c->vendor, family, c->model, c->revision, c->archrev, features, c->ppn, c->number, - c->proc_freq / 1000000, c->proc_freq % 1000000, + proc_freq / 1000, proc_freq % 1000, c->itc_freq / 1000000, c->itc_freq % 1000000, lpj*HZ/500000, (lpj*HZ/5000) % 100); #ifdef CONFIG_SMP diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 750e01dcbdf..64c4534b930 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -1256,8 +1257,11 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "stepping\t: unknown\n"); if (cpu_has(c,X86_FEATURE_TSC)) { + unsigned int freq = cpufreq_quick_get((unsigned)(c-cpu_data)); + if (!freq) + freq = cpu_khz; seq_printf(m, "cpu MHz\t\t: %u.%03u\n", - cpu_khz / 1000, (cpu_khz % 1000)); + freq / 1000, (freq % 1000)); } /* Cache size */ -- cgit v1.2.3 From 02959a875caec8cabd36111046ad537251ef405f Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Tue, 27 Dec 2005 23:39:51 -0500 Subject: gitignore: x86_64 files Add filters for x86_64 generated files. Signed-off-by: Brian Gerst Signed-off-by: Sam Ravnborg --- arch/x86_64/boot/.gitignore | 3 +++ arch/x86_64/boot/tools/.gitignore | 1 + arch/x86_64/ia32/.gitignore | 1 + 3 files changed, 5 insertions(+) create mode 100644 arch/x86_64/boot/.gitignore create mode 100644 arch/x86_64/boot/tools/.gitignore create mode 100644 arch/x86_64/ia32/.gitignore (limited to 'arch') diff --git a/arch/x86_64/boot/.gitignore b/arch/x86_64/boot/.gitignore new file mode 100644 index 00000000000..495f20c085d --- /dev/null +++ b/arch/x86_64/boot/.gitignore @@ -0,0 +1,3 @@ +bootsect +bzImage +setup diff --git a/arch/x86_64/boot/tools/.gitignore b/arch/x86_64/boot/tools/.gitignore new file mode 100644 index 00000000000..378eac25d31 --- /dev/null +++ b/arch/x86_64/boot/tools/.gitignore @@ -0,0 +1 @@ +build diff --git a/arch/x86_64/ia32/.gitignore b/arch/x86_64/ia32/.gitignore new file mode 100644 index 00000000000..48ab174fe5f --- /dev/null +++ b/arch/x86_64/ia32/.gitignore @@ -0,0 +1 @@ +vsyscall*.so -- cgit v1.2.3 From df7b5d13c6c850bc2e3ca6ccfb1038f36bbbcf19 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 3 Jan 2006 13:42:12 +0100 Subject: arch/arm26/nwfpe/fpmodule.c: remove kernel 2.0 #ifdef This patch removes an #ifdef for kernel 2.0 . Signed-off-by: Adrian Bunk --- arch/arm26/nwfpe/fpmodule.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm26/nwfpe/fpmodule.c b/arch/arm26/nwfpe/fpmodule.c index 528fa710aa3..5258c6096fb 100644 --- a/arch/arm26/nwfpe/fpmodule.c +++ b/arch/arm26/nwfpe/fpmodule.c @@ -46,10 +46,9 @@ typedef struct task_struct* PTASK; #ifdef MODULE void fp_send_sig(unsigned long sig, PTASK p, int priv); -#if LINUX_VERSION_CODE > 0x20115 + MODULE_AUTHOR("Scott Bambrough "); MODULE_DESCRIPTION("NWFPE floating point emulator"); -#endif #else #define fp_send_sig send_sig -- cgit v1.2.3 From 408045afbdb46e109a1a44e67af688e9ddf7ad66 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 21 Dec 2005 15:21:36 -0700 Subject: [IA64] incorrect return from ia64_pci_legacy_write() The function ia64_pci_legacy_write() returns 0 for everything except errors. This return value gets sent back to the user from pci_write_legacy_io(), making it look like every write fails. The trivial patch below copies the behavior of the SGI sn machvec and does what would be expected from something implementing a write() function. Signed-off-by: Alex Williamson Signed-off-by: Tony Luck --- arch/ia64/pci/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 20d76fae24e..30dbc98bf0b 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -700,7 +700,7 @@ int ia64_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size) */ int ia64_pci_legacy_write(struct pci_dev *bus, u16 port, u32 val, u8 size) { - int ret = 0; + int ret = size; switch (size) { case 1: -- cgit v1.2.3 From 81f280e22f14d6d976620acaa1b346a90f4e1adc Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Sat, 12 Nov 2005 14:22:11 +0000 Subject: [PATCH] USB: pxa27x OHCI - Separate platform code from main driver To allow multiple platforms to use the PXA27x OHCI driver, the platform code needs to be moved into the board specific files in arch/arm/mach-pxa. This patch does this for mainstone and adds preliminary hooks to allow other boards to use the driver. This has been compile tested for mainstone and successfully run on Spitz (Sharp Zaurus SL-C3000) with the addition of an appropriate board support file. Signed-off-by: Richard Purdie Signed-off-by: Nicolas Pitre Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-pxa/mainstone.c | 21 +++++++++++++++++++++ arch/arm/mach-pxa/pxa27x.c | 6 ++++++ 2 files changed, 27 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index 07892f4012d..277498ae5b6 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "generic.h" @@ -393,6 +394,25 @@ static struct platform_device *platform_devices[] __initdata = { &mst_flash_device[1], }; +static int mainstone_ohci_init(struct device *dev) +{ + /* setup Port1 GPIO pin. */ + pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */ + pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */ + + /* Set the Power Control Polarity Low and Power Sense + Polarity Low to active low. */ + UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) & + ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE); + + return 0; +} + +static struct pxaohci_platform_data mainstone_ohci_platform_data = { + .port_mode = PMM_PERPORT_MODE, + .init = mainstone_ohci_init, +}; + static void __init mainstone_init(void) { int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */ @@ -424,6 +444,7 @@ static void __init mainstone_init(void) pxa_set_mci_info(&mainstone_mci_platform_data); pxa_set_ficp_info(&mainstone_ficp_platform_data); + pxa_set_ohci_info(&mainstone_ohci_platform_data); } diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index c722a9a91fc..b41b1efaa2c 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "generic.h" @@ -194,6 +195,11 @@ static struct platform_device ohci_device = { .resource = pxa27x_ohci_resources, }; +void __init pxa_set_ohci_info(struct pxaohci_platform_data *info) +{ + ohci_device.dev.platform_data = info; +} + static struct platform_device *devices[] __initdata = { &ohci_device, }; -- cgit v1.2.3 From 312c004d36ce6c739512bac83b452f4c20ab1f62 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Wed, 16 Nov 2005 09:00:00 +0100 Subject: [PATCH] driver core: replace "hotplug" by "uevent" Leave the overloaded "hotplug" word to susbsystems which are handling real devices. The driver core does not "plug" anything, it just exports the state to userspace and generates events. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/vio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 71a6addf9f7..13c41495fe0 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -293,6 +293,6 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp, struct bus_type vio_bus_type = { .name = "vio", - .hotplug = vio_hotplug, + .uevent = vio_hotplug, .match = vio_bus_match, }; -- cgit v1.2.3 From 6d20b035dee4300e9786c6e1cb77a765c7f9460a Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Fri, 25 Nov 2005 20:04:26 -0800 Subject: [PATCH] driver kill hotplug word from sn and others fix The first of these changes s/hotplug/uevent/ was needed to compile sn2_defconfig (ia64/sn). The other three files changed are blind changes of all remaining bus_type.hotplug references I could find to bus_type.uevent. This patch attempts to finish similar changes made in the gregkh-driver-kill-hotplug-word-from-driver-core Nov 22 patch. Signed-off-by: Paul Jackson Signed-off-by: Greg Kroah-Hartman --- arch/arm/common/amba.c | 6 +++--- arch/ia64/sn/kernel/tiocx.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/common/amba.c b/arch/arm/common/amba.c index e1013112c35..c95ec9eab99 100644 --- a/arch/arm/common/amba.c +++ b/arch/arm/common/amba.c @@ -45,7 +45,7 @@ static int amba_match(struct device *dev, struct device_driver *drv) } #ifdef CONFIG_HOTPLUG -static int amba_hotplug(struct device *dev, char **envp, int nr_env, char *buf, int bufsz) +static int amba_uevent(struct device *dev, char **envp, int nr_env, char *buf, int bufsz) { struct amba_device *pcdev = to_amba_device(dev); @@ -58,7 +58,7 @@ static int amba_hotplug(struct device *dev, char **envp, int nr_env, char *buf, return 0; } #else -#define amba_hotplug NULL +#define amba_uevent NULL #endif static int amba_suspend(struct device *dev, pm_message_t state) @@ -88,7 +88,7 @@ static int amba_resume(struct device *dev) static struct bus_type amba_bustype = { .name = "amba", .match = amba_match, - .hotplug = amba_hotplug, + .uevent = amba_uevent, .suspend = amba_suspend, .resume = amba_resume, }; diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c index 0d8592a745a..768c21deb2e 100644 --- a/arch/ia64/sn/kernel/tiocx.c +++ b/arch/ia64/sn/kernel/tiocx.c @@ -65,7 +65,7 @@ static int tiocx_match(struct device *dev, struct device_driver *drv) } -static int tiocx_hotplug(struct device *dev, char **envp, int num_envp, +static int tiocx_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) { return -ENODEV; @@ -79,7 +79,7 @@ static void tiocx_bus_release(struct device *dev) struct bus_type tiocx_bus_type = { .name = "tiocx", .match = tiocx_match, - .hotplug = tiocx_hotplug, + .uevent = tiocx_uevent, }; /** -- cgit v1.2.3 From e28cc71572da38a5a12c1cfe4d7032017adccf69 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 4 Jan 2006 16:20:40 -0800 Subject: Relax the rw_verify_area() error checking. In particular, allow over-large read- or write-requests to be downgraded to a more reasonable range, rather than considering them outright errors. We want to protect lower layers from (the sadly all too common) overflow conditions, but prefer to do so by chopping the requests up, rather than just refusing them outright. Cc: Peter Anvin Cc: Ulrich Drepper Cc: Andi Kleen Cc: Al Viro Signed-off-by: Linus Torvalds --- arch/mips/kernel/linux32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 330cf84d21f..60353f5acc4 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -420,7 +420,7 @@ asmlinkage ssize_t sys32_pread(unsigned int fd, char * buf, goto out; pos = merge_64(a4, a5); ret = rw_verify_area(READ, file, &pos, count); - if (ret) + if (ret < 0) goto out; ret = -EINVAL; if (!file->f_op || !(read = file->f_op->read)) @@ -455,7 +455,7 @@ asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char * buf, goto out; pos = merge_64(a4, a5); ret = rw_verify_area(WRITE, file, &pos, count); - if (ret) + if (ret < 0) goto out; ret = -EINVAL; if (!file->f_op || !(write = file->f_op->write)) -- cgit v1.2.3 From 631b034724364b413e8a52e7c2e03a9d77e4c2b4 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert <76306.1226@compuserve.com> Date: Tue, 3 Jan 2006 22:36:14 -0500 Subject: [PATCH] i386: "invalid operand" -> "invalid opcode" According to the manual, INT 6 is "invalid opcode", not "invalid operand". Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Linus Torvalds --- arch/i386/kernel/traps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index f0dffa03fbb..ab0e9430f77 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -452,7 +452,7 @@ DO_VM86_ERROR( 3, SIGTRAP, "int3", int3) #endif DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds) -DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip) +DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip) DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) -- cgit v1.2.3 From 38c0b2c2aaab5595a140ade4410e01d407fff751 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Thu, 5 Jan 2006 13:30:52 -0800 Subject: [IA64] Fix compile warnings in setup.c arch/ia64/kernel/setup.c: In function `show_cpuinfo': arch/ia64/kernel/setup.c:576: warning: long unsigned int format, different type arg (arg 12) arch/ia64/kernel/setup.c:576: warning: long unsigned int format, different type arg (arg 13) Introduced by 95235ca2c20ac0b31a8eb39e2d599bcc3e9c9a10 Signed-off-by: Tony Luck --- arch/ia64/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 088e5dded8d..c33305d8e5e 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -518,7 +518,7 @@ show_cpuinfo (struct seq_file *m, void *v) char family[32], features[128], *cp, sep; struct cpuinfo_ia64 *c = v; unsigned long mask; - unsigned int proc_freq; + unsigned long proc_freq; int i; mask = c->features; -- cgit v1.2.3 From 9f155b9802bb7049cd0f216c3fe903b58620df11 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert <76306.1226@compuserve.com> Date: Thu, 5 Jan 2006 23:11:29 -0500 Subject: [PATCH] i386: PTRACE_POKEUSR: allow changing RF bit in EFLAGS register. Setting RF (resume flag) allows a debugger to resume execution after a code breakpoint without tripping the breakpoint again. It is reset by the CPU after execution of one instruction. Requested by Stephane Eranian: "I am trying to the user HW debug registers on i386 and I am running into a problem with ptrace() not allowing access to EFLAGS_RF for POKEUSER (see FLAG_MASK). [ ... ] It avoids the need to remove the breakpoint, single step, and reinstall. The equivalent functionality exists on IA-64 and is allowed by ptrace()" Cc: Stephane Eranian Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Linus Torvalds --- arch/i386/kernel/ptrace.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index 5ffbb4b7ad0..5c1fb6aada5 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -32,9 +32,12 @@ * in exit.c or in signal.c. */ -/* determines which flags the user has access to. */ -/* 1 = access 0 = no access */ -#define FLAG_MASK 0x00044dd5 +/* + * Determines which flags the user has access to [1 = access, 0 = no access]. + * Prohibits changing ID(21), VIP(20), VIF(19), VM(17), IOPL(12-13), IF(9). + * Also masks reserved bits (31-22, 15, 5, 3, 1). + */ +#define FLAG_MASK 0x00054dd5 /* set's the trap flag. */ #define TRAP_FLAG 0x100 -- cgit v1.2.3 From 8a9947552d43b0d20d5fa23ac0ba435d526be454 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 26 Nov 2005 20:28:06 +0100 Subject: [PATCH] i2c: Drop i2c_driver.flags, 2 of 3 Just about every i2c chip driver sets the I2C_DF_NOTIFY flag, so we can simply make it the default and drop the flag. If any driver really doesn't want to be notified when i2c adapters are added, that driver can simply omit to set .attach_adapter. This approach is also more robust as it prevents accidental NULL pointer dereferences. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-pxa/akita-ioexp.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/akita-ioexp.c b/arch/arm/mach-pxa/akita-ioexp.c index f6d73cc01f7..440ebb3c3db 100644 --- a/arch/arm/mach-pxa/akita-ioexp.c +++ b/arch/arm/mach-pxa/akita-ioexp.c @@ -127,7 +127,6 @@ static struct i2c_driver max7310_i2c_driver = { .owner = THIS_MODULE, .name = "akita-max7310", .id = I2C_DRIVERID_AKITAIOEXP, - .flags = I2C_DF_NOTIFY, .attach_adapter = max7310_attach_adapter, .detach_client = max7310_detach_client, }; -- cgit v1.2.3 From cde7859bda0d1124392b44e50aa11df99707e1d9 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 26 Nov 2005 21:00:54 +0100 Subject: [PATCH] i2c: Rework client usage count, 2 of 3 Make I2C_CLIENT_ALLOW_USE the default for all i2c clients. It doesn't hurt if the usage count is actually never used for any given driver, and allows for nice code simplifications in i2c-core. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-pxa/akita-ioexp.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/akita-ioexp.c b/arch/arm/mach-pxa/akita-ioexp.c index 440ebb3c3db..b6bff550c8e 100644 --- a/arch/arm/mach-pxa/akita-ioexp.c +++ b/arch/arm/mach-pxa/akita-ioexp.c @@ -133,7 +133,6 @@ static struct i2c_driver max7310_i2c_driver = { static struct i2c_client max7310_template = { name: "akita-max7310", - flags: I2C_CLIENT_ALLOW_USE, driver: &max7310_i2c_driver, }; -- cgit v1.2.3 From b33a665dba55c83f08cdd62aba1cd2672bccdd80 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 26 Nov 2005 20:54:10 +0100 Subject: [PATCH] i2c: Drop i2c_driver.{owner,name}, 10 of 11 We should use the i2c_driver.driver's .name and .owner fields instead of the i2c_driver's ones. This patch updates the drivers for arm arch. Signed-off-by: Jean Delvare CC: Laurent Riffard Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-pxa/akita-ioexp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/akita-ioexp.c b/arch/arm/mach-pxa/akita-ioexp.c index b6bff550c8e..6f7b96551ad 100644 --- a/arch/arm/mach-pxa/akita-ioexp.c +++ b/arch/arm/mach-pxa/akita-ioexp.c @@ -124,8 +124,10 @@ static int max7310_detach_client(struct i2c_client *client) } static struct i2c_driver max7310_i2c_driver = { - .owner = THIS_MODULE, - .name = "akita-max7310", + .driver = { + .owner = THIS_MODULE, + .name = "akita-max7310", + }, .id = I2C_DRIVERID_AKITAIOEXP, .attach_adapter = max7310_attach_adapter, .detach_client = max7310_detach_client, -- cgit v1.2.3 From 2b48716d1d2f2edb1e7cbc5ecf1cb2cb39373e33 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Dec 2005 15:33:15 -0800 Subject: [PATCH] I2C: Remove .owner setting from i2c_driver as it's no longer needed Now that i2c_add_driver() doesn't need the module owner to be set by hand, we can delete it from the drivers. This patch catches all of the drivers that I found in the current tree (if a driver sets the .owner by hand, it's not a problem, just not needed.) Signed-off-by: Greg Kroah-Hartman Cc: Jean Delvare --- arch/arm/mach-pxa/akita-ioexp.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/akita-ioexp.c b/arch/arm/mach-pxa/akita-ioexp.c index 6f7b96551ad..1b398742ab5 100644 --- a/arch/arm/mach-pxa/akita-ioexp.c +++ b/arch/arm/mach-pxa/akita-ioexp.c @@ -125,7 +125,6 @@ static int max7310_detach_client(struct i2c_client *client) static struct i2c_driver max7310_i2c_driver = { .driver = { - .owner = THIS_MODULE, .name = "akita-max7310", }, .id = I2C_DRIVERID_AKITAIOEXP, -- cgit v1.2.3 From fa57f9c2b841872ffad9d8f7b3de23d6ba33c30d Mon Sep 17 00:00:00 2001 From: Eugene Surovegin Date: Fri, 6 Jan 2006 00:11:26 -0800 Subject: [PATCH] ppc32: remove "jumbo" member from ocp_func_emac_data Remove the not needed anymore "jumbo" member from ocp_func_emac_data. Jumbo frame support is handled by PPC4xx EMAC driver internally now. Signed-off-by: Eugene Surovegin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/platforms/4xx/ibm440gx.c | 2 -- arch/ppc/platforms/4xx/ibm440sp.c | 1 - 2 files changed, 3 deletions(-) (limited to 'arch') diff --git a/arch/ppc/platforms/4xx/ibm440gx.c b/arch/ppc/platforms/4xx/ibm440gx.c index 956f45e4ef9..d24c09ee7b1 100644 --- a/arch/ppc/platforms/4xx/ibm440gx.c +++ b/arch/ppc/platforms/4xx/ibm440gx.c @@ -58,7 +58,6 @@ static struct ocp_func_emac_data ibm440gx_emac2_def = { .wol_irq = 65, /* WOL interrupt number */ .mdio_idx = -1, /* No shared MDIO */ .tah_idx = 0, /* TAH device index */ - .jumbo = 1, /* Jumbo frames supported */ }; static struct ocp_func_emac_data ibm440gx_emac3_def = { @@ -72,7 +71,6 @@ static struct ocp_func_emac_data ibm440gx_emac3_def = { .wol_irq = 67, /* WOL interrupt number */ .mdio_idx = -1, /* No shared MDIO */ .tah_idx = 1, /* TAH device index */ - .jumbo = 1, /* Jumbo frames supported */ }; OCP_SYSFS_EMAC_DATA() diff --git a/arch/ppc/platforms/4xx/ibm440sp.c b/arch/ppc/platforms/4xx/ibm440sp.c index feb17e41ef6..71a0117d359 100644 --- a/arch/ppc/platforms/4xx/ibm440sp.c +++ b/arch/ppc/platforms/4xx/ibm440sp.c @@ -31,7 +31,6 @@ static struct ocp_func_emac_data ibm440sp_emac0_def = { .wol_irq = 61, /* WOL interrupt number */ .mdio_idx = -1, /* No shared MDIO */ .tah_idx = -1, /* No TAH */ - .jumbo = 1, /* Jumbo frames supported */ }; OCP_SYSFS_EMAC_DATA() -- cgit v1.2.3 From e13ac219816c58579f40b48220b2fa5d94c30e84 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Fri, 6 Jan 2006 00:11:26 -0800 Subject: [PATCH] arch/ppc/kernel/idle.c: don't declare cpu variable in non-SMP kernels Disable declaration of cpu variable in default_idle function when building non-SMP kernels. Signed-off-by: Otavio Salvador Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/kernel/idle.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c index 821a75e4560..1be3ca5bae4 100644 --- a/arch/ppc/kernel/idle.c +++ b/arch/ppc/kernel/idle.c @@ -37,7 +37,6 @@ void default_idle(void) { void (*powersave)(void); - int cpu = smp_processor_id(); powersave = ppc_md.power_save; @@ -47,7 +46,8 @@ void default_idle(void) #ifdef CONFIG_SMP else { set_thread_flag(TIF_POLLING_NRFLAG); - while (!need_resched() && !cpu_is_offline(cpu)) + while (!need_resched() && + !cpu_is_offline(smp_processor_id())) barrier(); clear_thread_flag(TIF_POLLING_NRFLAG); } -- cgit v1.2.3 From 7558824a8d16e244072bfebc9e5e3e3b1b9af261 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Fri, 6 Jan 2006 00:11:30 -0800 Subject: [PATCH] ppc32: Remove useless file arch/ppc/platforms/mpc5200.c That file is a left-over of the 'old' OCP model that should have been erased during the change to platform model but I forgot it ... Signed-off-by: Sylvain Munaut Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/platforms/mpc5200.c | 53 -------------------------------------------- 1 file changed, 53 deletions(-) delete mode 100644 arch/ppc/platforms/mpc5200.c (limited to 'arch') diff --git a/arch/ppc/platforms/mpc5200.c b/arch/ppc/platforms/mpc5200.c deleted file mode 100644 index a58db438c16..00000000000 --- a/arch/ppc/platforms/mpc5200.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * arch/ppc/platforms/mpc5200.c - * - * OCP Definitions for the boards based on MPC5200 processor. Contains - * definitions for every common peripherals. (Mostly all but PSCs) - * - * Maintainer : Sylvain Munaut - * - * Copyright 2004 Sylvain Munaut - * - * 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 - - -static struct ocp_fs_i2c_data mpc5200_i2c_def = { - .flags = FS_I2C_CLOCK_5200, -}; - - -/* Here is the core_ocp struct. - * With all the devices common to all board. Even if port multiplexing is - * not setup for them (if the user don't want them, just don't select the - * config option). The potentially conflicting devices (like PSCs) goes in - * board specific file. - */ -struct ocp_def core_ocp[] = { - { - .vendor = OCP_VENDOR_FREESCALE, - .function = OCP_FUNC_IIC, - .index = 0, - .paddr = MPC52xx_I2C1, - .irq = OCP_IRQ_NA, /* MPC52xx_IRQ_I2C1 - Buggy */ - .pm = OCP_CPM_NA, - .additions = &mpc5200_i2c_def, - }, - { - .vendor = OCP_VENDOR_FREESCALE, - .function = OCP_FUNC_IIC, - .index = 1, - .paddr = MPC52xx_I2C2, - .irq = OCP_IRQ_NA, /* MPC52xx_IRQ_I2C2 - Buggy */ - .pm = OCP_CPM_NA, - .additions = &mpc5200_i2c_def, - }, - { /* Terminating entry */ - .vendor = OCP_VENDOR_INVALID - } -}; -- cgit v1.2.3 From 4aa7c80193c561e52c06351e0f521e697954a859 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Fri, 6 Jan 2006 00:11:34 -0800 Subject: [PATCH] ppc32: Fix static IO mapping for Freescale MPC52xx The current iomapping used MBAR_SIZE for the size argument of io_block_mapping, resulting in a call to setbat with a size argument of 64k which is invalid. This patch correct this and maps the whole 0xf0000000->0xffffffff range so that devices on the local bus are also included in the BAT mapping. Thanks to Bernhard Kuhn from Metrowerks for pointing this out. Signed-off-by: Sylvain Munaut Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/syslib/mpc52xx_setup.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c index bb2374585a7..a4a4b02227d 100644 --- a/arch/ppc/syslib/mpc52xx_setup.c +++ b/arch/ppc/syslib/mpc52xx_setup.c @@ -84,9 +84,11 @@ mpc52xx_set_bat(void) void __init mpc52xx_map_io(void) { - /* Here we only map the MBAR */ + /* Here we map the MBAR and the whole upper zone. MBAR is only + 64k but we can't map only 64k with BATs. Map the whole + 0xf0000000 range is ok and helps eventual lpb devices placed there */ io_block_mapping( - MPC52xx_MBAR_VIRT, MPC52xx_MBAR, MPC52xx_MBAR_SIZE, _PAGE_IO); + MPC52xx_MBAR_VIRT, MPC52xx_MBAR, 0x10000000, _PAGE_IO); } -- cgit v1.2.3 From dbeb198d9366eb3d3ad64444ceecb5b1d5b5d7ef Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Fri, 6 Jan 2006 00:11:35 -0800 Subject: [PATCH] ppc32: Remove __init qualifier from mpc52xx pci resources fixups The mpc52xx_pci_fixup_resources is not only called at init but also when there is a pci hotplug like when a cardbus card is plugged in. So that function is needed after init too. Thanks to Asier Llano Palacios for reporting this. Signed-off-by: Sylvain Munaut Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/syslib/mpc52xx_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/ppc/syslib/mpc52xx_pci.c b/arch/ppc/syslib/mpc52xx_pci.c index 4ac19080eb8..e6cb3e26615 100644 --- a/arch/ppc/syslib/mpc52xx_pci.c +++ b/arch/ppc/syslib/mpc52xx_pci.c @@ -151,7 +151,7 @@ mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs) #endif } -static void __init +static void mpc52xx_pci_fixup_resources(struct pci_dev *dev) { int i; -- cgit v1.2.3 From db674ed450f113518285f410c93abecd93e71a2f Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Fri, 6 Jan 2006 00:11:36 -0800 Subject: [PATCH] ppc32: Fix MPC52xx configuration space access This patch takes care of an errata of the MPC5200 by avoiding 32 bits access in type 1 configuration accesses. All others accesses are still 32 bits wide. It also adds some mb() since the simple out_be(...) are not sufficient in this case. Signed-off-by: Sylvain Munaut Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/syslib/mpc52xx_pci.c | 83 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 69 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/ppc/syslib/mpc52xx_pci.c b/arch/ppc/syslib/mpc52xx_pci.c index e6cb3e26615..2c5e6ddaf2c 100644 --- a/arch/ppc/syslib/mpc52xx_pci.c +++ b/arch/ppc/syslib/mpc52xx_pci.c @@ -24,6 +24,12 @@ #include +/* This macro is defined to activate the workaround for the bug + 435 of the MPC5200 (L25R). With it activated, we don't do any + 32 bits configuration access during type-1 cycles */ +#define MPC5200_BUG_435_WORKAROUND + + static int mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val) @@ -40,17 +46,39 @@ mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, ((bus->number - hose->bus_offset) << 16) | (devfn << 8) | (offset & 0xfc)); + mb(); + +#ifdef MPC5200_BUG_435_WORKAROUND + if (bus->number != hose->bus_offset) { + switch (len) { + case 1: + value = in_8(((u8 __iomem *)hose->cfg_data) + (offset & 3)); + break; + case 2: + value = in_le16(((u16 __iomem *)hose->cfg_data) + ((offset>>1) & 1)); + break; + + default: + value = in_le16((u16 __iomem *)hose->cfg_data) | + (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16); + break; + } + } + else +#endif + { + value = in_le32(hose->cfg_data); - value = in_le32(hose->cfg_data); - - if (len != 4) { - value >>= ((offset & 0x3) << 3); - value &= 0xffffffff >> (32 - (len << 3)); + if (len != 4) { + value >>= ((offset & 0x3) << 3); + value &= 0xffffffff >> (32 - (len << 3)); + } } *val = value; out_be32(hose->cfg_addr, 0); + mb(); return PCIBIOS_SUCCESSFUL; } @@ -71,21 +99,48 @@ mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, ((bus->number - hose->bus_offset) << 16) | (devfn << 8) | (offset & 0xfc)); + mb(); + +#ifdef MPC5200_BUG_435_WORKAROUND + if (bus->number != hose->bus_offset) { + switch (len) { + case 1: + out_8(((u8 __iomem *)hose->cfg_data) + + (offset & 3), val); + break; + case 2: + out_le16(((u16 __iomem *)hose->cfg_data) + + ((offset>>1) & 1), val); + break; + + default: + out_le16((u16 __iomem *)hose->cfg_data, + (u16)val); + out_le16(((u16 __iomem *)hose->cfg_data) + 1, + (u16)(val>>16)); + break; + } + } + else +#endif + { + if (len != 4) { + value = in_le32(hose->cfg_data); - if (len != 4) { - value = in_le32(hose->cfg_data); + offset = (offset & 0x3) << 3; + mask = (0xffffffff >> (32 - (len << 3))); + mask <<= offset; - offset = (offset & 0x3) << 3; - mask = (0xffffffff >> (32 - (len << 3))); - mask <<= offset; + value &= ~mask; + val = value | ((val << offset) & mask); + } - value &= ~mask; - val = value | ((val << offset) & mask); + out_le32(hose->cfg_data, val); } - - out_le32(hose->cfg_data, val); + mb(); out_be32(hose->cfg_addr, 0); + mb(); return PCIBIOS_SUCCESSFUL; } -- cgit v1.2.3 From 041cb6241fa97c4881dd19d79f783b2e077acd28 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Fri, 6 Jan 2006 00:11:37 -0800 Subject: [PATCH] ppc32: Fix MPC52xx PCI init in cas the bootloader didn't do it We were counting on the bootloader to init some stuff, like get the bus out of reset and enable accesses. Signed-off-by: Sylvain Munaut Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/syslib/mpc52xx_pci.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/ppc/syslib/mpc52xx_pci.c b/arch/ppc/syslib/mpc52xx_pci.c index 2c5e6ddaf2c..313c96ec7eb 100644 --- a/arch/ppc/syslib/mpc52xx_pci.c +++ b/arch/ppc/syslib/mpc52xx_pci.c @@ -154,9 +154,12 @@ static struct pci_ops mpc52xx_pci_ops = { static void __init mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs) { + u32 tmp; /* Setup control regs */ - /* Nothing to do afaik */ + tmp = in_be32(&pci_regs->scr); + tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + out_be32(&pci_regs->scr, tmp); /* Setup windows */ out_be32(&pci_regs->iw0btar, MPC52xx_PCI_IWBTAR_TRANSLATION( @@ -197,13 +200,12 @@ mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs) /* Not necessary and can be a bad thing if for example the bootloader is displaying a splash screen or ... Just left here for documentation purpose if anyone need it */ -#if 0 - u32 tmp; tmp = in_be32(&pci_regs->gscr); +#if 0 out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR); udelay(50); - out_be32(&pci_regs->gscr, tmp); #endif + out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR); } static void -- cgit v1.2.3 From f80257a25d9f73a0e6e377c7d6bf29b8938c042d Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Fri, 6 Jan 2006 00:11:38 -0800 Subject: [PATCH] ppc32: Allows compilation of a MPC52xx kernel without PCI Some custom cards might not need PCI, without this patch, compilation fails. Signed-off-by: Roger Blofeld Signed-off-by: Sylvain Munaut Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/platforms/lite5200.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/ppc/platforms/lite5200.c b/arch/ppc/platforms/lite5200.c index d44cc991179..7ed52dc340c 100644 --- a/arch/ppc/platforms/lite5200.c +++ b/arch/ppc/platforms/lite5200.c @@ -196,8 +196,10 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, mpc52xx_set_bat(); /* No ISA bus by default */ +#ifdef CONFIG_PCI isa_io_base = 0; isa_mem_base = 0; +#endif /* Powersave */ /* This is provided as an example on how to do it. But you -- cgit v1.2.3 From 683e2cc6dc5aa9bb4ba2f2e0662df9d7f0a1d6c2 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Fri, 6 Jan 2006 00:11:39 -0800 Subject: [PATCH] ppc32: Re-add embed_config.c to ml300/ep405 Commit 3e9e7c1d0b7a36fb8affb973a054c5098e27baa8 (ppc32: cleanup AMCC PPC40x eval boards to support U-Boot) broke the kernel for ML300 / EP405. It still compiles as there's a weak definition of the function in misc-embedded.c, but the kernel crashes as the bd_t fixup isn't performed. Signed-off-by: Peter Korsgaard Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/boot/simple/Makefile | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile index f3e9c534aa8..9533f8de238 100644 --- a/arch/ppc/boot/simple/Makefile +++ b/arch/ppc/boot/simple/Makefile @@ -190,6 +190,8 @@ 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_EP405) += embed_config.o +boot-$(CONFIG_XILINX_ML300) += embed_config.o boot-$(CONFIG_BSEIP) += iic.o boot-$(CONFIG_MBX) += iic.o pci.o qspan_pci.o boot-$(CONFIG_MV64X60) += misc-mv64x60.o -- cgit v1.2.3 From 5c40f7f373889930d176a515ec375b60a70b5b49 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 6 Jan 2006 00:11:43 -0800 Subject: [PATCH] FRV: Implement futex operations for FRV The attached patch implements futex operations for the FRV architecture. The operations are applicable to both MMU and no-MMU modes; though the EFAULT handling will be a little bit of wasted space on the latter. Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/frv/kernel/Makefile | 1 + arch/frv/kernel/futex.c | 242 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 243 insertions(+) create mode 100644 arch/frv/kernel/futex.c (limited to 'arch') diff --git a/arch/frv/kernel/Makefile b/arch/frv/kernel/Makefile index 981c2c7dec0..422f30ede57 100644 --- a/arch/frv/kernel/Makefile +++ b/arch/frv/kernel/Makefile @@ -20,3 +20,4 @@ obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o obj-$(CONFIG_PM) += pm.o cmode.o obj-$(CONFIG_MB93093_PDK) += pm-mb93093.o obj-$(CONFIG_SYSCTL) += sysctl.o +obj-$(CONFIG_FUTEX) += futex.o diff --git a/arch/frv/kernel/futex.c b/arch/frv/kernel/futex.c new file mode 100644 index 00000000000..eae874a970c --- /dev/null +++ b/arch/frv/kernel/futex.c @@ -0,0 +1,242 @@ +/* futex.c: futex operations + * + * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.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. + */ + +#include +#include +#include +#include + +/* + * the various futex operations; MMU fault checking is ignored under no-MMU + * conditions + */ +static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_oldval) +{ + int oldval, ret; + + asm("0: \n" + " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ + " ckeq icc3,cc7 \n" + "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ + " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ + "2: cst.p %3,%M0 ,cc3,#1 \n" + " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ + " beq icc3,#0,0b \n" + " setlos 0,%2 \n" + "3: \n" + ".subsection 2 \n" + "4: setlos %5,%2 \n" + " bra 3b \n" + ".previous \n" + ".section __ex_table,\"a\" \n" + " .balign 8 \n" + " .long 1b,4b \n" + " .long 2b,4b \n" + ".previous" + : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) + : "3"(oparg), "i"(-EFAULT) + : "memory", "cc7", "cc3", "icc3" + ); + + *_oldval = oldval; + return ret; +} + +static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_oldval) +{ + int oldval, ret; + + asm("0: \n" + " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ + " ckeq icc3,cc7 \n" + "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ + " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ + " add %1,%3,%3 \n" + "2: cst.p %3,%M0 ,cc3,#1 \n" + " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ + " beq icc3,#0,0b \n" + " setlos 0,%2 \n" + "3: \n" + ".subsection 2 \n" + "4: setlos %5,%2 \n" + " bra 3b \n" + ".previous \n" + ".section __ex_table,\"a\" \n" + " .balign 8 \n" + " .long 1b,4b \n" + " .long 2b,4b \n" + ".previous" + : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) + : "3"(oparg), "i"(-EFAULT) + : "memory", "cc7", "cc3", "icc3" + ); + + *_oldval = oldval; + return ret; +} + +static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_oldval) +{ + int oldval, ret; + + asm("0: \n" + " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ + " ckeq icc3,cc7 \n" + "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ + " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ + " or %1,%3,%3 \n" + "2: cst.p %3,%M0 ,cc3,#1 \n" + " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ + " beq icc3,#0,0b \n" + " setlos 0,%2 \n" + "3: \n" + ".subsection 2 \n" + "4: setlos %5,%2 \n" + " bra 3b \n" + ".previous \n" + ".section __ex_table,\"a\" \n" + " .balign 8 \n" + " .long 1b,4b \n" + " .long 2b,4b \n" + ".previous" + : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) + : "3"(oparg), "i"(-EFAULT) + : "memory", "cc7", "cc3", "icc3" + ); + + *_oldval = oldval; + return ret; +} + +static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_oldval) +{ + int oldval, ret; + + asm("0: \n" + " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ + " ckeq icc3,cc7 \n" + "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ + " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ + " and %1,%3,%3 \n" + "2: cst.p %3,%M0 ,cc3,#1 \n" + " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ + " beq icc3,#0,0b \n" + " setlos 0,%2 \n" + "3: \n" + ".subsection 2 \n" + "4: setlos %5,%2 \n" + " bra 3b \n" + ".previous \n" + ".section __ex_table,\"a\" \n" + " .balign 8 \n" + " .long 1b,4b \n" + " .long 2b,4b \n" + ".previous" + : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) + : "3"(oparg), "i"(-EFAULT) + : "memory", "cc7", "cc3", "icc3" + ); + + *_oldval = oldval; + return ret; +} + +static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_oldval) +{ + int oldval, ret; + + asm("0: \n" + " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ + " ckeq icc3,cc7 \n" + "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ + " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ + " xor %1,%3,%3 \n" + "2: cst.p %3,%M0 ,cc3,#1 \n" + " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ + " beq icc3,#0,0b \n" + " setlos 0,%2 \n" + "3: \n" + ".subsection 2 \n" + "4: setlos %5,%2 \n" + " bra 3b \n" + ".previous \n" + ".section __ex_table,\"a\" \n" + " .balign 8 \n" + " .long 1b,4b \n" + " .long 2b,4b \n" + ".previous" + : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) + : "3"(oparg), "i"(-EFAULT) + : "memory", "cc7", "cc3", "icc3" + ); + + *_oldval = oldval; + return ret; +} + +/*****************************************************************************/ +/* + * do the futex operations + */ +int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) +{ + int op = (encoded_op >> 28) & 7; + int cmp = (encoded_op >> 24) & 15; + int oparg = (encoded_op << 8) >> 20; + int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; + + if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) + oparg = 1 << oparg; + + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) + return -EFAULT; + + inc_preempt_count(); + + switch (op) { + case FUTEX_OP_SET: + ret = atomic_futex_op_xchg_set(oparg, uaddr, &oldval); + break; + case FUTEX_OP_ADD: + ret = atomic_futex_op_xchg_add(oparg, uaddr, &oldval); + break; + case FUTEX_OP_OR: + ret = atomic_futex_op_xchg_or(oparg, uaddr, &oldval); + break; + case FUTEX_OP_ANDN: + ret = atomic_futex_op_xchg_and(~oparg, uaddr, &oldval); + break; + case FUTEX_OP_XOR: + ret = atomic_futex_op_xchg_xor(oparg, uaddr, &oldval); + break; + default: + ret = -ENOSYS; + break; + } + + dec_preempt_count(); + + if (!ret) { + switch (cmp) { + case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; + case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; + case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; + case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; + case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; + case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; + default: ret = -ENOSYS; break; + } + } + + return ret; + +} /* end futex_atomic_op_inuser() */ -- cgit v1.2.3 From 8efc0ab50edbac5c65191b8a58dfdab3741b7901 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 6 Jan 2006 00:11:44 -0800 Subject: [PATCH] frv: fix signal handling The attached patch makes FRV signal handling work properly: (1) After do_notify_resume() has been called, the work flags must be checked again (there may be another signal to deliver or the process might require rescheduling for instance). (2) After the signal frame is set up on the userspace stack, ptrace() should be given an opportunity to single-step into the signal handler. (3) The error state from setting up a signal frame should be passed back up the call chain. (4) The segfault handler shouldn't be preemptively reset in the arch if we fail to deliver a SEGV signal: force_sig() will take care of that. Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/frv/kernel/entry.S | 2 +- arch/frv/kernel/signal.c | 73 +++++++++++++++++++++++++++++------------------- 2 files changed, 46 insertions(+), 29 deletions(-) (limited to 'arch') diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S index ad10ea59545..5f6548388b7 100644 --- a/arch/frv/kernel/entry.S +++ b/arch/frv/kernel/entry.S @@ -1076,7 +1076,7 @@ __entry_work_notifysig: LEDS 0x6410 ori.p gr4,#0,gr8 call do_notify_resume - bra __entry_return_direct + bra __entry_resume_userspace # perform syscall entry tracing __syscall_trace_entry: diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index d4ccc0728df..89a1cf5c076 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c @@ -297,7 +297,8 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, /* * */ -static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs) +static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, + struct pt_regs *regs) { struct sigframe __user *frame; int rsig; @@ -362,26 +363,30 @@ static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct p set_fs(USER_DS); + /* the tracer may want to single-step inside the handler */ + if (test_thread_flag(TIF_SINGLESTEP)) + ptrace_notify(SIGTRAP); + #if DEBUG_SIG printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", - sig, current->comm, current->pid, frame, regs->pc, frame->pretcode); + sig, current->comm, current->pid, frame, regs->pc, + frame->pretcode); #endif - return; + return 1; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + return 0; + } /* end setup_frame() */ /*****************************************************************************/ /* * */ -static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs * regs) +static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs * regs) { struct rt_sigframe __user *frame; int rsig; @@ -457,17 +462,21 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, set_fs(USER_DS); + /* the tracer may want to single-step inside the handler */ + if (test_thread_flag(TIF_SINGLESTEP)) + ptrace_notify(SIGTRAP); + #if DEBUG_SIG printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", - sig, current->comm, current->pid, frame, regs->pc, frame->pretcode); + sig, current->comm, current->pid, frame, regs->pc, + frame->pretcode); #endif - return; + return 1; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; force_sig(SIGSEGV, current); + return 0; } /* end setup_rt_frame() */ @@ -475,10 +484,12 @@ give_sigsegv: /* * OK, we're invoking a handler */ -static void handle_signal(unsigned long sig, siginfo_t *info, - struct k_sigaction *ka, sigset_t *oldset, - struct pt_regs *regs) +static int handle_signal(unsigned long sig, siginfo_t *info, + struct k_sigaction *ka, sigset_t *oldset, + struct pt_regs *regs) { + int ret; + /* Are we from a system call? */ if (in_syscall(regs)) { /* If so, check system call restarting.. */ @@ -493,6 +504,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info, regs->gr8 = -EINTR; break; } + /* fallthrough */ case -ERESTARTNOINTR: regs->gr8 = regs->orig_gr8; @@ -502,16 +514,22 @@ static void handle_signal(unsigned long sig, siginfo_t *info, /* Set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(sig, ka, info, oldset, regs); + ret = setup_rt_frame(sig, ka, info, oldset, regs); else - setup_frame(sig, ka, oldset, regs); + ret = setup_frame(sig, ka, oldset, regs); + + if (ret) { + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked, ¤t->blocked, + &ka->sa.sa_mask); + if (!(ka->sa.sa_flags & SA_NODEFER)) + sigaddset(¤t->blocked, sig); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + } + + return ret; - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked, sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); } /* end handle_signal() */ /*****************************************************************************/ @@ -542,12 +560,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); - if (signr > 0) { - handle_signal(signr, &info, &ka, oldset, regs); - return 1; - } + if (signr > 0) + return handle_signal(signr, &info, &ka, oldset, regs); - no_signal: +no_signal: /* Did we come from a system call? */ if (regs->syscallno >= 0) { /* Restart the system call - no handlers present */ @@ -565,6 +581,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) } return 0; + } /* end do_signal() */ /*****************************************************************************/ -- cgit v1.2.3 From fef2b580eb50281ae1d2413ab340f677f6722281 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 6 Jan 2006 00:11:45 -0800 Subject: [PATCH] frv: improve signal handling The attached patch improves the signal handling: (1) It makes do_signal() static as it isn't called from anywhere outside of the arch code. (2) It removes the regs argument to all the static functions within that file, using __frame instead (which is the same thing held in a global register). Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/frv/kernel/signal.c | 102 +++++++++++++++++++++++------------------------ 1 file changed, 50 insertions(+), 52 deletions(-) (limited to 'arch') diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index 89a1cf5c076..5b7146f54fd 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c @@ -35,7 +35,7 @@ struct fdpic_func_descriptor { unsigned long GOT; }; -asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); +static int do_signal(sigset_t *oldset); /* * Atomically swap in the new signal mask, and wait for a signal. @@ -55,7 +55,7 @@ asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask) while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(__frame, &saveset)) + if (do_signal(&saveset)) /* return the signal number as the return value of this function * - this is an utterly evil hack. syscalls should not invoke do_signal() * as entry.S sets regs->gr8 to the return value of the system call @@ -91,7 +91,7 @@ asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize) while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(__frame, &saveset)) + if (do_signal(&saveset)) /* return the signal number as the return value of this function * - this is an utterly evil hack. syscalls should not invoke do_signal() * as entry.S sets regs->gr8 to the return value of the system call @@ -276,13 +276,12 @@ static int setup_sigcontext(struct sigcontext __user *sc, unsigned long mask) * Determine which stack to use.. */ static inline void __user *get_sigframe(struct k_sigaction *ka, - struct pt_regs *regs, size_t frame_size) { unsigned long sp; /* Default to using normal stack */ - sp = regs->sp; + sp = __frame->sp; /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { @@ -291,19 +290,19 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, } return (void __user *) ((sp - frame_size) & ~7UL); + } /* end get_sigframe() */ /*****************************************************************************/ /* * */ -static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, - struct pt_regs *regs) +static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) { struct sigframe __user *frame; int rsig; - frame = get_sigframe(ka, regs, sizeof(*frame)); + frame = get_sigframe(ka, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; @@ -347,18 +346,18 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, } /* set up registers for signal handler */ - regs->sp = (unsigned long) frame; - regs->lr = (unsigned long) &frame->retcode; - regs->gr8 = sig; + __frame->sp = (unsigned long) frame; + __frame->lr = (unsigned long) &frame->retcode; + __frame->gr8 = sig; if (get_personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor *) ka->sa.sa_handler; - __get_user(regs->pc, &funcptr->text); - __get_user(regs->gr15, &funcptr->GOT); + __get_user(__frame->pc, &funcptr->text); + __get_user(__frame->gr15, &funcptr->GOT); } else { - regs->pc = (unsigned long) ka->sa.sa_handler; - regs->gr15 = 0; + __frame->pc = (unsigned long) ka->sa.sa_handler; + __frame->gr15 = 0; } set_fs(USER_DS); @@ -369,7 +368,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, #if DEBUG_SIG printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", - sig, current->comm, current->pid, frame, regs->pc, + sig, current->comm, current->pid, frame, __frame->pc, frame->pretcode); #endif @@ -386,12 +385,12 @@ give_sigsegv: * */ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs * regs) + sigset_t *set) { struct rt_sigframe __user *frame; int rsig; - frame = get_sigframe(ka, regs, sizeof(*frame)); + frame = get_sigframe(ka, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; @@ -414,7 +413,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, if (__put_user(0, &frame->uc.uc_flags) || __put_user(0, &frame->uc.uc_link) || __put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) || - __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags) || + __put_user(sas_ss_flags(__frame->sp), &frame->uc.uc_stack.ss_flags) || __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size)) goto give_sigsegv; @@ -445,19 +444,19 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, } /* Set up registers for signal handler */ - regs->sp = (unsigned long) frame; - regs->lr = (unsigned long) &frame->retcode; - regs->gr8 = sig; - regs->gr9 = (unsigned long) &frame->info; + __frame->sp = (unsigned long) frame; + __frame->lr = (unsigned long) &frame->retcode; + __frame->gr8 = sig; + __frame->gr9 = (unsigned long) &frame->info; if (get_personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor *funcptr = (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; - __get_user(regs->pc, &funcptr->text); - __get_user(regs->gr15, &funcptr->GOT); + __get_user(__frame->pc, &funcptr->text); + __get_user(__frame->gr15, &funcptr->GOT); } else { - regs->pc = (unsigned long) ka->sa.sa_handler; - regs->gr15 = 0; + __frame->pc = (unsigned long) ka->sa.sa_handler; + __frame->gr15 = 0; } set_fs(USER_DS); @@ -468,7 +467,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, #if DEBUG_SIG printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", - sig, current->comm, current->pid, frame, regs->pc, + sig, current->comm, current->pid, frame, __frame->pc, frame->pretcode); #endif @@ -485,38 +484,37 @@ give_sigsegv: * OK, we're invoking a handler */ static int handle_signal(unsigned long sig, siginfo_t *info, - struct k_sigaction *ka, sigset_t *oldset, - struct pt_regs *regs) + struct k_sigaction *ka, sigset_t *oldset) { int ret; /* Are we from a system call? */ - if (in_syscall(regs)) { + if (in_syscall(__frame)) { /* If so, check system call restarting.. */ - switch (regs->gr8) { + switch (__frame->gr8) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: - regs->gr8 = -EINTR; + __frame->gr8 = -EINTR; break; case -ERESTARTSYS: if (!(ka->sa.sa_flags & SA_RESTART)) { - regs->gr8 = -EINTR; + __frame->gr8 = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: - regs->gr8 = regs->orig_gr8; - regs->pc -= 4; + __frame->gr8 = __frame->orig_gr8; + __frame->pc -= 4; } } /* Set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) - ret = setup_rt_frame(sig, ka, info, oldset, regs); + ret = setup_rt_frame(sig, ka, info, oldset); else - ret = setup_frame(sig, ka, oldset, regs); + ret = setup_frame(sig, ka, oldset); if (ret) { spin_lock_irq(¤t->sighand->siglock); @@ -538,7 +536,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info, * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -int do_signal(struct pt_regs *regs, sigset_t *oldset) +static int do_signal(sigset_t *oldset) { struct k_sigaction ka; siginfo_t info; @@ -550,7 +548,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) * kernel mode. Just return without doing anything * if so. */ - if (!user_mode(regs)) + if (!user_mode(__frame)) return 1; if (try_to_freeze()) @@ -559,24 +557,24 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, &ka, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, __frame, NULL); if (signr > 0) - return handle_signal(signr, &info, &ka, oldset, regs); + return handle_signal(signr, &info, &ka, oldset); no_signal: /* Did we come from a system call? */ - if (regs->syscallno >= 0) { + if (__frame->syscallno >= 0) { /* Restart the system call - no handlers present */ - if (regs->gr8 == -ERESTARTNOHAND || - regs->gr8 == -ERESTARTSYS || - regs->gr8 == -ERESTARTNOINTR) { - regs->gr8 = regs->orig_gr8; - regs->pc -= 4; + if (__frame->gr8 == -ERESTARTNOHAND || + __frame->gr8 == -ERESTARTSYS || + __frame->gr8 == -ERESTARTNOINTR) { + __frame->gr8 = __frame->orig_gr8; + __frame->pc -= 4; } - if (regs->gr8 == -ERESTART_RESTARTBLOCK){ - regs->gr8 = __NR_restart_syscall; - regs->pc -= 4; + if (__frame->gr8 == -ERESTART_RESTARTBLOCK){ + __frame->gr8 = __NR_restart_syscall; + __frame->pc -= 4; } } @@ -597,6 +595,6 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags) /* deal with pending signal delivery */ if (thread_info_flags & _TIF_SIGPENDING) - do_signal(__frame, NULL); + do_signal(NULL); } /* end do_notify_resume() */ -- cgit v1.2.3 From 7c4cb60e5b97677424e95baee9c29df54b26e6ba Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 6 Jan 2006 00:11:47 -0800 Subject: [PATCH] x86: GDT alignment fix Make GDT page aligned and page padded to support running inside of a hypervisor. This prevents false sharing of the GDT page with other hot data, which is not allowed in Xen, and causes performance problems in VMware. Rather than go back to the old method of statically allocating the GDT (which wastes unneded space for non-present CPUs), the GDT for APs is allocated dynamically. Signed-off-by: Zachary Amsden Cc: "Seth, Rohit" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apm.c | 2 ++ arch/i386/kernel/cpu/common.c | 3 --- arch/i386/kernel/head.S | 2 ++ arch/i386/kernel/i386_ksyms.c | 3 +-- arch/i386/kernel/smpboot.c | 6 ++++++ 5 files changed, 11 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 1e60acbed3c..6c8e483ce9e 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -2317,6 +2317,8 @@ static int __init apm_init(void) for (i = 0; i < NR_CPUS; i++) { struct desc_struct *gdt = get_cpu_gdt_table(i); + if (!gdt) + continue; set_base(gdt[APM_CS >> 3], __va((unsigned long)apm_info.bios.cseg << 4)); set_base(gdt[APM_CS_16 >> 3], diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 31e344b26ba..cbc32069683 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -18,9 +18,6 @@ #include "cpu.h" -DEFINE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]); -EXPORT_PER_CPU_SYMBOL(cpu_gdt_table); - DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]); EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack); diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index e437fb36749..870f20bf33c 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -525,3 +525,5 @@ ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* 0xf0 - unused */ .quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */ + /* Be sure this is zeroed to avoid false validations in Xen */ + .fill PAGE_SIZE_asm / 8 - GDT_ENTRIES,8,0 diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c index 180f070d03c..3999bec50c3 100644 --- a/arch/i386/kernel/i386_ksyms.c +++ b/arch/i386/kernel/i386_ksyms.c @@ -3,8 +3,7 @@ #include #include -/* This is definitely a GPL-only symbol */ -EXPORT_SYMBOL_GPL(cpu_gdt_table); +EXPORT_SYMBOL_GPL(cpu_gdt_descr); EXPORT_SYMBOL(__down_failed); EXPORT_SYMBOL(__down_failed_interruptible); diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 9ed449af8e9..b3c2e2c2674 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -903,6 +903,12 @@ static int __devinit do_boot_cpu(int apicid, int cpu) unsigned long start_eip; unsigned short nmi_high = 0, nmi_low = 0; + if (!cpu_gdt_descr[cpu].address && + !(cpu_gdt_descr[cpu].address = get_zeroed_page(GFP_KERNEL))) { + printk("Failed to allocate GDT for CPU %d\n", cpu); + return 1; + } + ++cpucount; /* -- cgit v1.2.3 From e43d674f44dc885a2476cab3537e639d9eaa31a9 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 6 Jan 2006 00:11:48 -0800 Subject: [PATCH] i386: don't blindly enable interrupts in die() Rather than blindly re-enabling interrupts in die(), save their state upon entry and then restore that state. If the kernel is in really bad condition and faults with interrupts disabled, re-enabling them in die() may cause even more trouble, implying more chances of data corruption. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/traps.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index ab0e9430f77..bb36a989db7 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -306,14 +306,17 @@ void die(const char * str, struct pt_regs * regs, long err) .lock_owner_depth = 0 }; static int die_counter; + unsigned long flags; if (die.lock_owner != raw_smp_processor_id()) { console_verbose(); - spin_lock_irq(&die.lock); + spin_lock_irqsave(&die.lock, flags); die.lock_owner = smp_processor_id(); die.lock_owner_depth = 0; bust_spinlocks(1); } + else + local_save_flags(flags); if (++die.lock_owner_depth < 3) { int nl = 0; @@ -340,7 +343,7 @@ void die(const char * str, struct pt_regs * regs, long err) bust_spinlocks(0); die.lock_owner = -1; - spin_unlock_irq(&die.lock); + spin_unlock_irqrestore(&die.lock, flags); if (kexec_should_crash(current)) crash_kexec(regs); -- cgit v1.2.3 From d43c6e8083ac8baeb1a167510aea34fcef396e33 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 6 Jan 2006 00:11:49 -0800 Subject: [PATCH] i386: move SIMD initialization Move some code unrelated to any dealing with hardware bugs from i386's bugs.h to a more logical place. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/traps.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'arch') diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index bb36a989db7..f0c4060bd4d 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -1098,6 +1098,28 @@ void __init trap_init(void) #endif set_trap_gate(19,&simd_coprocessor_error); + if (cpu_has_fxsr) { + /* + * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned. + * Generates a compile-time "error: zero width for bit-field" if + * the alignment is wrong. + */ + struct fxsrAlignAssert { + int _:!(offsetof(struct task_struct, + thread.i387.fxsave) & 15); + }; + + printk(KERN_INFO "Enabling fast FPU save and restore... "); + set_in_cr4(X86_CR4_OSFXSR); + printk("done.\n"); + } + if (cpu_has_xmm) { + printk(KERN_INFO "Enabling unmasked SIMD FPU exception " + "support... "); + set_in_cr4(X86_CR4_OSXMMEXCPT); + printk("done.\n"); + } + set_system_gate(SYSCALL_VECTOR,&system_call); /* -- cgit v1.2.3 From eb05c3249a8e8a675e79d221f4a0874dc10ec903 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 6 Jan 2006 00:11:49 -0800 Subject: [PATCH] i386: fix bound check IDT gate Other than apparently commonly assumed, the bound instruction does not require the corresponding IDT entry to have DPL 3. Acked-by: "Seth, Rohit" Acked-by: Zachary Amsden Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/traps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index f0c4060bd4d..53ad954e3ba 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -1078,9 +1078,9 @@ void __init trap_init(void) set_trap_gate(0,÷_error); set_intr_gate(1,&debug); set_intr_gate(2,&nmi); - set_system_intr_gate(3, &int3); /* int3-5 can be called from all */ + set_system_intr_gate(3, &int3); /* int3/4 can be called from all */ set_system_gate(4,&overflow); - set_system_gate(5,&bounds); + set_trap_gate(5,&bounds); set_trap_gate(6,&invalid_op); set_trap_gate(7,&device_not_available); set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS); -- cgit v1.2.3 From ff6e8c0d5e47f0ceeebde86ec2f5919dbd5beb67 Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 6 Jan 2006 00:11:50 -0800 Subject: [PATCH] x86: Cr4 is valid on some 486s So some 486 processors do have CR4 register. Allow them to present it in register dumps by using the old fault technique rather than testing processor family. Thanks to Maciej for noticing this. Signed-off-by: Zachary Amsden Cc: "Seth, Rohit" Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/process.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 2333aead056..6081a10d341 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -308,9 +308,7 @@ void show_regs(struct pt_regs * regs) cr0 = read_cr0(); cr2 = read_cr2(); cr3 = read_cr3(); - if (current_cpu_data.x86 > 4) { - cr4 = read_cr4(); - } + cr4 = read_cr4_safe(); printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4); show_trace(NULL, ®s->esp); } -- cgit v1.2.3 From 3012d2d209580c78b5927d55c60a10891be8befd Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 6 Jan 2006 00:11:53 -0800 Subject: [PATCH] x86: Always relax segments APM BIOSes have many bugs regarding proper representation of the appropriate segment limits for calling the BIOS. By default, APM_RELAX_SEGMENTS is always turned on to support running the APM BIOS on these buggy machines. Keeping 64k limits poses very little danger to the kernel, because the pages where the APM BIOS is located will always be in low physical memory BIOS areas, which should already be marked reserved, and only buggy BIOSes would possibly overstep the segment bounds with writes to data anyway. Since forcing stricter limits breaks many machines and is not default behavior, it seems reasonable to deprecate the older code which may cause APM BIOS to fault. If you really have a badly enough broken APM BIOS that you have to turn off APM_RELAX_SEGMENTS, seems like the best recourse here would be to disable the APM BIOS and / or not compile it into your kernel to begin with, and / or add your system to the known bad list. The reason I want to deprecate this code is there is underlying brokenness with the set_limit macros, and getting rid of many of the call sites rather than rewriting them seems to be the simplest and most correct course of action. Signed-off-by: Zachary Amsden Acked-by: "Seth, Rohit" Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apm.c | 55 ++++++++++++++++---------------------------------- 1 file changed, 17 insertions(+), 38 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 6c8e483ce9e..0d2981120cd 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -302,17 +302,6 @@ extern int (*console_blank_hook)(int); #include "apm.h" -/* - * Define to make all _set_limit calls use 64k limits. The APM 1.1 BIOS is - * supposed to provide limit information that it recognizes. Many machines - * do this correctly, but many others do not restrict themselves to their - * claimed limit. When this happens, they will cause a segmentation - * violation in the kernel at boot time. Most BIOS's, however, will - * respect a 64k limit, so we use that. If you want to be pedantic and - * hold your BIOS to its claims, then undefine this. - */ -#define APM_RELAX_SEGMENTS - /* * Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend. * This patched by Chad Miller , original code by @@ -2312,9 +2301,20 @@ static int __init apm_init(void) set_base(bad_bios_desc, __va((unsigned long)0x40 << 4)); _set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4)); + /* + * Set up the long jump entry point to the APM BIOS, which is called + * from inline assembly. + */ apm_bios_entry.offset = apm_info.bios.offset; apm_bios_entry.segment = APM_CS; + /* + * The APM 1.1 BIOS is supposed to provide limit information that it + * recognizes. Many machines do this correctly, but many others do + * not restrict themselves to their claimed limit. When this happens, + * they will cause a segmentation violation in the kernel at boot time. + * Most BIOS's, however, will respect a 64k limit, so we use that. + */ for (i = 0; i < NR_CPUS; i++) { struct desc_struct *gdt = get_cpu_gdt_table(i); if (!gdt) @@ -2325,33 +2325,12 @@ static int __init apm_init(void) __va((unsigned long)apm_info.bios.cseg_16 << 4)); set_base(gdt[APM_DS >> 3], __va((unsigned long)apm_info.bios.dseg << 4)); -#ifndef APM_RELAX_SEGMENTS - if (apm_info.bios.version == 0x100) { -#endif - /* For ASUS motherboard, Award BIOS rev 110 (and others?) */ - _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1); - /* For some unknown machine. */ - _set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1); - /* For the DEC Hinote Ultra CT475 (and others?) */ - _set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1); -#ifndef APM_RELAX_SEGMENTS - } else { - _set_limit((char *)&gdt[APM_CS >> 3], - (apm_info.bios.cseg_len - 1) & 0xffff); - _set_limit((char *)&gdt[APM_CS_16 >> 3], - (apm_info.bios.cseg_16_len - 1) & 0xffff); - _set_limit((char *)&gdt[APM_DS >> 3], - (apm_info.bios.dseg_len - 1) & 0xffff); - /* workaround for broken BIOSes */ - if (apm_info.bios.cseg_len <= apm_info.bios.offset) - _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 -1); - if (apm_info.bios.dseg_len <= 0x40) { /* 0x40 * 4kB == 64kB */ - /* for the BIOS that assumes granularity = 1 */ - gdt[APM_DS >> 3].b |= 0x800000; - printk(KERN_NOTICE "apm: we set the granularity of dseg.\n"); - } - } -#endif + /* For ASUS motherboard, Award BIOS rev 110 (and others?) */ + _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1); + /* For some unknown machine. */ + _set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1); + /* For the DEC Hinote Ultra CT475 (and others?) */ + _set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1); } apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info); -- cgit v1.2.3 From 99022c4695d3f45fcf7f3827aa46dd2d9e53e365 Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 6 Jan 2006 00:11:53 -0800 Subject: [PATCH] x86: Apm seg in gdt Since APM BIOS segment limits are now fixed, set them in head.S GDT and don't use the complicated _set_limit() macro expansion. Signed-off-by: Zachary Amsden Acked-by: "Seth, Rohit" Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apm.c | 6 ------ arch/i386/kernel/head.S | 9 +++++---- 2 files changed, 5 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 0d2981120cd..45199bb6455 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -2325,12 +2325,6 @@ static int __init apm_init(void) __va((unsigned long)apm_info.bios.cseg_16 << 4)); set_base(gdt[APM_DS >> 3], __va((unsigned long)apm_info.bios.dseg << 4)); - /* For ASUS motherboard, Award BIOS rev 110 (and others?) */ - _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1); - /* For some unknown machine. */ - _set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1); - /* For the DEC Hinote Ultra CT475 (and others?) */ - _set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1); } apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info); diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index 870f20bf33c..37b599fa4d1 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -510,13 +510,14 @@ ENTRY(cpu_gdt_table) .quad 0x0080920000000000 /* 0xa0 16-bit data */ .quad 0x0080920000000000 /* 0xa8 16-bit data */ .quad 0x0080920000000000 /* 0xb0 16-bit data */ + /* * The APM segments have byte granularity and their bases - * and limits are set at run time. + * are set at run time. All have 64k limits. */ - .quad 0x00409a0000000000 /* 0xb8 APM CS code */ - .quad 0x00009a0000000000 /* 0xc0 APM CS 16 code (16 bit) */ - .quad 0x0040920000000000 /* 0xc8 APM DS data */ + .quad 0x00409a000000ffff /* 0xb8 APM CS code */ + .quad 0x00009a000000ffff /* 0xc0 APM CS 16 code (16 bit) */ + .quad 0x004092000000ffff /* 0xc8 APM DS data */ .quad 0x0000920000000000 /* 0xd0 - ESPFIX 16-bit SS */ .quad 0x0000000000000000 /* 0xd8 - unused */ -- cgit v1.2.3 From 5fe9fe3c6f9a1ae7aa224bb7a66eb9aad9e4abef Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 6 Jan 2006 00:11:55 -0800 Subject: [PATCH] x86: Pnp byte granularity The one remaining caller of set_limit, the PnP BIOS code, calls into the PnP BIOS, passing kernel parameters in and out. These parameteres may be passed from arbitrary kernel virtual memory, so they deserve strict protection to stop a bad BIOS from smashing beyond the object size. Unfortunately, the use of set_limit was badly botching this by setting the limit in terms of pages, when it really should have byte granularity. When doing this, I discovered my BIOS had the buggy code during the "get system device node" call: mov ax, es:[bx] Which is harmless, but has a trivial workaround. Signed-off-by: Zachary Amsden Cc: "Seth, Rohit" Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/head.S | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index 37b599fa4d1..58d2746670b 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -504,12 +504,12 @@ ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* 0x80 TSS descriptor */ .quad 0x0000000000000000 /* 0x88 LDT descriptor */ - /* Segments used for calling PnP BIOS */ - .quad 0x00c09a0000000000 /* 0x90 32-bit code */ - .quad 0x00809a0000000000 /* 0x98 16-bit code */ - .quad 0x0080920000000000 /* 0xa0 16-bit data */ - .quad 0x0080920000000000 /* 0xa8 16-bit data */ - .quad 0x0080920000000000 /* 0xb0 16-bit data */ + /* Segments used for calling PnP BIOS have byte granularity */ + .quad 0x00409a0000000000 /* 0x90 32-bit code */ + .quad 0x00009a0000000000 /* 0x98 16-bit code */ + .quad 0x0000920000000000 /* 0xa0 16-bit data */ + .quad 0x0000920000000000 /* 0xa8 16-bit data */ + .quad 0x0000920000000000 /* 0xb0 16-bit data */ /* * The APM segments have byte granularity and their bases -- cgit v1.2.3 From e6a9918c9617ed21f71f2f20b45efe06822c8f00 Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 6 Jan 2006 00:11:56 -0800 Subject: [PATCH] x86: Fixed pnp bios limits PnP BIOS data, code, and 32-bit entry segments all have fixed limits as well; set them in the GDT rather than adding more code. It would be nice to add these fixups to the boot GDT rather than setting the GDT for each CPU; perhaps I can wiggle this in later, but getting it in before the subsys init looks tricky. Also, make some progress on deprecating the ugly Q_SET_SEL macros. Signed-off-by: Zachary Amsden Cc: "Seth, Rohit" Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/head.S | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index 58d2746670b..5884469f6bf 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -504,10 +504,14 @@ ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* 0x80 TSS descriptor */ .quad 0x0000000000000000 /* 0x88 LDT descriptor */ - /* Segments used for calling PnP BIOS have byte granularity */ - .quad 0x00409a0000000000 /* 0x90 32-bit code */ - .quad 0x00009a0000000000 /* 0x98 16-bit code */ - .quad 0x0000920000000000 /* 0xa0 16-bit data */ + /* + * Segments used for calling PnP BIOS have byte granularity. + * They code segments and data segments have fixed 64k limits, + * the transfer segment sizes are set at run time. + */ + .quad 0x00409a000000ffff /* 0x90 32-bit code */ + .quad 0x00009a000000ffff /* 0x98 16-bit code */ + .quad 0x000092000000ffff /* 0xa0 16-bit data */ .quad 0x0000920000000000 /* 0xa8 16-bit data */ .quad 0x0000920000000000 /* 0xb0 16-bit data */ -- cgit v1.2.3 From 2891dcdc4538e8f4ce50c9d1eea457cf2d81fb5b Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 6 Jan 2006 00:11:57 -0800 Subject: [PATCH] x86: Stop deleting nt Stop deleting NT bit from EFLAGS. See arch/i386/kernel/head.S line 223, which does something even better. Signed-off-by: Zachary Amsden Cc: "Seth, Rohit" Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/common.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index cbc32069683..cca655688ff 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -595,11 +595,6 @@ void __devinit cpu_init(void) load_gdt(&cpu_gdt_descr[cpu]); load_idt(&idt_descr); - /* - * Delete NT - */ - __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); - /* * Set up and load the per-CPU TSS and LDT */ -- cgit v1.2.3 From 92f17f0171e864a2cbe448c5b7b473e72a7d27b8 Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 6 Jan 2006 00:11:58 -0800 Subject: [PATCH] x86: Apm is on cpu zero only APM BIOS code has a protective wrapper that runs it only on CPU zero. Thus, no need to set APM BIOS segments in the GDT for other CPUs. Signed-off-by: Zachary Amsden Acked-by: "Seth, Rohit" Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apm.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 45199bb6455..d0b488056cc 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -2222,8 +2222,8 @@ static struct dmi_system_id __initdata apm_dmi_table[] = { static int __init apm_init(void) { struct proc_dir_entry *apm_proc; + struct desc_struct *gdt; int ret; - int i; dmi_check_system(apm_dmi_table); @@ -2314,18 +2314,17 @@ static int __init apm_init(void) * not restrict themselves to their claimed limit. When this happens, * they will cause a segmentation violation in the kernel at boot time. * Most BIOS's, however, will respect a 64k limit, so we use that. + * + * Note we only set APM segments on CPU zero, since we pin the APM + * code to that CPU. */ - for (i = 0; i < NR_CPUS; i++) { - struct desc_struct *gdt = get_cpu_gdt_table(i); - if (!gdt) - continue; - set_base(gdt[APM_CS >> 3], - __va((unsigned long)apm_info.bios.cseg << 4)); - set_base(gdt[APM_CS_16 >> 3], - __va((unsigned long)apm_info.bios.cseg_16 << 4)); - set_base(gdt[APM_DS >> 3], - __va((unsigned long)apm_info.bios.dseg << 4)); - } + gdt = get_cpu_gdt_table(0); + set_base(gdt[APM_CS >> 3], + __va((unsigned long)apm_info.bios.cseg << 4)); + set_base(gdt[APM_CS_16 >> 3], + __va((unsigned long)apm_info.bios.cseg_16 << 4)); + set_base(gdt[APM_DS >> 3], + __va((unsigned long)apm_info.bios.dseg << 4)); apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info); if (apm_proc) -- cgit v1.2.3 From 2684927c6b938ec7a679891e0ec1fa0709c521bd Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 6 Jan 2006 00:11:59 -0800 Subject: [PATCH] x86: Deprecate useless bug Remove the "temporary debugging check" which has managed to live for quite some time, and is clearly unneeded. The mm can never be live at this point, so clearly checking the LDT in the mm->context is redundant as well. Signed-off-by: Zachary Amsden Cc: "Seth, Rohit" Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/process.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 6081a10d341..45e7f0ac4b0 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -402,17 +402,7 @@ void flush_thread(void) void release_thread(struct task_struct *dead_task) { - if (dead_task->mm) { - // temporary debugging check - if (dead_task->mm->context.size) { - printk("WARNING: dead process %8s still has LDT? <%p/%d>\n", - dead_task->comm, - dead_task->mm->context.ldt, - dead_task->mm->context.size); - BUG(); - } - } - + BUG_ON(dead_task->mm); release_vm86_irqs(dead_task); } -- cgit v1.2.3 From 63aaf3086baea7b94c218053af8237f9dbac5d05 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Fri, 6 Jan 2006 00:12:02 -0800 Subject: [PATCH] x86/x86_64: mark rodata section read only: x86 parts x86 specific parts to make the .rodata section read only Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Signed-off-by: Adrian Bunk Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/Kconfig.debug | 10 ++++++++++ arch/i386/mm/init.c | 24 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+) (limited to 'arch') diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug index c48b424dd64..bf32ecc9ad0 100644 --- a/arch/i386/Kconfig.debug +++ b/arch/i386/Kconfig.debug @@ -42,6 +42,16 @@ config DEBUG_PAGEALLOC This results in a large slowdown, but helps to find certain types of memory corruptions. +config DEBUG_RODATA + bool "Write protect kernel read-only data structures" + depends on DEBUG_KERNEL + help + Mark the kernel read-only data as write-protected in the pagetables, + in order to catch accidental (and incorrect) writes to such const + data. This option may have a slight performance impact because a + portion of the kernel code won't be covered by a 2MB TLB anymore. + If in doubt, say "N". + config 4KSTACKS bool "Use 4Kb for kernel stacks instead of 8Kb" depends on DEBUG_KERNEL diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 06e26f00623..7df494b51a5 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -735,6 +735,30 @@ void free_initmem(void) printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (__init_end - __init_begin) >> 10); } +#ifdef CONFIG_DEBUG_RODATA + +extern char __start_rodata, __end_rodata; +void mark_rodata_ro(void) +{ + unsigned long addr = (unsigned long)&__start_rodata; + + for (; addr < (unsigned long)&__end_rodata; addr += PAGE_SIZE) + change_page_attr(virt_to_page(addr), 1, PAGE_KERNEL_RO); + + printk ("Write protecting the kernel read-only data: %luk\n", + (unsigned long)(&__end_rodata - &__start_rodata) >> 10); + + /* + * change_page_attr() requires a global_flush_tlb() call after it. + * We do this after the printk so that if something went wrong in the + * change, the printk gets out at least to give a better debug hint + * of who is the culprit. + */ + global_flush_tlb(); +} +#endif + + #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { -- cgit v1.2.3 From c728252c7a072628bd3932ff87943d1e12423359 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Fri, 6 Jan 2006 00:12:03 -0800 Subject: [PATCH] x86/x86_64: mark rodata section read only: generic x86-64 bugfix Bug fix required for the .rodata work on x86-64: when change_page_attr() and friends need to break up a 2Mb page into 4Kb pages, it always set the NX bit on the PMD, which causes the cpu to consider the entire 2Mb region to be NX regardless of the actual PTE perms. This is fine in general, with one big exception: the 2Mb page that covers the last part of the kernel .text! The fix is to not invent a new permission for the new PMD entry, but to just inherit the existing one minus the PSE bit. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/mm/pageattr.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c index b90e8fe9eeb..35f1f1aab06 100644 --- a/arch/x86_64/mm/pageattr.c +++ b/arch/x86_64/mm/pageattr.c @@ -128,6 +128,7 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot, pte_t *kpte; struct page *kpte_page; unsigned kpte_flags; + pgprot_t ref_prot2; kpte = lookup_address(address); if (!kpte) return 0; kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK); @@ -140,10 +141,14 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot, * split_large_page will take the reference for this change_page_attr * on the split page. */ - struct page *split = split_large_page(address, prot, ref_prot); + + struct page *split; + ref_prot2 = __pgprot(pgprot_val(pte_pgprot(*lookup_address(address))) & ~(1<<_PAGE_BIT_PSE)); + + split = split_large_page(address, prot, ref_prot2); if (!split) return -ENOMEM; - set_pte(kpte,mk_pte(split, ref_prot)); + set_pte(kpte,mk_pte(split, ref_prot2)); kpte_page = split; } get_page(kpte_page); -- cgit v1.2.3 From 67df197b1a07944c2e0e40ded3d4fd07d108e110 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Fri, 6 Jan 2006 00:12:04 -0800 Subject: [PATCH] x86/x86_64: mark rodata section read-only: x86-64 support x86-64 specific parts to make the .rodata section read only Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/Kconfig.debug | 10 ++++++++++ arch/x86_64/mm/init.c | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+) (limited to 'arch') diff --git a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug index e2c6e64a85e..fcb06a50fdd 100644 --- a/arch/x86_64/Kconfig.debug +++ b/arch/x86_64/Kconfig.debug @@ -9,6 +9,16 @@ config INIT_DEBUG Fill __init and __initdata at the end of boot. This helps debugging illegal uses of __init and __initdata after initialization. +config DEBUG_RODATA + bool "Write protect kernel read-only data structures" + depends on DEBUG_KERNEL + help + Mark the kernel read-only data as write-protected in the pagetables, + in order to catch accidental (and incorrect) writes to such const data. + This option may have a slight performance impact because a portion + of the kernel code won't be covered by a 2MB TLB anymore. + If in doubt, say "N". + config IOMMU_DEBUG depends on GART_IOMMU && DEBUG_KERNEL bool "Enable IOMMU debugging" diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index c016dfe8478..1faae5fc1c0 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c @@ -498,6 +498,29 @@ void free_initmem(void) printk ("Freeing unused kernel memory: %luk freed\n", (__init_end - __init_begin) >> 10); } +#ifdef CONFIG_DEBUG_RODATA + +extern char __start_rodata, __end_rodata; +void mark_rodata_ro(void) +{ + unsigned long addr = (unsigned long)&__start_rodata; + + for (; addr < (unsigned long)&__end_rodata; addr += PAGE_SIZE) + change_page_attr_addr(addr, 1, PAGE_KERNEL_RO); + + printk ("Write protecting the kernel read-only data: %luk\n", + (&__end_rodata - &__start_rodata) >> 10); + + /* + * change_page_attr_addr() requires a global_flush_tlb() call after it. + * We do this after the printk so that if something went wrong in the + * change, the printk gets out at least to give a better debug hint + * of who is the culprit. + */ + global_flush_tlb(); +} +#endif + #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { -- cgit v1.2.3 From bb152f53120d66c98c1f16518407df6a84f23714 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Fri, 6 Jan 2006 00:12:05 -0800 Subject: [PATCH] x86/x86_64: mark rodata section read-only: make some datastructures const Mark some key kernel datastructures readonly. This patch was previously posted on Jun 28th but was back then not merged because nothing was enforcing rodata anyway.. well that changed now :) Patch by Christoph Lameter and Dave Jones Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/entry.S | 1 + arch/i386/kernel/syscall_table.S | 1 - arch/x86_64/ia32/ia32entry.S | 2 +- arch/x86_64/kernel/syscall.c | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index e50b9315524..607c0600750 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -657,6 +657,7 @@ ENTRY(spurious_interrupt_bug) pushl $do_spurious_interrupt_bug jmp error_code +.section .rodata,"a" #include "syscall_table.S" syscall_table_size=(.-sys_call_table) diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index 9b21a31d4f4..f7ba4acc20e 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S @@ -1,4 +1,3 @@ -.data ENTRY(sys_call_table) .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */ .long sys_exit diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S index e0eb0c712fe..df0773c9bdb 100644 --- a/arch/x86_64/ia32/ia32entry.S +++ b/arch/x86_64/ia32/ia32entry.S @@ -341,7 +341,7 @@ ENTRY(ia32_ptregs_common) jmp ia32_sysret /* misbalances the return cache */ CFI_ENDPROC - .data + .section .rodata,"a" .align 8 .globl ia32_sys_call_table ia32_sys_call_table: diff --git a/arch/x86_64/kernel/syscall.c b/arch/x86_64/kernel/syscall.c index e263685f864..7c176b3edde 100644 --- a/arch/x86_64/kernel/syscall.c +++ b/arch/x86_64/kernel/syscall.c @@ -19,7 +19,7 @@ typedef void (*sys_call_ptr_t)(void); extern void sys_ni_syscall(void); -sys_call_ptr_t sys_call_table[__NR_syscall_max+1] __cacheline_aligned = { +const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = { /* Smells like a like a compiler bug -- it doesn't work when the & below is removed. */ [0 ... __NR_syscall_max] = &sys_ni_syscall, #include -- cgit v1.2.3 From 215c3409eed16c89b6d11ea1126bd9d4f36b9afd Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Fri, 6 Jan 2006 00:12:06 -0800 Subject: [PATCH] i386 sparsemem for single node systems Allow SPARSEMEM to be enabled on non-numa x86 systems. This is made dependant on EXPERIMENTAL also being set. When an in-tree user (such as simulated numa) exists it should be made dependant on that. The plan is to have no options and no selector as normal when !EXPERIMENTAL. When EXPERIMENTAL we enable the FLATMEM and SPARSEMEM options for X86_PC whilst maintaining DISCONTIGMEM and SPARSEMEM for NUMA. Signed-off-by: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/Kconfig | 8 ++++++-- arch/i386/kernel/setup.c | 8 ++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 6004bb0795e..968fabd8723 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -464,7 +464,6 @@ config NUMA depends on SMP && HIGHMEM64G && (X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI)) default n if X86_PC default y if (X86_NUMAQ || X86_SUMMIT) - select SPARSEMEM_STATIC # Need comments to help the hapless user trying to turn on NUMA support comment "NUMA (NUMA-Q) requires SMP, 64GB highmem support" @@ -493,6 +492,10 @@ config HAVE_ARCH_ALLOC_REMAP depends on NUMA default y +config ARCH_FLATMEM_ENABLE + def_bool y + depends on (ARCH_SELECT_MEMORY_MODEL && X86_PC) + config ARCH_DISCONTIGMEM_ENABLE def_bool y depends on NUMA @@ -503,7 +506,8 @@ config ARCH_DISCONTIGMEM_DEFAULT config ARCH_SPARSEMEM_ENABLE def_bool y - depends on NUMA + depends on (NUMA || (X86_PC && EXPERIMENTAL)) + select SPARSEMEM_STATIC config ARCH_SELECT_MEMORY_MODEL def_bool y diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index fdfcb0cba9b..27c956db046 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -954,6 +954,12 @@ efi_find_max_pfn(unsigned long start, unsigned long end, void *arg) return 0; } +static int __init +efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg) +{ + memory_present(0, start, end); + return 0; +} /* * Find the highest page frame number we have available @@ -965,6 +971,7 @@ void __init find_max_pfn(void) max_pfn = 0; if (efi_enabled) { efi_memmap_walk(efi_find_max_pfn, &max_pfn); + efi_memmap_walk(efi_memory_present_wrapper, NULL); return; } @@ -979,6 +986,7 @@ void __init find_max_pfn(void) continue; if (end > max_pfn) max_pfn = end; + memory_present(0, start, end); } } -- cgit v1.2.3 From e72c8585e09f127a69a1608bb5ccd1e3fc0dd41e Mon Sep 17 00:00:00 2001 From: Ashok Raj Date: Fri, 6 Jan 2006 00:12:09 -0800 Subject: [PATCH] make bigsmp the default mode if CONFIG_HOTPLUG_CPU If we are using hotplug enabled kernel, then make bigsmp the default mode. Signed-off-by: Ashok Raj Signed-off-by: Venkatesh Pallipadi Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/mpparse.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c index 1ca5269b1e8..91a64016956 100644 --- a/arch/i386/kernel/mpparse.c +++ b/arch/i386/kernel/mpparse.c @@ -38,6 +38,12 @@ int smp_found_config; unsigned int __initdata maxcpus = NR_CPUS; +#ifdef CONFIG_HOTPLUG_CPU +#define CPU_HOTPLUG_ENABLED (1) +#else +#define CPU_HOTPLUG_ENABLED (0) +#endif + /* * Various Linux-internal data structures created from the * MP-table. @@ -219,14 +225,18 @@ static void __devinit MP_processor_info (struct mpc_config_processor *m) cpu_set(num_processors, cpu_possible_map); num_processors++; - if ((num_processors > 8) && - ((APIC_XAPIC(ver) && - (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)) || - (boot_cpu_data.x86_vendor == X86_VENDOR_AMD))) - def_to_bigsmp = 1; - else - def_to_bigsmp = 0; - + if (CPU_HOTPLUG_ENABLED || (num_processors > 8)) { + switch (boot_cpu_data.x86_vendor) { + case X86_VENDOR_INTEL: + if (!APIC_XAPIC(ver)) { + def_to_bigsmp = 0; + break; + } + /* If P4 and above fall through */ + case X86_VENDOR_AMD: + def_to_bigsmp = 1; + } + } bios_cpu_apicid[num_processors - 1] = m->mpc_apicid; } -- cgit v1.2.3 From f8af095d3a4c8300b4e63ee2c4bb198b565d9431 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 6 Jan 2006 00:12:10 -0800 Subject: [PATCH] x86: change_page_attr() fix The 'make rodata read-only' patch in -mm exposes a latent bug in the 32-bit change_page_attr() function, which causes certain CPUs (Those with NX basically) to reboot instantly after pages are marked read-only. The same bug got fixed a while back on x86-64, but never got propagated to i386. Stuart Hayes from Dell also picked up on this last June, but it never got fixed, as the only thing affected by it aparently was the nvidia driver. Blatantly stealing description from his post.. "It doesn't appear to be fixed (in the i386 arch). The change_page_attr()/split_large_page() code will still still set all the 4K PTEs to PAGE_KERNEL (setting the _PAGE_NX bit) when a large page needs to be split. This wouldn't be a problem for the bulk of the kernel memory, but there are pages in the lower 4MB of memory that's free, and are part of large executable pages that also contain kernel code. If change_page_attr() is called on these, it will set the _PAGE_NX bit on the whole 2MB region that was covered by the large page, causing a large chunk of kernel code to be non-executable." Signed-off-by: Arjan van de Ven Signed-off-by: Dave Jones Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/mm/pageattr.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c index f600fc244f0..c30a16df644 100644 --- a/arch/i386/mm/pageattr.c +++ b/arch/i386/mm/pageattr.c @@ -13,6 +13,7 @@ #include #include #include +#include static DEFINE_SPINLOCK(cpa_lock); static struct list_head df_list = LIST_HEAD_INIT(df_list); @@ -36,7 +37,8 @@ pte_t *lookup_address(unsigned long address) return pte_offset_kernel(pmd, address); } -static struct page *split_large_page(unsigned long address, pgprot_t prot) +static struct page *split_large_page(unsigned long address, pgprot_t prot, + pgprot_t ref_prot) { int i; unsigned long addr; @@ -54,7 +56,7 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot) pbase = (pte_t *)page_address(base); for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) { set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT, - addr == address ? prot : PAGE_KERNEL)); + addr == address ? prot : ref_prot)); } return base; } @@ -98,11 +100,18 @@ static void set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte) */ static inline void revert_page(struct page *kpte_page, unsigned long address) { - pte_t *linear = (pte_t *) + pgprot_t ref_prot; + pte_t *linear; + + ref_prot = + ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext) + ? PAGE_KERNEL_LARGE_EXEC : PAGE_KERNEL_LARGE; + + linear = (pte_t *) pmd_offset(pud_offset(pgd_offset_k(address), address), address); set_pmd_pte(linear, address, pfn_pte((__pa(address) & LARGE_PAGE_MASK) >> PAGE_SHIFT, - PAGE_KERNEL_LARGE)); + ref_prot)); } static int @@ -123,10 +132,16 @@ __change_page_attr(struct page *page, pgprot_t prot) if ((pte_val(*kpte) & _PAGE_PSE) == 0) { set_pte_atomic(kpte, mk_pte(page, prot)); } else { - struct page *split = split_large_page(address, prot); + pgprot_t ref_prot; + struct page *split; + + ref_prot = + ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext) + ? PAGE_KERNEL_EXEC : PAGE_KERNEL; + split = split_large_page(address, prot, ref_prot); if (!split) return -ENOMEM; - set_pmd_pte(kpte,address,mk_pte(split, PAGE_KERNEL)); + set_pmd_pte(kpte,address,mk_pte(split, ref_prot)); kpte_page = split; } get_page(kpte_page); -- cgit v1.2.3 From e31b88ba49460653bab87423287bb68743f5de5c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 6 Jan 2006 00:12:11 -0800 Subject: [PATCH] x86: missing printk newline in apic boot option parser Missing newline in printk. Signed-off-by: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 496a2c9909f..d8f94e78de8 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -721,7 +721,7 @@ static int __init apic_set_verbosity(char *str) apic_verbosity = APIC_VERBOSE; else printk(KERN_WARNING "APIC Verbosity level %s not recognised" - " use apic=verbose or apic=debug", str); + " use apic=verbose or apic=debug\n", str); return 0; } -- cgit v1.2.3 From 6926d570b6159c6a7f65921ca119a675b12fef86 Mon Sep 17 00:00:00 2001 From: Daniel Marjamaki Date: Fri, 6 Jan 2006 00:12:12 -0800 Subject: [PATCH] arch/i386/kernel/msr.c: removed unused variable Removed the unused variable "rv". Signed-off-by: Daniel Marjamaki Signed-off-by: H. Peter Anvin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/msr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c index 44470fea430..1d0a55e6876 100644 --- a/arch/i386/kernel/msr.c +++ b/arch/i386/kernel/msr.c @@ -172,7 +172,6 @@ static ssize_t msr_read(struct file *file, char __user * buf, { u32 __user *tmp = (u32 __user *) buf; u32 data[2]; - size_t rv; u32 reg = *ppos; int cpu = iminor(file->f_dentry->d_inode); int err; @@ -180,7 +179,7 @@ static ssize_t msr_read(struct file *file, char __user * buf, if (count % 8) return -EINVAL; /* Invalid chunk size */ - for (rv = 0; count; count -= 8) { + for (; count; count -= 8) { err = do_rdmsr(cpu, reg, &data[0], &data[1]); if (err) return err; -- cgit v1.2.3 From 6b7f430ee0a269464aa29159eb464e647ca313d3 Mon Sep 17 00:00:00 2001 From: Daniel Marjamaki Date: Fri, 6 Jan 2006 00:12:13 -0800 Subject: [PATCH] arch/i386/kernel/cpuid.c: unused variable Removed the unused variable "rv". Signed-off-by: Daniel Marjamaki Signed-off-by: H. Peter Anvin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpuid.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c index 13bae799e62..006141d1c12 100644 --- a/arch/i386/kernel/cpuid.c +++ b/arch/i386/kernel/cpuid.c @@ -117,14 +117,13 @@ static ssize_t cpuid_read(struct file *file, char __user *buf, { char __user *tmp = buf; u32 data[4]; - size_t rv; u32 reg = *ppos; int cpu = iminor(file->f_dentry->d_inode); if (count % 16) return -EINVAL; /* Invalid chunk size */ - for (rv = 0; count; count -= 16) { + for (; count; count -= 16) { do_cpuid(cpu, reg, data); if (copy_to_user(tmp, &data, 16)) return -EFAULT; -- cgit v1.2.3 From f90b8116032f4216d260e31f966a3585319387ac Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Fri, 6 Jan 2006 00:12:14 -0800 Subject: [PATCH] Base support for AMD Geode GX/LX processors Provide basic support for the AMD Geode GX and LX processors. Signed-off-by: Jordan Crouse Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/Kconfig.cpu | 14 ++++++++++---- arch/i386/kernel/cpu/amd.c | 7 ++++++- arch/i386/kernel/cpu/cyrix.c | 27 ++++++++++++++++++++++++++- 3 files changed, 42 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu index 53bbb3c008e..79603b3471f 100644 --- a/arch/i386/Kconfig.cpu +++ b/arch/i386/Kconfig.cpu @@ -39,6 +39,7 @@ config M386 - "Winchip-2" for IDT Winchip 2. - "Winchip-2A" for IDT Winchips with 3dNow! capabilities. - "GeodeGX1" for Geode GX1 (Cyrix MediaGX). + - "Geode GX/LX" For AMD Geode GX and LX processors. - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3. - "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above). @@ -171,6 +172,11 @@ config MGEODEGX1 help Select this for a Geode GX1 (Cyrix MediaGX) chip. +config MGEODE_LX + bool "Geode GX/LX" + help + Select this for AMD Geode GX and LX processors. + config MCYRIXIII bool "CyrixIII/VIA-C3" help @@ -220,8 +226,8 @@ config X86_XADD config X86_L1_CACHE_SHIFT int default "7" if MPENTIUM4 || X86_GENERIC - default "4" if X86_ELAN || M486 || M386 - default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODEGX1 + default "4" if X86_ELAN || M486 || M386 || MGEODEGX1 + default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX default "6" if MK7 || MK8 || MPENTIUMM config RWSEM_GENERIC_SPINLOCK @@ -290,12 +296,12 @@ config X86_INTEL_USERCOPY config X86_USE_PPRO_CHECKSUM bool - depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON + depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX default y config X86_USE_3DNOW bool - depends on MCYRIXIII || MK7 + depends on MCYRIXIII || MK7 || MGEODE_LX default y config X86_OOSTORE diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index e344ef88cfc..e7697e077f6 100644 --- a/arch/i386/kernel/cpu/amd.c +++ b/arch/i386/kernel/cpu/amd.c @@ -161,8 +161,13 @@ static void __init init_amd(struct cpuinfo_x86 *c) set_bit(X86_FEATURE_K6_MTRR, c->x86_capability); break; } - break; + if (c->x86_model == 10) { + /* AMD Geode LX is model 10 */ + /* placeholder for any needed mods */ + break; + } + break; case 6: /* An Athlon/Duron */ /* Bit 15 of Athlon specific MSR 15, needs to be 0 diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c index ff87cc22b32..75015975d03 100644 --- a/arch/i386/kernel/cpu/cyrix.c +++ b/arch/i386/kernel/cpu/cyrix.c @@ -342,6 +342,31 @@ static void __init init_cyrix(struct cpuinfo_x86 *c) return; } +/* + * Handle National Semiconductor branded processors + */ +static void __devinit init_nsc(struct cpuinfo_x86 *c) +{ + /* There may be GX1 processors in the wild that are branded + * NSC and not Cyrix. + * + * This function only handles the GX processor, and kicks every + * thing else to the Cyrix init function above - that should + * cover any processors that might have been branded differently + * after NSC aquired Cyrix. + * + * If this breaks your GX1 horribly, please e-mail + * info-linux@ldcmail.amd.com to tell us. + */ + + /* Handle the GX (Formally known as the GX2) */ + + if (c->x86 == 5 && c->x86_model == 5) + display_cacheinfo(c); + else + init_cyrix(c); +} + /* * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected * by the fact that they preserve the flags across the division of 5/2. @@ -422,7 +447,7 @@ int __init cyrix_init_cpu(void) static struct cpu_dev nsc_cpu_dev __initdata = { .c_vendor = "NSC", .c_ident = { "Geode by NSC" }, - .c_init = init_cyrix, + .c_init = init_nsc, .c_identify = generic_identify, }; -- cgit v1.2.3 From 3841b0a173cb6fc52163e67c03280543f2412db3 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Fri, 6 Jan 2006 00:12:16 -0800 Subject: [PATCH] APM Screen Blanking fix - Fix screen blanking on BIOSes that return APM_NOT_ENGAGED when APM enabled screen blanking is not turned on. The original code only tried to set the state on device 0x100, and then 0x1FF, and I added 0x101 to the mix too. - Clean up logic in apm_console_blank(). - Prevent the error message from printing out twice. Cc: Jordan Crouse Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apm.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index d0b488056cc..2d793d4aef1 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -1064,22 +1064,23 @@ static int apm_engage_power_management(u_short device, int enable) static int apm_console_blank(int blank) { - int error; - u_short state; + int error, i; + u_short state; + static const u_short dev[3] = { 0x100, 0x1FF, 0x101 }; state = blank ? APM_STATE_STANDBY : APM_STATE_READY; - /* Blank the first display device */ - error = set_power_state(0x100, state); - if ((error != APM_SUCCESS) && (error != APM_NO_ERROR)) { - /* try to blank them all instead */ - error = set_power_state(0x1ff, state); - if ((error != APM_SUCCESS) && (error != APM_NO_ERROR)) - /* try to blank device one instead */ - error = set_power_state(0x101, state); + + for (i = 0; i < ARRAY_SIZE(dev); i++) { + error = set_power_state(dev[i], state); + + if ((error == APM_SUCCESS) || (error == APM_NO_ERROR)) + return 1; + + if (error == APM_NOT_ENGAGED) + break; } - if ((error == APM_SUCCESS) || (error == APM_NO_ERROR)) - return 1; - if (error == APM_NOT_ENGAGED) { + + if (error == APM_NOT_ENGAGED && state != APM_STATE_READY) { static int tried; int eng_error; if (tried++ == 0) { -- cgit v1.2.3 From bcf0f0d233fc76e7c59c7f731caad555428d0e8d Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 6 Jan 2006 00:12:17 -0800 Subject: [PATCH] fix cpu frequency detection in arch/i386/kernel/timers/timer_tsc.c::recalibrate_cpu_khz() When we re-calibrate the frequency, it is likely that an interrupt (as for example the main system clock) will be triggered by the system. Therefore the calibration may not be accurate. This will also provide a fix to bug #5266. Many thanks to Larry Finger for helping resolving this issue. Signed-off-by: Bruno Ducrot Cc: john stultz Cc: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/timers/timer_tsc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c index d395e3b4248..47675bbbb31 100644 --- a/arch/i386/kernel/timers/timer_tsc.c +++ b/arch/i386/kernel/timers/timer_tsc.c @@ -330,7 +330,9 @@ int recalibrate_cpu_khz(void) unsigned int cpu_khz_old = cpu_khz; if (cpu_has_tsc) { + local_irq_disable(); init_cpu_khz(); + local_irq_enable(); cpu_data[0].loops_per_jiffy = cpufreq_scale(cpu_data[0].loops_per_jiffy, cpu_khz_old, -- cgit v1.2.3 From 76865c3f87e825dda0c458b02f30dd8ae64b7bdc Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Fri, 6 Jan 2006 00:12:19 -0800 Subject: [PATCH] i386: ioapic virtual wire mode fix o Currently, during kexec reboot, IOAPIC is re-programmed back to virtual wire mode if there was an i8259 connected to it. This enables getting timer interrupts in second kernel in legacy mode. o After putting into virtual wire mode, IOAPIC delivers the i8259 interrupts to CPU0. This works well for kexec but not for kdump as we might crash on a different CPU and second kernel will not see timer interrupts. o This patch modifies the redirection table entry to deliver the timer interrupts to the cpu we are rebooting (instead of hardcoding to zero). This ensures that second kernel receives timer interrupts even on a non-boot cpu. Signed-off-by: Vivek Goyal Cc: Andi Kleen Cc: "Seth, Rohit" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/io_apic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 22c8675c79f..7554f8fd874 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -1722,8 +1722,8 @@ void disable_IO_APIC(void) entry.dest_mode = 0; /* Physical */ entry.delivery_mode = dest_ExtINT; /* ExtInt */ entry.vector = 0; - entry.dest.physical.physical_dest = 0; - + entry.dest.physical.physical_dest = + GET_APIC_ID(apic_read(APIC_ID)); /* * Add it to the IO-APIC irq-routing table: -- cgit v1.2.3 From 766c3f94d4492ee4ec60b65693e71ee4b1d6fd68 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Fri, 6 Jan 2006 00:12:20 -0800 Subject: [PATCH] i386: Handle HP laptop rebooting properly. Signed-off-by: Ben Collins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/reboot.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c index 2afe0f8d555..2fa5803a759 100644 --- a/arch/i386/kernel/reboot.c +++ b/arch/i386/kernel/reboot.c @@ -111,12 +111,12 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"), }, }, - { /* Handle problems with rebooting on HP nc6120 */ + { /* Handle problems with rebooting on HP laptops */ .callback = set_bios_reboot, - .ident = "HP Compaq nc6120", + .ident = "HP Compaq Laptop", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nc6120"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"), }, }, { } -- cgit v1.2.3 From 1fa744e6e91a895750b9980d13fcfc5791a0cd91 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Fri, 6 Jan 2006 00:12:20 -0800 Subject: [PATCH] cpu hotplug/x86_64: disable interrupt in play_dead With physical CPU hotplug, the CPU is hot removed and it should not receive any interrupts. Disabling interrupt is much safer. This basically is what we do in ia64 & x86. Signed-off-by: Shaohua Li Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/process.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 7519fc520eb..3060ed97b75 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -157,7 +157,7 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait); DECLARE_PER_CPU(int, cpu_state); #include -/* We don't actually take CPU down, just spin without interrupts. */ +/* We halt the CPU with physical CPU hotplug */ static inline void play_dead(void) { idle_task_exit(); @@ -166,8 +166,9 @@ static inline void play_dead(void) /* Ack it */ __get_cpu_var(cpu_state) = CPU_DEAD; + local_irq_disable(); while (1) - safe_halt(); + halt(); } #else static inline void play_dead(void) -- cgit v1.2.3 From 0595bf3bca9d9932a05b06dd438f40f01d27cd33 Mon Sep 17 00:00:00 2001 From: Ivan Kokshaysky Date: Fri, 6 Jan 2006 00:12:22 -0800 Subject: [PATCH] Alpha: convert to generic irq framework (alpha part) Kconfig tweaks and tons of deletions. Signed-off-by: Ivan Kokshaysky Cc: Christoph Hellwig Cc: Richard Henderson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/alpha/Kconfig | 13 + arch/alpha/kernel/alpha_ksyms.c | 1 - arch/alpha/kernel/irq.c | 630 +--------------------------------------- 3 files changed, 22 insertions(+), 622 deletions(-) (limited to 'arch') diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 786491f9ceb..153337ff1d7 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -40,6 +40,19 @@ config GENERIC_IOMAP bool default n +config GENERIC_HARDIRQS + bool + default y + +config GENERIC_IRQ_PROBE + bool + default y + +config AUTO_IRQ_AFFINITY + bool + depends on SMP + default y + source "init/Kconfig" diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index 24ae9a36607..f3e98f83778 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c @@ -175,7 +175,6 @@ EXPORT_SYMBOL(up); */ #ifdef CONFIG_SMP -EXPORT_SYMBOL(synchronize_irq); EXPORT_SYMBOL(flush_tlb_mm); EXPORT_SYMBOL(flush_tlb_range); EXPORT_SYMBOL(flush_tlb_page); diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index b6114f5c0d2..76be5cf0de1 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -32,214 +32,25 @@ #include #include -/* - * Controller mappings for all interrupt sources: - */ -irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { - [0 ... NR_IRQS-1] = { - .handler = &no_irq_type, - .lock = SPIN_LOCK_UNLOCKED - } -}; - -static void register_irq_proc(unsigned int irq); - volatile unsigned long irq_err_count; -/* - * Special irq handlers. - */ - -irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) -{ - return IRQ_NONE; -} - -/* - * Generic no controller code - */ - -static void no_irq_enable_disable(unsigned int irq) { } -static unsigned int no_irq_startup(unsigned int irq) { return 0; } - -static void -no_irq_ack(unsigned int irq) +void ack_bad_irq(unsigned int irq) { irq_err_count++; printk(KERN_CRIT "Unexpected IRQ trap at vector %u\n", irq); } -struct hw_interrupt_type no_irq_type = { - .typename = "none", - .startup = no_irq_startup, - .shutdown = no_irq_enable_disable, - .enable = no_irq_enable_disable, - .disable = no_irq_enable_disable, - .ack = no_irq_ack, - .end = no_irq_enable_disable, -}; - -int -handle_IRQ_event(unsigned int irq, struct pt_regs *regs, - struct irqaction *action) -{ - int status = 1; /* Force the "do bottom halves" bit */ - int ret; - - do { - if (!(action->flags & SA_INTERRUPT)) - local_irq_enable(); - else - local_irq_disable(); - - ret = action->handler(irq, action->dev_id, regs); - if (ret == IRQ_HANDLED) - status |= action->flags; - action = action->next; - } while (action); - if (status & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - local_irq_disable(); - - return status; -} - -/* - * Generic enable/disable code: this just calls - * down into the PIC-specific version for the actual - * hardware disable after having gotten the irq - * controller lock. - */ -void inline -disable_irq_nosync(unsigned int irq) -{ - irq_desc_t *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&desc->lock, flags); - if (!desc->depth++) { - desc->status |= IRQ_DISABLED; - desc->handler->disable(irq); - } - spin_unlock_irqrestore(&desc->lock, flags); -} - -/* - * Synchronous version of the above, making sure the IRQ is - * no longer running on any other IRQ.. - */ -void -disable_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - synchronize_irq(irq); -} - -void -enable_irq(unsigned int irq) -{ - irq_desc_t *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&desc->lock, flags); - switch (desc->depth) { - case 1: { - unsigned int status = desc->status & ~IRQ_DISABLED; - desc->status = status; - if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { - desc->status = status | IRQ_REPLAY; - hw_resend_irq(desc->handler,irq); - } - desc->handler->enable(irq); - /* fall-through */ - } - default: - desc->depth--; - break; - case 0: - printk(KERN_ERR "enable_irq() unbalanced from %p\n", - __builtin_return_address(0)); - } - spin_unlock_irqrestore(&desc->lock, flags); -} - -int -setup_irq(unsigned int irq, struct irqaction * new) -{ - int shared = 0; - struct irqaction *old, **p; - unsigned long flags; - irq_desc_t *desc = irq_desc + irq; - - if (desc->handler == &no_irq_type) - return -ENOSYS; - - /* - * Some drivers like serial.c use request_irq() heavily, - * so we have to be careful not to interfere with a - * running system. - */ - if (new->flags & SA_SAMPLE_RANDOM) { - /* - * This function might sleep, we want to call it first, - * outside of the atomic block. - * Yes, this might clear the entropy pool if the wrong - * driver is attempted to be loaded, without actually - * installing a new handler, but is this really a problem, - * only the sysadmin is able to do this. - */ - rand_initialize_irq(irq); - } - - /* - * The following block of code has to be executed atomically - */ - spin_lock_irqsave(&desc->lock,flags); - p = &desc->action; - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) { - spin_unlock_irqrestore(&desc->lock,flags); - return -EBUSY; - } - - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; - } - - *p = new; - - if (!shared) { - desc->depth = 0; - desc->status &= - ~(IRQ_DISABLED|IRQ_AUTODETECT|IRQ_WAITING|IRQ_INPROGRESS); - desc->handler->startup(irq); - } - spin_unlock_irqrestore(&desc->lock,flags); - - return 0; -} - -static struct proc_dir_entry * root_irq_dir; -static struct proc_dir_entry * irq_dir[NR_IRQS]; - #ifdef CONFIG_SMP -static struct proc_dir_entry * smp_affinity_entry[NR_IRQS]; static char irq_user_affinity[NR_IRQS]; -static cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL }; -static void -select_smp_affinity(int irq) +int +select_smp_affinity(unsigned int irq) { static int last_cpu; int cpu = last_cpu + 1; - if (! irq_desc[irq].handler->set_affinity || irq_user_affinity[irq]) - return; + if (!irq_desc[irq].handler->set_affinity || irq_user_affinity[irq]) + return 1; while (!cpu_possible(cpu)) cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0); @@ -247,208 +58,10 @@ select_smp_affinity(int irq) irq_affinity[irq] = cpumask_of_cpu(cpu); irq_desc[irq].handler->set_affinity(irq, cpumask_of_cpu(cpu)); + return 0; } - -static int -irq_affinity_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; -} - -static int -irq_affinity_write_proc(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - int irq = (long) data, full_count = count, err; - cpumask_t new_value; - - if (!irq_desc[irq].handler->set_affinity) - return -EIO; - - err = cpumask_parse(buffer, count, new_value); - - /* The special value 0 means release control of the - affinity to kernel. */ - cpus_and(new_value, new_value, cpu_online_map); - if (cpus_empty(new_value)) { - irq_user_affinity[irq] = 0; - select_smp_affinity(irq); - } - /* Do not allow disabling IRQs completely - it's a too easy - way to make the system unusable accidentally :-) At least - one online CPU still has to be targeted. */ - else { - irq_affinity[irq] = new_value; - irq_user_affinity[irq] = 1; - irq_desc[irq].handler->set_affinity(irq, new_value); - } - - return full_count; -} - #endif /* CONFIG_SMP */ -#define MAX_NAMELEN 10 - -static void -register_irq_proc (unsigned int irq) -{ - char name [MAX_NAMELEN]; - - if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) || - irq_dir[irq]) - return; - - memset(name, 0, MAX_NAMELEN); - sprintf(name, "%d", irq); - - /* create /proc/irq/1234 */ - irq_dir[irq] = proc_mkdir(name, root_irq_dir); - -#ifdef CONFIG_SMP - if (irq_desc[irq].handler->set_affinity) { - struct proc_dir_entry *entry; - /* create /proc/irq/1234/smp_affinity */ - entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); - - if (entry) { - entry->nlink = 1; - entry->data = (void *)(long)irq; - entry->read_proc = irq_affinity_read_proc; - entry->write_proc = irq_affinity_write_proc; - } - - smp_affinity_entry[irq] = entry; - } -#endif -} - -void -init_irq_proc (void) -{ - int i; - - /* create /proc/irq */ - root_irq_dir = proc_mkdir("irq", NULL); - -#ifdef CONFIG_SMP - /* create /proc/irq/prof_cpu_mask */ - create_prof_cpu_mask(root_irq_dir); -#endif - - /* - * Create entries for all existing IRQs. - */ - for (i = 0; i < ACTUAL_NR_IRQS; i++) { - if (irq_desc[i].handler == &no_irq_type) - continue; - register_irq_proc(i); - } -} - -int -request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, const char * devname, void *dev_id) -{ - int retval; - struct irqaction * action; - - if (irq >= ACTUAL_NR_IRQS) - return -EINVAL; - if (!handler) - return -EINVAL; - -#if 1 - /* - * Sanity-check: shared interrupts should REALLY pass in - * a real dev-ID, otherwise we'll have trouble later trying - * to figure out which interrupt is which (messes up the - * interrupt freeing logic etc). - */ - if ((irqflags & SA_SHIRQ) && !dev_id) { - printk(KERN_ERR - "Bad boy: %s (at %p) called us without a dev_id!\n", - devname, __builtin_return_address(0)); - } -#endif - - action = (struct irqaction *) - kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if (!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - cpus_clear(action->mask); - action->name = devname; - action->next = NULL; - action->dev_id = dev_id; - -#ifdef CONFIG_SMP - select_smp_affinity(irq); -#endif - - retval = setup_irq(irq, action); - if (retval) - kfree(action); - return retval; -} - -EXPORT_SYMBOL(request_irq); - -void -free_irq(unsigned int irq, void *dev_id) -{ - irq_desc_t *desc; - struct irqaction **p; - unsigned long flags; - - if (irq >= ACTUAL_NR_IRQS) { - printk(KERN_CRIT "Trying to free IRQ%d\n", irq); - return; - } - - desc = irq_desc + irq; - spin_lock_irqsave(&desc->lock,flags); - p = &desc->action; - for (;;) { - struct irqaction * action = *p; - if (action) { - struct irqaction **pp = p; - p = &action->next; - if (action->dev_id != dev_id) - continue; - - /* Found - now remove it from the list of entries. */ - *pp = action->next; - if (!desc->action) { - desc->status |= IRQ_DISABLED; - desc->handler->shutdown(irq); - } - spin_unlock_irqrestore(&desc->lock,flags); - -#ifdef CONFIG_SMP - /* Wait to make sure it's not being used on - another CPU. */ - while (desc->status & IRQ_INPROGRESS) - barrier(); -#endif - kfree(action); - return; - } - printk(KERN_ERR "Trying to free free IRQ%d\n",irq); - spin_unlock_irqrestore(&desc->lock,flags); - return; - } -} - -EXPORT_SYMBOL(free_irq); - int show_interrupts(struct seq_file *p, void *v) { @@ -531,10 +144,6 @@ handle_irq(int irq, struct pt_regs * regs) * 0 return value means that this irq is already being * handled by some other CPU. (or is disabled) */ - int cpu = smp_processor_id(); - irq_desc_t *desc = irq_desc + irq; - struct irqaction * action; - unsigned int status; static unsigned int illegal_count=0; if ((unsigned) irq > ACTUAL_NR_IRQS && illegal_count < MAX_ILLEGAL_IRQS ) { @@ -546,229 +155,8 @@ handle_irq(int irq, struct pt_regs * regs) } irq_enter(); - kstat_cpu(cpu).irqs[irq]++; - spin_lock_irq(&desc->lock); /* mask also the higher prio events */ - desc->handler->ack(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 (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { - action = desc->action; - 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 (!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 handle_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); - handle_IRQ_event(irq, regs, action); - spin_lock(&desc->lock); - - if (!(desc->status & IRQ_PENDING) - || (desc->status & IRQ_LEVEL)) - break; - desc->status &= ~IRQ_PENDING; - } - desc->status &= ~IRQ_INPROGRESS; -out: - /* - * The ->end() handler has to deal with interrupts which got - * disabled while the handler was running. - */ - desc->handler->end(irq); - spin_unlock(&desc->lock); - + local_irq_disable(); + __do_IRQ(irq, regs); + local_irq_enable(); irq_exit(); } - -/* - * IRQ autodetection code.. - * - * This depends on the fact that any interrupt that - * comes in on to an unassigned handler will get stuck - * with "IRQ_WAITING" cleared and the interrupt - * disabled. - */ -unsigned long -probe_irq_on(void) -{ - int i; - irq_desc_t *desc; - unsigned long delay; - unsigned long val; - - /* Something may have generated an irq long ago and we want to - flush such a longstanding irq before considering it as spurious. */ - for (i = NR_IRQS-1; i >= 0; i--) { - desc = irq_desc + i; - - spin_lock_irq(&desc->lock); - if (!irq_desc[i].action) - irq_desc[i].handler->startup(i); - spin_unlock_irq(&desc->lock); - } - - /* Wait for longstanding interrupts to trigger. */ - for (delay = jiffies + HZ/50; time_after(delay, jiffies); ) - /* about 20ms delay */ barrier(); - - /* enable any unassigned irqs (we must startup again here because - if a longstanding irq happened in the previous stage, it may have - masked itself) first, enable any unassigned irqs. */ - for (i = NR_IRQS-1; i >= 0; i--) { - desc = irq_desc + i; - - spin_lock_irq(&desc->lock); - if (!desc->action) { - desc->status |= IRQ_AUTODETECT | IRQ_WAITING; - if (desc->handler->startup(i)) - desc->status |= IRQ_PENDING; - } - spin_unlock_irq(&desc->lock); - } - - /* - * Wait for spurious interrupts to trigger - */ - for (delay = jiffies + HZ/10; time_after(delay, jiffies); ) - /* about 100ms delay */ barrier(); - - /* - * Now filter out any obviously spurious interrupts - */ - val = 0; - for (i=0; ilock); - status = desc->status; - - if (status & IRQ_AUTODETECT) { - /* It triggered already - consider it spurious. */ - if (!(status & IRQ_WAITING)) { - desc->status = status & ~IRQ_AUTODETECT; - desc->handler->shutdown(i); - } else - if (i < 32) - val |= 1 << i; - } - spin_unlock_irq(&desc->lock); - } - - return val; -} - -EXPORT_SYMBOL(probe_irq_on); - -/* - * Return a mask of triggered interrupts (this - * can handle only legacy ISA interrupts). - */ -unsigned int -probe_irq_mask(unsigned long val) -{ - int i; - unsigned int mask; - - mask = 0; - for (i = 0; i < NR_IRQS; i++) { - irq_desc_t *desc = irq_desc + i; - unsigned int status; - - spin_lock_irq(&desc->lock); - status = desc->status; - - if (status & IRQ_AUTODETECT) { - /* We only react to ISA interrupts */ - if (!(status & IRQ_WAITING)) { - if (i < 16) - mask |= 1 << i; - } - - desc->status = status & ~IRQ_AUTODETECT; - desc->handler->shutdown(i); - } - spin_unlock_irq(&desc->lock); - } - - return mask & val; -} - -/* - * Get the result of the IRQ probe.. A negative result means that - * we have several candidates (but we return the lowest-numbered - * one). - */ - -int -probe_irq_off(unsigned long val) -{ - int i, irq_found, nr_irqs; - - nr_irqs = 0; - irq_found = 0; - for (i=0; ilock); - status = desc->status; - - if (status & IRQ_AUTODETECT) { - if (!(status & IRQ_WAITING)) { - if (!nr_irqs) - irq_found = i; - nr_irqs++; - } - desc->status = status & ~IRQ_AUTODETECT; - desc->handler->shutdown(i); - } - spin_unlock_irq(&desc->lock); - } - - if (nr_irqs > 1) - irq_found = -irq_found; - return irq_found; -} - -EXPORT_SYMBOL(probe_irq_off); - -#ifdef CONFIG_SMP -void synchronize_irq(unsigned int irq) -{ - /* is there anything to synchronize with? */ - if (!irq_desc[irq].action) - return; - - while (irq_desc[irq].status & IRQ_INPROGRESS) - barrier(); -} -#endif -- cgit v1.2.3 From 60c83c77c4a6a399d55e4f9ad156bccdfe51c96b Mon Sep 17 00:00:00 2001 From: Hirokazu Takata Date: Fri, 6 Jan 2006 00:18:39 -0800 Subject: [PATCH] m32r: trivial fix to remove unused instructions A trivial fix to remove unused instructions. Signed-off-by: Naoto Sugai Signed-off-by: Hirokazu Takata Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/m32r/kernel/entry.S | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S index 396c94218cc..f6d4a5821a2 100644 --- a/arch/m32r/kernel/entry.S +++ b/arch/m32r/kernel/entry.S @@ -651,8 +651,6 @@ ENTRY(rie_handler) /* void rie_handler(int error_code) */ SWITCH_TO_KERNEL_STACK SAVE_ALL - mvfc r0, bpc - ld r1, @r0 ldi r1, #0x20 ; error_code mv r0, sp ; pt_regs bl do_rie_handler -- cgit v1.2.3 From 9287d95ea194abf32fab24c6909f8ea55ab0292f Mon Sep 17 00:00:00 2001 From: Hirokazu Takata Date: Fri, 6 Jan 2006 00:18:41 -0800 Subject: [PATCH] m32r: Support M32104UT target platform This patch is for supporting a new target platform, Renesas M32104UT evaluation board. The M32104UT is an eval board based on an uT-Engine specification. This board has an MMU-less M32R family processor, M32104. http://www-wa0.personal-media.co.jp/pmc/archive/te/te_m32104_e.pdf This board is one of the most popular M32R platform, so we have ported Linux/M32R to it. Signed-off-by: Naoto Sugai Signed-off-by: Hirokazu Takata Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/m32r/Kconfig | 26 +- arch/m32r/boot/compressed/head.S | 5 + arch/m32r/boot/setup.S | 9 + arch/m32r/kernel/Makefile | 1 + arch/m32r/kernel/entry.S | 17 +- arch/m32r/kernel/io_m32104ut.c | 298 +++++++++++++++ arch/m32r/kernel/setup.c | 7 +- arch/m32r/kernel/setup_m32104ut.c | 162 +++++++++ arch/m32r/kernel/time.c | 4 +- arch/m32r/m32104ut/defconfig.m32104ut | 657 ++++++++++++++++++++++++++++++++++ arch/m32r/mm/cache.c | 10 + 11 files changed, 1185 insertions(+), 11 deletions(-) create mode 100644 arch/m32r/kernel/io_m32104ut.c create mode 100644 arch/m32r/kernel/setup_m32104ut.c create mode 100644 arch/m32r/m32104ut/defconfig.m32104ut (limited to 'arch') diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index 4d100f3886e..fae67bbb52f 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig @@ -81,6 +81,12 @@ config PLAT_MAPPI2 config PLAT_MAPPI3 bool "Mappi-III(M3A-2170)" +config PLAT_M32104UT + bool "M32104UT" + help + The M3T-M32104UT is an reference board based on uT-Engine + specification. This board has a M32104 chip. + endchoice choice @@ -93,6 +99,10 @@ config CHIP_M32700 config CHIP_M32102 bool "M32102" +config CHIP_M32104 + bool "M32104" + depends on PLAT_M32104UT + config CHIP_VDEC2 bool "VDEC2" @@ -115,7 +125,7 @@ config TLB_ENTRIES config ISA_M32R bool - depends on CHIP_M32102 + depends on CHIP_M32102 || CHIP_M32104 default y config ISA_M32R2 @@ -140,6 +150,7 @@ config BUS_CLOCK default "50000000" if PLAT_MAPPI3 default "50000000" if PLAT_M32700UT default "50000000" if PLAT_OPSPUT + default "54000000" if PLAT_M32104UT default "33333333" if PLAT_OAKS32R default "20000000" if PLAT_MAPPI2 @@ -157,6 +168,7 @@ config MEMORY_START default "08000000" if PLAT_USRV default "08000000" if PLAT_M32700UT default "08000000" if PLAT_OPSPUT + default "04000000" if PLAT_M32104UT default "01000000" if PLAT_OAKS32R config MEMORY_SIZE @@ -166,6 +178,7 @@ config MEMORY_SIZE default "02000000" if PLAT_USRV default "01000000" if PLAT_M32700UT default "01000000" if PLAT_OPSPUT + default "01000000" if PLAT_M32104UT default "00800000" if PLAT_OAKS32R config NOHIGHMEM @@ -174,21 +187,22 @@ config NOHIGHMEM config ARCH_DISCONTIGMEM_ENABLE bool "Internal RAM Support" - depends on CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP + depends on CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP || CHIP_M32104 default y source "mm/Kconfig" config IRAM_START hex "Internal memory start address (hex)" - default "00f00000" - depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP) && DISCONTIGMEM + default "00f00000" if !CHIP_M32104 + default "00700000" if CHIP_M32104 + depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP || CHIP_M32104) && DISCONTIGMEM config IRAM_SIZE hex "Internal memory size (hex)" - depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP) && DISCONTIGMEM + depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP || CHIP_M32104) && DISCONTIGMEM default "00080000" if CHIP_M32700 - default "00010000" if CHIP_M32102 || CHIP_OPSP + default "00010000" if CHIP_M32102 || CHIP_OPSP || CHIP_M32104 default "00008000" if CHIP_VDEC2 # diff --git a/arch/m32r/boot/compressed/head.S b/arch/m32r/boot/compressed/head.S index 07cfd6ad1ae..234d8b1e0ac 100644 --- a/arch/m32r/boot/compressed/head.S +++ b/arch/m32r/boot/compressed/head.S @@ -143,6 +143,11 @@ startup: ldi r0, -2 ldi r1, 0x0100 ; invalidate stb r1, @r0 +#elif defined(CONFIG_CHIP_M32104) + /* Cache flush */ + ldi r0, -2 + ldi r1, 0x0700 ; invalidate i-cache, copy back d-cache + sth r1, @r0 #else #error "put your cache flush function, please" #endif diff --git a/arch/m32r/boot/setup.S b/arch/m32r/boot/setup.S index 5d256434b4a..742669fab8a 100644 --- a/arch/m32r/boot/setup.S +++ b/arch/m32r/boot/setup.S @@ -80,6 +80,10 @@ ENTRY(boot) ldi r1, #0x101 ; cache on (with invalidation) ; ldi r1, #0x00 ; cache off st r1, @r0 +#elif defined(CONFIG_CHIP_M32104) + ldi r0, #-4 ;LDIMM (r0, M32R_MCCR) + ldi r1, #0x703 ; cache on (with invalidation) + st r1, @r0 #else #error unknown chip configuration #endif @@ -115,10 +119,15 @@ mmu_on: st r1, @(MATM_offset,r0) ; Set MATM (T bit ON) ld r0, @(MATM_offset,r0) ; Check #else +#if defined(CONFIG_CHIP_M32700) seth r0,#high(M32R_MCDCAR) or3 r0,r0,#low(M32R_MCDCAR) ld24 r1,#0x8080 st r1,@r0 +#elif defined(CONFIG_CHIP_M32104) + LDIMM (r2, eit_vector) ; set EVB(cr5) + mvtc r2, cr5 +#endif #endif /* CONFIG_MMU */ jmp r13 nop diff --git a/arch/m32r/kernel/Makefile b/arch/m32r/kernel/Makefile index 6c6b6c37663..5a2fa886906 100644 --- a/arch/m32r/kernel/Makefile +++ b/arch/m32r/kernel/Makefile @@ -16,5 +16,6 @@ obj-$(CONFIG_PLAT_M32700UT) += setup_m32700ut.o io_m32700ut.o obj-$(CONFIG_PLAT_OPSPUT) += setup_opsput.o io_opsput.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_PLAT_OAKS32R) += setup_oaks32r.o io_oaks32r.o +obj-$(CONFIG_PLAT_M32104UT) += setup_m32104ut.o io_m32104ut.o EXTRA_AFLAGS := -traditional diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S index f6d4a5821a2..3871b65f0c8 100644 --- a/arch/m32r/kernel/entry.S +++ b/arch/m32r/kernel/entry.S @@ -315,7 +315,7 @@ ENTRY(ei_handler) mv r1, sp ; arg1(regs) #if defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) \ || defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \ - || defined(CONFIG_CHIP_OPSP) + || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104) ; GET_ICU_STATUS; seth r0, #shigh(M32R_ICU_ISTS_ADDR) @@ -541,7 +541,20 @@ check_int2: bra check_end .fillinsn check_end: -#endif /* CONFIG_PLAT_OPSPUT */ +#elif defined(CONFIG_PLAT_M32104UT) + add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt + bnez r2, check_end + ; read ICU status register of PLD + seth r0, #high(PLD_ICUISTS) + or3 r0, r0, #low(PLD_ICUISTS) + lduh r0, @r0 + slli r0, #21 + srli r0, #27 ; ISN + addi r0, #(M32104UT_PLD_IRQ_BASE) + bra check_end + .fillinsn +check_end: +#endif /* CONFIG_PLAT_M32104UT */ bl do_IRQ #endif /* CONFIG_SMP */ ld r14, @sp+ diff --git a/arch/m32r/kernel/io_m32104ut.c b/arch/m32r/kernel/io_m32104ut.c new file mode 100644 index 00000000000..3df4215f164 --- /dev/null +++ b/arch/m32r/kernel/io_m32104ut.c @@ -0,0 +1,298 @@ +/* + * linux/arch/m32r/kernel/io_m32104ut.c + * + * Typical I/O routines for M32104UT board. + * + * Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata, + * Hitoshi Yamamoto, Mamoru Sakugawa, + * Naoto Sugai, Hayato Fujiwara + */ + +#include +#include +#include +#include +#include + +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) +#include + +#define M32R_PCC_IOMAP_SIZE 0x1000 + +#define M32R_PCC_IOSTART0 0x1000 +#define M32R_PCC_IOEND0 (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1) + +extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int); +extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int); +extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int); +extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); +#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */ + +#define PORT2ADDR(port) _port2addr(port) + +static inline void *_port2addr(unsigned long port) +{ + return (void *)(port + NONCACHE_OFFSET); +} + +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) +static inline void *__port2addr_ata(unsigned long port) +{ + static int dummy_reg; + + switch (port) { + case 0x1f0: return (void *)0xac002000; + case 0x1f1: return (void *)0xac012800; + case 0x1f2: return (void *)0xac012002; + case 0x1f3: return (void *)0xac012802; + case 0x1f4: return (void *)0xac012004; + case 0x1f5: return (void *)0xac012804; + case 0x1f6: return (void *)0xac012006; + case 0x1f7: return (void *)0xac012806; + case 0x3f6: return (void *)0xac01200e; + default: return (void *)&dummy_reg; + } +} +#endif + +/* + * M32104T-LAN is located in the extended bus space + * from 0x01000000 to 0x01ffffff on physical address. + * The base address of LAN controller(LAN91C111) is 0x300. + */ +#define LAN_IOSTART 0x300 +#define LAN_IOEND 0x320 +static inline void *_port2addr_ne(unsigned long port) +{ + return (void *)(port + NONCACHE_OFFSET + 0x01000000); +} + +static inline void delay(void) +{ + __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory"); +} + +/* + * NIC I/O function + */ + +#define PORT2ADDR_NE(port) _port2addr_ne(port) + +static inline unsigned char _ne_inb(void *portp) +{ + return *(volatile unsigned char *)portp; +} + +static inline unsigned short _ne_inw(void *portp) +{ + return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp); +} + +static inline void _ne_insb(void *portp, void *addr, unsigned long count) +{ + unsigned char *buf = (unsigned char *)addr; + + while (count--) + *buf++ = _ne_inb(portp); +} + +static inline void _ne_outb(unsigned char b, void *portp) +{ + *(volatile unsigned char *)portp = b; +} + +static inline void _ne_outw(unsigned short w, void *portp) +{ + *(volatile unsigned short *)portp = cpu_to_le16(w); +} + +unsigned char _inb(unsigned long port) +{ + if (port >= LAN_IOSTART && port < LAN_IOEND) + return _ne_inb(PORT2ADDR_NE(port)); + + return *(volatile unsigned char *)PORT2ADDR(port); +} + +unsigned short _inw(unsigned long port) +{ + if (port >= LAN_IOSTART && port < LAN_IOEND) + return _ne_inw(PORT2ADDR_NE(port)); + + return *(volatile unsigned short *)PORT2ADDR(port); +} + +unsigned long _inl(unsigned long port) +{ + return *(volatile unsigned long *)PORT2ADDR(port); +} + +unsigned char _inb_p(unsigned long port) +{ + unsigned char v = _inb(port); + delay(); + return (v); +} + +unsigned short _inw_p(unsigned long port) +{ + unsigned short v = _inw(port); + delay(); + return (v); +} + +unsigned long _inl_p(unsigned long port) +{ + unsigned long v = _inl(port); + delay(); + return (v); +} + +void _outb(unsigned char b, unsigned long port) +{ + if (port >= LAN_IOSTART && port < LAN_IOEND) + _ne_outb(b, PORT2ADDR_NE(port)); + else + *(volatile unsigned char *)PORT2ADDR(port) = b; +} + +void _outw(unsigned short w, unsigned long port) +{ + if (port >= LAN_IOSTART && port < LAN_IOEND) + _ne_outw(w, PORT2ADDR_NE(port)); + else + *(volatile unsigned short *)PORT2ADDR(port) = w; +} + +void _outl(unsigned long l, unsigned long port) +{ + *(volatile unsigned long *)PORT2ADDR(port) = l; +} + +void _outb_p(unsigned char b, unsigned long port) +{ + _outb(b, port); + delay(); +} + +void _outw_p(unsigned short w, unsigned long port) +{ + _outw(w, port); + delay(); +} + +void _outl_p(unsigned long l, unsigned long port) +{ + _outl(l, port); + delay(); +} + +void _insb(unsigned int port, void *addr, unsigned long count) +{ + if (port >= LAN_IOSTART && port < LAN_IOEND) + _ne_insb(PORT2ADDR_NE(port), addr, count); + else { + unsigned char *buf = addr; + unsigned char *portp = PORT2ADDR(port); + while (count--) + *buf++ = *(volatile unsigned char *)portp; + } +} + +void _insw(unsigned int port, void *addr, unsigned long count) +{ + unsigned short *buf = addr; + unsigned short *portp; + + if (port >= LAN_IOSTART && port < LAN_IOEND) { + /* + * This portion is only used by smc91111.c to read data + * from the DATA_REG. Do not swap the data. + */ + portp = PORT2ADDR_NE(port); + while (count--) + *buf++ = *(volatile unsigned short *)portp; +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) + } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { + pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short), + count, 1); +#endif +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + portp = __port2addr_ata(port); + while (count--) + *buf++ = *(volatile unsigned short *)portp; +#endif + } else { + portp = PORT2ADDR(port); + while (count--) + *buf++ = *(volatile unsigned short *)portp; + } +} + +void _insl(unsigned int port, void *addr, unsigned long count) +{ + unsigned long *buf = addr; + unsigned long *portp; + + portp = PORT2ADDR(port); + while (count--) + *buf++ = *(volatile unsigned long *)portp; +} + +void _outsb(unsigned int port, const void *addr, unsigned long count) +{ + const unsigned char *buf = addr; + unsigned char *portp; + + if (port >= LAN_IOSTART && port < LAN_IOEND) { + portp = PORT2ADDR_NE(port); + while (count--) + _ne_outb(*buf++, portp); + } else { + portp = PORT2ADDR(port); + while (count--) + *(volatile unsigned char *)portp = *buf++; + } +} + +void _outsw(unsigned int port, const void *addr, unsigned long count) +{ + const unsigned short *buf = addr; + unsigned short *portp; + + if (port >= LAN_IOSTART && port < LAN_IOEND) { + /* + * This portion is only used by smc91111.c to write data + * into the DATA_REG. Do not swap the data. + */ + portp = PORT2ADDR_NE(port); + while (count--) + *(volatile unsigned short *)portp = *buf++; +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + portp = __port2addr_ata(port); + while (count--) + *(volatile unsigned short *)portp = *buf++; +#endif +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) + } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { + pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short), + count, 1); +#endif + } else { + portp = PORT2ADDR(port); + while (count--) + *(volatile unsigned short *)portp = *buf++; + } +} + +void _outsl(unsigned int port, const void *addr, unsigned long count) +{ + const unsigned long *buf = addr; + unsigned char *portp; + + portp = PORT2ADDR(port); + while (count--) + *(volatile unsigned long *)portp = *buf++; +} diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c index f722ec8eb02..c2e4dccf011 100644 --- a/arch/m32r/kernel/setup.c +++ b/arch/m32r/kernel/setup.c @@ -320,6 +320,9 @@ static int show_cpuinfo(struct seq_file *m, void *v) #elif defined(CONFIG_CHIP_MP) seq_printf(m, "cpu family\t: M32R-MP\n" "cache size\t: I-xxKB/D-xxKB\n"); +#elif defined(CONFIG_CHIP_M32104) + seq_printf(m,"cpu family\t: M32104\n" + "cache size\t: I-8KB/D-8KB\n"); #else seq_printf(m, "cpu family\t: Unknown\n"); #endif @@ -340,6 +343,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "Machine\t\t: uServer\n"); #elif defined(CONFIG_PLAT_OAKS32R) seq_printf(m, "Machine\t\t: OAKS32R\n"); +#elif defined(CONFIG_PLAT_M32104UT) + seq_printf(m, "Machine\t\t: M3T-M32104UT uT Engine board\n"); #else seq_printf(m, "Machine\t\t: Unknown\n"); #endif @@ -389,7 +394,7 @@ unsigned long cpu_initialized __initdata = 0; */ #if defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) \ || defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \ - || defined(CONFIG_CHIP_OPSP) + || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104) void __init cpu_init (void) { int cpu_id = smp_processor_id(); diff --git a/arch/m32r/kernel/setup_m32104ut.c b/arch/m32r/kernel/setup_m32104ut.c new file mode 100644 index 00000000000..ab16c664609 --- /dev/null +++ b/arch/m32r/kernel/setup_m32104ut.c @@ -0,0 +1,162 @@ +/* + * linux/arch/m32r/kernel/setup_m32104ut.c + * + * Setup routines for M32104UT Board + * + * Copyright (c) 2002-2005 Hiroyuki Kondo, Hirokazu Takata, + * Hitoshi Yamamoto, Mamoru Sakugawa, + * Naoto Sugai, Hayato Fujiwara + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) + +#ifndef CONFIG_SMP +typedef struct { + unsigned long icucr; /* ICU Control Register */ +} icu_data_t; +#endif /* CONFIG_SMP */ + +icu_data_t icu_data[NR_IRQS]; + +static void disable_m32104ut_irq(unsigned int irq) +{ + unsigned long port, data; + + port = irq2port(irq); + data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7; + outl(data, port); +} + +static void enable_m32104ut_irq(unsigned int irq) +{ + unsigned long port, data; + + port = irq2port(irq); + data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6; + outl(data, port); +} + +static void mask_and_ack_m32104ut(unsigned int irq) +{ + disable_m32104ut_irq(irq); +} + +static void end_m32104ut_irq(unsigned int irq) +{ + enable_m32104ut_irq(irq); +} + +static unsigned int startup_m32104ut_irq(unsigned int irq) +{ + enable_m32104ut_irq(irq); + return (0); +} + +static void shutdown_m32104ut_irq(unsigned int irq) +{ + unsigned long port; + + port = irq2port(irq); + outl(M32R_ICUCR_ILEVEL7, port); +} + +static struct hw_interrupt_type m32104ut_irq_type = +{ + .typename = "M32104UT-IRQ", + .startup = startup_m32104ut_irq, + .shutdown = shutdown_m32104ut_irq, + .enable = enable_m32104ut_irq, + .disable = disable_m32104ut_irq, + .ack = mask_and_ack_m32104ut, + .end = end_m32104ut_irq +}; + +void __init init_IRQ(void) +{ + static int once = 0; + + if (once) + return; + else + once++; + +#if defined(CONFIG_SMC91X) + /* INT#0: LAN controller on M32104UT-LAN (SMC91C111)*/ + irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED; + irq_desc[M32R_IRQ_INT0].handler = &m32104ut_irq_type; + irq_desc[M32R_IRQ_INT0].action = 0; + irq_desc[M32R_IRQ_INT0].depth = 1; + icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD11; /* "H" level sense */ + disable_m32104ut_irq(M32R_IRQ_INT0); +#endif /* CONFIG_SMC91X */ + + /* MFT2 : system timer */ + irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED; + irq_desc[M32R_IRQ_MFT2].handler = &m32104ut_irq_type; + irq_desc[M32R_IRQ_MFT2].action = 0; + irq_desc[M32R_IRQ_MFT2].depth = 1; + icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN; + disable_m32104ut_irq(M32R_IRQ_MFT2); + +#ifdef CONFIG_SERIAL_M32R_SIO + /* SIO0_R : uart receive data */ + irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED; + irq_desc[M32R_IRQ_SIO0_R].handler = &m32104ut_irq_type; + irq_desc[M32R_IRQ_SIO0_R].action = 0; + irq_desc[M32R_IRQ_SIO0_R].depth = 1; + icu_data[M32R_IRQ_SIO0_R].icucr = M32R_ICUCR_IEN; + disable_m32104ut_irq(M32R_IRQ_SIO0_R); + + /* SIO0_S : uart send data */ + irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED; + irq_desc[M32R_IRQ_SIO0_S].handler = &m32104ut_irq_type; + irq_desc[M32R_IRQ_SIO0_S].action = 0; + irq_desc[M32R_IRQ_SIO0_S].depth = 1; + icu_data[M32R_IRQ_SIO0_S].icucr = M32R_ICUCR_IEN; + disable_m32104ut_irq(M32R_IRQ_SIO0_S); +#endif /* CONFIG_SERIAL_M32R_SIO */ +} + +#if defined(CONFIG_SMC91X) + +#define LAN_IOSTART 0x300 +#define LAN_IOEND 0x320 +static struct resource smc91x_resources[] = { + [0] = { + .start = (LAN_IOSTART), + .end = (LAN_IOEND), + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = M32R_IRQ_INT0, + .end = M32R_IRQ_INT0, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device smc91x_device = { + .name = "smc91x", + .id = 0, + .num_resources = ARRAY_SIZE(smc91x_resources), + .resource = smc91x_resources, +}; +#endif + +static int __init platform_init(void) +{ +#if defined(CONFIG_SMC91X) + platform_device_register(&smc91x_device); +#endif + return 0; +} +arch_initcall(platform_init); diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c index 2ebce2063fe..b8e68b54230 100644 --- a/arch/m32r/kernel/time.c +++ b/arch/m32r/kernel/time.c @@ -57,7 +57,7 @@ static unsigned long do_gettimeoffset(void) #if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \ || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \ - || defined(CONFIG_CHIP_OPSP) + || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104) #ifndef CONFIG_SMP unsigned long count; @@ -268,7 +268,7 @@ void __init time_init(void) #if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \ || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \ - || defined(CONFIG_CHIP_OPSP) + || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104) /* M32102 MFT setup */ setup_irq(M32R_IRQ_MFT2, &irq0); diff --git a/arch/m32r/m32104ut/defconfig.m32104ut b/arch/m32r/m32104ut/defconfig.m32104ut new file mode 100644 index 00000000000..454de336803 --- /dev/null +++ b/arch/m32r/m32104ut/defconfig.m32104ut @@ -0,0 +1,657 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.14 +# Wed Nov 9 16:04:51 2005 +# +CONFIG_M32R=y +# CONFIG_UID16 is not set +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y + +# +# Code maturity level options +# +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_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_HOTPLUG=y +# CONFIG_KOBJECT_UEVENT is not set +# 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 is not set +# CONFIG_EPOLL is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_TINY_SHMEM=y +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Processor type and features +# +# CONFIG_PLAT_MAPPI is not set +# CONFIG_PLAT_USRV is not set +# CONFIG_PLAT_M32700UT is not set +# CONFIG_PLAT_OPSPUT is not set +# CONFIG_PLAT_OAKS32R is not set +# CONFIG_PLAT_MAPPI2 is not set +# CONFIG_PLAT_MAPPI3 is not set +CONFIG_PLAT_M32104UT=y +# CONFIG_CHIP_M32700 is not set +# CONFIG_CHIP_M32102 is not set +CONFIG_CHIP_M32104=y +# CONFIG_CHIP_VDEC2 is not set +# CONFIG_CHIP_OPSP is not set +CONFIG_ISA_M32R=y +CONFIG_BUS_CLOCK=54000000 +CONFIG_TIMER_DIVIDE=128 +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_MEMORY_START=04000000 +CONFIG_MEMORY_SIZE=01000000 +CONFIG_NOHIGHMEM=y +# CONFIG_ARCH_DISCONTIGMEM_ENABLE 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_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +CONFIG_GENERIC_CALIBRATE_DELAY=y +# CONFIG_PREEMPT is not set +# CONFIG_SMP is not set + +# +# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# +# CONFIG_ISA is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y + +# +# PC-card bridges +# + +# +# PCI Hotplug Support +# + +# +# Executable file formats +# +CONFIG_BINFMT_FLAT=y +# CONFIG_BINFMT_ZFLAT is not set +# CONFIG_BINFMT_SHARED_FLAT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# 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 is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# 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 +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_SMC91X=y +# CONFIG_NE2000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# +# Wan interfaces +# +# CONFIG_WAN 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 +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_M32R_SIO=y +CONFIG_SERIAL_M32R_SIO_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=y +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# Multimedia Capabilities Port drivers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# InfiniBand support +# + +# +# 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=y +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_INOTIFY is not set +# 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 +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=932 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# 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 +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +CONFIG_NLS_CODEPAGE_932=y +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_FS is not set +# CONFIG_FRAME_POINTER is not set +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_DEBUG_STACK_USAGE is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +CONFIG_LIBCRC32C=y +CONFIG_ZLIB_INFLATE=y diff --git a/arch/m32r/mm/cache.c b/arch/m32r/mm/cache.c index 31b0789c199..c6f72a64ae1 100644 --- a/arch/m32r/mm/cache.c +++ b/arch/m32r/mm/cache.c @@ -26,6 +26,16 @@ #define MCCR ((volatile unsigned char*)0xfffffffe) #define MCCR_IIV (1UL << 0) /* I-cache invalidate */ #define MCCR_ICACHE_INV MCCR_IIV +#elif defined(CONFIG_CHIP_M32104) +#define MCCR ((volatile unsigned long*)0xfffffffc) +#define MCCR_IIV (1UL << 8) /* I-cache invalidate */ +#define MCCR_DIV (1UL << 9) /* D-cache invalidate */ +#define MCCR_DCB (1UL << 10) /* D-cache copy back */ +#define MCCR_ICM (1UL << 0) /* I-cache mode [0:off,1:on] */ +#define MCCR_DCM (1UL << 1) /* D-cache mode [0:off,1:on] */ +#define MCCR_ICACHE_INV MCCR_IIV +#define MCCR_DCACHE_CB MCCR_DCB +#define MCCR_DCACHE_CBINV (MCCR_DIV|MCCR_DCB) #endif /* CONFIG_CHIP_XNUX2 || CONFIG_CHIP_M32700 */ #ifndef MCCR -- cgit v1.2.3 From 46ea178b7a5162405bf70954d769165cf2161309 Mon Sep 17 00:00:00 2001 From: Hirokazu Takata Date: Fri, 6 Jan 2006 00:18:43 -0800 Subject: [PATCH] m32r: Update _port2addr to use NONCACHE_OFFSET Modify _port2addr*() routines in arch/m32r/kernel/io_*.c to use NONCACHE_OFFSET instead of hard-coding of a constant address. This modification is also required to support an M3A-ZA36 FPGA eva board in case an MMU-less synthesizable m32r core is used. Signed-off-by: Hirokazu Takata Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/m32r/kernel/io_m32104ut.c | 24 ++++++++++---------- arch/m32r/kernel/io_m32700ut.c | 24 ++++++++++---------- arch/m32r/kernel/io_mappi.c | 2 +- arch/m32r/kernel/io_mappi2.c | 24 ++++++++++---------- arch/m32r/kernel/io_mappi3.c | 51 +++++++++++++++++++++++++----------------- arch/m32r/kernel/io_oaks32r.c | 2 +- arch/m32r/kernel/io_opsput.c | 6 ++--- 7 files changed, 71 insertions(+), 62 deletions(-) (limited to 'arch') diff --git a/arch/m32r/kernel/io_m32104ut.c b/arch/m32r/kernel/io_m32104ut.c index 3df4215f164..d26adab9586 100644 --- a/arch/m32r/kernel/io_m32104ut.c +++ b/arch/m32r/kernel/io_m32104ut.c @@ -32,7 +32,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); static inline void *_port2addr(unsigned long port) { - return (void *)(port + NONCACHE_OFFSET); + return (void *)(port | NONCACHE_OFFSET); } #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) @@ -41,15 +41,15 @@ static inline void *__port2addr_ata(unsigned long port) static int dummy_reg; switch (port) { - case 0x1f0: return (void *)0xac002000; - case 0x1f1: return (void *)0xac012800; - case 0x1f2: return (void *)0xac012002; - case 0x1f3: return (void *)0xac012802; - case 0x1f4: return (void *)0xac012004; - case 0x1f5: return (void *)0xac012804; - case 0x1f6: return (void *)0xac012006; - case 0x1f7: return (void *)0xac012806; - case 0x3f6: return (void *)0xac01200e; + case 0x1f0: return (void *)(0x0c002000 | NONCACHE_OFFSET); + case 0x1f1: return (void *)(0x0c012800 | NONCACHE_OFFSET); + case 0x1f2: return (void *)(0x0c012002 | NONCACHE_OFFSET); + case 0x1f3: return (void *)(0x0c012802 | NONCACHE_OFFSET); + case 0x1f4: return (void *)(0x0c012004 | NONCACHE_OFFSET); + case 0x1f5: return (void *)(0x0c012804 | NONCACHE_OFFSET); + case 0x1f6: return (void *)(0x0c012006 | NONCACHE_OFFSET); + case 0x1f7: return (void *)(0x0c012806 | NONCACHE_OFFSET); + case 0x3f6: return (void *)(0x0c01200e | NONCACHE_OFFSET); default: return (void *)&dummy_reg; } } @@ -60,8 +60,8 @@ static inline void *__port2addr_ata(unsigned long port) * from 0x01000000 to 0x01ffffff on physical address. * The base address of LAN controller(LAN91C111) is 0x300. */ -#define LAN_IOSTART 0x300 -#define LAN_IOEND 0x320 +#define LAN_IOSTART (0x300 | NONCACHE_OFFSET) +#define LAN_IOEND (0x320 | NONCACHE_OFFSET) static inline void *_port2addr_ne(unsigned long port) { return (void *)(port + NONCACHE_OFFSET + 0x01000000); diff --git a/arch/m32r/kernel/io_m32700ut.c b/arch/m32r/kernel/io_m32700ut.c index eda9f963c1e..939932d6cc0 100644 --- a/arch/m32r/kernel/io_m32700ut.c +++ b/arch/m32r/kernel/io_m32700ut.c @@ -36,7 +36,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); static inline void *_port2addr(unsigned long port) { - return (void *)(port + NONCACHE_OFFSET); + return (void *)(port | NONCACHE_OFFSET); } #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) @@ -45,15 +45,15 @@ static inline void *__port2addr_ata(unsigned long port) static int dummy_reg; switch (port) { - case 0x1f0: return (void *)0xac002000; - case 0x1f1: return (void *)0xac012800; - case 0x1f2: return (void *)0xac012002; - case 0x1f3: return (void *)0xac012802; - case 0x1f4: return (void *)0xac012004; - case 0x1f5: return (void *)0xac012804; - case 0x1f6: return (void *)0xac012006; - case 0x1f7: return (void *)0xac012806; - case 0x3f6: return (void *)0xac01200e; + case 0x1f0: return (void *)(0x0c002000 | NONCACHE_OFFSET); + case 0x1f1: return (void *)(0x0c012800 | NONCACHE_OFFSET); + case 0x1f2: return (void *)(0x0c012002 | NONCACHE_OFFSET); + case 0x1f3: return (void *)(0x0c012802 | NONCACHE_OFFSET); + case 0x1f4: return (void *)(0x0c012004 | NONCACHE_OFFSET); + case 0x1f5: return (void *)(0x0c012804 | NONCACHE_OFFSET); + case 0x1f6: return (void *)(0x0c012006 | NONCACHE_OFFSET); + case 0x1f7: return (void *)(0x0c012806 | NONCACHE_OFFSET); + case 0x3f6: return (void *)(0x0c01200e | NONCACHE_OFFSET); default: return (void *)&dummy_reg; } } @@ -64,8 +64,8 @@ static inline void *__port2addr_ata(unsigned long port) * from 0x10000000 to 0x13ffffff on physical address. * The base address of LAN controller(LAN91C111) is 0x300. */ -#define LAN_IOSTART 0xa0000300 -#define LAN_IOEND 0xa0000320 +#define LAN_IOSTART (0x300 | NONCACHE_OFFSET) +#define LAN_IOEND (0x320 | NONCACHE_OFFSET) static inline void *_port2addr_ne(unsigned long port) { return (void *)(port + 0x10000000); diff --git a/arch/m32r/kernel/io_mappi.c b/arch/m32r/kernel/io_mappi.c index 3c3da042fbd..a662b537c5b 100644 --- a/arch/m32r/kernel/io_mappi.c +++ b/arch/m32r/kernel/io_mappi.c @@ -31,7 +31,7 @@ extern void pcc_iowrite(int, unsigned long, void *, size_t, size_t, int); static inline void *_port2addr(unsigned long port) { - return (void *)(port | (NONCACHE_OFFSET)); + return (void *)(port | NONCACHE_OFFSET); } static inline void *_port2addr_ne(unsigned long port) diff --git a/arch/m32r/kernel/io_mappi2.c b/arch/m32r/kernel/io_mappi2.c index df3c729cb3e..e72d725606a 100644 --- a/arch/m32r/kernel/io_mappi2.c +++ b/arch/m32r/kernel/io_mappi2.c @@ -33,7 +33,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); static inline void *_port2addr(unsigned long port) { - return (void *)(port | (NONCACHE_OFFSET)); + return (void *)(port | NONCACHE_OFFSET); } #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) @@ -42,22 +42,22 @@ static inline void *__port2addr_ata(unsigned long port) static int dummy_reg; switch (port) { - case 0x1f0: return (void *)0xac002000; - case 0x1f1: return (void *)0xac012800; - case 0x1f2: return (void *)0xac012002; - case 0x1f3: return (void *)0xac012802; - case 0x1f4: return (void *)0xac012004; - case 0x1f5: return (void *)0xac012804; - case 0x1f6: return (void *)0xac012006; - case 0x1f7: return (void *)0xac012806; - case 0x3f6: return (void *)0xac01200e; + case 0x1f0: return (void *)(0x0c002000 | NONCACHE_OFFSET); + case 0x1f1: return (void *)(0x0c012800 | NONCACHE_OFFSET); + case 0x1f2: return (void *)(0x0c012002 | NONCACHE_OFFSET); + case 0x1f3: return (void *)(0x0c012802 | NONCACHE_OFFSET); + case 0x1f4: return (void *)(0x0c012004 | NONCACHE_OFFSET); + case 0x1f5: return (void *)(0x0c012804 | NONCACHE_OFFSET); + case 0x1f6: return (void *)(0x0c012006 | NONCACHE_OFFSET); + case 0x1f7: return (void *)(0x0c012806 | NONCACHE_OFFSET); + case 0x3f6: return (void *)(0x0c01200e | NONCACHE_OFFSET); default: return (void *)&dummy_reg; } } #endif -#define LAN_IOSTART 0xa0000300 -#define LAN_IOEND 0xa0000320 +#define LAN_IOSTART (0x300 | NONCACHE_OFFSET) +#define LAN_IOEND (0x320 | NONCACHE_OFFSET) #ifdef CONFIG_CHIP_OPSP static inline void *_port2addr_ne(unsigned long port) { diff --git a/arch/m32r/kernel/io_mappi3.c b/arch/m32r/kernel/io_mappi3.c index f80321a5876..ed6da930bc6 100644 --- a/arch/m32r/kernel/io_mappi3.c +++ b/arch/m32r/kernel/io_mappi3.c @@ -33,7 +33,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); static inline void *_port2addr(unsigned long port) { - return (void *)(port + NONCACHE_OFFSET); + return (void *)(port | NONCACHE_OFFSET); } #if defined(CONFIG_IDE) @@ -43,33 +43,42 @@ static inline void *__port2addr_ata(unsigned long port) switch (port) { /* IDE0 CF */ - case 0x1f0: return (void *)0xb4002000; - case 0x1f1: return (void *)0xb4012800; - case 0x1f2: return (void *)0xb4012002; - case 0x1f3: return (void *)0xb4012802; - case 0x1f4: return (void *)0xb4012004; - case 0x1f5: return (void *)0xb4012804; - case 0x1f6: return (void *)0xb4012006; - case 0x1f7: return (void *)0xb4012806; - case 0x3f6: return (void *)0xb401200e; + case 0x1f0: return (void *)(0x14002000 | NONCACHE_OFFSET); + case 0x1f1: return (void *)(0x14012800 | NONCACHE_OFFSET); + case 0x1f2: return (void *)(0x14012002 | NONCACHE_OFFSET); + case 0x1f3: return (void *)(0x14012802 | NONCACHE_OFFSET); + case 0x1f4: return (void *)(0x14012004 | NONCACHE_OFFSET); + case 0x1f5: return (void *)(0x14012804 | NONCACHE_OFFSET); + case 0x1f6: return (void *)(0x14012006 | NONCACHE_OFFSET); + case 0x1f7: return (void *)(0x14012806 | NONCACHE_OFFSET); + case 0x3f6: return (void *)(0x1401200e | NONCACHE_OFFSET); /* IDE1 IDE */ - case 0x170: return (void *)0xb4810000; /* Data 16bit */ - case 0x171: return (void *)0xb4810002; /* Features / Error */ - case 0x172: return (void *)0xb4810004; /* Sector count */ - case 0x173: return (void *)0xb4810006; /* Sector number */ - case 0x174: return (void *)0xb4810008; /* Cylinder low */ - case 0x175: return (void *)0xb481000a; /* Cylinder high */ - case 0x176: return (void *)0xb481000c; /* Device head */ - case 0x177: return (void *)0xb481000e; /* Command */ - case 0x376: return (void *)0xb480800c; /* Device control / Alt status */ + case 0x170: /* Data 16bit */ + return (void *)(0x14810000 | NONCACHE_OFFSET); + case 0x171: /* Features / Error */ + return (void *)(0x14810002 | NONCACHE_OFFSET); + case 0x172: /* Sector count */ + return (void *)(0x14810004 | NONCACHE_OFFSET); + case 0x173: /* Sector number */ + return (void *)(0x14810006 | NONCACHE_OFFSET); + case 0x174: /* Cylinder low */ + return (void *)(0x14810008 | NONCACHE_OFFSET); + case 0x175: /* Cylinder high */ + return (void *)(0x1481000a | NONCACHE_OFFSET); + case 0x176: /* Device head */ + return (void *)(0x1481000c | NONCACHE_OFFSET); + case 0x177: /* Command */ + return (void *)(0x1481000e | NONCACHE_OFFSET); + case 0x376: /* Device control / Alt status */ + return (void *)(0x1480800c | NONCACHE_OFFSET); default: return (void *)&dummy_reg; } } #endif -#define LAN_IOSTART 0xa0000300 -#define LAN_IOEND 0xa0000320 +#define LAN_IOSTART (0x300 | NONCACHE_OFFSET) +#define LAN_IOEND (0x320 | NONCACHE_OFFSET) static inline void *_port2addr_ne(unsigned long port) { return (void *)(port + 0x10000000); diff --git a/arch/m32r/kernel/io_oaks32r.c b/arch/m32r/kernel/io_oaks32r.c index 8be323931e4..910dd131c22 100644 --- a/arch/m32r/kernel/io_oaks32r.c +++ b/arch/m32r/kernel/io_oaks32r.c @@ -16,7 +16,7 @@ static inline void *_port2addr(unsigned long port) { - return (void *)(port | (NONCACHE_OFFSET)); + return (void *)(port | NONCACHE_OFFSET); } static inline void *_port2addr_ne(unsigned long port) diff --git a/arch/m32r/kernel/io_opsput.c b/arch/m32r/kernel/io_opsput.c index 4793bd18e11..bec69297db3 100644 --- a/arch/m32r/kernel/io_opsput.c +++ b/arch/m32r/kernel/io_opsput.c @@ -36,7 +36,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); static inline void *_port2addr(unsigned long port) { - return (void *)(port | (NONCACHE_OFFSET)); + return (void *)(port | NONCACHE_OFFSET); } /* @@ -44,8 +44,8 @@ static inline void *_port2addr(unsigned long port) * from 0x10000000 to 0x13ffffff on physical address. * The base address of LAN controller(LAN91C111) is 0x300. */ -#define LAN_IOSTART 0xa0000300 -#define LAN_IOEND 0xa0000320 +#define LAN_IOSTART (0x300 | NONCACHE_OFFSET) +#define LAN_IOEND (0x320 | NONCACHE_OFFSET) static inline void *_port2addr_ne(unsigned long port) { return (void *)(port + 0x10000000); -- cgit v1.2.3 From 9b791d4766c19ac014a7b81a551efe4a7511e12a Mon Sep 17 00:00:00 2001 From: Hirokazu Takata Date: Fri, 6 Jan 2006 00:18:44 -0800 Subject: [PATCH] m32r: Fix M32104 cache flushing routines This patch fixes cache memory parameter setting for the M32104 target. So far, its performance seemed to have been degraded due to incorrect cache parameter setting. * arch/m32r/boot/setup.S: Set SFR(Special Fuction Registers) region to be non-cachable explicitly. * arch/m32r/mm/cache.c: Fix cache flushing routines not to switch off the M32104 cache. Signed-off-by: Hayato Fujiwara Signed-off-by: Hirokazu Takata Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/m32r/boot/setup.S | 15 ++++++++++++--- arch/m32r/mm/cache.c | 28 +++++++++++++++++++++------- 2 files changed, 33 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/m32r/boot/setup.S b/arch/m32r/boot/setup.S index 742669fab8a..398542507d8 100644 --- a/arch/m32r/boot/setup.S +++ b/arch/m32r/boot/setup.S @@ -1,11 +1,10 @@ /* * linux/arch/m32r/boot/setup.S -- A setup code. * - * Copyright (C) 2001, 2002 Hiroyuki Kondo, Hirokazu Takata, - * and Hitoshi Yamamoto + * Copyright (C) 2001-2005 Hiroyuki Kondo, Hirokazu Takata, + * Hitoshi Yamamoto, Hayato Fujiwara * */ -/* $Id$ */ #include #include @@ -81,6 +80,16 @@ ENTRY(boot) ; ldi r1, #0x00 ; cache off st r1, @r0 #elif defined(CONFIG_CHIP_M32104) + ldi r0, #-96 ; DNCR0 + seth r1, #0x0060 ; from 0x00600000 + or3 r1, r1, #0x0005 ; size 2MB + st r1, @r0 + seth r1, #0x0100 ; from 0x01000000 + or3 r1, r1, #0x0003 ; size 16MB + st r1, @+r0 + seth r1, #0x0200 ; from 0x02000000 + or3 r1, r1, #0x0002 ; size 32MB + st r1, @+r0 ldi r0, #-4 ;LDIMM (r0, M32R_MCCR) ldi r1, #0x703 ; cache on (with invalidation) st r1, @r0 diff --git a/arch/m32r/mm/cache.c b/arch/m32r/mm/cache.c index c6f72a64ae1..9f54dd93701 100644 --- a/arch/m32r/mm/cache.c +++ b/arch/m32r/mm/cache.c @@ -1,7 +1,7 @@ /* * linux/arch/m32r/mm/cache.c * - * Copyright (C) 2002 Hirokazu Takata + * Copyright (C) 2002-2005 Hirokazu Takata, Hayato Fujiwara */ #include @@ -9,7 +9,8 @@ #undef MCCR -#if defined(CONFIG_CHIP_XNUX2) || defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_OPSP) +#if defined(CONFIG_CHIP_XNUX2) || defined(CONFIG_CHIP_M32700) \ + || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_OPSP) /* Cache Control Register */ #define MCCR ((volatile unsigned long*)0xfffffffc) #define MCCR_CC (1UL << 7) /* Cache mode modify bit */ @@ -27,7 +28,7 @@ #define MCCR_IIV (1UL << 0) /* I-cache invalidate */ #define MCCR_ICACHE_INV MCCR_IIV #elif defined(CONFIG_CHIP_M32104) -#define MCCR ((volatile unsigned long*)0xfffffffc) +#define MCCR ((volatile unsigned short*)0xfffffffe) #define MCCR_IIV (1UL << 8) /* I-cache invalidate */ #define MCCR_DIV (1UL << 9) /* D-cache invalidate */ #define MCCR_DCB (1UL << 10) /* D-cache copy back */ @@ -36,7 +37,7 @@ #define MCCR_ICACHE_INV MCCR_IIV #define MCCR_DCACHE_CB MCCR_DCB #define MCCR_DCACHE_CBINV (MCCR_DIV|MCCR_DCB) -#endif /* CONFIG_CHIP_XNUX2 || CONFIG_CHIP_M32700 */ +#endif #ifndef MCCR #error Unknown cache type. @@ -47,29 +48,42 @@ void _flush_cache_all(void) { #if defined(CONFIG_CHIP_M32102) + unsigned char mccr; *MCCR = MCCR_ICACHE_INV; +#elif defined(CONFIG_CHIP_M32104) + unsigned short mccr; + + /* Copyback and invalidate D-cache */ + /* Invalidate I-cache */ + *MCCR |= (MCCR_ICACHE_INV | MCCR_DCACHE_CBINV); #else unsigned long mccr; /* Copyback and invalidate D-cache */ /* Invalidate I-cache */ *MCCR = MCCR_ICACHE_INV | MCCR_DCACHE_CBINV; - while ((mccr = *MCCR) & MCCR_IIV); /* loop while invalidating... */ #endif + while ((mccr = *MCCR) & MCCR_IIV); /* loop while invalidating... */ } /* Copy back D-cache and invalidate I-cache all */ void _flush_cache_copyback_all(void) { #if defined(CONFIG_CHIP_M32102) + unsigned char mccr; *MCCR = MCCR_ICACHE_INV; +#elif defined(CONFIG_CHIP_M32104) + unsigned short mccr; + + /* Copyback and invalidate D-cache */ + /* Invalidate I-cache */ + *MCCR |= (MCCR_ICACHE_INV | MCCR_DCACHE_CB); #else unsigned long mccr; /* Copyback D-cache */ /* Invalidate I-cache */ *MCCR = MCCR_ICACHE_INV | MCCR_DCACHE_CB; - while ((mccr = *MCCR) & MCCR_IIV); /* loop while invalidating... */ - #endif + while ((mccr = *MCCR) & MCCR_IIV); /* loop while invalidating... */ } -- cgit v1.2.3 From adfc31c67f4515ed4bad1ef9555cbacdfc24e8d3 Mon Sep 17 00:00:00 2001 From: Hirokazu Takata Date: Fri, 6 Jan 2006 00:18:45 -0800 Subject: [PATCH] m32r: Remove unnecessary icu_data_t definitions This patch removes unnecessary struct icu_data_t definitions of arch/m32r/kernel/setup_*.c. Signed-off-by: Hayato Fujiwara Signed-off-by: Hirokazu Takata Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/m32r/kernel/setup_m32104ut.c | 6 ------ arch/m32r/kernel/setup_m32700ut.c | 8 -------- arch/m32r/kernel/setup_mappi.c | 6 ------ arch/m32r/kernel/setup_mappi2.c | 6 ------ arch/m32r/kernel/setup_mappi3.c | 6 ------ arch/m32r/kernel/setup_oaks32r.c | 6 ------ arch/m32r/kernel/setup_opsput.c | 8 -------- arch/m32r/kernel/setup_usrv.c | 6 ------ 8 files changed, 52 deletions(-) (limited to 'arch') diff --git a/arch/m32r/kernel/setup_m32104ut.c b/arch/m32r/kernel/setup_m32104ut.c index ab16c664609..6328e1357a8 100644 --- a/arch/m32r/kernel/setup_m32104ut.c +++ b/arch/m32r/kernel/setup_m32104ut.c @@ -20,12 +20,6 @@ #define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) -#ifndef CONFIG_SMP -typedef struct { - unsigned long icucr; /* ICU Control Register */ -} icu_data_t; -#endif /* CONFIG_SMP */ - icu_data_t icu_data[NR_IRQS]; static void disable_m32104ut_irq(unsigned int irq) diff --git a/arch/m32r/kernel/setup_m32700ut.c b/arch/m32r/kernel/setup_m32700ut.c index cb76916b014..fad1fc99bb2 100644 --- a/arch/m32r/kernel/setup_m32700ut.c +++ b/arch/m32r/kernel/setup_m32700ut.c @@ -26,15 +26,7 @@ */ #define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) -#ifndef CONFIG_SMP -typedef struct { - unsigned long icucr; /* ICU Control Register */ -} icu_data_t; -static icu_data_t icu_data[M32700UT_NUM_CPU_IRQ]; -#else icu_data_t icu_data[M32700UT_NUM_CPU_IRQ]; -#endif /* CONFIG_SMP */ - static void disable_m32700ut_irq(unsigned int irq) { diff --git a/arch/m32r/kernel/setup_mappi.c b/arch/m32r/kernel/setup_mappi.c index 501d798cf05..00f253209cb 100644 --- a/arch/m32r/kernel/setup_mappi.c +++ b/arch/m32r/kernel/setup_mappi.c @@ -19,12 +19,6 @@ #define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) -#ifndef CONFIG_SMP -typedef struct { - unsigned long icucr; /* ICU Control Register */ -} icu_data_t; -#endif /* CONFIG_SMP */ - icu_data_t icu_data[NR_IRQS]; static void disable_mappi_irq(unsigned int irq) diff --git a/arch/m32r/kernel/setup_mappi2.c b/arch/m32r/kernel/setup_mappi2.c index 7f2db5bfd62..eebc9d8b4e7 100644 --- a/arch/m32r/kernel/setup_mappi2.c +++ b/arch/m32r/kernel/setup_mappi2.c @@ -19,12 +19,6 @@ #define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) -#ifndef CONFIG_SMP -typedef struct { - unsigned long icucr; /* ICU Control Register */ -} icu_data_t; -#endif /* CONFIG_SMP */ - icu_data_t icu_data[NR_IRQS]; static void disable_mappi2_irq(unsigned int irq) diff --git a/arch/m32r/kernel/setup_mappi3.c b/arch/m32r/kernel/setup_mappi3.c index f6ecdf7f555..d2ff021e2d3 100644 --- a/arch/m32r/kernel/setup_mappi3.c +++ b/arch/m32r/kernel/setup_mappi3.c @@ -19,12 +19,6 @@ #define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) -#ifndef CONFIG_SMP -typedef struct { - unsigned long icucr; /* ICU Control Register */ -} icu_data_t; -#endif /* CONFIG_SMP */ - icu_data_t icu_data[NR_IRQS]; static void disable_mappi3_irq(unsigned int irq) diff --git a/arch/m32r/kernel/setup_oaks32r.c b/arch/m32r/kernel/setup_oaks32r.c index 45add5b76f1..0e9e63538c0 100644 --- a/arch/m32r/kernel/setup_oaks32r.c +++ b/arch/m32r/kernel/setup_oaks32r.c @@ -18,12 +18,6 @@ #define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) -#ifndef CONFIG_SMP -typedef struct { - unsigned long icucr; /* ICU Control Register */ -} icu_data_t; -#endif /* CONFIG_SMP */ - icu_data_t icu_data[NR_IRQS]; static void disable_oaks32r_irq(unsigned int irq) diff --git a/arch/m32r/kernel/setup_opsput.c b/arch/m32r/kernel/setup_opsput.c index 1fbb140854e..548e8fc7949 100644 --- a/arch/m32r/kernel/setup_opsput.c +++ b/arch/m32r/kernel/setup_opsput.c @@ -27,15 +27,7 @@ */ #define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) -#ifndef CONFIG_SMP -typedef struct { - unsigned long icucr; /* ICU Control Register */ -} icu_data_t; -static icu_data_t icu_data[OPSPUT_NUM_CPU_IRQ]; -#else icu_data_t icu_data[OPSPUT_NUM_CPU_IRQ]; -#endif /* CONFIG_SMP */ - static void disable_opsput_irq(unsigned int irq) { diff --git a/arch/m32r/kernel/setup_usrv.c b/arch/m32r/kernel/setup_usrv.c index 634741bf9d3..64be659a23e 100644 --- a/arch/m32r/kernel/setup_usrv.c +++ b/arch/m32r/kernel/setup_usrv.c @@ -18,12 +18,6 @@ #define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) -#if !defined(CONFIG_SMP) -typedef struct { - unsigned long icucr; /* ICU Control Register */ -} icu_data_t; -#endif /* CONFIG_SMP */ - icu_data_t icu_data[M32700UT_NUM_CPU_IRQ]; static void disable_mappi_irq(unsigned int irq) -- cgit v1.2.3 From 32588918254cff7c03651dcbd3d8cc2301aba5bd Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 6 Jan 2006 00:18:45 -0800 Subject: [PATCH] m68knommu: enable_irq/disable_irq mach_enable_irq/mach_disable_irq are never actually set, so let's remove them. Signed-off-by: Christoph Hellwig Cc: Greg Ungerer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/m68knommu/kernel/m68k_ksyms.c | 2 -- arch/m68knommu/kernel/setup.c | 2 -- 2 files changed, 4 deletions(-) (limited to 'arch') diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c index e93a5ad5649..b2c62eeb3ba 100644 --- a/arch/m68knommu/kernel/m68k_ksyms.c +++ b/arch/m68knommu/kernel/m68k_ksyms.c @@ -38,8 +38,6 @@ EXPORT_SYMBOL(strncmp); EXPORT_SYMBOL(ip_fast_csum); -EXPORT_SYMBOL(mach_enable_irq); -EXPORT_SYMBOL(mach_disable_irq); EXPORT_SYMBOL(kernel_thread); /* Networking helper routines. */ diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c index abb80fa2b94..93120b9bfff 100644 --- a/arch/m68knommu/kernel/setup.c +++ b/arch/m68knommu/kernel/setup.c @@ -65,8 +65,6 @@ void (*mach_kbd_leds) (unsigned int) = NULL; /* machine dependent irq functions */ void (*mach_init_IRQ) (void) = NULL; irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL; -void (*mach_enable_irq) (unsigned int) = NULL; -void (*mach_disable_irq) (unsigned int) = NULL; int (*mach_get_irq_list) (struct seq_file *, void *) = NULL; void (*mach_process_int) (int irq, struct pt_regs *fp) = NULL; void (*mach_trap_init) (void); -- cgit v1.2.3 From 118c1f27b838c5d1cf5338dc5abff52ceb364826 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 6 Jan 2006 00:18:47 -0800 Subject: [PATCH] cris: kgdb: remove double_this() Doesn't make much sense and unused. Signed-off-by: Alexey Dobriyan Signed-off-by: Adrian Bunk Cc: Mikael Starvik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/cris/arch-v10/kernel/kgdb.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'arch') diff --git a/arch/cris/arch-v10/kernel/kgdb.c b/arch/cris/arch-v10/kernel/kgdb.c index b72e6a91a63..34528da9881 100644 --- a/arch/cris/arch-v10/kernel/kgdb.c +++ b/arch/cris/arch-v10/kernel/kgdb.c @@ -569,12 +569,6 @@ gdb_cris_strtol (const char *s, char **endptr, int base) return x; } -int -double_this(int x) -{ - return 2 * x; -} - /********************************* Register image ****************************/ /* Copy the content of a register image into another. The size n is the size of the register image. Due to struct assignment generation of -- cgit v1.2.3 From 970d6e3a3461ebc62bc3fc6d4962c936cb2ed97c Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:18:48 -0800 Subject: [PATCH] uml: use kstrdup There were a bunch of calls to uml_strdup dating from before kstrdup was introduced. This changes those calls. It doesn't eliminate the definition since there is still a couple of calls in userspace code (which should probably call the libc strdup). Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/line.c | 10 +++++----- arch/um/drivers/mconsole_kern.c | 2 +- arch/um/drivers/net_kern.c | 2 +- arch/um/drivers/ubd_kern.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index e0fdffa2d54..c31fc541e21 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -562,10 +562,11 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed int line_config(struct line *lines, unsigned int num, char *str) { - char *new = uml_strdup(str); + char *new; + new = kstrdup(str, GFP_KERNEL); if(new == NULL){ - printk("line_config - uml_strdup failed\n"); + printk("line_config - kstrdup failed\n"); return -ENOMEM; } return !line_setup(lines, num, new, 0); @@ -677,10 +678,9 @@ void lines_init(struct line *lines, int nlines) INIT_LIST_HEAD(&line->chan_list); spin_lock_init(&line->lock); if(line->init_str != NULL){ - line->init_str = uml_strdup(line->init_str); + line->init_str = kstrdup(line->init_str, GFP_KERNEL); if(line->init_str == NULL) - printk("lines_init - uml_strdup returned " - "NULL\n"); + printk("lines_init - kstrdup returned NULL\n"); } } } diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 12c95368124..b3678641045 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -563,7 +563,7 @@ int mconsole_init(void) } if(notify_socket != NULL){ - notify_socket = uml_strdup(notify_socket); + notify_socket = kstrdup(notify_socket, GFP_KERNEL); if(notify_socket != NULL) mconsole_notify(notify_socket, MCONSOLE_SOCKET, mconsole_socket_name, diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 84c73a300ac..29785f64302 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -586,7 +586,7 @@ static int net_config(char *str) err = eth_parse(str, &n, &str); if(err) return(err); - str = uml_strdup(str); + str = kstrdup(str, GFP_KERNEL); if(str == NULL){ printk(KERN_ERR "net_config failed to strdup string\n"); return(-1); diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 93898917cbe..1fe0dcd9f46 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -706,7 +706,7 @@ static int ubd_config(char *str) { int n, err; - str = uml_strdup(str); + str = kstrdup(str, GFP_KERNEL); if(str == NULL){ printk(KERN_ERR "ubd_config failed to strdup string\n"); return(1); -- cgit v1.2.3 From 1b57e9c27882a908f180d4daf72ee12c6f137178 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:18:49 -0800 Subject: [PATCH] uml: non-void functions should return something There are a few functions which are declared to return something, but don't. These are actually infinite loops which are forced to be declared as non-void. This makes them all return 0. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/ubd_kern.c | 13 ++----------- arch/um/kernel/sigio_user.c | 2 ++ arch/um/os-Linux/aio.c | 2 ++ 3 files changed, 6 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 1fe0dcd9f46..73f9652b2ee 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -1387,15 +1387,6 @@ int io_thread(void *arg) printk("io_thread - write failed, fd = %d, err = %d\n", kernel_fd, -n); } -} -/* - * 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: - */ + return 0; +} diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c index 48b1f644b9a..62e5cfdf218 100644 --- a/arch/um/kernel/sigio_user.c +++ b/arch/um/kernel/sigio_user.c @@ -216,6 +216,8 @@ static int write_sigio_thread(void *unused) "err = %d\n", -n); } } + + return 0; } static int need_poll(int n) diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index ffa759addd3..0b78bb7a994 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c @@ -210,6 +210,8 @@ static int not_aio_thread(void *arg) printk("not_aio_thread - write failed, fd = %d, " "err = %d\n", aio_req_fd_r, -err); } + + return 0; } static int aio_pid = -1; -- cgit v1.2.3 From d50084a2991f3d9490d5c0f3af72e6fe1515a493 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:18:50 -0800 Subject: [PATCH] uml: Formatting changes This patch makes a bunch of non-functional changes - return(foo); becomes return foo; some statements are broken across lines for readability some trailing whitespace is cleaned up open_one_chan took four arguments, three of which could be deduced from the first. Accordingly, they were eliminated. some examples of "} else {" had a newline added some whitespace cleanup in the indentation lines_init got some control flow cleanup some long lines were broken removed another emacs-specific C formatting comment Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/chan_kern.c | 124 ++++++----- arch/um/drivers/line.c | 47 ++-- arch/um/drivers/mconsole_kern.c | 25 ++- arch/um/drivers/ssl.c | 29 +-- arch/um/drivers/stdio_console.c | 26 +-- arch/um/include/chan_kern.h | 11 - arch/um/include/line.h | 22 +- arch/um/os-Linux/aio.c | 465 ++++++++++++++++++++-------------------- 8 files changed, 381 insertions(+), 368 deletions(-) (limited to 'arch') diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 5b58fad4529..8b1262e9fb6 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -58,7 +58,7 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts) { my_puts("Using a channel type which is configured out of " "UML\n"); - return(NULL); + return NULL; } static int not_configged_open(int input, int output, int primary, void *data, @@ -66,7 +66,7 @@ static int not_configged_open(int input, int output, int primary, void *data, { my_puts("Using a channel type which is configured out of " "UML\n"); - return(-ENODEV); + return -ENODEV; } static void not_configged_close(int fd, void *data) @@ -79,21 +79,21 @@ static int not_configged_read(int fd, char *c_out, void *data) { my_puts("Using a channel type which is configured out of " "UML\n"); - return(-EIO); + return -EIO; } static int not_configged_write(int fd, const char *buf, int len, void *data) { my_puts("Using a channel type which is configured out of " "UML\n"); - return(-EIO); + return -EIO; } static int not_configged_console_write(int fd, const char *buf, int len) { my_puts("Using a channel type which is configured out of " "UML\n"); - return(-EIO); + return -EIO; } static int not_configged_window_size(int fd, void *data, unsigned short *rows, @@ -101,7 +101,7 @@ static int not_configged_window_size(int fd, void *data, unsigned short *rows, { my_puts("Using a channel type which is configured out of " "UML\n"); - return(-ENODEV); + return -ENODEV; } static void not_configged_free(void *data) @@ -135,17 +135,17 @@ int generic_read(int fd, char *c_out, void *unused) n = os_read_file(fd, c_out, sizeof(*c_out)); if(n == -EAGAIN) - return(0); + return 0; else if(n == 0) - return(-EIO); - return(n); + return -EIO; + return n; } /* XXX Trivial wrapper around os_write_file */ int generic_write(int fd, const char *buf, int n, void *unused) { - return(os_write_file(fd, buf, n)); + return os_write_file(fd, buf, n); } int generic_window_size(int fd, void *unused, unsigned short *rows_out, @@ -156,14 +156,14 @@ int generic_window_size(int fd, void *unused, unsigned short *rows_out, ret = os_window_size(fd, &rows, &cols); if(ret < 0) - return(ret); + return ret; ret = ((*rows_out != rows) || (*cols_out != cols)); *rows_out = rows; *cols_out = cols; - return(ret); + return ret; } void generic_free(void *data) @@ -186,25 +186,29 @@ static void tty_receive_char(struct tty_struct *tty, char ch) } } - if((tty->flip.flag_buf_ptr == NULL) || + if((tty->flip.flag_buf_ptr == NULL) || (tty->flip.char_buf_ptr == NULL)) return; tty_insert_flip_char(tty, ch, TTY_NORMAL); } -static int open_one_chan(struct chan *chan, int input, int output, int primary) +static int open_one_chan(struct chan *chan) { int fd; - if(chan->opened) return(0); - if(chan->ops->open == NULL) fd = 0; - else fd = (*chan->ops->open)(input, output, primary, chan->data, - &chan->dev); - if(fd < 0) return(fd); + if(chan->opened) + return 0; + + if(chan->ops->open == NULL) + fd = 0; + else fd = (*chan->ops->open)(chan->input, chan->output, chan->primary, + chan->data, &chan->dev); + if(fd < 0) + return fd; chan->fd = fd; chan->opened = 1; - return(0); + return 0; } int open_chan(struct list_head *chans) @@ -215,11 +219,11 @@ int open_chan(struct list_head *chans) list_for_each(ele, chans){ chan = list_entry(ele, struct chan, list); - ret = open_one_chan(chan, chan->input, chan->output, - chan->primary); - if(chan->primary) err = ret; + ret = open_one_chan(chan); + if(chan->primary) + err = ret; } - return(err); + return err; } void chan_enable_winch(struct list_head *chans, struct tty_struct *tty) @@ -267,7 +271,7 @@ void close_chan(struct list_head *chans) } } -int write_chan(struct list_head *chans, const char *buf, int len, +int write_chan(struct list_head *chans, const char *buf, int len, int write_irq) { struct list_head *ele; @@ -285,7 +289,7 @@ int write_chan(struct list_head *chans, const char *buf, int len, reactivate_fd(chan->fd, write_irq); } } - return(ret); + return ret; } int console_write_chan(struct list_head *chans, const char *buf, int len) @@ -301,10 +305,11 @@ int console_write_chan(struct list_head *chans, const char *buf, int len) n = chan->ops->console_write(chan->fd, buf, len); if(chan->primary) ret = n; } - return(ret); + return ret; } -int console_open_chan(struct line *line, struct console *co, struct chan_opts *opts) +int console_open_chan(struct line *line, struct console *co, + struct chan_opts *opts) { if (!list_empty(&line->chan_list)) return 0; @@ -327,12 +332,13 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out, list_for_each(ele, chans){ chan = list_entry(ele, struct chan, list); if(chan->primary){ - if(chan->ops->window_size == NULL) return(0); - return(chan->ops->window_size(chan->fd, chan->data, - rows_out, cols_out)); + if(chan->ops->window_size == NULL) + return 0; + return chan->ops->window_size(chan->fd, chan->data, + rows_out, cols_out); } } - return(0); + return 0; } void free_one_chan(struct chan *chan) @@ -363,23 +369,23 @@ static int one_chan_config_string(struct chan *chan, char *str, int size, if(chan == NULL){ CONFIG_CHUNK(str, size, n, "none", 1); - return(n); + return n; } CONFIG_CHUNK(str, size, n, chan->ops->type, 0); if(chan->dev == NULL){ CONFIG_CHUNK(str, size, n, "", 1); - return(n); + return n; } CONFIG_CHUNK(str, size, n, ":", 0); CONFIG_CHUNK(str, size, n, chan->dev, 0); - return(n); + return n; } -static int chan_pair_config_string(struct chan *in, struct chan *out, +static int chan_pair_config_string(struct chan *in, struct chan *out, char *str, int size, char **error_out) { int n; @@ -390,7 +396,7 @@ static int chan_pair_config_string(struct chan *in, struct chan *out, if(in == out){ CONFIG_CHUNK(str, size, n, "", 1); - return(n); + return n; } CONFIG_CHUNK(str, size, n, ",", 1); @@ -399,10 +405,10 @@ static int chan_pair_config_string(struct chan *in, struct chan *out, size -= n; CONFIG_CHUNK(str, size, n, "", 1); - return(n); + return n; } -int chan_config_string(struct list_head *chans, char *str, int size, +int chan_config_string(struct list_head *chans, char *str, int size, char **error_out) { struct list_head *ele; @@ -418,7 +424,7 @@ int chan_config_string(struct list_head *chans, char *str, int size, out = chan; } - return(chan_pair_config_string(in, out, str, size, error_out)); + return chan_pair_config_string(in, out, str, size, error_out); } struct chan_type { @@ -462,7 +468,7 @@ struct chan_type chan_table[] = { #endif }; -static struct chan *parse_chan(char *str, int pri, int device, +static struct chan *parse_chan(char *str, int pri, int device, struct chan_opts *opts) { struct chan_type *entry; @@ -484,14 +490,17 @@ static struct chan *parse_chan(char *str, int pri, int device, if(ops == NULL){ my_printf("parse_chan couldn't parse \"%s\"\n", str); - return(NULL); + return NULL; } - if(ops->init == NULL) return(NULL); + if(ops->init == NULL) + return NULL; data = (*ops->init)(str, device, opts); - if(data == NULL) return(NULL); + if(data == NULL) + return NULL; chan = kmalloc(sizeof(*chan), GFP_ATOMIC); - if(chan == NULL) return(NULL); + if(chan == NULL) + return NULL; *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), .primary = 1, .input = 0, @@ -501,7 +510,7 @@ static struct chan *parse_chan(char *str, int pri, int device, .pri = pri, .ops = ops, .data = data }); - return(chan); + return chan; } int parse_chan_pair(char *str, struct list_head *chans, int pri, int device, @@ -512,7 +521,8 @@ int parse_chan_pair(char *str, struct list_head *chans, int pri, int device, if(!list_empty(chans)){ chan = list_entry(chans->next, struct chan, list); - if(chan->pri >= pri) return(0); + if(chan->pri >= pri) + return 0; free_chan(chans); INIT_LIST_HEAD(chans); } @@ -523,23 +533,29 @@ int parse_chan_pair(char *str, struct list_head *chans, int pri, int device, *out = '\0'; out++; new = parse_chan(in, pri, device, opts); - if(new == NULL) return(-1); + if(new == NULL) + return -1; + new->input = 1; list_add(&new->list, chans); new = parse_chan(out, pri, device, opts); - if(new == NULL) return(-1); + if(new == NULL) + return -1; + list_add(&new->list, chans); new->output = 1; } else { new = parse_chan(str, pri, device, opts); - if(new == NULL) return(-1); + if(new == NULL) + return -1; + list_add(&new->list, chans); new->input = 1; new->output = 1; } - return(0); + return 0; } int chan_out_fd(struct list_head *chans) @@ -550,9 +566,9 @@ int chan_out_fd(struct list_head *chans) list_for_each(ele, chans){ chan = list_entry(ele, struct chan, list); if(chan->primary && chan->output) - return(chan->fd); + return chan->fd; } - return(-1); + return -1; } void chan_interrupt(struct list_head *chans, struct work_struct *task, @@ -567,7 +583,7 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task, chan = list_entry(ele, struct chan, list); if(!chan->input || (chan->ops->read == NULL)) continue; do { - if((tty != NULL) && + if((tty != NULL) && (tty->flip.count >= TTY_FLIPBUF_SIZE)){ schedule_work(task); goto out; diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index c31fc541e21..2ee00cbe8f9 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -124,7 +124,8 @@ static int buffer_data(struct line *line, const char *buf, int len) if (len < end){ memcpy(line->tail, buf, len); line->tail += len; - } else { + } + else { /* The circular buffer is wrapping */ memcpy(line->tail, buf, end); buf += end; @@ -170,7 +171,7 @@ static int flush_buffer(struct line *line) } count = line->tail - line->head; - n = write_chan(&line->chan_list, line->head, count, + n = write_chan(&line->chan_list, line->head, count, line->driver->write_irq); if(n < 0) @@ -227,7 +228,7 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len) if (err <= 0 && (err != -EAGAIN || !ret)) ret = err; } else { - n = write_chan(&line->chan_list, buf, len, + n = write_chan(&line->chan_list, buf, len, line->driver->write_irq); if (n < 0) { ret = n; @@ -384,13 +385,13 @@ int line_setup_irq(int fd, int input, int output, struct tty_struct *tty) if (input) err = um_request_irq(driver->read_irq, fd, IRQ_READ, - line_interrupt, flags, + line_interrupt, flags, driver->read_irq_name, tty); if (err) return err; if (output) err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, - line_write_interrupt, flags, + line_write_interrupt, flags, driver->write_irq_name, tty); line->have_irq = 1; return err; @@ -512,10 +513,11 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed /* We said con=/ssl= instead of con#=, so we are configuring all * consoles at once.*/ n = -1; - } else { + } + else { n = simple_strtoul(init, &end, 0); if(*end != '='){ - printk(KERN_ERR "line_setup failed to parse \"%s\"\n", + printk(KERN_ERR "line_setup failed to parse \"%s\"\n", init); return 0; } @@ -527,7 +529,8 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed printk("line_setup - %d out of range ((0 ... %d) allowed)\n", n, num - 1); return 0; - } else if (n >= 0){ + } + else if (n >= 0){ if (lines[n].count > 0) { printk("line_setup - device %d is open\n", n); return 0; @@ -541,11 +544,13 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed lines[n].valid = 1; } } - } else if(!all_allowed){ + } + else if(!all_allowed){ printk("line_setup - can't configure all devices from " "mconsole\n"); return 0; - } else { + } + else { for(i = 0; i < num; i++){ if(lines[i].init_pri <= INIT_ALL){ lines[i].init_pri = INIT_ALL; @@ -627,7 +632,7 @@ int line_remove(struct line *lines, unsigned int num, int n) } struct tty_driver *line_register_devfs(struct lines *set, - struct line_driver *line_driver, + struct line_driver *line_driver, struct tty_operations *ops, struct line *lines, int nlines) { @@ -656,7 +661,7 @@ struct tty_driver *line_register_devfs(struct lines *set, } for(i = 0; i < nlines; i++){ - if(!lines[i].valid) + if(!lines[i].valid) tty_unregister_device(driver, i); } @@ -677,11 +682,12 @@ void lines_init(struct line *lines, int nlines) line = &lines[i]; INIT_LIST_HEAD(&line->chan_list); spin_lock_init(&line->lock); - if(line->init_str != NULL){ - line->init_str = kstrdup(line->init_str, GFP_KERNEL); - if(line->init_str == NULL) - printk("lines_init - kstrdup returned NULL\n"); - } + if(line->init_str == NULL) + continue; + + line->init_str = kstrdup(line->init_str, GFP_KERNEL); + if(line->init_str == NULL) + printk("lines_init - kstrdup returned NULL\n"); } } @@ -717,8 +723,7 @@ irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused) tty = winch->tty; if (tty != NULL) { line = tty->driver_data; - chan_window_size(&line->chan_list, - &tty->winsize.ws_row, + chan_window_size(&line->chan_list, &tty->winsize.ws_row, &tty->winsize.ws_col); kill_pg(tty->pgrp, SIGWINCH, 1); } @@ -749,7 +754,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty) spin_unlock(&winch_handler_lock); if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, - SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, + SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, "winch", winch) < 0) printk("register_winch_irq - failed to register IRQ\n"); } @@ -800,7 +805,7 @@ static void winch_cleanup(void) deactivate_fd(winch->fd, WINCH_IRQ); os_close_file(winch->fd); } - if(winch->pid != -1) + if(winch->pid != -1) os_kill_process(winch->pid, 1); } } diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index b3678641045..355866af5e0 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -34,7 +34,7 @@ #include "irq_kern.h" #include "choose-mode.h" -static int do_unlink_socket(struct notifier_block *notifier, +static int do_unlink_socket(struct notifier_block *notifier, unsigned long what, void *data) { return(mconsole_unlink_socket()); @@ -46,7 +46,7 @@ static struct notifier_block reboot_notifier = { .priority = 0, }; -/* Safe without explicit locking for now. Tasklets provide their own +/* Safe without explicit locking for now. Tasklets provide their own * locking, and the interrupt handler is safe because it can't interrupt * itself and it can only happen on CPU 0. */ @@ -60,7 +60,7 @@ static void mc_work_proc(void *unused) while(!list_empty(&mc_requests)){ local_save_flags(flags); - req = list_entry(mc_requests.next, struct mconsole_entry, + req = list_entry(mc_requests.next, struct mconsole_entry, list); list_del(&req->list); local_irq_restore(flags); @@ -103,8 +103,8 @@ void mconsole_version(struct mc_request *req) { char version[256]; - sprintf(version, "%s %s %s %s %s", system_utsname.sysname, - system_utsname.nodename, system_utsname.release, + sprintf(version, "%s %s %s %s %s", system_utsname.sysname, + system_utsname.nodename, system_utsname.release, system_utsname.version, system_utsname.machine); mconsole_reply(req, version, 0, 0); } @@ -348,7 +348,7 @@ static struct mc_device *mconsole_find_dev(char *name) #define CONFIG_BUF_SIZE 64 -static void mconsole_get_config(int (*get_config)(char *, char *, int, +static void mconsole_get_config(int (*get_config)(char *, char *, int, char **), struct mc_request *req, char *name) { @@ -389,7 +389,6 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int, out: if(buf != default_buf) kfree(buf); - } void mconsole_config(struct mc_request *req) @@ -420,7 +419,7 @@ void mconsole_config(struct mc_request *req) void mconsole_remove(struct mc_request *req) { - struct mc_device *dev; + struct mc_device *dev; char *ptr = req->request.data, *err_msg = ""; char error[256]; int err, start, end, n; @@ -534,7 +533,7 @@ void mconsole_stack(struct mc_request *req) /* Changed by mconsole_setup, which is __setup, and called before SMP is * active. */ -static char *notify_socket = NULL; +static char *notify_socket = NULL; int mconsole_init(void) { @@ -566,13 +565,13 @@ int mconsole_init(void) notify_socket = kstrdup(notify_socket, GFP_KERNEL); if(notify_socket != NULL) mconsole_notify(notify_socket, MCONSOLE_SOCKET, - mconsole_socket_name, + mconsole_socket_name, strlen(mconsole_socket_name) + 1); else printk(KERN_ERR "mconsole_setup failed to strdup " "string\n"); } - printk("mconsole (version %d) initialized on %s\n", + printk("mconsole (version %d) initialized on %s\n", MCONSOLE_VERSION, mconsole_socket_name); return(0); } @@ -585,7 +584,7 @@ static int write_proc_mconsole(struct file *file, const char __user *buffer, char *buf; buf = kmalloc(count + 1, GFP_KERNEL); - if(buf == NULL) + if(buf == NULL) return(-ENOMEM); if(copy_from_user(buf, buffer, count)){ @@ -661,7 +660,7 @@ static int notify_panic(struct notifier_block *self, unsigned long unused1, if(notify_socket == NULL) return(0); - mconsole_notify(notify_socket, MCONSOLE_PANIC, message, + mconsole_notify(notify_socket, MCONSOLE_PANIC, message, strlen(message) + 1); return(0); } diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index 62e04ecfada..95a3eaa7163 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -69,7 +69,7 @@ static struct line_driver driver = { .name = "ssl", .config = ssl_config, .get_config = ssl_get_config, - .id = line_id, + .id = line_id, .remove = ssl_remove, }, }; @@ -84,21 +84,21 @@ static struct lines lines = LINES_INIT(NR_PORTS); static int ssl_config(char *str) { - return(line_config(serial_lines, - sizeof(serial_lines)/sizeof(serial_lines[0]), str)); + return line_config(serial_lines, + sizeof(serial_lines)/sizeof(serial_lines[0]), str); } static int ssl_get_config(char *dev, char *str, int size, char **error_out) { - return(line_get_config(dev, serial_lines, - sizeof(serial_lines)/sizeof(serial_lines[0]), - str, size, error_out)); + return line_get_config(dev, serial_lines, + sizeof(serial_lines)/sizeof(serial_lines[0]), + str, size, error_out); } static int ssl_remove(int n) { - return line_remove(serial_lines, - sizeof(serial_lines)/sizeof(serial_lines[0]), n); + return line_remove(serial_lines, + sizeof(serial_lines)/sizeof(serial_lines[0]), n); } int ssl_open(struct tty_struct *tty, struct file *filp) @@ -183,7 +183,7 @@ static int ssl_console_setup(struct console *co, char *options) { struct line *line = &serial_lines[co->index]; - return console_open_chan(line,co,&opts); + return console_open_chan(line, co, &opts); } static struct console ssl_cons = { @@ -199,10 +199,11 @@ int ssl_init(void) { char *new_title; - printk(KERN_INFO "Initializing software serial port version %d\n", + printk(KERN_INFO "Initializing software serial port version %d\n", ssl_version); ssl_driver = line_register_devfs(&lines, &driver, &ssl_ops, - serial_lines, ARRAY_SIZE(serial_lines)); + serial_lines, + ARRAY_SIZE(serial_lines)); lines_init(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0])); @@ -212,7 +213,7 @@ int ssl_init(void) ssl_init_done = 1; register_console(&ssl_cons); - return(0); + return 0; } late_initcall(ssl_init); @@ -227,9 +228,9 @@ __uml_exitcall(ssl_exit); static int ssl_chan_setup(char *str) { - return(line_setup(serial_lines, + return line_setup(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0]), - str, 1)); + str, 1); } __setup("ssl", ssl_chan_setup); diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 005aa6333b6..8f3b168a4b6 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -75,7 +75,7 @@ static struct line_driver driver = { .name = "con", .config = con_config, .get_config = con_get_config, - .id = line_id, + .id = line_id, .remove = con_remove, }, }; @@ -86,23 +86,23 @@ static struct lines console_lines = LINES_INIT(MAX_TTYS); * individual elements are protected by individual semaphores. */ struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), - [ 1 ... MAX_TTYS - 1 ] = + [ 1 ... MAX_TTYS - 1 ] = LINE_INIT(CONFIG_CON_CHAN, &driver) }; static int con_config(char *str) { - return(line_config(vts, sizeof(vts)/sizeof(vts[0]), str)); + return line_config(vts, sizeof(vts)/sizeof(vts[0]), str); } static int con_get_config(char *dev, char *str, int size, char **error_out) { - return(line_get_config(dev, vts, sizeof(vts)/sizeof(vts[0]), str, - size, error_out)); + return line_get_config(dev, vts, sizeof(vts)/sizeof(vts[0]), str, + size, error_out); } static int con_remove(int n) { - return line_remove(vts, sizeof(vts)/sizeof(vts[0]), n); + return line_remove(vts, sizeof(vts)/sizeof(vts[0]), n); } static int con_open(struct tty_struct *tty, struct file *filp) @@ -117,7 +117,7 @@ static struct tty_operations console_ops = { .close = line_close, .write = line_write, .put_char = line_put_char, - .write_room = line_write_room, + .write_room = line_write_room, .chars_in_buffer = line_chars_in_buffer, .flush_buffer = line_flush_buffer, .flush_chars = line_flush_chars, @@ -126,7 +126,7 @@ static struct tty_operations console_ops = { }; static void uml_console_write(struct console *console, const char *string, - unsigned len) + unsigned len) { struct line *line = &vts[console->index]; unsigned long flags; @@ -146,7 +146,7 @@ static int uml_console_setup(struct console *co, char *options) { struct line *line = &vts[co->index]; - return console_open_chan(line,co,&opts); + return console_open_chan(line, co, &opts); } static struct console stdiocons = { @@ -156,7 +156,7 @@ static struct console stdiocons = { .setup = uml_console_setup, .flags = CON_PRINTBUFFER, .index = -1, - .data = &vts, + .data = &vts, }; int stdio_init(void) @@ -166,7 +166,7 @@ int stdio_init(void) console_driver = line_register_devfs(&console_lines, &driver, &console_ops, vts, ARRAY_SIZE(vts)); - if (NULL == console_driver) + if (console_driver == NULL) return -1; printk(KERN_INFO "Initialized stdio console driver\n"); @@ -178,7 +178,7 @@ int stdio_init(void) con_init_done = 1; register_console(&stdiocons); - return(0); + return 0; } late_initcall(stdio_init); @@ -192,7 +192,7 @@ __uml_exitcall(console_exit); static int console_chan_setup(char *str) { - return(line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1)); + return line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1); } __setup("con", console_chan_setup); __channel_help(console_chan_setup, "con"); diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h index da9a6717e7a..9ac06910710 100644 --- a/arch/um/include/chan_kern.h +++ b/arch/um/include/chan_kern.h @@ -47,14 +47,3 @@ extern int chan_config_string(struct list_head *chans, char *str, int size, char **error_out); #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/line.h b/arch/um/include/line.h index 5323d22a6ca..315788ce59f 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -64,8 +64,8 @@ struct line { head : NULL, \ tail : NULL, \ sigio : 0, \ - driver : d, \ - have_irq : 0 } + driver : d, \ + have_irq : 0 } struct lines { int num; @@ -74,11 +74,12 @@ struct lines { #define LINES_INIT(n) { num : n } extern void line_close(struct tty_struct *tty, struct file * filp); -extern int line_open(struct line *lines, struct tty_struct *tty, +extern int line_open(struct line *lines, struct tty_struct *tty, struct chan_opts *opts); extern int line_setup(struct line *lines, unsigned int sizeof_lines, char *init, int all_allowed); -extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len); +extern int line_write(struct tty_struct *tty, const unsigned char *buf, + int len); extern void line_put_char(struct tty_struct *tty, unsigned char ch); extern void line_set_termios(struct tty_struct *tty, struct termios * old); extern int line_chars_in_buffer(struct tty_struct *tty); @@ -89,21 +90,24 @@ extern int line_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg); extern char *add_xterm_umid(char *base); -extern int line_setup_irq(int fd, int input, int output, struct tty_struct *tty); +extern int line_setup_irq(int fd, int input, int output, + struct tty_struct *tty); extern void line_close_chan(struct line *line); extern void line_disable(struct tty_struct *tty, int current_irq); -extern struct tty_driver * line_register_devfs(struct lines *set, - struct line_driver *line_driver, +extern struct tty_driver * line_register_devfs(struct lines *set, + struct line_driver *line_driver, struct tty_operations *driver, struct line *lines, int nlines); extern void lines_init(struct line *lines, int nlines); extern void close_lines(struct line *lines, int nlines); -extern int line_config(struct line *lines, unsigned int sizeof_lines, char *str); +extern int line_config(struct line *lines, unsigned int sizeof_lines, + char *str); extern int line_id(char **str, int *start_out, int *end_out); extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n); -extern int line_get_config(char *dev, struct line *lines, unsigned int sizeof_lines, char *str, +extern int line_get_config(char *dev, struct line *lines, + unsigned int sizeof_lines, char *str, int size, char **error_out); #endif diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index 0b78bb7a994..f897140cc4a 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c @@ -16,12 +16,12 @@ #include "mode.h" struct aio_thread_req { - enum aio_type type; - int io_fd; - unsigned long long offset; - char *buf; - int len; - struct aio_context *aio; + enum aio_type type; + int io_fd; + unsigned long long offset; + char *buf; + int len; + struct aio_context *aio; }; static int aio_req_fd_r = -1; @@ -38,18 +38,18 @@ static int aio_req_fd_w = -1; static long io_setup(int n, aio_context_t *ctxp) { - return syscall(__NR_io_setup, n, ctxp); + return syscall(__NR_io_setup, n, ctxp); } static long io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) { - return syscall(__NR_io_submit, ctx, nr, iocbpp); + return syscall(__NR_io_submit, ctx, nr, iocbpp); } static long io_getevents(aio_context_t ctx_id, long min_nr, long nr, - struct io_event *events, struct timespec *timeout) + struct io_event *events, struct timespec *timeout) { - return syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout); + return syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout); } #endif @@ -66,150 +66,150 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr, */ static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf, - int len, unsigned long long offset, struct aio_context *aio) + int len, unsigned long long offset, struct aio_context *aio) { - struct iocb iocb, *iocbp = &iocb; - char c; - int err; - - iocb = ((struct iocb) { .aio_data = (unsigned long) aio, - .aio_reqprio = 0, - .aio_fildes = fd, - .aio_buf = (unsigned long) buf, - .aio_nbytes = len, - .aio_offset = offset, - .aio_reserved1 = 0, - .aio_reserved2 = 0, - .aio_reserved3 = 0 }); - - switch(type){ - case AIO_READ: - iocb.aio_lio_opcode = IOCB_CMD_PREAD; - err = io_submit(ctx, 1, &iocbp); - break; - case AIO_WRITE: - iocb.aio_lio_opcode = IOCB_CMD_PWRITE; - err = io_submit(ctx, 1, &iocbp); - break; - case AIO_MMAP: - iocb.aio_lio_opcode = IOCB_CMD_PREAD; - iocb.aio_buf = (unsigned long) &c; - iocb.aio_nbytes = sizeof(c); - err = io_submit(ctx, 1, &iocbp); - break; - default: - printk("Bogus op in do_aio - %d\n", type); - err = -EINVAL; - break; - } - - if(err > 0) - err = 0; + struct iocb iocb, *iocbp = &iocb; + char c; + int err; + + iocb = ((struct iocb) { .aio_data = (unsigned long) aio, + .aio_reqprio = 0, + .aio_fildes = fd, + .aio_buf = (unsigned long) buf, + .aio_nbytes = len, + .aio_offset = offset, + .aio_reserved1 = 0, + .aio_reserved2 = 0, + .aio_reserved3 = 0 }); + + switch(type){ + case AIO_READ: + iocb.aio_lio_opcode = IOCB_CMD_PREAD; + err = io_submit(ctx, 1, &iocbp); + break; + case AIO_WRITE: + iocb.aio_lio_opcode = IOCB_CMD_PWRITE; + err = io_submit(ctx, 1, &iocbp); + break; + case AIO_MMAP: + iocb.aio_lio_opcode = IOCB_CMD_PREAD; + iocb.aio_buf = (unsigned long) &c; + iocb.aio_nbytes = sizeof(c); + err = io_submit(ctx, 1, &iocbp); + break; + default: + printk("Bogus op in do_aio - %d\n", type); + err = -EINVAL; + break; + } + + if(err > 0) + err = 0; else err = -errno; - return err; + return err; } static aio_context_t ctx = 0; static int aio_thread(void *arg) { - struct aio_thread_reply reply; - struct io_event event; - int err, n, reply_fd; - - signal(SIGWINCH, SIG_IGN); - - while(1){ - n = io_getevents(ctx, 1, 1, &event, NULL); - if(n < 0){ - if(errno == EINTR) - continue; - printk("aio_thread - io_getevents failed, " - "errno = %d\n", errno); - } - else { - reply = ((struct aio_thread_reply) - { .data = (void *) (long) event.data, - .err = event.res }); + struct aio_thread_reply reply; + struct io_event event; + int err, n, reply_fd; + + signal(SIGWINCH, SIG_IGN); + + while(1){ + n = io_getevents(ctx, 1, 1, &event, NULL); + if(n < 0){ + if(errno == EINTR) + continue; + printk("aio_thread - io_getevents failed, " + "errno = %d\n", errno); + } + else { + reply = ((struct aio_thread_reply) + { .data = (void *) (long) event.data, + .err = event.res }); reply_fd = ((struct aio_context *) reply.data)->reply_fd; err = os_write_file(reply_fd, &reply, sizeof(reply)); - if(err != sizeof(reply)) + if(err != sizeof(reply)) printk("aio_thread - write failed, fd = %d, " - "err = %d\n", aio_req_fd_r, -err); - } - } - return 0; + "err = %d\n", aio_req_fd_r, -err); + } + } + return 0; } #endif static int do_not_aio(struct aio_thread_req *req) { - char c; - int err; - - switch(req->type){ - case AIO_READ: - err = os_seek_file(req->io_fd, req->offset); - if(err) - goto out; - - err = os_read_file(req->io_fd, req->buf, req->len); - break; - case AIO_WRITE: - err = os_seek_file(req->io_fd, req->offset); - if(err) - goto out; - - err = os_write_file(req->io_fd, req->buf, req->len); - break; - case AIO_MMAP: - err = os_seek_file(req->io_fd, req->offset); - if(err) - goto out; - - err = os_read_file(req->io_fd, &c, sizeof(c)); - break; - default: - printk("do_not_aio - bad request type : %d\n", req->type); - err = -EINVAL; - break; - } - - out: - return err; + char c; + int err; + + switch(req->type){ + case AIO_READ: + err = os_seek_file(req->io_fd, req->offset); + if(err) + goto out; + + err = os_read_file(req->io_fd, req->buf, req->len); + break; + case AIO_WRITE: + err = os_seek_file(req->io_fd, req->offset); + if(err) + goto out; + + err = os_write_file(req->io_fd, req->buf, req->len); + break; + case AIO_MMAP: + err = os_seek_file(req->io_fd, req->offset); + if(err) + goto out; + + err = os_read_file(req->io_fd, &c, sizeof(c)); + break; + default: + printk("do_not_aio - bad request type : %d\n", req->type); + err = -EINVAL; + break; + } + +out: + return err; } static int not_aio_thread(void *arg) { - struct aio_thread_req req; - struct aio_thread_reply reply; - int err; - - signal(SIGWINCH, SIG_IGN); - while(1){ - err = os_read_file(aio_req_fd_r, &req, sizeof(req)); - if(err != sizeof(req)){ - if(err < 0) - printk("not_aio_thread - read failed, " - "fd = %d, err = %d\n", aio_req_fd_r, - -err); - else { - printk("not_aio_thread - short read, fd = %d, " - "length = %d\n", aio_req_fd_r, err); - } - continue; - } - err = do_not_aio(&req); - reply = ((struct aio_thread_reply) { .data = req.aio, - .err = err }); - err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply)); - if(err != sizeof(reply)) - printk("not_aio_thread - write failed, fd = %d, " - "err = %d\n", aio_req_fd_r, -err); - } + struct aio_thread_req req; + struct aio_thread_reply reply; + int err; + + signal(SIGWINCH, SIG_IGN); + while(1){ + err = os_read_file(aio_req_fd_r, &req, sizeof(req)); + if(err != sizeof(req)){ + if(err < 0) + printk("not_aio_thread - read failed, " + "fd = %d, err = %d\n", aio_req_fd_r, + -err); + else { + printk("not_aio_thread - short read, fd = %d, " + "length = %d\n", aio_req_fd_r, err); + } + continue; + } + err = do_not_aio(&req); + reply = ((struct aio_thread_reply) { .data = req.aio, + .err = err }); + err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply)); + if(err != sizeof(reply)) + printk("not_aio_thread - write failed, fd = %d, " + "err = %d\n", aio_req_fd_r, -err); + } return 0; } @@ -218,93 +218,93 @@ static int aio_pid = -1; static int init_aio_24(void) { - unsigned long stack; - int fds[2], err; - - err = os_pipe(fds, 1, 1); - if(err) - goto out; - - aio_req_fd_w = fds[0]; - aio_req_fd_r = fds[1]; - err = run_helper_thread(not_aio_thread, NULL, - CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); - if(err < 0) - goto out_close_pipe; - - aio_pid = err; - goto out; - - out_close_pipe: - os_close_file(fds[0]); - os_close_file(fds[1]); - aio_req_fd_w = -1; - aio_req_fd_r = -1; - out: + unsigned long stack; + int fds[2], err; + + err = os_pipe(fds, 1, 1); + if(err) + goto out; + + aio_req_fd_w = fds[0]; + aio_req_fd_r = fds[1]; + err = run_helper_thread(not_aio_thread, NULL, + CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); + if(err < 0) + goto out_close_pipe; + + aio_pid = err; + goto out; + +out_close_pipe: + os_close_file(fds[0]); + os_close_file(fds[1]); + aio_req_fd_w = -1; + aio_req_fd_r = -1; +out: #ifndef HAVE_AIO_ABI printk("/usr/include/linux/aio_abi.h not present during build\n"); #endif printk("2.6 host AIO support not used - falling back to I/O " "thread\n"); - return 0; + return 0; } #ifdef HAVE_AIO_ABI #define DEFAULT_24_AIO 0 static int init_aio_26(void) { - unsigned long stack; - int err; + unsigned long stack; + int err; - if(io_setup(256, &ctx)){ + if(io_setup(256, &ctx)){ err = -errno; - printk("aio_thread failed to initialize context, err = %d\n", - errno); - return err; - } + printk("aio_thread failed to initialize context, err = %d\n", + errno); + return err; + } - err = run_helper_thread(aio_thread, NULL, - CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); - if(err < 0) - return err; + err = run_helper_thread(aio_thread, NULL, + CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); + if(err < 0) + return err; - aio_pid = err; + aio_pid = err; printk("Using 2.6 host AIO\n"); - return 0; + return 0; } static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, unsigned long long offset, struct aio_context *aio) { - struct aio_thread_reply reply; - int err; - - err = do_aio(ctx, type, io_fd, buf, len, offset, aio); - if(err){ - reply = ((struct aio_thread_reply) { .data = aio, - .err = err }); - err = os_write_file(aio->reply_fd, &reply, sizeof(reply)); - if(err != sizeof(reply)) - printk("submit_aio_26 - write failed, " - "fd = %d, err = %d\n", aio->reply_fd, -err); - else err = 0; - } - - return err; + struct aio_thread_reply reply; + int err; + + err = do_aio(ctx, type, io_fd, buf, len, offset, aio); + if(err){ + reply = ((struct aio_thread_reply) { .data = aio, + .err = err }); + err = os_write_file(aio->reply_fd, &reply, sizeof(reply)); + if(err != sizeof(reply)) + printk("submit_aio_26 - write failed, " + "fd = %d, err = %d\n", aio->reply_fd, -err); + else err = 0; + } + + return err; } #else #define DEFAULT_24_AIO 1 static int init_aio_26(void) { - return -ENOSYS; + return -ENOSYS; } static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, unsigned long long offset, struct aio_context *aio) { - return -ENOSYS; + return -ENOSYS; } #endif @@ -312,8 +312,8 @@ static int aio_24 = DEFAULT_24_AIO; static int __init set_aio_24(char *name, int *add) { - aio_24 = 1; - return 0; + aio_24 = 1; + return 0; } __uml_setup("aio=2.4", set_aio_24, @@ -330,28 +330,27 @@ __uml_setup("aio=2.4", set_aio_24, static int init_aio(void) { - int err; - - CHOOSE_MODE(({ - if(!aio_24){ - printk("Disabling 2.6 AIO in tt mode\n"); - aio_24 = 1; - } }), (void) 0); - - if(!aio_24){ - err = init_aio_26(); - if(err && (errno == ENOSYS)){ - printk("2.6 AIO not supported on the host - " - "reverting to 2.4 AIO\n"); - aio_24 = 1; - } - else return err; - } - - if(aio_24) - return init_aio_24(); - - return 0; + int err; + + CHOOSE_MODE(({ if(!aio_24){ + printk("Disabling 2.6 AIO in tt mode\n"); + aio_24 = 1; + } }), (void) 0); + + if(!aio_24){ + err = init_aio_26(); + if(err && (errno == ENOSYS)){ + printk("2.6 AIO not supported on the host - " + "reverting to 2.4 AIO\n"); + aio_24 = 1; + } + else return err; + } + + if(aio_24) + return init_aio_24(); + + return 0; } /* The reason for the __initcall/__uml_exitcall asymmetry is that init_aio @@ -364,8 +363,8 @@ __initcall(init_aio); static void exit_aio(void) { - if(aio_pid != -1) - os_kill_process(aio_pid, 1); + if(aio_pid != -1) + os_kill_process(aio_pid, 1); } __uml_exitcall(exit_aio); @@ -373,30 +372,30 @@ __uml_exitcall(exit_aio); static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len, unsigned long long offset, struct aio_context *aio) { - struct aio_thread_req req = { .type = type, - .io_fd = io_fd, - .offset = offset, - .buf = buf, - .len = len, - .aio = aio, - }; - int err; - - err = os_write_file(aio_req_fd_w, &req, sizeof(req)); - if(err == sizeof(req)) - err = 0; - - return err; + struct aio_thread_req req = { .type = type, + .io_fd = io_fd, + .offset = offset, + .buf = buf, + .len = len, + .aio = aio, + }; + int err; + + err = os_write_file(aio_req_fd_w, &req, sizeof(req)); + if(err == sizeof(req)) + err = 0; + + return err; } int submit_aio(enum aio_type type, int io_fd, char *buf, int len, - unsigned long long offset, int reply_fd, - struct aio_context *aio) + unsigned long long offset, int reply_fd, + struct aio_context *aio) { - aio->reply_fd = reply_fd; - if(aio_24) - return submit_aio_24(type, io_fd, buf, len, offset, aio); - else { - return submit_aio_26(type, io_fd, buf, len, offset, aio); - } + aio->reply_fd = reply_fd; + if(aio_24) + return submit_aio_24(type, io_fd, buf, len, offset, aio); + else { + return submit_aio_26(type, io_fd, buf, len, offset, aio); + } } -- cgit v1.2.3 From 0834cc77af6a8a650f803d4a7c3c0f134b366f87 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:18:51 -0800 Subject: [PATCH] uml: use ARRAY_SIZE This patch replaces instances of "sizeof(foo)/sizeof(foo[0])" with ARRAY_SIZE(foo), which expands to the same thing. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/ssl.c | 20 +++++++------------- arch/um/drivers/stdio_console.c | 13 ++++++------- 2 files changed, 13 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index 95a3eaa7163..8564784cd2e 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -84,21 +84,18 @@ static struct lines lines = LINES_INIT(NR_PORTS); static int ssl_config(char *str) { - return line_config(serial_lines, - sizeof(serial_lines)/sizeof(serial_lines[0]), str); + return line_config(serial_lines, ARRAY_SIZE(serial_lines), str); } static int ssl_get_config(char *dev, char *str, int size, char **error_out) { - return line_get_config(dev, serial_lines, - sizeof(serial_lines)/sizeof(serial_lines[0]), - str, size, error_out); + return line_get_config(dev, serial_lines, ARRAY_SIZE(serial_lines), str, + size, error_out); } static int ssl_remove(int n) { - return line_remove(serial_lines, - sizeof(serial_lines)/sizeof(serial_lines[0]), n); + return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n); } int ssl_open(struct tty_struct *tty, struct file *filp) @@ -205,7 +202,7 @@ int ssl_init(void) serial_lines, ARRAY_SIZE(serial_lines)); - lines_init(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0])); + lines_init(serial_lines, ARRAY_SIZE(serial_lines)); new_title = add_xterm_umid(opts.xterm_title); if (new_title != NULL) @@ -221,16 +218,13 @@ static void ssl_exit(void) { if (!ssl_init_done) return; - close_lines(serial_lines, - sizeof(serial_lines)/sizeof(serial_lines[0])); + close_lines(serial_lines, ARRAY_SIZE(serial_lines)); } __uml_exitcall(ssl_exit); static int ssl_chan_setup(char *str) { - return line_setup(serial_lines, - sizeof(serial_lines)/sizeof(serial_lines[0]), - str, 1); + return line_setup(serial_lines, ARRAY_SIZE(serial_lines), str, 1); } __setup("ssl", ssl_chan_setup); diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 8f3b168a4b6..b77f7d2ab83 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -91,18 +91,17 @@ struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), static int con_config(char *str) { - return line_config(vts, sizeof(vts)/sizeof(vts[0]), str); + return line_config(vts, ARRAY_SIZE(vts), str); } static int con_get_config(char *dev, char *str, int size, char **error_out) { - return line_get_config(dev, vts, sizeof(vts)/sizeof(vts[0]), str, - size, error_out); + return line_get_config(dev, vts, ARRAY_SIZE(vts), str, size, error_out); } static int con_remove(int n) { - return line_remove(vts, sizeof(vts)/sizeof(vts[0]), n); + return line_remove(vts, ARRAY_SIZE(vts), n); } static int con_open(struct tty_struct *tty, struct file *filp) @@ -170,7 +169,7 @@ int stdio_init(void) return -1; printk(KERN_INFO "Initialized stdio console driver\n"); - lines_init(vts, sizeof(vts)/sizeof(vts[0])); + lines_init(vts, ARRAY_SIZE(vts)); new_title = add_xterm_umid(opts.xterm_title); if(new_title != NULL) @@ -186,13 +185,13 @@ static void console_exit(void) { if (!con_init_done) return; - close_lines(vts, sizeof(vts)/sizeof(vts[0])); + close_lines(vts, ARRAY_SIZE(vts)); } __uml_exitcall(console_exit); static int console_chan_setup(char *str) { - return line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1); + return line_setup(vts, ARRAY_SIZE(vts), str, 1); } __setup("con", console_chan_setup); __channel_help(console_chan_setup, "con"); -- cgit v1.2.3 From 88890b88742debb97006df264b653d18acdc80d0 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:18:52 -0800 Subject: [PATCH] uml: Remove unneeded structure field This removes a structure field which turned out to be pointless, and references to it. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/chan_kern.c | 16 ++++++---------- arch/um/drivers/line.c | 2 +- arch/um/include/chan_kern.h | 5 ++--- 3 files changed, 9 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 8b1262e9fb6..59c9b3f7c84 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -315,7 +315,7 @@ int console_open_chan(struct line *line, struct console *co, return 0; if (0 != parse_chan_pair(line->init_str, &line->chan_list, - line->init_pri, co->index, opts)) + co->index, opts)) return -1; if (0 != open_chan(&line->chan_list)) return -1; @@ -468,8 +468,7 @@ struct chan_type chan_table[] = { #endif }; -static struct chan *parse_chan(char *str, int pri, int device, - struct chan_opts *opts) +static struct chan *parse_chan(char *str, int device, struct chan_opts *opts) { struct chan_type *entry; struct chan_ops *ops; @@ -507,13 +506,12 @@ static struct chan *parse_chan(char *str, int pri, int device, .output = 0, .opened = 0, .fd = -1, - .pri = pri, .ops = ops, .data = data }); return chan; } -int parse_chan_pair(char *str, struct list_head *chans, int pri, int device, +int parse_chan_pair(char *str, struct list_head *chans, int device, struct chan_opts *opts) { struct chan *new, *chan; @@ -521,8 +519,6 @@ int parse_chan_pair(char *str, struct list_head *chans, int pri, int device, if(!list_empty(chans)){ chan = list_entry(chans->next, struct chan, list); - if(chan->pri >= pri) - return 0; free_chan(chans); INIT_LIST_HEAD(chans); } @@ -532,14 +528,14 @@ int parse_chan_pair(char *str, struct list_head *chans, int pri, int device, in = str; *out = '\0'; out++; - new = parse_chan(in, pri, device, opts); + new = parse_chan(in, device, opts); if(new == NULL) return -1; new->input = 1; list_add(&new->list, chans); - new = parse_chan(out, pri, device, opts); + new = parse_chan(out, device, opts); if(new == NULL) return -1; @@ -547,7 +543,7 @@ int parse_chan_pair(char *str, struct list_head *chans, int pri, int device, new->output = 1; } else { - new = parse_chan(str, pri, device, opts); + new = parse_chan(str, device, opts); if(new == NULL) return -1; diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 2ee00cbe8f9..80ade224d74 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -438,7 +438,7 @@ int line_open(struct line *lines, struct tty_struct *tty, } if (list_empty(&line->chan_list)) { err = parse_chan_pair(line->init_str, &line->chan_list, - line->init_pri, tty->index, opts); + tty->index, opts); if(err) goto out; err = open_chan(&line->chan_list); if(err) goto out; diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h index 9ac06910710..22bf3a73437 100644 --- a/arch/um/include/chan_kern.h +++ b/arch/um/include/chan_kern.h @@ -20,15 +20,14 @@ struct chan { unsigned int output:1; unsigned int opened:1; int fd; - enum chan_init_pri pri; struct chan_ops *ops; void *data; }; extern void chan_interrupt(struct list_head *chans, struct work_struct *task, struct tty_struct *tty, int irq); -extern int parse_chan_pair(char *str, struct list_head *chans, int pri, - int device, struct chan_opts *opts); +extern int parse_chan_pair(char *str, struct list_head *chans, int device, + struct chan_opts *opts); extern int open_chan(struct list_head *chans); extern int write_chan(struct list_head *chans, const char *buf, int len, int write_irq); -- cgit v1.2.3 From d571cd18f225542460b5d9b83e5e0d507be71656 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:18:53 -0800 Subject: [PATCH] uml: Move mconsole support out of generic code A bit of restructuring which eliminates the all_allowed argument (which is mconsole-specific) to line_setup. That logic is moved to the mconsole callback. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/line.c | 21 ++++++++++----------- arch/um/drivers/ssl.c | 2 +- arch/um/drivers/stdio_console.c | 2 +- arch/um/include/line.h | 4 ++-- 4 files changed, 14 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 80ade224d74..9af55ece198 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -500,11 +500,9 @@ void close_lines(struct line *lines, int nlines) /* Common setup code for both startup command line and mconsole initialization. * @lines contains the the array (of size @num) to modify; * @init is the setup string; - * @all_allowed is a boolean saying if we can setup the whole @lines - * at once. For instance, it will be usually true for startup init. (where we - * can use con=xterm) and false for mconsole.*/ + */ -int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed) +int line_setup(struct line *lines, unsigned int num, char *init) { int i, n; char *end; @@ -545,11 +543,6 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed } } } - else if(!all_allowed){ - printk("line_setup - can't configure all devices from " - "mconsole\n"); - return 0; - } else { for(i = 0; i < num; i++){ if(lines[i].init_pri <= INIT_ALL){ @@ -569,12 +562,18 @@ int line_config(struct line *lines, unsigned int num, char *str) { char *new; + if(*str == '='){ + printk("line_config - can't configure all devices from " + "mconsole\n"); + return 1; + } + new = kstrdup(str, GFP_KERNEL); if(new == NULL){ printk("line_config - kstrdup failed\n"); return -ENOMEM; } - return !line_setup(lines, num, new, 0); + return !line_setup(lines, num, new); } int line_get_config(char *name, struct line *lines, unsigned int num, char *str, @@ -628,7 +627,7 @@ int line_remove(struct line *lines, unsigned int num, int n) char config[sizeof("conxxxx=none\0")]; sprintf(config, "%d=none", n); - return !line_setup(lines, num, config, 0); + return !line_setup(lines, num, config); } struct tty_driver *line_register_devfs(struct lines *set, diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index 8564784cd2e..e1895d9babb 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -224,7 +224,7 @@ __uml_exitcall(ssl_exit); static int ssl_chan_setup(char *str) { - return line_setup(serial_lines, ARRAY_SIZE(serial_lines), str, 1); + return line_setup(serial_lines, ARRAY_SIZE(serial_lines), str); } __setup("ssl", ssl_chan_setup); diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index b77f7d2ab83..72000d3a19e 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -191,7 +191,7 @@ __uml_exitcall(console_exit); static int console_chan_setup(char *str) { - return line_setup(vts, ARRAY_SIZE(vts), str, 1); + return line_setup(vts, ARRAY_SIZE(vts), str); } __setup("con", console_chan_setup); __channel_help(console_chan_setup, "con"); diff --git a/arch/um/include/line.h b/arch/um/include/line.h index 315788ce59f..e22c9e0f2d0 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -76,8 +76,8 @@ struct lines { extern void line_close(struct tty_struct *tty, struct file * filp); extern int line_open(struct line *lines, struct tty_struct *tty, struct chan_opts *opts); -extern int line_setup(struct line *lines, unsigned int sizeof_lines, char *init, - int all_allowed); +extern int line_setup(struct line *lines, unsigned int sizeof_lines, + char *init); extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len); extern void line_put_char(struct tty_struct *tty, unsigned char ch); -- cgit v1.2.3 From 9010772cdff36072dd509ec72c1a55fccde8e58e Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:18:54 -0800 Subject: [PATCH] uml: Add static initializations and declarations Some structure fields were being dynamically initialized when they could be initialized at compile-time instead. This also makes some declarations static (in the C sense). Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/line.c | 7 +++---- arch/um/drivers/mconsole_kern.c | 6 +++--- arch/um/drivers/net_kern.c | 4 ++-- arch/um/include/line.h | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 9af55ece198..1c2cc5d48bb 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -668,19 +668,18 @@ struct tty_driver *line_register_devfs(struct lines *set, return driver; } -static spinlock_t winch_handler_lock; -LIST_HEAD(winch_handlers); +static DEFINE_SPINLOCK(winch_handler_lock); +static LIST_HEAD(winch_handlers); void lines_init(struct line *lines, int nlines) { struct line *line; int i; - spin_lock_init(&winch_handler_lock); for(i = 0; i < nlines; i++){ line = &lines[i]; INIT_LIST_HEAD(&line->chan_list); - spin_lock_init(&line->lock); + if(line->init_str == NULL) continue; diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 355866af5e0..b5217bd7bc4 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -51,7 +51,7 @@ static struct notifier_block reboot_notifier = { * itself and it can only happen on CPU 0. */ -LIST_HEAD(mc_requests); +static LIST_HEAD(mc_requests); static void mc_work_proc(void *unused) { @@ -69,7 +69,7 @@ static void mc_work_proc(void *unused) } } -DECLARE_WORK(mconsole_work, mc_work_proc, NULL); +static DECLARE_WORK(mconsole_work, mc_work_proc, NULL); static irqreturn_t mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs) @@ -535,7 +535,7 @@ void mconsole_stack(struct mc_request *req) */ static char *notify_socket = NULL; -int mconsole_init(void) +static int mconsole_init(void) { /* long to avoid size mismatch warnings from gcc */ long sock; diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 29785f64302..deb24828e6a 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -34,7 +34,7 @@ #define DRIVER_NAME "uml-netdev" static DEFINE_SPINLOCK(opened_lock); -LIST_HEAD(opened); +static LIST_HEAD(opened); static int uml_net_rx(struct net_device *dev) { @@ -266,7 +266,7 @@ void uml_net_user_timer_expire(unsigned long _conn) } static DEFINE_SPINLOCK(devices_lock); -static struct list_head devices = LIST_HEAD_INIT(devices); +static LIST_HEAD(devices); static struct platform_driver uml_net_driver = { .driver = { diff --git a/arch/um/include/line.h b/arch/um/include/line.h index e22c9e0f2d0..351d3ac30b7 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -58,8 +58,8 @@ struct line { #define LINE_INIT(str, d) \ { init_str : str, \ init_pri : INIT_STATIC, \ - chan_list : { }, \ valid : 1, \ + lock : SPIN_LOCK_UNLOCKED, \ buffer : NULL, \ head : NULL, \ tail : NULL, \ -- cgit v1.2.3 From 418e55d49b0ec7d2e7a033f2dd083f5b2ab7d119 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:18:54 -0800 Subject: [PATCH] uml: line_setup interface change line_setup is changed to return the device which it set up, rather than just success or failure. This will be important in the line-config patch. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/line.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 1c2cc5d48bb..1352a212964 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -555,12 +555,13 @@ int line_setup(struct line *lines, unsigned int num, char *init) } } } - return 1; + return n == -1 ? num : n; } int line_config(struct line *lines, unsigned int num, char *str) { char *new; + int n; if(*str == '='){ printk("line_config - can't configure all devices from " @@ -573,7 +574,8 @@ int line_config(struct line *lines, unsigned int num, char *str) printk("line_config - kstrdup failed\n"); return -ENOMEM; } - return !line_setup(lines, num, new); + n = line_setup(lines, num, new); + return n < 0 ? n : 0; } int line_get_config(char *name, struct line *lines, unsigned int num, char *str, @@ -624,10 +626,14 @@ int line_id(char **str, int *start_out, int *end_out) int line_remove(struct line *lines, unsigned int num, int n) { + int err; char config[sizeof("conxxxx=none\0")]; sprintf(config, "%d=none", n); - return !line_setup(lines, num, config); + err = line_setup(lines, num, config); + if(err >= 0) + err = 0; + return err; } struct tty_driver *line_register_devfs(struct lines *set, -- cgit v1.2.3 From 1f80171e81ed0d08dcdb6efe239d7b929aef498f Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:18:55 -0800 Subject: [PATCH] uml: move console configuration This patch changes when console devices are configured in order to prepare the ground for the next patch. parse_chan_pair is now done earlier, when initcalls are run, rather than when the device is opened. When a host device disappears, the channel list is closed, but not freed. This is required by the previous change. line_config now takes the options structure as an argument, and line_open doesn't. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/chan_kern.c | 14 +++++--------- arch/um/drivers/line.c | 34 +++++++++++++++++++++------------- arch/um/drivers/ssl.c | 6 +++--- arch/um/drivers/stdio_console.c | 6 +++--- arch/um/include/line.h | 7 +++---- 5 files changed, 35 insertions(+), 32 deletions(-) (limited to 'arch') diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 59c9b3f7c84..31b69c4ea80 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -311,14 +311,12 @@ int console_write_chan(struct list_head *chans, const char *buf, int len) int console_open_chan(struct line *line, struct console *co, struct chan_opts *opts) { - if (!list_empty(&line->chan_list)) - return 0; + int err; + + err = open_chan(&line->chan_list); + if(err) + return err; - if (0 != parse_chan_pair(line->init_str, &line->chan_list, - co->index, opts)) - return -1; - if (0 != open_chan(&line->chan_list)) - return -1; printk("Console initialized on /dev/%s%d\n",co->name,co->index); return 0; } @@ -596,13 +594,11 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task, tty_hangup(tty); line_disable(tty, irq); close_chan(chans); - free_chan(chans); return; } else { if(chan->ops->close != NULL) chan->ops->close(chan->fd, chan->data); - free_one_chan(chan); } } } diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 1352a212964..da81d22ec04 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -419,8 +419,7 @@ void line_disable(struct tty_struct *tty, int current_irq) line->have_irq = 0; } -int line_open(struct line *lines, struct tty_struct *tty, - struct chan_opts *opts) +int line_open(struct line *lines, struct tty_struct *tty) { struct line *line; int err = 0; @@ -436,13 +435,11 @@ int line_open(struct line *lines, struct tty_struct *tty, err = -ENODEV; goto out; } - if (list_empty(&line->chan_list)) { - err = parse_chan_pair(line->init_str, &line->chan_list, - tty->index, opts); - if(err) goto out; - err = open_chan(&line->chan_list); - if(err) goto out; - } + + err = open_chan(&line->chan_list); + if(err) + goto out; + /* Here the interrupt is registered.*/ enable_chan(&line->chan_list, tty); INIT_WORK(&line->task, line_timer_cb, tty); @@ -558,8 +555,10 @@ int line_setup(struct line *lines, unsigned int num, char *init) return n == -1 ? num : n; } -int line_config(struct line *lines, unsigned int num, char *str) +int line_config(struct line *lines, unsigned int num, char *str, + struct chan_opts *opts) { + struct line *line; char *new; int n; @@ -572,10 +571,14 @@ int line_config(struct line *lines, unsigned int num, char *str) new = kstrdup(str, GFP_KERNEL); if(new == NULL){ printk("line_config - kstrdup failed\n"); - return -ENOMEM; + return 1; } n = line_setup(lines, num, new); - return n < 0 ? n : 0; + if(n < 0) + return 1; + + line = &lines[n]; + return parse_chan_pair(line->init_str, &line->chan_list, n, opts); } int line_get_config(char *name, struct line *lines, unsigned int num, char *str, @@ -677,7 +680,7 @@ struct tty_driver *line_register_devfs(struct lines *set, static DEFINE_SPINLOCK(winch_handler_lock); static LIST_HEAD(winch_handlers); -void lines_init(struct line *lines, int nlines) +void lines_init(struct line *lines, int nlines, struct chan_opts *opts) { struct line *line; int i; @@ -692,6 +695,11 @@ void lines_init(struct line *lines, int nlines) line->init_str = kstrdup(line->init_str, GFP_KERNEL); if(line->init_str == NULL) printk("lines_init - kstrdup returned NULL\n"); + + if(parse_chan_pair(line->init_str, &line->chan_list, i, opts)){ + printk("parse_chan_pair failed for device %d\n", i); + line->valid = 0; + } } } diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index e1895d9babb..6823dc5d665 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -84,7 +84,7 @@ static struct lines lines = LINES_INIT(NR_PORTS); static int ssl_config(char *str) { - return line_config(serial_lines, ARRAY_SIZE(serial_lines), str); + return line_config(serial_lines, ARRAY_SIZE(serial_lines), str, &opts); } static int ssl_get_config(char *dev, char *str, int size, char **error_out) @@ -100,7 +100,7 @@ static int ssl_remove(int n) int ssl_open(struct tty_struct *tty, struct file *filp) { - return line_open(serial_lines, tty, &opts); + return line_open(serial_lines, tty); } #if 0 @@ -202,7 +202,7 @@ int ssl_init(void) serial_lines, ARRAY_SIZE(serial_lines)); - lines_init(serial_lines, ARRAY_SIZE(serial_lines)); + lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts); new_title = add_xterm_umid(opts.xterm_title); if (new_title != NULL) diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 72000d3a19e..6d4edda9b51 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -91,7 +91,7 @@ struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), static int con_config(char *str) { - return line_config(vts, ARRAY_SIZE(vts), str); + return line_config(vts, ARRAY_SIZE(vts), str, &opts); } static int con_get_config(char *dev, char *str, int size, char **error_out) @@ -106,7 +106,7 @@ static int con_remove(int n) static int con_open(struct tty_struct *tty, struct file *filp) { - return line_open(vts, tty, &opts); + return line_open(vts, tty); } static int con_init_done = 0; @@ -169,7 +169,7 @@ int stdio_init(void) return -1; printk(KERN_INFO "Initialized stdio console driver\n"); - lines_init(vts, ARRAY_SIZE(vts)); + lines_init(vts, ARRAY_SIZE(vts), &opts); new_title = add_xterm_umid(opts.xterm_title); if(new_title != NULL) diff --git a/arch/um/include/line.h b/arch/um/include/line.h index 351d3ac30b7..474398ba120 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -74,8 +74,7 @@ struct lines { #define LINES_INIT(n) { num : n } extern void line_close(struct tty_struct *tty, struct file * filp); -extern int line_open(struct line *lines, struct tty_struct *tty, - struct chan_opts *opts); +extern int line_open(struct line *lines, struct tty_struct *tty); extern int line_setup(struct line *lines, unsigned int sizeof_lines, char *init); extern int line_write(struct tty_struct *tty, const unsigned char *buf, @@ -99,11 +98,11 @@ extern struct tty_driver * line_register_devfs(struct lines *set, struct tty_operations *driver, struct line *lines, int nlines); -extern void lines_init(struct line *lines, int nlines); +extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts); extern void close_lines(struct line *lines, int nlines); extern int line_config(struct line *lines, unsigned int sizeof_lines, - char *str); + char *str, struct chan_opts *opts); extern int line_id(char **str, int *start_out, int *end_out); extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n); extern int line_get_config(char *dev, struct line *lines, -- cgit v1.2.3 From 165dc5911627a9c4752e909a0da661b96b6fd269 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:18:57 -0800 Subject: [PATCH] uml: Simplify console opening/closing and irq registration This patch simplifies the opening and closing of host console devices and the registration and deregistration of IRQs. The intent is to make it obvious that an IRQ can't exist without an open file descriptor. chan_enable will now open the channel, and when both opening and IRQ registration are desired, this should be used. Opening only is done for the initial console, so that interface still needs to exist. The free_irqs_later interface is now gone. It was intended to avoid freeing an IRQ while it was being processed. It did this, but it didn't eliminate the possiblity of free_irq being called from an interrupt, which is bad. In its place is a list of irqs to be freed, which is processed by the signal handler just before exiting. close_one_chan now disables irqs. When a host device disappears, it is just closed, and that disables IRQs. The device id registered with the IRQ is now the chan structure, not the tty. This is because the interrupt arrives on a descriptor associated with the channel. This caused equivalent changes in the arguments to line_timer_cb. line_disable is gone since it is not used any more. The count field in the line structure is gone. tty->count is used instead. The complicated logic in sigio_handler with freeing IRQs when necessary and making sure its idea of the next irq is correct is now much simpler. The irq list can't be rearranged underneath it, so it is now a simple list walk. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/chan_kern.c | 111 +++++++++++++++++++++++++++--------------- arch/um/drivers/line.c | 116 ++++++++++++++++++-------------------------- arch/um/include/chan_kern.h | 9 ++-- arch/um/include/irq_user.h | 13 +---- arch/um/include/line.h | 6 +-- arch/um/kernel/irq_user.c | 48 +++--------------- 6 files changed, 137 insertions(+), 166 deletions(-) (limited to 'arch') diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 31b69c4ea80..1bb920c0d77 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -240,20 +240,65 @@ void chan_enable_winch(struct list_head *chans, struct tty_struct *tty) } } -void enable_chan(struct list_head *chans, struct tty_struct *tty) +void enable_chan(struct line *line) { struct list_head *ele; struct chan *chan; - list_for_each(ele, chans){ + list_for_each(ele, &line->chan_list){ chan = list_entry(ele, struct chan, list); - if(!chan->opened) continue; + if(open_one_chan(chan)) + continue; + + if(chan->enabled) + continue; + line_setup_irq(chan->fd, chan->input, chan->output, line, + chan); + chan->enabled = 1; + } +} + +static LIST_HEAD(irqs_to_free); + +void free_irqs(void) +{ + struct chan *chan; + + while(!list_empty(&irqs_to_free)){ + chan = list_entry(irqs_to_free.next, struct chan, free_list); + list_del(&chan->free_list); + + if(chan->input) + free_irq(chan->line->driver->read_irq, chan); + if(chan->output) + free_irq(chan->line->driver->write_irq, chan); + chan->enabled = 0; + } +} + +static void close_one_chan(struct chan *chan, int delay_free_irq) +{ + if(!chan->opened) + return; - line_setup_irq(chan->fd, chan->input, chan->output, tty); + if(delay_free_irq){ + list_add(&chan->free_list, &irqs_to_free); + } + else { + if(chan->input) + free_irq(chan->line->driver->read_irq, chan); + if(chan->output) + free_irq(chan->line->driver->write_irq, chan); + chan->enabled = 0; } + if(chan->ops->close != NULL) + (*chan->ops->close)(chan->fd, chan->data); + + chan->opened = 0; + chan->fd = -1; } -void close_chan(struct list_head *chans) +void close_chan(struct list_head *chans, int delay_free_irq) { struct chan *chan; @@ -263,11 +308,7 @@ void close_chan(struct list_head *chans) * so it must be the last closed. */ list_for_each_entry_reverse(chan, chans, list) { - if(!chan->opened) continue; - if(chan->ops->close != NULL) - (*chan->ops->close)(chan->fd, chan->data); - chan->opened = 0; - chan->fd = -1; + close_one_chan(chan, delay_free_irq); } } @@ -339,24 +380,27 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out, return 0; } -void free_one_chan(struct chan *chan) +void free_one_chan(struct chan *chan, int delay_free_irq) { list_del(&chan->list); + + close_one_chan(chan, delay_free_irq); + if(chan->ops->free != NULL) (*chan->ops->free)(chan->data); - free_irq_by_fd(chan->fd); + if(chan->primary && chan->output) ignore_sigio_fd(chan->fd); kfree(chan); } -void free_chan(struct list_head *chans) +void free_chan(struct list_head *chans, int delay_free_irq) { struct list_head *ele, *next; struct chan *chan; list_for_each_safe(ele, next, chans){ chan = list_entry(ele, struct chan, list); - free_one_chan(chan); + free_one_chan(chan, delay_free_irq); } } @@ -466,7 +510,8 @@ struct chan_type chan_table[] = { #endif }; -static struct chan *parse_chan(char *str, int device, struct chan_opts *opts) +static struct chan *parse_chan(struct line *line, char *str, int device, + struct chan_opts *opts) { struct chan_type *entry; struct chan_ops *ops; @@ -499,25 +544,30 @@ static struct chan *parse_chan(char *str, int device, struct chan_opts *opts) if(chan == NULL) return NULL; *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), + .free_list = + LIST_HEAD_INIT(chan->free_list), + .line = line, .primary = 1, .input = 0, .output = 0, .opened = 0, + .enabled = 0, .fd = -1, .ops = ops, .data = data }); return chan; } -int parse_chan_pair(char *str, struct list_head *chans, int device, +int parse_chan_pair(char *str, struct line *line, int device, struct chan_opts *opts) { + struct list_head *chans = &line->chan_list; struct chan *new, *chan; char *in, *out; if(!list_empty(chans)){ chan = list_entry(chans->next, struct chan, list); - free_chan(chans); + free_chan(chans, 0); INIT_LIST_HEAD(chans); } @@ -526,14 +576,14 @@ int parse_chan_pair(char *str, struct list_head *chans, int device, in = str; *out = '\0'; out++; - new = parse_chan(in, device, opts); + new = parse_chan(line, in, device, opts); if(new == NULL) return -1; new->input = 1; list_add(&new->list, chans); - new = parse_chan(out, device, opts); + new = parse_chan(line, out, device, opts); if(new == NULL) return -1; @@ -541,7 +591,7 @@ int parse_chan_pair(char *str, struct list_head *chans, int device, new->output = 1; } else { - new = parse_chan(str, device, opts); + new = parse_chan(line, str, device, opts); if(new == NULL) return -1; @@ -592,27 +642,12 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task, if(chan->primary){ if(tty != NULL) tty_hangup(tty); - line_disable(tty, irq); - close_chan(chans); + close_chan(chans, 1); return; } - else { - if(chan->ops->close != NULL) - chan->ops->close(chan->fd, chan->data); - } + else close_one_chan(chan, 1); } } out: if(tty) tty_flip_buffer_push(tty); } - -/* - * 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/drivers/line.c b/arch/um/drivers/line.c index da81d22ec04..851a7c8caae 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -23,8 +23,9 @@ static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused) { - struct tty_struct *tty = data; - struct line *line = tty->driver_data; + struct chan *chan = data; + struct line *line = chan->line; + struct tty_struct *tty = line->tty; if (line) chan_interrupt(&line->chan_list, &line->task, tty, irq); @@ -33,10 +34,10 @@ static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused) static void line_timer_cb(void *arg) { - struct tty_struct *tty = arg; - struct line *line = tty->driver_data; + struct line *line = arg; - line_interrupt(line->driver->read_irq, arg, NULL); + chan_interrupt(&line->chan_list, &line->task, line->tty, + line->driver->read_irq); } /* Returns the free space inside the ring buffer of this line. @@ -342,8 +343,9 @@ int line_ioctl(struct tty_struct *tty, struct file * file, static irqreturn_t line_write_interrupt(int irq, void *data, struct pt_regs *unused) { - struct tty_struct *tty = data; - struct line *line = tty->driver_data; + struct chan *chan = data; + struct line *line = chan->line; + struct tty_struct *tty = line->tty; int err; /* Interrupts are enabled here because we registered the interrupt with @@ -365,7 +367,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data, if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && (tty->ldisc.write_wakeup != NULL)) (tty->ldisc.write_wakeup)(tty); - + /* BLOCKING mode * In blocking mode, everything sleeps on tty->write_wait. * Sleeping in the console driver would break non-blocking @@ -377,52 +379,29 @@ static irqreturn_t line_write_interrupt(int irq, void *data, return IRQ_HANDLED; } -int line_setup_irq(int fd, int input, int output, struct tty_struct *tty) +int line_setup_irq(int fd, int input, int output, struct line *line, void *data) { - struct line *line = tty->driver_data; struct line_driver *driver = line->driver; int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM; if (input) err = um_request_irq(driver->read_irq, fd, IRQ_READ, line_interrupt, flags, - driver->read_irq_name, tty); + driver->read_irq_name, data); if (err) return err; if (output) err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, line_write_interrupt, flags, - driver->write_irq_name, tty); + driver->write_irq_name, data); line->have_irq = 1; return err; } -void line_disable(struct tty_struct *tty, int current_irq) -{ - struct line *line = tty->driver_data; - - if(!line->have_irq) - return; - - if(line->driver->read_irq == current_irq) - free_irq_later(line->driver->read_irq, tty); - else { - free_irq(line->driver->read_irq, tty); - } - - if(line->driver->write_irq == current_irq) - free_irq_later(line->driver->write_irq, tty); - else { - free_irq(line->driver->write_irq, tty); - } - - line->have_irq = 0; -} - int line_open(struct line *lines, struct tty_struct *tty) { struct line *line; - int err = 0; + int err = -ENODEV; line = &lines[tty->index]; tty->driver_data = line; @@ -430,29 +409,29 @@ int line_open(struct line *lines, struct tty_struct *tty) /* The IRQ which takes this lock is not yet enabled and won't be run * before the end, so we don't need to use spin_lock_irq.*/ spin_lock(&line->lock); - if (tty->count == 1) { - if (!line->valid) { - err = -ENODEV; - goto out; - } - err = open_chan(&line->chan_list); - if(err) - goto out; - - /* Here the interrupt is registered.*/ - enable_chan(&line->chan_list, tty); - INIT_WORK(&line->task, line_timer_cb, tty); - } + tty->driver_data = line; + line->tty = tty; + if(!line->valid) + goto out; + + if(tty->count == 1){ + /* Here the device is opened, if necessary, and interrupt + * is registered. + */ + enable_chan(line); + INIT_WORK(&line->task, line_timer_cb, line); + + if(!line->sigio){ + chan_enable_winch(&line->chan_list, tty); + line->sigio = 1; + } - if(!line->sigio){ - chan_enable_winch(&line->chan_list, tty); - line->sigio = 1; + chan_window_size(&line->chan_list, &tty->winsize.ws_row, + &tty->winsize.ws_col); } - chan_window_size(&line->chan_list, &tty->winsize.ws_row, - &tty->winsize.ws_col); - line->count++; + err = 0; out: spin_unlock(&line->lock); return err; @@ -472,15 +451,14 @@ void line_close(struct tty_struct *tty, struct file * filp) /* We ignore the error anyway! */ flush_buffer(line); - line->count--; - if (tty->count == 1) { - line_disable(tty, -1); + if(tty->count == 1){ + line->tty = NULL; tty->driver_data = NULL; - } - if((line->count == 0) && line->sigio){ - unregister_winch(tty); - line->sigio = 0; + if(line->sigio){ + unregister_winch(tty); + line->sigio = 0; + } } spin_unlock_irq(&line->lock); @@ -491,7 +469,7 @@ void close_lines(struct line *lines, int nlines) int i; for(i = 0; i < nlines; i++) - close_chan(&lines[i].chan_list); + close_chan(&lines[i].chan_list, 0); } /* Common setup code for both startup command line and mconsole initialization. @@ -526,7 +504,7 @@ int line_setup(struct line *lines, unsigned int num, char *init) return 0; } else if (n >= 0){ - if (lines[n].count > 0) { + if (lines[n].tty != NULL) { printk("line_setup - device %d is open\n", n); return 0; } @@ -537,7 +515,7 @@ int line_setup(struct line *lines, unsigned int num, char *init) else { lines[n].init_str = init; lines[n].valid = 1; - } + } } } else { @@ -578,7 +556,7 @@ int line_config(struct line *lines, unsigned int num, char *str, return 1; line = &lines[n]; - return parse_chan_pair(line->init_str, &line->chan_list, n, opts); + return parse_chan_pair(line->init_str, line, n, opts); } int line_get_config(char *name, struct line *lines, unsigned int num, char *str, @@ -604,7 +582,7 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, spin_lock(&line->lock); if(!line->valid) CONFIG_CHUNK(str, size, n, "none", 1); - else if(line->count == 0) + else if(line->tty == NULL) CONFIG_CHUNK(str, size, n, line->init_str, 1); else n = chan_config_string(&line->chan_list, str, size, error_out); spin_unlock(&line->lock); @@ -696,7 +674,7 @@ void lines_init(struct line *lines, int nlines, struct chan_opts *opts) if(line->init_str == NULL) printk("lines_init - kstrdup returned NULL\n"); - if(parse_chan_pair(line->init_str, &line->chan_list, i, opts)){ + if(parse_chan_pair(line->init_str, line, i, opts)){ printk("parse_chan_pair failed for device %d\n", i); line->valid = 0; } @@ -831,7 +809,7 @@ char *add_xterm_umid(char *base) umid = get_umid(1); if(umid == NULL) return base; - + len = strlen(base) + strlen(" ()") + strlen(umid) + 1; title = kmalloc(len, GFP_KERNEL); if(title == NULL){ diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h index 22bf3a73437..84d1f64f979 100644 --- a/arch/um/include/chan_kern.h +++ b/arch/um/include/chan_kern.h @@ -14,11 +14,14 @@ struct chan { struct list_head list; + struct list_head free_list; + struct line *line; char *dev; unsigned int primary:1; unsigned int input:1; unsigned int output:1; unsigned int opened:1; + unsigned int enabled:1; int fd; struct chan_ops *ops; void *data; @@ -26,7 +29,7 @@ struct chan { extern void chan_interrupt(struct list_head *chans, struct work_struct *task, struct tty_struct *tty, int irq); -extern int parse_chan_pair(char *str, struct list_head *chans, int device, +extern int parse_chan_pair(char *str, struct line *line, int device, struct chan_opts *opts); extern int open_chan(struct list_head *chans); extern int write_chan(struct list_head *chans, const char *buf, int len, @@ -35,9 +38,9 @@ extern int console_write_chan(struct list_head *chans, const char *buf, int len); extern int console_open_chan(struct line *line, struct console *co, struct chan_opts *opts); -extern void close_chan(struct list_head *chans); extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty); -extern void enable_chan(struct list_head *chans, struct tty_struct *tty); +extern void enable_chan(struct line *line); +extern void close_chan(struct list_head *chans, int delay_free_irq); extern int chan_window_size(struct list_head *chans, unsigned short *rows_out, unsigned short *cols_out); diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h index f724b717213..b61deb8b362 100644 --- a/arch/um/include/irq_user.h +++ b/arch/um/include/irq_user.h @@ -18,19 +18,8 @@ extern int deactivate_all_fds(void); extern void forward_interrupts(int pid); extern void init_irq_signals(int on_sigstack); extern void forward_ipi(int fd, int pid); -extern void free_irq_later(int irq, void *dev_id); extern int activate_ipi(int fd, int pid); extern unsigned long irq_lock(void); extern void irq_unlock(unsigned long flags); -#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: - */ +#endif diff --git a/arch/um/include/line.h b/arch/um/include/line.h index 474398ba120..e6cc3abfd4d 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -32,6 +32,7 @@ struct line_driver { }; struct line { + struct tty_struct *tty; char *init_str; int init_pri; struct list_head chan_list; @@ -89,10 +90,9 @@ extern int line_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg); extern char *add_xterm_umid(char *base); -extern int line_setup_irq(int fd, int input, int output, - struct tty_struct *tty); +extern int line_setup_irq(int fd, int input, int output, struct line *line, + void *data); extern void line_close_chan(struct line *line); -extern void line_disable(struct tty_struct *tty, int current_irq); extern struct tty_driver * line_register_devfs(struct lines *set, struct line_driver *line_driver, struct tty_operations *driver, diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c index c3ccaf24f3e..50a2aa35cda 100644 --- a/arch/um/kernel/irq_user.c +++ b/arch/um/kernel/irq_user.c @@ -29,7 +29,6 @@ struct irq_fd { int pid; int events; int current_events; - int freed; }; static struct irq_fd *active_fds = NULL; @@ -41,9 +40,11 @@ static int pollfds_size = 0; extern int io_count, intr_count; +extern void free_irqs(void); + void sigio_handler(int sig, union uml_pt_regs *regs) { - struct irq_fd *irq_fd, *next; + struct irq_fd *irq_fd; int i, n; if(smp_sigio_handler()) return; @@ -66,29 +67,15 @@ void sigio_handler(int sig, union uml_pt_regs *regs) irq_fd = irq_fd->next; } - for(irq_fd = active_fds; irq_fd != NULL; irq_fd = next){ - next = irq_fd->next; + for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ if(irq_fd->current_events != 0){ irq_fd->current_events = 0; do_IRQ(irq_fd->irq, regs); - - /* This is here because the next irq may be - * freed in the handler. If a console goes - * away, both the read and write irqs will be - * freed. After do_IRQ, ->next will point to - * a good IRQ. - * Irqs can't be freed inside their handlers, - * so the next best thing is to have them - * marked as needing freeing, so that they - * can be freed here. - */ - next = irq_fd->next; - if(irq_fd->freed){ - free_irq(irq_fd->irq, irq_fd->id); - } } } } + + free_irqs(); } int activate_ipi(int fd, int pid) @@ -136,8 +123,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id) .irq = irq, .pid = pid, .events = events, - .current_events = 0, - .freed = 0 } ); + .current_events = 0 } ); /* Critical section - locked by a spinlock because this stuff can * be changed from interrupt handlers. The stuff above is done @@ -313,26 +299,6 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) return(irq); } -void free_irq_later(int irq, void *dev_id) -{ - struct irq_fd *irq_fd; - unsigned long flags; - - flags = irq_lock(); - for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ - if((irq_fd->irq == irq) && (irq_fd->id == dev_id)) - break; - } - if(irq_fd == NULL){ - printk("free_irq_later found no irq, irq = %d, " - "dev_id = 0x%p\n", irq, dev_id); - goto out; - } - irq_fd->freed = 1; - out: - irq_unlock(flags); -} - void reactivate_fd(int fd, int irqnum) { struct irq_fd *irq; -- cgit v1.2.3 From 9159c9dfffe1746d58b015ceaa3b7b8e99ee9d5c Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:18:58 -0800 Subject: [PATCH] uml: Fix flip_buf full handling When the tty flip_buf is full, it's a good idea to delay the input processing for a jiffy, rather than just scheduling the tasklet immediately. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/chan_kern.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 1bb920c0d77..36df55ad64c 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -629,7 +629,7 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task, do { if((tty != NULL) && (tty->flip.count >= TTY_FLIPBUF_SIZE)){ - schedule_work(task); + schedule_delayed_work(task, 1); goto out; } err = chan->ops->read(chan->fd, &c, chan->data); -- cgit v1.2.3 From e4dcee8099802c71437a15b940f66106d9f88b2f Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:18:58 -0800 Subject: [PATCH] uml: Add throttling to console driver This patch adds support for throttling and unthrottling input when the tty driver can't handle it. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/chan_kern.c | 26 ++++++++++++++++++++++++++ arch/um/drivers/line.c | 29 +++++++++++++++++++++++++++-- arch/um/drivers/ssl.c | 14 ++------------ arch/um/drivers/stdio_console.c | 2 ++ arch/um/include/chan_kern.h | 2 ++ arch/um/include/line.h | 4 ++++ 6 files changed, 63 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 36df55ad64c..cd13b91b9ff 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -312,6 +312,32 @@ void close_chan(struct list_head *chans, int delay_free_irq) } } +void deactivate_chan(struct list_head *chans, int irq) +{ + struct list_head *ele; + + struct chan *chan; + list_for_each(ele, chans) { + chan = list_entry(ele, struct chan, list); + + if(chan->enabled && chan->input) + deactivate_fd(chan->fd, irq); + } +} + +void reactivate_chan(struct list_head *chans, int irq) +{ + struct list_head *ele; + struct chan *chan; + + list_for_each(ele, chans) { + chan = list_entry(ele, struct chan, list); + + if(chan->enabled && chan->input) + reactivate_fd(chan->fd, irq); + } +} + int write_chan(struct list_head *chans, const char *buf, int len, int write_irq) { diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 851a7c8caae..b8e3e800ee4 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -36,8 +36,9 @@ static void line_timer_cb(void *arg) { struct line *line = arg; - chan_interrupt(&line->chan_list, &line->task, line->tty, - line->driver->read_irq); + if(!line->throttled) + chan_interrupt(&line->chan_list, &line->task, line->tty, + line->driver->read_irq); } /* Returns the free space inside the ring buffer of this line. @@ -340,6 +341,30 @@ int line_ioctl(struct tty_struct *tty, struct file * file, return ret; } +void line_throttle(struct tty_struct *tty) +{ + struct line *line = tty->driver_data; + + deactivate_chan(&line->chan_list, line->driver->read_irq); + line->throttled = 1; +} + +void line_unthrottle(struct tty_struct *tty) +{ + struct line *line = tty->driver_data; + + line->throttled = 0; + chan_interrupt(&line->chan_list, &line->task, tty, + line->driver->read_irq); + + /* Maybe there is enough stuff pending that calling the interrupt + * throttles us again. In this case, line->throttled will be 1 + * again and we shouldn't turn the interrupt back on. + */ + if(!line->throttled) + reactivate_chan(&line->chan_list, line->driver->read_irq); +} + static irqreturn_t line_write_interrupt(int irq, void *data, struct pt_regs *unused) { diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index 6823dc5d665..a32ef55cb24 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -109,16 +109,6 @@ static void ssl_flush_buffer(struct tty_struct *tty) return; } -static void ssl_throttle(struct tty_struct * tty) -{ - printk(KERN_ERR "Someone should implement ssl_throttle\n"); -} - -static void ssl_unthrottle(struct tty_struct * tty) -{ - printk(KERN_ERR "Someone should implement ssl_unthrottle\n"); -} - static void ssl_stop(struct tty_struct *tty) { printk(KERN_ERR "Someone should implement ssl_stop\n"); @@ -145,9 +135,9 @@ static struct tty_operations ssl_ops = { .flush_chars = line_flush_chars, .set_termios = line_set_termios, .ioctl = line_ioctl, + .throttle = line_throttle, + .unthrottle = line_unthrottle, #if 0 - .throttle = ssl_throttle, - .unthrottle = ssl_unthrottle, .stop = ssl_stop, .start = ssl_start, .hangup = ssl_hangup, diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 6d4edda9b51..61db8b2fc83 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -122,6 +122,8 @@ static struct tty_operations console_ops = { .flush_chars = line_flush_chars, .set_termios = line_set_termios, .ioctl = line_ioctl, + .throttle = line_throttle, + .unthrottle = line_unthrottle, }; static void uml_console_write(struct console *console, const char *string, diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h index 84d1f64f979..1bb5e9d9427 100644 --- a/arch/um/include/chan_kern.h +++ b/arch/um/include/chan_kern.h @@ -38,6 +38,8 @@ extern int console_write_chan(struct list_head *chans, const char *buf, int len); extern int console_open_chan(struct line *line, struct console *co, struct chan_opts *opts); +extern void deactivate_chan(struct list_head *chans, int irq); +extern void reactivate_chan(struct list_head *chans, int irq); extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty); extern void enable_chan(struct line *line); extern void close_chan(struct list_head *chans, int delay_free_irq); diff --git a/arch/um/include/line.h b/arch/um/include/line.h index e6cc3abfd4d..6f4d680dc1d 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -38,6 +38,7 @@ struct line { struct list_head chan_list; int valid; int count; + int throttled; /*This lock is actually, mostly, local to*/ spinlock_t lock; @@ -60,6 +61,7 @@ struct line { { init_str : str, \ init_pri : INIT_STATIC, \ valid : 1, \ + throttled : 0, \ lock : SPIN_LOCK_UNLOCKED, \ buffer : NULL, \ head : NULL, \ @@ -88,6 +90,8 @@ extern void line_flush_chars(struct tty_struct *tty); extern int line_write_room(struct tty_struct *tty); extern int line_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg); +extern void line_throttle(struct tty_struct *tty); +extern void line_unthrottle(struct tty_struct *tty); extern char *add_xterm_umid(char *base); extern int line_setup_irq(int fd, int input, int output, struct line *line, -- cgit v1.2.3 From 2264c475e4bf7427e59921953c89a5693ecb506f Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:18:59 -0800 Subject: [PATCH] uml: separate libc-dependent umid code I reworked Gennady's umid OS abstraction patch because the code shouldn't be moved entirely to os. As it turns out, I moved most of it anyway. This patch is the minimal one needed to move the code and have it work. It turns out that the concept of the umid is OS-independent, but almost everything else about the implementation is OS-dependent. This is code movement without cleanup - a follow-on patch tidies everything up without shuffling code around. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/kern.h | 13 +- arch/um/include/os.h | 17 +-- arch/um/kernel/Makefile | 6 +- arch/um/kernel/process_kern.c | 4 - arch/um/kernel/umid.c | 327 +++--------------------------------------- arch/um/os-Linux/Makefile | 4 +- arch/um/os-Linux/umid.c | 292 +++++++++++++++++++++++++++++++++++++ 7 files changed, 324 insertions(+), 339 deletions(-) create mode 100644 arch/um/os-Linux/umid.c (limited to 'arch') diff --git a/arch/um/include/kern.h b/arch/um/include/kern.h index 1e3170768b5..7d223beccbc 100644 --- a/arch/um/include/kern.h +++ b/arch/um/include/kern.h @@ -17,7 +17,7 @@ extern int errno; extern int clone(int (*proc)(void *), void *sp, int flags, void *data); extern int sleep(int); -extern int printf(char *fmt, ...); +extern int printf(const char *fmt, ...); extern char *strerror(int errnum); extern char *ptsname(int __fd); extern int munmap(void *, int); @@ -35,15 +35,6 @@ extern int read(unsigned int, char *, int); extern int pipe(int *); extern int sched_yield(void); extern int ptrace(int op, int pid, long addr, long data); + #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 2cccfa5b8ab..258444e5b9b 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -213,15 +213,10 @@ extern int run_helper_thread(int (*proc)(void *), void *arg, int stack_order); extern int helper_wait(int pid); -#endif +/* umid.c */ -/* - * 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: - */ +extern int umid_file_name(char *name, char *buf, int len); +extern int set_umid(char *name, int (*printer)(const char *fmt, ...)); +extern char *get_umid(int only_if_set); + +#endif diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 3de9d21e36b..6f7700593a6 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -10,8 +10,8 @@ obj-y = config.o exec_kern.o exitcode.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 \ - umid.o user_util.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 obj-$(CONFIG_GPROF) += gprof_syms.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 time.o tty_log.o umid.o user_util.o +USER_OBJS := $(user-objs-y) config.o time.o tty_log.o user_util.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index 34b54a3e213..651abf255bc 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -324,10 +324,6 @@ int user_context(unsigned long sp) return(stack != (unsigned long) current_thread); } -extern void remove_umid_dir(void); - -__uml_exitcall(remove_umid_dir); - extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; void do_uml_exitcalls(void) diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c index 0b21d59ba0c..772c7cfbd8e 100644 --- a/arch/um/kernel/umid.c +++ b/arch/um/kernel/umid.c @@ -3,61 +3,34 @@ * Licensed under the GPL */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "user.h" -#include "umid.h" +#include "linux/stddef.h" +#include "linux/kernel.h" +#include "asm/errno.h" #include "init.h" #include "os.h" -#include "user_util.h" -#include "choose-mode.h" +#include "kern.h" -#define UMID_LEN 64 -#define UML_DIR "~/.uml/" - -/* Changed by set_umid and make_umid, which are run early in boot */ -static char umid[UMID_LEN] = { 0 }; - -/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */ -static char *uml_dir = UML_DIR; - -/* Changed by set_umid */ -static int umid_is_random = 1; +/* Changed by set_umid_arg and umid_file_name */ +int umid_is_random = 0; static int umid_inited = 0; -/* Have we created the files? Should we remove them? */ -static int umid_owned = 0; -static int make_umid(int (*printer)(const char *fmt, ...)); - -static int __init set_umid(char *name, int is_random, - int (*printer)(const char *fmt, ...)) +static int __init set_umid_arg(char *name, int *add) { - if(umid_inited){ - (*printer)("Unique machine name can't be set twice\n"); - return(-1); - } + int err; - if(strlen(name) > UMID_LEN - 1) - (*printer)("Unique machine name is being truncated to %d " - "characters\n", UMID_LEN); - strlcpy(umid, name, sizeof(umid)); + if(umid_inited) + return 0; - umid_is_random = is_random; - umid_inited = 1; - return 0; -} - -static int __init set_umid_arg(char *name, int *add) -{ *add = 0; - return(set_umid(name, 0, printf)); + err = set_umid(name, printf); + if(err == -EEXIST){ + printf("umid '%s' already in use\n", name); + umid_is_random = 1; + } + else if(!err) + umid_inited = 1; + + return 0; } __uml_setup("umid=", set_umid_arg, @@ -66,265 +39,3 @@ __uml_setup("umid=", set_umid_arg, " is used for naming the pid file and management console socket.\n\n" ); -int __init umid_file_name(char *name, char *buf, int len) -{ - int n; - - if(!umid_inited && make_umid(printk)) return(-1); - - n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1; - if(n > len){ - printk("umid_file_name : buffer too short\n"); - return(-1); - } - - sprintf(buf, "%s%s/%s", uml_dir, umid, name); - return(0); -} - -extern int tracing_pid; - -static void __init create_pid_file(void) -{ - char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; - char pid[sizeof("nnnnn\0")]; - int fd, n; - - if(umid_file_name("pid", file, sizeof(file))) - return; - - fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))), - 0644); - if(fd < 0){ - printf("Open of machine pid file \"%s\" failed: %s\n", - file, strerror(-fd)); - return; - } - - sprintf(pid, "%d\n", os_getpid()); - n = os_write_file(fd, pid, strlen(pid)); - if(n != strlen(pid)) - printf("Write of pid file failed - err = %d\n", -n); - os_close_file(fd); -} - -static int actually_do_remove(char *dir) -{ - DIR *directory; - struct dirent *ent; - int len; - char file[256]; - - directory = opendir(dir); - if(directory == NULL){ - printk("actually_do_remove : couldn't open directory '%s', " - "errno = %d\n", dir, errno); - return(1); - } - while((ent = readdir(directory)) != NULL){ - if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) - continue; - len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1; - if(len > sizeof(file)){ - printk("Not deleting '%s' from '%s' - name too long\n", - ent->d_name, dir); - continue; - } - sprintf(file, "%s/%s", dir, ent->d_name); - if(unlink(file) < 0){ - printk("actually_do_remove : couldn't remove '%s' " - "from '%s', errno = %d\n", ent->d_name, dir, - errno); - return(1); - } - } - if(rmdir(dir) < 0){ - printk("actually_do_remove : couldn't rmdir '%s', " - "errno = %d\n", dir, errno); - return(1); - } - return(0); -} - -void remove_umid_dir(void) -{ - char dir[strlen(uml_dir) + UMID_LEN + 1]; - if (!umid_owned) - return; - - sprintf(dir, "%s%s", uml_dir, umid); - actually_do_remove(dir); -} - -char *get_umid(int only_if_set) -{ - if(only_if_set && umid_is_random) - return NULL; - return umid; -} - -static int not_dead_yet(char *dir) -{ - char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; - char pid[sizeof("nnnnn\0")], *end; - int dead, fd, p, n; - - sprintf(file, "%s/pid", dir); - dead = 0; - fd = os_open_file(file, of_read(OPENFLAGS()), 0); - if(fd < 0){ - if(fd != -ENOENT){ - printk("not_dead_yet : couldn't open pid file '%s', " - "err = %d\n", file, -fd); - return(1); - } - dead = 1; - } - if(fd > 0){ - n = os_read_file(fd, pid, sizeof(pid)); - if(n < 0){ - printk("not_dead_yet : couldn't read pid file '%s', " - "err = %d\n", file, -n); - return(1); - } - p = strtoul(pid, &end, 0); - if(end == pid){ - printk("not_dead_yet : couldn't parse pid file '%s', " - "errno = %d\n", file, errno); - dead = 1; - } - if(((kill(p, 0) < 0) && (errno == ESRCH)) || - (p == CHOOSE_MODE(tracing_pid, os_getpid()))) - dead = 1; - } - if(!dead) - return(1); - return(actually_do_remove(dir)); -} - -static int __init set_uml_dir(char *name, int *add) -{ - if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){ - uml_dir = malloc(strlen(name) + 2); - if(uml_dir == NULL){ - printf("Failed to malloc uml_dir - error = %d\n", - errno); - uml_dir = name; - /* Return 0 here because do_initcalls doesn't look at - * the return value. - */ - return(0); - } - sprintf(uml_dir, "%s/", name); - } - else uml_dir = name; - return(0); -} - -static int __init make_uml_dir(void) -{ - char dir[MAXPATHLEN + 1] = { '\0' }; - int len; - - if(*uml_dir == '~'){ - char *home = getenv("HOME"); - - if(home == NULL){ - printf("make_uml_dir : no value in environment for " - "$HOME\n"); - exit(1); - } - strlcpy(dir, home, sizeof(dir)); - uml_dir++; - } - strlcat(dir, uml_dir, sizeof(dir)); - len = strlen(dir); - if (len > 0 && dir[len - 1] != '/') - strlcat(dir, "/", sizeof(dir)); - - uml_dir = malloc(strlen(dir) + 1); - if (uml_dir == NULL) { - printf("make_uml_dir : malloc failed, errno = %d\n", errno); - exit(1); - } - strcpy(uml_dir, dir); - - if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){ - printf("Failed to mkdir %s: %s\n", uml_dir, strerror(errno)); - return(-1); - } - return 0; -} - -static int __init make_umid(int (*printer)(const char *fmt, ...)) -{ - int fd, err; - char tmp[strlen(uml_dir) + UMID_LEN + 1]; - - strlcpy(tmp, uml_dir, sizeof(tmp)); - - if(!umid_inited){ - strcat(tmp, "XXXXXX"); - fd = mkstemp(tmp); - if(fd < 0){ - (*printer)("make_umid - mkstemp(%s) failed: %s\n", - tmp,strerror(errno)); - return(1); - } - - os_close_file(fd); - /* There's a nice tiny little race between this unlink and - * the mkdir below. It'd be nice if there were a mkstemp - * for directories. - */ - unlink(tmp); - set_umid(&tmp[strlen(uml_dir)], 1, printer); - } - - sprintf(tmp, "%s%s", uml_dir, umid); - - err = mkdir(tmp, 0777); - if(err < 0){ - if(errno == EEXIST){ - if(not_dead_yet(tmp)){ - (*printer)("umid '%s' is in use\n", umid); - umid_owned = 0; - return(-1); - } - err = mkdir(tmp, 0777); - } - } - if(err < 0){ - (*printer)("Failed to create %s - errno = %d\n", umid, errno); - return(-1); - } - - umid_owned = 1; - return 0; -} - -__uml_setup("uml_dir=", set_uml_dir, -"uml_dir=\n" -" The location to place the pid and umid files.\n\n" -); - -static int __init make_umid_setup(void) -{ - /* one function with the ordering we need ... */ - make_uml_dir(); - make_umid(printf); - create_pid_file(); - return 0; -} -__uml_postsetup(make_umid_setup); - -/* - * 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 b83ac8e21c3..11e30b13e31 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -4,11 +4,11 @@ # 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/ \ + start_up.o time.o tt.o tty.o uaccess.o umid.o user_syms.o drivers/ \ sys-$(SUBARCH)/ 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 + start_up.o time.o tt.o tty.o uaccess.o umid.o elf_aux.o: $(ARCH_DIR)/kernel-offsets.h CFLAGS_elf_aux.o += -I$(objtree)/arch/um diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c new file mode 100644 index 00000000000..77d69a348cf --- /dev/null +++ b/arch/um/os-Linux/umid.c @@ -0,0 +1,292 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "init.h" +#include "os.h" +#include "user.h" +#include "mode.h" + +#define UML_DIR "~/.uml/" + +#define UMID_LEN 64 + +/* Changed by set_umid, which is run early in boot */ +char umid[UMID_LEN] = { 0 }; + +/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */ +static char *uml_dir = UML_DIR; + +static int __init make_uml_dir(void) +{ + char dir[512] = { '\0' }; + int len; + + if(*uml_dir == '~'){ + char *home = getenv("HOME"); + + if(home == NULL){ + printf("make_uml_dir : no value in environment for " + "$HOME\n"); + exit(1); + } + strlcpy(dir, home, sizeof(dir)); + uml_dir++; + } + strlcat(dir, uml_dir, sizeof(dir)); + len = strlen(dir); + if (len > 0 && dir[len - 1] != '/') + strlcat(dir, "/", sizeof(dir)); + + uml_dir = malloc(strlen(dir) + 1); + if (uml_dir == NULL) { + printf("make_uml_dir : malloc failed, errno = %d\n", errno); + exit(1); + } + strcpy(uml_dir, dir); + + if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){ + printf("Failed to mkdir '%s': %s\n", uml_dir, strerror(errno)); + return(-1); + } + return 0; +} + +static int actually_do_remove(char *dir) +{ + DIR *directory; + struct dirent *ent; + int len; + char file[256]; + + directory = opendir(dir); + if(directory == NULL){ + printk("actually_do_remove : couldn't open directory '%s', " + "errno = %d\n", dir, errno); + return(1); + } + while((ent = readdir(directory)) != NULL){ + if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) + continue; + len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1; + if(len > sizeof(file)){ + printk("Not deleting '%s' from '%s' - name too long\n", + ent->d_name, dir); + continue; + } + sprintf(file, "%s/%s", dir, ent->d_name); + if(unlink(file) < 0){ + printk("actually_do_remove : couldn't remove '%s' " + "from '%s', errno = %d\n", ent->d_name, dir, + errno); + return(1); + } + } + if(rmdir(dir) < 0){ + printk("actually_do_remove : couldn't rmdir '%s', " + "errno = %d\n", dir, errno); + return(1); + } + return(0); +} + +extern int tracing_pid; + +static int not_dead_yet(char *dir) +{ + char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; + char pid[sizeof("nnnnn\0")], *end; + int dead, fd, p, n; + + sprintf(file, "%s/pid", dir); + dead = 0; + fd = os_open_file(file, of_read(OPENFLAGS()), 0); + if(fd < 0){ + if(fd != -ENOENT){ + printk("not_dead_yet : couldn't open pid file '%s', " + "err = %d\n", file, -fd); + return(1); + } + dead = 1; + } + if(fd > 0){ + n = os_read_file(fd, pid, sizeof(pid)); + if(n < 0){ + printk("not_dead_yet : couldn't read pid file '%s', " + "err = %d\n", file, -n); + return(1); + } + p = strtoul(pid, &end, 0); + if(end == pid){ + printk("not_dead_yet : couldn't parse pid file '%s', " + "errno = %d\n", file, errno); + dead = 1; + } + if(((kill(p, 0) < 0) && (errno == ESRCH)) || + (p == CHOOSE_MODE(tracing_pid, os_getpid()))) + dead = 1; + } + if(!dead) + return(1); + return(actually_do_remove(dir)); +} + +static void __init create_pid_file(void) +{ + char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; + char pid[sizeof("nnnnn\0")]; + int fd, n; + + if(umid_file_name("pid", file, sizeof(file))) + return; + + fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))), + 0644); + if(fd < 0){ + printf("Open of machine pid file \"%s\" failed: %s\n", + file, strerror(-fd)); + return; + } + + sprintf(pid, "%d\n", os_getpid()); + n = os_write_file(fd, pid, strlen(pid)); + if(n != strlen(pid)) + printf("Write of pid file failed - err = %d\n", -n); + os_close_file(fd); +} + +int __init set_umid(char *name, int (*printer)(const char *fmt, ...)) +{ + if(strlen(name) > UMID_LEN - 1) + (*printer)("Unique machine name is being truncated to %d " + "characters\n", UMID_LEN); + strlcpy(umid, name, sizeof(umid)); + + return 0; +} + +static int umid_setup = 0; + +int __init make_umid(int (*printer)(const char *fmt, ...)) +{ + int fd, err; + char tmp[256]; + + make_uml_dir(); + + if(*umid == '\0'){ + strlcpy(tmp, uml_dir, sizeof(tmp)); + strcat(tmp, "XXXXXX"); + fd = mkstemp(tmp); + if(fd < 0){ + (*printer)("make_umid - mkstemp(%s) failed: %s\n", + tmp,strerror(errno)); + return(1); + } + + os_close_file(fd); + /* There's a nice tiny little race between this unlink and + * the mkdir below. It'd be nice if there were a mkstemp + * for directories. + */ + unlink(tmp); + set_umid(&tmp[strlen(uml_dir)], printer); + } + + sprintf(tmp, "%s%s", uml_dir, umid); + err = mkdir(tmp, 0777); + if(err < 0){ + if(errno == EEXIST){ + if(not_dead_yet(tmp)) + return -EEXIST; + err = mkdir(tmp, 0777); + } + } + if(err < 0){ + (*printer)("Failed to create %s - errno = %d\n", umid, errno); + return(-1); + } + + umid_setup = 1; + + create_pid_file(); + + return 0; +} + +static int __init make_umid_init(void) +{ + make_umid(printk); + + return(0); +} + +__initcall(make_umid_init); + +int __init umid_file_name(char *name, char *buf, int len) +{ + int n, err; + + if(!umid_setup){ + err = make_umid(printk); + if(err) + return err; + } + + n = strlen(uml_dir) + strlen(umid) + strlen("/") + strlen(name) + 1; + if(n > len){ + printk("umid_file_name : buffer too short\n"); + return(-1); + } + + sprintf(buf, "%s%s/%s", uml_dir, umid, name); + return(0); +} + +extern int umid_is_random; + +char *get_umid(int only_if_set) +{ + if(only_if_set && umid_is_random) + return NULL; + return umid; +} + +static int __init set_uml_dir(char *name, int *add) +{ + if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){ + uml_dir = malloc(strlen(name) + 2); + if(uml_dir == NULL){ + printf("Failed to malloc uml_dir - error = %d\n", + errno); + uml_dir = name; + /* Return 0 here because do_initcalls doesn't look at + * the return value. + */ + return(0); + } + sprintf(uml_dir, "%s/", name); + } + else uml_dir = name; + return(0); +} + +__uml_setup("uml_dir=", set_uml_dir, +"uml_dir=\n" +" The location to place the pid and umid files.\n\n" +); + +static void remove_umid_dir(void) +{ + char dir[strlen(uml_dir) + UMID_LEN + 1]; + + sprintf(dir, "%s%s", uml_dir, umid); + actually_do_remove(dir); +} + +__uml_exitcall(remove_umid_dir); -- cgit v1.2.3 From 7eebe8a9c51686927709a57b1f2725d371014abc Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:19:01 -0800 Subject: [PATCH] uml: umid cleanup This patch cleans up the umid code: - The only_if_set argument to get_umid is gone. - get_umid returns an empty string rather than NULL if there is no umid. - umid_is_random is gone since its users went away. - Some printfs were turned into printks because the code runs late enough that printk is working. - Error paths were cleaned up. - Some functions now return an error and let the caller print the error message rather than printing it themselves. This eliminates the practice of passing a pointer to printf or printk in, depending on where in the boot process we are. - Major tidying of not_dead_yet - mostly error path cleanup, plus a comment explaining why it doesn't react to errors the way you might expect. - Calls to os_* interfaces that were moved under os are changed back to their native libc forms. - snprintf, strlcpy, and their bounds-checking friends are used more often, replacing by-hand bounds checking in some places. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/line.c | 4 +- arch/um/include/os.h | 4 +- arch/um/include/user_util.h | 1 - arch/um/kernel/um_arch.c | 4 +- arch/um/kernel/umid.c | 12 +- arch/um/os-Linux/umid.c | 265 +++++++++++++++++++++++++------------------- 6 files changed, 164 insertions(+), 126 deletions(-) (limited to 'arch') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index b8e3e800ee4..a3c39373adb 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -831,8 +831,8 @@ char *add_xterm_umid(char *base) char *umid, *title; int len; - umid = get_umid(1); - if(umid == NULL) + umid = get_umid(); + if(*umid == '\0') return base; len = strlen(base) + strlen(" ()") + strlen(umid) + 1; diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 258444e5b9b..c279ee6d89e 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -216,7 +216,7 @@ extern int helper_wait(int pid); /* umid.c */ extern int umid_file_name(char *name, char *buf, int len); -extern int set_umid(char *name, int (*printer)(const char *fmt, ...)); -extern char *get_umid(int only_if_set); +extern int set_umid(char *name); +extern char *get_umid(void); #endif diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h index bb505e01d99..b9984003e60 100644 --- a/arch/um/include/user_util.h +++ b/arch/um/include/user_util.h @@ -64,7 +64,6 @@ extern void setup_machinename(char *machine_out); extern void setup_hostinfo(void); extern void do_exec(int old_pid, int new_pid); extern void tracer_panic(char *msg, ...); -extern char *get_umid(int only_if_set); extern void do_longjmp(void *p, int val); extern int detach(int pid, int sig); extern int attach(int pid); diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 142a9493912..26626b2b917 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -146,8 +146,8 @@ void set_cmdline(char *cmd) if(CHOOSE_MODE(honeypot, 0)) return; - umid = get_umid(1); - if(umid != NULL){ + umid = get_umid(); + if(*umid != '\0'){ snprintf(argv1_begin, (argv1_end - argv1_begin) * sizeof(*ptr), "(%s) ", umid); diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c index 772c7cfbd8e..4eaee823bfd 100644 --- a/arch/um/kernel/umid.c +++ b/arch/um/kernel/umid.c @@ -3,15 +3,13 @@ * Licensed under the GPL */ -#include "linux/stddef.h" -#include "linux/kernel.h" #include "asm/errno.h" #include "init.h" #include "os.h" #include "kern.h" +#include "linux/kernel.h" -/* Changed by set_umid_arg and umid_file_name */ -int umid_is_random = 0; +/* Changed by set_umid_arg */ static int umid_inited = 0; static int __init set_umid_arg(char *name, int *add) @@ -22,11 +20,9 @@ static int __init set_umid_arg(char *name, int *add) return 0; *add = 0; - err = set_umid(name, printf); - if(err == -EEXIST){ + err = set_umid(name); + if(err == -EEXIST) printf("umid '%s' already in use\n", name); - umid_is_random = 1; - } else if(!err) umid_inited = 1; diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c index 77d69a348cf..ecf107ae5ac 100644 --- a/arch/um/os-Linux/umid.c +++ b/arch/um/os-Linux/umid.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include "init.h" @@ -25,15 +26,16 @@ static char *uml_dir = UML_DIR; static int __init make_uml_dir(void) { char dir[512] = { '\0' }; - int len; + int len, err; if(*uml_dir == '~'){ char *home = getenv("HOME"); + err = -ENOENT; if(home == NULL){ - printf("make_uml_dir : no value in environment for " + printk("make_uml_dir : no value in environment for " "$HOME\n"); - exit(1); + goto err; } strlcpy(dir, home, sizeof(dir)); uml_dir++; @@ -43,18 +45,26 @@ static int __init make_uml_dir(void) if (len > 0 && dir[len - 1] != '/') strlcat(dir, "/", sizeof(dir)); + err = -ENOMEM; uml_dir = malloc(strlen(dir) + 1); if (uml_dir == NULL) { printf("make_uml_dir : malloc failed, errno = %d\n", errno); - exit(1); + goto err; } strcpy(uml_dir, dir); if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){ printf("Failed to mkdir '%s': %s\n", uml_dir, strerror(errno)); - return(-1); + err = -errno; + goto err_free; } return 0; + +err_free: + free(uml_dir); +err: + uml_dir = NULL; + return err; } static int actually_do_remove(char *dir) @@ -65,75 +75,88 @@ static int actually_do_remove(char *dir) char file[256]; directory = opendir(dir); - if(directory == NULL){ - printk("actually_do_remove : couldn't open directory '%s', " - "errno = %d\n", dir, errno); - return(1); - } + if(directory == NULL) + return -errno; + while((ent = readdir(directory)) != NULL){ if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue; len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1; - if(len > sizeof(file)){ - printk("Not deleting '%s' from '%s' - name too long\n", - ent->d_name, dir); - continue; - } + if(len > sizeof(file)) + return -E2BIG; + sprintf(file, "%s/%s", dir, ent->d_name); - if(unlink(file) < 0){ - printk("actually_do_remove : couldn't remove '%s' " - "from '%s', errno = %d\n", ent->d_name, dir, - errno); - return(1); - } - } - if(rmdir(dir) < 0){ - printk("actually_do_remove : couldn't rmdir '%s', " - "errno = %d\n", dir, errno); - return(1); + if(unlink(file) < 0) + return -errno; } - return(0); + if(rmdir(dir) < 0) + return -errno; + + return 0; } -extern int tracing_pid; +/* This says that there isn't already a user of the specified directory even if + * there are errors during the checking. This is because if these errors + * happen, the directory is unusable by the pre-existing UML, so we might as + * well take it over. This could happen either by + * the existing UML somehow corrupting its umid directory + * something other than UML sticking stuff in the directory + * this boot racing with a shutdown of the other UML + * In any of these cases, the directory isn't useful for anything else. + */ static int not_dead_yet(char *dir) { char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; char pid[sizeof("nnnnn\0")], *end; - int dead, fd, p, n; + int dead, fd, p, n, err; + + n = snprintf(file, sizeof(file), "%s/pid", dir); + if(n >= sizeof(file)){ + printk("not_dead_yet - pid filename too long\n"); + err = -E2BIG; + goto out; + } - sprintf(file, "%s/pid", dir); dead = 0; - fd = os_open_file(file, of_read(OPENFLAGS()), 0); + fd = open(file, O_RDONLY); if(fd < 0){ if(fd != -ENOENT){ printk("not_dead_yet : couldn't open pid file '%s', " "err = %d\n", file, -fd); - return(1); } - dead = 1; + goto out; } - if(fd > 0){ - n = os_read_file(fd, pid, sizeof(pid)); - if(n < 0){ - printk("not_dead_yet : couldn't read pid file '%s', " - "err = %d\n", file, -n); - return(1); - } - p = strtoul(pid, &end, 0); - if(end == pid){ - printk("not_dead_yet : couldn't parse pid file '%s', " - "errno = %d\n", file, errno); - dead = 1; - } - if(((kill(p, 0) < 0) && (errno == ESRCH)) || - (p == CHOOSE_MODE(tracing_pid, os_getpid()))) - dead = 1; + + err = 0; + n = read(fd, pid, sizeof(pid)); + if(n <= 0){ + printk("not_dead_yet : couldn't read pid file '%s', " + "err = %d\n", file, -n); + goto out_close; + } + + p = strtoul(pid, &end, 0); + if(end == pid){ + printk("not_dead_yet : couldn't parse pid file '%s', " + "errno = %d\n", file, errno); + goto out_close; } - if(!dead) - return(1); - return(actually_do_remove(dir)); + + if((kill(p, 0) == 0) || (errno != ESRCH)) + return 1; + + err = actually_do_remove(dir); + if(err) + printk("not_dead_yet - actually_do_remove failed with " + "err = %d\n", err); + + return err; + + out_close: + close(fd); + out: + return 0; } static void __init create_pid_file(void) @@ -145,26 +168,26 @@ static void __init create_pid_file(void) if(umid_file_name("pid", file, sizeof(file))) return; - fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))), - 0644); + fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644); if(fd < 0){ - printf("Open of machine pid file \"%s\" failed: %s\n", + printk("Open of machine pid file \"%s\" failed: %s\n", file, strerror(-fd)); return; } - sprintf(pid, "%d\n", os_getpid()); - n = os_write_file(fd, pid, strlen(pid)); + snprintf(pid, sizeof(pid), "%d\n", getpid()); + n = write(fd, pid, strlen(pid)); if(n != strlen(pid)) - printf("Write of pid file failed - err = %d\n", -n); - os_close_file(fd); + printk("Write of pid file failed - err = %d\n", -n); + + close(fd); } -int __init set_umid(char *name, int (*printer)(const char *fmt, ...)) +int __init set_umid(char *name) { if(strlen(name) > UMID_LEN - 1) - (*printer)("Unique machine name is being truncated to %d " - "characters\n", UMID_LEN); + return -E2BIG; + strlcpy(umid, name, sizeof(umid)); return 0; @@ -172,44 +195,56 @@ int __init set_umid(char *name, int (*printer)(const char *fmt, ...)) static int umid_setup = 0; -int __init make_umid(int (*printer)(const char *fmt, ...)) +int __init make_umid(void) { int fd, err; char tmp[256]; + if(umid_setup) + return 0; + make_uml_dir(); if(*umid == '\0'){ strlcpy(tmp, uml_dir, sizeof(tmp)); - strcat(tmp, "XXXXXX"); + strlcat(tmp, "XXXXXX", sizeof(tmp)); fd = mkstemp(tmp); if(fd < 0){ - (*printer)("make_umid - mkstemp(%s) failed: %s\n", - tmp,strerror(errno)); - return(1); + printk("make_umid - mkstemp(%s) failed: %s\n", + tmp, strerror(errno)); + err = -errno; + goto err; } - os_close_file(fd); + close(fd); + + set_umid(&tmp[strlen(uml_dir)]); + /* There's a nice tiny little race between this unlink and * the mkdir below. It'd be nice if there were a mkstemp * for directories. */ - unlink(tmp); - set_umid(&tmp[strlen(uml_dir)], printer); + if(unlink(tmp)){ + err = -errno; + goto err; + } } - sprintf(tmp, "%s%s", uml_dir, umid); + snprintf(tmp, sizeof(tmp), "%s%s", uml_dir, umid); err = mkdir(tmp, 0777); if(err < 0){ - if(errno == EEXIST){ - if(not_dead_yet(tmp)) - return -EEXIST; - err = mkdir(tmp, 0777); - } + err = -errno; + if(errno != EEXIST) + goto err; + + if(not_dead_yet(tmp) < 0) + goto err; + + err = mkdir(tmp, 0777); } if(err < 0){ - (*printer)("Failed to create %s - errno = %d\n", umid, errno); - return(-1); + printk("Failed to create '%s' - err = %d\n", umid, err); + goto err_rmdir; } umid_setup = 1; @@ -217,13 +252,18 @@ int __init make_umid(int (*printer)(const char *fmt, ...)) create_pid_file(); return 0; + + err_rmdir: + rmdir(tmp); + err: + return err; } static int __init make_umid_init(void) { - make_umid(printk); + make_umid(); - return(0); + return 0; } __initcall(make_umid_init); @@ -232,48 +272,48 @@ int __init umid_file_name(char *name, char *buf, int len) { int n, err; - if(!umid_setup){ - err = make_umid(printk); - if(err) - return err; - } + err = make_umid(); + if(err) + return err; - n = strlen(uml_dir) + strlen(umid) + strlen("/") + strlen(name) + 1; - if(n > len){ + n = snprintf(buf, len, "%s%s/%s", uml_dir, umid, name); + if(n >= len){ printk("umid_file_name : buffer too short\n"); - return(-1); + return -E2BIG; } - sprintf(buf, "%s%s/%s", uml_dir, umid, name); - return(0); + return 0; } -extern int umid_is_random; - -char *get_umid(int only_if_set) +char *get_umid(void) { - if(only_if_set && umid_is_random) - return NULL; return umid; } static int __init set_uml_dir(char *name, int *add) { - if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){ - uml_dir = malloc(strlen(name) + 2); - if(uml_dir == NULL){ - printf("Failed to malloc uml_dir - error = %d\n", - errno); - uml_dir = name; - /* Return 0 here because do_initcalls doesn't look at - * the return value. - */ - return(0); - } - sprintf(uml_dir, "%s/", name); + if(*name == '\0'){ + printf("uml_dir can't be an empty string\n"); + return 0; } - else uml_dir = name; - return(0); + + if(name[strlen(name) - 1] == '/'){ + uml_dir = name; + return 0; + } + + uml_dir = malloc(strlen(name) + 2); + if(uml_dir == NULL){ + printf("Failed to malloc uml_dir - error = %d\n", errno); + + /* Return 0 here because do_initcalls doesn't look at + * the return value. + */ + return 0; + } + sprintf(uml_dir, "%s/", name); + + return 0; } __uml_setup("uml_dir=", set_uml_dir, @@ -283,10 +323,13 @@ __uml_setup("uml_dir=", set_uml_dir, static void remove_umid_dir(void) { - char dir[strlen(uml_dir) + UMID_LEN + 1]; + char dir[strlen(uml_dir) + UMID_LEN + 1], err; sprintf(dir, "%s%s", uml_dir, umid); - actually_do_remove(dir); + err = actually_do_remove(dir); + if(err) + printf("remove_umid_dir - actually_do_remove failed with " + "err = %d\n", err); } __uml_exitcall(remove_umid_dir); -- cgit v1.2.3 From e464bf2bed027ea185992b44bf4b0326387a520d Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:19:01 -0800 Subject: [PATCH] uml: SIGWINCH handling cleanup Code cleanup - unregister_winch and winch_cleanup had some duplicate code. This is now abstracted out into free_winch. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/line.c | 54 ++++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 30 deletions(-) (limited to 'arch') diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index a3c39373adb..46ceb25a995 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -774,55 +774,49 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty) printk("register_winch_irq - failed to register IRQ\n"); } +static void free_winch(struct winch *winch) +{ + list_del(&winch->list); + + if(winch->pid != -1) + os_kill_process(winch->pid, 1); + if(winch->fd != -1) + os_close_file(winch->fd); + + free_irq(WINCH_IRQ, winch); + kfree(winch); +} + static void unregister_winch(struct tty_struct *tty) { struct list_head *ele; - struct winch *winch, *found = NULL; + struct winch *winch; spin_lock(&winch_handler_lock); + list_for_each(ele, &winch_handlers){ winch = list_entry(ele, struct winch, list); if(winch->tty == tty){ - found = winch; - break; + free_winch(winch); + break; } } - if(found == NULL) - goto err; - - list_del(&winch->list); - spin_unlock(&winch_handler_lock); - - if(winch->pid != -1) - os_kill_process(winch->pid, 1); - - free_irq(WINCH_IRQ, winch); - kfree(winch); - - return; -err: spin_unlock(&winch_handler_lock); } -/* XXX: No lock as it's an exitcall... is this valid? Depending on cleanup - * order... are we sure that nothing else is done on the list? */ static void winch_cleanup(void) { - struct list_head *ele; + struct list_head *ele, *next; struct winch *winch; - list_for_each(ele, &winch_handlers){ + spin_lock(&winch_handler_lock); + + list_for_each_safe(ele, next, &winch_handlers){ winch = list_entry(ele, struct winch, list); - if(winch->fd != -1){ - /* Why is this different from the above free_irq(), - * which deactivates SIGIO? This searches the FD - * somewhere else and removes it from the list... */ - deactivate_fd(winch->fd, WINCH_IRQ); - os_close_file(winch->fd); - } - if(winch->pid != -1) - os_kill_process(winch->pid, 1); + free_winch(winch); } + + spin_unlock(&winch_handler_lock); } __uml_exitcall(winch_cleanup); -- cgit v1.2.3 From 44700a4469b6bb89e6f1edd32b8a4a915dd967c6 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:19:02 -0800 Subject: [PATCH] uml: better diagnostics for broken configs Produce a compile-time error if both MODE_SKAS and MODE_TT are disabled. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/choose-mode.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/um/include/choose-mode.h b/arch/um/include/choose-mode.h index f25fa83a5da..b87b36a87d9 100644 --- a/arch/um/include/choose-mode.h +++ b/arch/um/include/choose-mode.h @@ -23,6 +23,9 @@ static inline void *__choose_mode(void *tt, void *skas) { #elif defined(UML_CONFIG_MODE_TT) #define CHOOSE_MODE(tt, skas) (tt) + +#else +#error CONFIG_MODE_SKAS and CONFIG_MODE_TT are both disabled #endif #define CHOOSE_MODE_PROC(tt, skas, args...) \ -- cgit v1.2.3 From 7b033e1fdeef3d8bacac3cd5cfa53c9d670d1f3d Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:19:03 -0800 Subject: [PATCH] uml: add mconsole_reply variant with length param This is needed for the console output patch, since we have a possibly non-NULL-terminated string there. So, the new interface takes a string and a length, and the old interface calls strlen on its string and calls the new interface with the length. There's also a bit of whitespace cleanup. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/mconsole_user.c | 12 +++++++++--- arch/um/include/mconsole.h | 8 +++++--- 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index 310c1f823f2..4b109fe7fff 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c @@ -122,12 +122,12 @@ int mconsole_get_request(int fd, struct mc_request *req) return(1); } -int mconsole_reply(struct mc_request *req, char *str, int err, int more) +int mconsole_reply_len(struct mc_request *req, const char *str, int total, + int err, int more) { struct mconsole_reply reply; - int total, len, n; + int len, n; - total = strlen(str); do { reply.err = err; @@ -155,6 +155,12 @@ int mconsole_reply(struct mc_request *req, char *str, int err, int more) return(0); } +int mconsole_reply(struct mc_request *req, const char *str, int err, int more) +{ + return mconsole_reply_len(req, str, strlen(str), err, more); +} + + int mconsole_unlink_socket(void) { unlink(mconsole_socket_name); diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h index b1b512f4703..58f67d39110 100644 --- a/arch/um/include/mconsole.h +++ b/arch/um/include/mconsole.h @@ -32,7 +32,7 @@ struct mconsole_reply { struct mconsole_notify { u32 magic; - u32 version; + u32 version; enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG, MCONSOLE_USER_NOTIFY } type; u32 len; @@ -66,7 +66,9 @@ struct mc_request extern char mconsole_socket_name[]; extern int mconsole_unlink_socket(void); -extern int mconsole_reply(struct mc_request *req, char *reply, int err, +extern int mconsole_reply_len(struct mc_request *req, const char *reply, + int len, int err, int more); +extern int mconsole_reply(struct mc_request *req, const char *str, int err, int more); extern void mconsole_version(struct mc_request *req); @@ -84,7 +86,7 @@ extern void mconsole_proc(struct mc_request *req); extern void mconsole_stack(struct mc_request *req); extern int mconsole_get_request(int fd, struct mc_request *req); -extern int mconsole_notify(char *sock_name, int type, const void *data, +extern int mconsole_notify(char *sock_name, int type, const void *data, int len); extern char *mconsole_notify_socket(void); extern void lock_notify(void); -- cgit v1.2.3 From 6f517d3fc862d3c8d8ba65c0b2472d399aceb9ed Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:19:04 -0800 Subject: [PATCH] uml: capture printk output for mconsole stack The stack command now sends the printk output back to the mconsole client. This is done by registering a special console for the mconsole driver. This receives all printk output. Normally, it is ignored, but when a stack command is issued, any printk output will be sent back to the client. This will capture any printk output, whether it is stack output or not, since we can't tell the difference. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/mconsole_kern.c | 87 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index b5217bd7bc4..e9bbc14f365 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -20,6 +20,7 @@ #include "linux/namei.h" #include "linux/proc_fs.h" #include "linux/syscalls.h" +#include "linux/console.h" #include "asm/irq.h" #include "asm/uaccess.h" #include "user_util.h" @@ -480,6 +481,82 @@ void mconsole_sysrq(struct mc_request *req) } #endif +static DEFINE_SPINLOCK(console_lock); +static LIST_HEAD(clients); +static char console_buf[MCONSOLE_MAX_DATA]; +static int console_index = 0; + +static void console_write(struct console *console, const char *string, + unsigned len) +{ + struct list_head *ele; + int n; + + if(list_empty(&clients)) + return; + + while(1){ + n = min(len, ARRAY_SIZE(console_buf) - console_index); + strncpy(&console_buf[console_index], string, n); + console_index += n; + string += n; + len -= n; + if(len == 0) + return; + + list_for_each(ele, &clients){ + struct mconsole_entry *entry; + + entry = list_entry(ele, struct mconsole_entry, list); + mconsole_reply_len(&entry->request, console_buf, + console_index, 0, 1); + } + + console_index = 0; + } +} + +static struct console mc_console = { .name = "mc", + .write = console_write, + .flags = CON_PRINTBUFFER | CON_ENABLED, + .index = -1 }; + +static int mc_add_console(void) +{ + register_console(&mc_console); + return 0; +} + +late_initcall(mc_add_console); + +static void with_console(struct mc_request *req, void (*proc)(void *), + void *arg) +{ + struct mconsole_entry entry; + unsigned long flags; + + INIT_LIST_HEAD(&entry.list); + entry.request = *req; + list_add(&entry.list, &clients); + spin_lock_irqsave(&console_lock, flags); + + (*proc)(arg); + + mconsole_reply_len(req, console_buf, console_index, 0, 0); + console_index = 0; + + spin_unlock_irqrestore(&console_lock, flags); + list_del(&entry.list); +} + +static void stack_proc(void *arg) +{ + struct task_struct *from = current, *to = arg; + + to->thread.saved_task = from; + switch_to(from, to, from); +} + /* Mconsole stack trace * Added by Allan Graves, Jeff Dike * Dumps a stacks registers to the linux console. @@ -489,7 +566,7 @@ void do_stack(struct mc_request *req) { char *ptr = req->request.data; int pid_requested= -1; - struct task_struct *from = NULL; + struct task_struct *from = NULL; struct task_struct *to = NULL; /* Would be nice: @@ -507,17 +584,15 @@ void do_stack(struct mc_request *req) return; } - from = current; - to = find_task_by_pid(pid_requested); + from = current; + to = find_task_by_pid(pid_requested); if((to == NULL) || (pid_requested == 0)) { mconsole_reply(req, "Couldn't find that pid", 1, 0); return; } - to->thread.saved_task = current; - switch_to(from, to, from); - mconsole_reply(req, "Stack Dumped to console and message log", 0, 0); + with_console(req, stack_proc, to); } void mconsole_stack(struct mc_request *req) -- cgit v1.2.3 From 4111b025dc64f33803d2147565147428dc51d014 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:19:05 -0800 Subject: [PATCH] uml: capture printk output for mconsole sysrq Pass sysrq output back to the mconsole client using the mechanism introduced for stack output. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/mconsole_kern.c | 48 +++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 18 deletions(-) (limited to 'arch') diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index e9bbc14f365..8b453a7e685 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -463,24 +463,6 @@ void mconsole_remove(struct mc_request *req) mconsole_reply(req, err_msg, err, 0); } -#ifdef CONFIG_MAGIC_SYSRQ -void mconsole_sysrq(struct mc_request *req) -{ - char *ptr = req->request.data; - - ptr += strlen("sysrq"); - while(isspace(*ptr)) ptr++; - - mconsole_reply(req, "", 0, 0); - handle_sysrq(*ptr, ¤t->thread.regs, NULL); -} -#else -void mconsole_sysrq(struct mc_request *req) -{ - mconsole_reply(req, "Sysrq not compiled in", 1, 0); -} -#endif - static DEFINE_SPINLOCK(console_lock); static LIST_HEAD(clients); static char console_buf[MCONSOLE_MAX_DATA]; @@ -549,6 +531,36 @@ static void with_console(struct mc_request *req, void (*proc)(void *), list_del(&entry.list); } +#ifdef CONFIG_MAGIC_SYSRQ +static void sysrq_proc(void *arg) +{ + char *op = arg; + + handle_sysrq(*op, ¤t->thread.regs, NULL); +} + +void mconsole_sysrq(struct mc_request *req) +{ + char *ptr = req->request.data; + + ptr += strlen("sysrq"); + while(isspace(*ptr)) ptr++; + + /* With 'b', the system will shut down without a chance to reply, + * so in this case, we reply first. + */ + if(*ptr == 'b') + mconsole_reply(req, "", 0, 0); + + with_console(req, sysrq_proc, ptr); +} +#else +void mconsole_sysrq(struct mc_request *req) +{ + mconsole_reply(req, "Sysrq not compiled in", 1, 0); +} +#endif + static void stack_proc(void *arg) { struct task_struct *from = current, *to = arg; -- cgit v1.2.3 From 3a331a511a2fe522034f3958eecf58751be434ac Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:19:05 -0800 Subject: [PATCH] uml: fix whitespace in mconsole driver Fix up some bogus spacing in the mconsole driver. Also delete the emacs formatting comment at the end. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/mconsole_kern.c | 96 ++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 54 deletions(-) (limited to 'arch') diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 8b453a7e685..be610125429 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -422,7 +422,7 @@ void mconsole_remove(struct mc_request *req) { struct mc_device *dev; char *ptr = req->request.data, *err_msg = ""; - char error[256]; + char error[256]; int err, start, end, n; ptr += strlen("remove"); @@ -433,33 +433,33 @@ void mconsole_remove(struct mc_request *req) return; } - ptr = &ptr[strlen(dev->name)]; - - err = 1; - n = (*dev->id)(&ptr, &start, &end); - if(n < 0){ - err_msg = "Couldn't parse device number"; - goto out; - } - else if((n < start) || (n > end)){ - sprintf(error, "Invalid device number - must be between " - "%d and %d", start, end); - err_msg = error; - goto out; - } + ptr = &ptr[strlen(dev->name)]; + + err = 1; + n = (*dev->id)(&ptr, &start, &end); + if(n < 0){ + err_msg = "Couldn't parse device number"; + goto out; + } + else if((n < start) || (n > end)){ + sprintf(error, "Invalid device number - must be between " + "%d and %d", start, end); + err_msg = error; + goto out; + } err = (*dev->remove)(n); - switch(err){ - case -ENODEV: - err_msg = "Device doesn't exist"; - break; - case -EBUSY: - err_msg = "Device is currently open"; - break; - default: - break; - } - out: + switch(err){ + case -ENODEV: + err_msg = "Device doesn't exist"; + break; + case -EBUSY: + err_msg = "Device is currently open"; + break; + default: + break; + } +out: mconsole_reply(req, err_msg, err, 0); } @@ -576,34 +576,33 @@ static void stack_proc(void *arg) */ void do_stack(struct mc_request *req) { - char *ptr = req->request.data; - int pid_requested= -1; + char *ptr = req->request.data; + int pid_requested= -1; struct task_struct *from = NULL; struct task_struct *to = NULL; - /* Would be nice: - * 1) Send showregs output to mconsole. + /* Would be nice: + * 1) Send showregs output to mconsole. * 2) Add a way to stack dump all pids. */ - ptr += strlen("stack"); - while(isspace(*ptr)) ptr++; + ptr += strlen("stack"); + while(isspace(*ptr)) ptr++; - /* Should really check for multiple pids or reject bad args here */ - /* What do the arguments in mconsole_reply mean? */ - if(sscanf(ptr, "%d", &pid_requested) == 0){ - mconsole_reply(req, "Please specify a pid", 1, 0); - return; - } + /* Should really check for multiple pids or reject bad args here */ + /* What do the arguments in mconsole_reply mean? */ + if(sscanf(ptr, "%d", &pid_requested) == 0){ + mconsole_reply(req, "Please specify a pid", 1, 0); + return; + } from = current; to = find_task_by_pid(pid_requested); - if((to == NULL) || (pid_requested == 0)) { - mconsole_reply(req, "Couldn't find that pid", 1, 0); - return; - } - + if((to == NULL) || (pid_requested == 0)) { + mconsole_reply(req, "Couldn't find that pid", 1, 0); + return; + } with_console(req, stack_proc, to); } @@ -772,14 +771,3 @@ char *mconsole_notify_socket(void) } EXPORT_SYMBOL(mconsole_notify_socket); - -/* - * 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: - */ -- cgit v1.2.3 From 8d93c700a489eba08514222df414a23852a85d2b Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 6 Jan 2006 00:19:06 -0800 Subject: [PATCH] uml: free network IRQ correctly Free the network IRQ when closing down the network devices at shutdown. Delete the device from the opened devices list on close. These prevent an -EBADF when later disabling SIGIO on all extant descriptors and a complaint from free_irq about freeing the IRQ twice. Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/net_kern.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index deb24828e6a..fb1f9fb9b87 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -150,6 +150,7 @@ static int uml_net_close(struct net_device *dev) if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); lp->fd = -1; + list_del(&lp->list); spin_unlock(&lp->lock); return 0; @@ -715,6 +716,7 @@ static void close_devices(void) list_for_each(ele, &opened){ lp = list_entry(ele, struct uml_net_private, list); + free_irq(lp->dev->irq, lp->dev); if((lp->close != NULL) && (lp->fd >= 0)) (*lp->close)(lp->fd, &lp->user); if(lp->remove != NULL) (*lp->remove)(&lp->user); -- cgit v1.2.3 From 973bd9937569146de0917f54f05b2942f8257912 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Fri, 6 Jan 2006 00:19:07 -0800 Subject: [PATCH] s390: atomic primitives Hugh Dickins Fix the broken atomic_cmpxchg primitive. Add atomic_sub_and_test, atomic64_sub_return, atomic64_sub_and_test, atomic64_cmpxchg, atomic64_add_unless and atomic64_inc_not_zero. Replace old style atomic_compare_and_swap by atomic_cmpxchg. Shorten the whole header by defining most primitives with the two inline functions atomic_add_return and atomic_sub_return. In addition this patch contains the s390 related fixes of Hugh's "mm: fill arch atomic64 gaps" patch. Signed-off-by: Martin Schwidefsky Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/kernel/machine_kexec.c | 2 +- arch/s390/kernel/smp.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index 5aa71b05b8a..f0ed5c642c7 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c @@ -85,7 +85,7 @@ kexec_halt_all_cpus(void *kernel_image) pfault_fini(); #endif - if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid)) + if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1) signal_processor(smp_processor_id(), sigp_stop); /* Wait for all other cpus to enter stopped state */ diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 5856b3fda6b..bd5b311006b 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -263,7 +263,7 @@ static void do_machine_restart(void * __unused) int cpu; static atomic_t cpuid = ATOMIC_INIT(-1); - if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid)) + if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1) signal_processor(smp_processor_id(), sigp_stop); /* Wait for all other cpus to enter stopped state */ @@ -313,7 +313,7 @@ static void do_machine_halt(void * __unused) { static atomic_t cpuid = ATOMIC_INIT(-1); - if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid) == 0) { + if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) == -1) { smp_send_stop(); if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0) cpcmd(vmhalt_cmd, NULL, 0, NULL); @@ -332,7 +332,7 @@ static void do_machine_power_off(void * __unused) { static atomic_t cpuid = ATOMIC_INIT(-1); - if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid) == 0) { + if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) == -1) { smp_send_stop(); if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0) cpcmd(vmpoff_cmd, NULL, 0, NULL); -- cgit v1.2.3 From a63a4931c301a14ca79c41fec0b99d898dbba1fb Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Fri, 6 Jan 2006 00:19:09 -0800 Subject: [PATCH] s390: uaccess warnings Convert __access_ok to an inline C function and change __get_user primitive to avoid uaccess compiler warnings. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/kernel/compat_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index ed877d0f27e..41b197a3f3a 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -279,7 +279,7 @@ asmlinkage long sys32_getegid16(void) static inline long get_tv32(struct timeval *o, struct compat_timeval *i) { - return (!access_ok(VERIFY_READ, tv32, sizeof(*tv32)) || + return (!access_ok(VERIFY_READ, o, sizeof(*o)) || (__get_user(o->tv_sec, &i->tv_sec) || __get_user(o->tv_usec, &i->tv_usec))); } -- cgit v1.2.3 From 4e3df37e7fb4e41bec84465ff31949737160ed58 Mon Sep 17 00:00:00 2001 From: Cedric Le Goater Date: Fri, 6 Jan 2006 00:19:10 -0800 Subject: [PATCH] s390: rt_sigreturn fix Check return code of do_sigaltstack and force a SIGSEGV if it is -EFAULT. Signed-off-by: Martin Schwidefsky Signed-off-by: Cedric Le Goater Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/kernel/compat_signal.c | 2 -- arch/s390/kernel/signal.c | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index 4ff6808456e..fa2b3bc22f2 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -467,8 +467,6 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) if (err) goto badframe; - /* It is more difficult to avoid calling this function than to - call it and ignore errors. */ set_fs (KERNEL_DS); do_sigaltstack((stack_t __user *)&st, NULL, regs->gprs[15]); set_fs (old_fs); diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index 6e0110d7119..13592d00a10 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -254,9 +254,9 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) if (restore_sigregs(regs, &frame->uc.uc_mcontext)) goto badframe; - /* It is more difficult to avoid calling this function than to - call it and ignore errors. */ - do_sigaltstack(&frame->uc.uc_stack, NULL, regs->gprs[15]); + if (do_sigaltstack(&frame->uc.uc_stack, NULL, + regs->gprs[15]) == -EFAULT) + goto badframe; return regs->gprs[2]; badframe: -- cgit v1.2.3 From 088c4ec16aa6b865dcf690051ddac30eb2bf6bcc Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Fri, 6 Jan 2006 00:19:11 -0800 Subject: [PATCH] s390: update default configuration Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/defconfig | 55 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 45d44c6bb39..0c495fe8311 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.14-rc1 -# Wed Sep 14 16:46:19 2005 +# Linux kernel version: 2.6.15-rc2 +# Mon Nov 21 13:51:30 2005 # CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y @@ -64,6 +64,24 @@ CONFIG_MODVERSIONS=y CONFIG_KMOD=y CONFIG_STOP_MACHINE=y +# +# Block layer +# +# CONFIG_LBD is not set + +# +# IO Schedulers +# +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" + # # Base setup # @@ -97,6 +115,7 @@ CONFIG_FLATMEM_MANUAL=y CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 # # I/O subsystem configuration @@ -188,10 +207,18 @@ CONFIG_IPV6=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=y CONFIG_NET_SCH_CLK_JIFFIES=y # CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set # CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# CONFIG_NET_SCH_CBQ=m # CONFIG_NET_SCH_HTB is not set # CONFIG_NET_SCH_HFSC is not set @@ -204,8 +231,10 @@ CONFIG_NET_SCH_GRED=m CONFIG_NET_SCH_DSMARK=m # CONFIG_NET_SCH_NETEM is not set # CONFIG_NET_SCH_INGRESS is not set -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y + +# +# Classification +# CONFIG_NET_CLS=y # CONFIG_NET_CLS_BASIC is not set CONFIG_NET_CLS_TCINDEX=m @@ -214,18 +243,18 @@ CONFIG_NET_CLS_ROUTE=y CONFIG_NET_CLS_FW=m CONFIG_NET_CLS_U32=m # CONFIG_CLS_U32_PERF is not set -# CONFIG_NET_CLS_IND is not set CONFIG_NET_CLS_RSVP=m CONFIG_NET_CLS_RSVP6=m # CONFIG_NET_EMATCH is not set # CONFIG_NET_CLS_ACT is not set CONFIG_NET_CLS_POLICE=y +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_ESTIMATOR=y # # Network testing # # CONFIG_NET_PKTGEN is not set -# CONFIG_NETFILTER_NETLINK is not set # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set @@ -276,6 +305,7 @@ CONFIG_SCSI_FC_ATTRS=y # # SCSI low-level drivers # +# CONFIG_ISCSI_TCP is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_DEBUG is not set CONFIG_ZFCP=y @@ -292,7 +322,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y -# CONFIG_LBD is not set # CONFIG_CDROM_PKTCDVD is not set # @@ -305,15 +334,8 @@ CONFIG_DASD_PROFILE=y CONFIG_DASD_ECKD=y CONFIG_DASD_FBA=y CONFIG_DASD_DIAG=y +CONFIG_DASD_EER=m # CONFIG_DASD_CMB is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_ATA_OVER_ETH is not set # @@ -378,7 +400,6 @@ CONFIG_S390_TAPE_34XX=m # CONFIG_VMLOGRDR is not set # CONFIG_VMCP is not set # CONFIG_MONREADER is not set -# CONFIG_DCSS_SHM is not set # # Cryptographic devices @@ -593,6 +614,8 @@ CONFIG_DEBUG_PREEMPT=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 # # Security options -- cgit v1.2.3 From 089545f0c71bab6511395c2a060d7f81a99bad58 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Fri, 6 Jan 2006 00:19:12 -0800 Subject: [PATCH] s390: cputime_t fixes There are some more places where the use of cputime_t instead of an integer type and the associated macros is necessary for the virtual cputime accounting on s390. Affected are the s390 specific appldata code and BSD process accounting. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/appldata/appldata_os.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/s390/appldata/appldata_os.c b/arch/s390/appldata/appldata_os.c index e0a476bf4fd..99ddd3bf2fb 100644 --- a/arch/s390/appldata/appldata_os.c +++ b/arch/s390/appldata/appldata_os.c @@ -141,19 +141,19 @@ static void appldata_get_os_data(void *data) j = 0; for_each_online_cpu(i) { os_data->os_cpu[j].per_cpu_user = - kstat_cpu(i).cpustat.user; + cputime_to_jiffies(kstat_cpu(i).cpustat.user); os_data->os_cpu[j].per_cpu_nice = - kstat_cpu(i).cpustat.nice; + cputime_to_jiffies(kstat_cpu(i).cpustat.nice); os_data->os_cpu[j].per_cpu_system = - kstat_cpu(i).cpustat.system; + cputime_to_jiffies(kstat_cpu(i).cpustat.system); os_data->os_cpu[j].per_cpu_idle = - kstat_cpu(i).cpustat.idle; + cputime_to_jiffies(kstat_cpu(i).cpustat.idle); os_data->os_cpu[j].per_cpu_irq = - kstat_cpu(i).cpustat.irq; + cputime_to_jiffies(kstat_cpu(i).cpustat.irq); os_data->os_cpu[j].per_cpu_softirq = - kstat_cpu(i).cpustat.softirq; + cputime_to_jiffies(kstat_cpu(i).cpustat.softirq); os_data->os_cpu[j].per_cpu_iowait = - kstat_cpu(i).cpustat.iowait; + cputime_to_jiffies(kstat_cpu(i).cpustat.iowait); j++; } -- cgit v1.2.3 From d0f4c16febf258ba8c0f917ac3ba935fc5459566 Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Fri, 6 Jan 2006 00:19:16 -0800 Subject: [PATCH] s390: add oprofile callgraph support Signed-off-by: Andreas Krebbel Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/oprofile/Makefile | 2 +- arch/s390/oprofile/backtrace.c | 79 ++++++++++++++++++++++++++++++++++++++++++ arch/s390/oprofile/init.c | 4 +++ 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 arch/s390/oprofile/backtrace.c (limited to 'arch') diff --git a/arch/s390/oprofile/Makefile b/arch/s390/oprofile/Makefile index ec349276258..537b2d840e6 100644 --- a/arch/s390/oprofile/Makefile +++ b/arch/s390/oprofile/Makefile @@ -6,4 +6,4 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ oprofilefs.o oprofile_stats.o \ timer_int.o ) -oprofile-y := $(DRIVER_OBJS) init.o +oprofile-y := $(DRIVER_OBJS) init.o backtrace.o diff --git a/arch/s390/oprofile/backtrace.c b/arch/s390/oprofile/backtrace.c new file mode 100644 index 00000000000..bc4b84a35ca --- /dev/null +++ b/arch/s390/oprofile/backtrace.c @@ -0,0 +1,79 @@ +/** + * arch/s390/oprofile/backtrace.c + * + * S390 Version + * Copyright (C) 2005 IBM Corporation, IBM Deutschland Entwicklung GmbH. + * Author(s): Andreas Krebbel + */ + +#include + +#include /* for struct stack_frame */ + +static unsigned long +__show_trace(unsigned int *depth, unsigned long sp, + unsigned long low, unsigned long high) +{ + struct stack_frame *sf; + struct pt_regs *regs; + + while (*depth) { + sp = sp & PSW_ADDR_INSN; + if (sp < low || sp > high - sizeof(*sf)) + return sp; + sf = (struct stack_frame *) sp; + (*depth)--; + oprofile_add_trace(sf->gprs[8] & PSW_ADDR_INSN); + + /* Follow the backchain. */ + while (*depth) { + low = sp; + sp = sf->back_chain & PSW_ADDR_INSN; + if (!sp) + break; + if (sp <= low || sp > high - sizeof(*sf)) + return sp; + sf = (struct stack_frame *) sp; + (*depth)--; + oprofile_add_trace(sf->gprs[8] & PSW_ADDR_INSN); + + } + + if (*depth == 0) + break; + + /* Zero backchain detected, check for interrupt frame. */ + sp = (unsigned long) (sf + 1); + if (sp <= low || sp > high - sizeof(*regs)) + return sp; + regs = (struct pt_regs *) sp; + (*depth)--; + oprofile_add_trace(sf->gprs[8] & PSW_ADDR_INSN); + low = sp; + sp = regs->gprs[15]; + } + return sp; +} + +void s390_backtrace(struct pt_regs * const regs, unsigned int depth) +{ + unsigned long head; + struct stack_frame* head_sf; + + if (user_mode (regs)) + return; + + head = regs->gprs[15]; + head_sf = (struct stack_frame*)head; + + if (!head_sf->back_chain) + return; + + head = head_sf->back_chain; + + head = __show_trace(&depth, head, S390_lowcore.async_stack - ASYNC_SIZE, + S390_lowcore.async_stack); + + __show_trace(&depth, head, S390_lowcore.thread_info, + S390_lowcore.thread_info + THREAD_SIZE); +} diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c index a65ead0e200..7a995113b91 100644 --- a/arch/s390/oprofile/init.c +++ b/arch/s390/oprofile/init.c @@ -12,8 +12,12 @@ #include #include + +extern void s390_backtrace(struct pt_regs * const regs, unsigned int depth); + int __init oprofile_arch_init(struct oprofile_operations* ops) { + ops->backtrace = s390_backtrace; return -ENODEV; } -- cgit v1.2.3 From c1e26e1ef7ab50f30e5fbf004fe96ed44321ca78 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Fri, 6 Jan 2006 00:19:17 -0800 Subject: [PATCH] s390: in-kernel crypto rename Replace all references to z990 by s390 in the in-kernel crypto files in arch/s390/crypto. The code is not specific to a particular machine (z990) but to the s390 platform. Big diff, does nothing.. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/crypto/Makefile | 6 +- arch/s390/crypto/crypt_s390.h | 383 ++++++++++++++++++++++++++++++++++++ arch/s390/crypto/crypt_s390_query.c | 113 +++++++++++ arch/s390/crypto/crypt_z990.h | 374 ----------------------------------- arch/s390/crypto/crypt_z990_query.c | 111 ----------- arch/s390/crypto/des_s390.c | 284 ++++++++++++++++++++++++++ arch/s390/crypto/des_z990.c | 284 -------------------------- arch/s390/crypto/sha1_s390.c | 167 ++++++++++++++++ arch/s390/crypto/sha1_z990.c | 167 ---------------- arch/s390/defconfig | 4 +- 10 files changed, 952 insertions(+), 941 deletions(-) create mode 100644 arch/s390/crypto/crypt_s390.h create mode 100644 arch/s390/crypto/crypt_s390_query.c delete mode 100644 arch/s390/crypto/crypt_z990.h delete mode 100644 arch/s390/crypto/crypt_z990_query.c create mode 100644 arch/s390/crypto/des_s390.c delete mode 100644 arch/s390/crypto/des_z990.c create mode 100644 arch/s390/crypto/sha1_s390.c delete mode 100644 arch/s390/crypto/sha1_z990.c (limited to 'arch') diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile index 96a05e6b51e..50843f8d095 100644 --- a/arch/s390/crypto/Makefile +++ b/arch/s390/crypto/Makefile @@ -2,7 +2,7 @@ # Cryptographic API # -obj-$(CONFIG_CRYPTO_SHA1_Z990) += sha1_z990.o -obj-$(CONFIG_CRYPTO_DES_Z990) += des_z990.o des_check_key.o +obj-$(CONFIG_CRYPTO_SHA1_S390) += sha1_s390.o +obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o des_check_key.o -obj-$(CONFIG_CRYPTO_TEST) += crypt_z990_query.o +obj-$(CONFIG_CRYPTO_TEST) += crypt_s390_query.o diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h new file mode 100644 index 00000000000..4d24f668975 --- /dev/null +++ b/arch/s390/crypto/crypt_s390.h @@ -0,0 +1,383 @@ +/* + * Cryptographic API. + * + * Support for s390 cryptographic instructions. + * + * Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation + * Author(s): Thomas Spatzier (tspat@de.ibm.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. + * + */ +#ifndef _CRYPTO_ARCH_S390_CRYPT_S390_H +#define _CRYPTO_ARCH_S390_CRYPT_S390_H + +#include + +#define CRYPT_S390_OP_MASK 0xFF00 +#define CRYPT_S390_FUNC_MASK 0x00FF + +/* s930 cryptographic operations */ +enum crypt_s390_operations { + CRYPT_S390_KM = 0x0100, + CRYPT_S390_KMC = 0x0200, + CRYPT_S390_KIMD = 0x0300, + CRYPT_S390_KLMD = 0x0400, + CRYPT_S390_KMAC = 0x0500 +}; + +/* function codes for KM (CIPHER MESSAGE) instruction + * 0x80 is the decipher modifier bit + */ +enum crypt_s390_km_func { + KM_QUERY = CRYPT_S390_KM | 0, + KM_DEA_ENCRYPT = CRYPT_S390_KM | 1, + KM_DEA_DECRYPT = CRYPT_S390_KM | 1 | 0x80, + KM_TDEA_128_ENCRYPT = CRYPT_S390_KM | 2, + KM_TDEA_128_DECRYPT = CRYPT_S390_KM | 2 | 0x80, + KM_TDEA_192_ENCRYPT = CRYPT_S390_KM | 3, + KM_TDEA_192_DECRYPT = CRYPT_S390_KM | 3 | 0x80, +}; + +/* function codes for KMC (CIPHER MESSAGE WITH CHAINING) + * instruction + */ +enum crypt_s390_kmc_func { + KMC_QUERY = CRYPT_S390_KMC | 0, + KMC_DEA_ENCRYPT = CRYPT_S390_KMC | 1, + KMC_DEA_DECRYPT = CRYPT_S390_KMC | 1 | 0x80, + KMC_TDEA_128_ENCRYPT = CRYPT_S390_KMC | 2, + KMC_TDEA_128_DECRYPT = CRYPT_S390_KMC | 2 | 0x80, + KMC_TDEA_192_ENCRYPT = CRYPT_S390_KMC | 3, + KMC_TDEA_192_DECRYPT = CRYPT_S390_KMC | 3 | 0x80, +}; + +/* function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) + * instruction + */ +enum crypt_s390_kimd_func { + KIMD_QUERY = CRYPT_S390_KIMD | 0, + KIMD_SHA_1 = CRYPT_S390_KIMD | 1, +}; + +/* function codes for KLMD (COMPUTE LAST MESSAGE DIGEST) + * instruction + */ +enum crypt_s390_klmd_func { + KLMD_QUERY = CRYPT_S390_KLMD | 0, + KLMD_SHA_1 = CRYPT_S390_KLMD | 1, +}; + +/* function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) + * instruction + */ +enum crypt_s390_kmac_func { + KMAC_QUERY = CRYPT_S390_KMAC | 0, + KMAC_DEA = CRYPT_S390_KMAC | 1, + KMAC_TDEA_128 = CRYPT_S390_KMAC | 2, + KMAC_TDEA_192 = CRYPT_S390_KMAC | 3 +}; + +/* status word for s390 crypto instructions' QUERY functions */ +struct crypt_s390_query_status { + u64 high; + u64 low; +}; + +/* + * Standard fixup and ex_table sections for crypt_s390 inline functions. + * label 0: the s390 crypto operation + * label 1: just after 1 to catch illegal operation exception + * (unsupported model) + * label 6: the return point after fixup + * label 7: set error value if exception _in_ crypto operation + * label 8: set error value if illegal operation exception + * [ret] is the variable to receive the error code + * [ERR] is the error code value + */ +#ifndef __s390x__ +#define __crypt_s390_fixup \ + ".section .fixup,\"ax\" \n" \ + "7: lhi %0,%h[e1] \n" \ + " bras 1,9f \n" \ + " .long 6b \n" \ + "8: lhi %0,%h[e2] \n" \ + " bras 1,9f \n" \ + " .long 6b \n" \ + "9: l 1,0(1) \n" \ + " br 1 \n" \ + ".previous \n" \ + ".section __ex_table,\"a\" \n" \ + " .align 4 \n" \ + " .long 0b,7b \n" \ + " .long 1b,8b \n" \ + ".previous" +#else /* __s390x__ */ +#define __crypt_s390_fixup \ + ".section .fixup,\"ax\" \n" \ + "7: lhi %0,%h[e1] \n" \ + " jg 6b \n" \ + "8: lhi %0,%h[e2] \n" \ + " jg 6b \n" \ + ".previous\n" \ + ".section __ex_table,\"a\" \n" \ + " .align 8 \n" \ + " .quad 0b,7b \n" \ + " .quad 1b,8b \n" \ + ".previous" +#endif /* __s390x__ */ + +/* + * Standard code for setting the result of s390 crypto instructions. + * %0: the register which will receive the result + * [result]: the register containing the result (e.g. second operand length + * to compute number of processed bytes]. + */ +#ifndef __s390x__ +#define __crypt_s390_set_result \ + " lr %0,%[result] \n" +#else /* __s390x__ */ +#define __crypt_s390_set_result \ + " lgr %0,%[result] \n" +#endif + +/* + * Executes the KM (CIPHER MESSAGE) operation of the CPU. + * @param func: the function code passed to KM; see crypt_s390_km_func + * @param param: address of parameter block; see POP for details on each func + * @param dest: address of destination memory area + * @param src: address of source memory area + * @param src_len: length of src operand in bytes + * @returns < zero for failure, 0 for the query func, number of processed bytes + * for encryption/decryption funcs + */ +static inline int +crypt_s390_km(long func, void* param, u8* dest, const u8* src, long src_len) +{ + register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; + register void* __param asm("1") = param; + register u8* __dest asm("4") = dest; + register const u8* __src asm("2") = src; + register long __src_len asm("3") = src_len; + int ret; + + ret = 0; + __asm__ __volatile__ ( + "0: .insn rre,0xB92E0000,%1,%2 \n" /* KM opcode */ + "1: brc 1,0b \n" /* handle partial completion */ + __crypt_s390_set_result + "6: \n" + __crypt_s390_fixup + : "+d" (ret), "+a" (__dest), "+a" (__src), + [result] "+d" (__src_len) + : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), + "a" (__param) + : "cc", "memory" + ); + if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){ + ret = src_len - ret; + } + return ret; +} + +/* + * Executes the KMC (CIPHER MESSAGE WITH CHAINING) operation of the CPU. + * @param func: the function code passed to KM; see crypt_s390_kmc_func + * @param param: address of parameter block; see POP for details on each func + * @param dest: address of destination memory area + * @param src: address of source memory area + * @param src_len: length of src operand in bytes + * @returns < zero for failure, 0 for the query func, number of processed bytes + * for encryption/decryption funcs + */ +static inline int +crypt_s390_kmc(long func, void* param, u8* dest, const u8* src, long src_len) +{ + register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; + register void* __param asm("1") = param; + register u8* __dest asm("4") = dest; + register const u8* __src asm("2") = src; + register long __src_len asm("3") = src_len; + int ret; + + ret = 0; + __asm__ __volatile__ ( + "0: .insn rre,0xB92F0000,%1,%2 \n" /* KMC opcode */ + "1: brc 1,0b \n" /* handle partial completion */ + __crypt_s390_set_result + "6: \n" + __crypt_s390_fixup + : "+d" (ret), "+a" (__dest), "+a" (__src), + [result] "+d" (__src_len) + : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), + "a" (__param) + : "cc", "memory" + ); + if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){ + ret = src_len - ret; + } + return ret; +} + +/* + * Executes the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) operation + * of the CPU. + * @param func: the function code passed to KM; see crypt_s390_kimd_func + * @param param: address of parameter block; see POP for details on each func + * @param src: address of source memory area + * @param src_len: length of src operand in bytes + * @returns < zero for failure, 0 for the query func, number of processed bytes + * for digest funcs + */ +static inline int +crypt_s390_kimd(long func, void* param, const u8* src, long src_len) +{ + register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; + register void* __param asm("1") = param; + register const u8* __src asm("2") = src; + register long __src_len asm("3") = src_len; + int ret; + + ret = 0; + __asm__ __volatile__ ( + "0: .insn rre,0xB93E0000,%1,%1 \n" /* KIMD opcode */ + "1: brc 1,0b \n" /* handle partical completion */ + __crypt_s390_set_result + "6: \n" + __crypt_s390_fixup + : "+d" (ret), "+a" (__src), [result] "+d" (__src_len) + : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), + "a" (__param) + : "cc", "memory" + ); + if (ret >= 0 && (func & CRYPT_S390_FUNC_MASK)){ + ret = src_len - ret; + } + return ret; +} + +/* + * Executes the KLMD (COMPUTE LAST MESSAGE DIGEST) operation of the CPU. + * @param func: the function code passed to KM; see crypt_s390_klmd_func + * @param param: address of parameter block; see POP for details on each func + * @param src: address of source memory area + * @param src_len: length of src operand in bytes + * @returns < zero for failure, 0 for the query func, number of processed bytes + * for digest funcs + */ +static inline int +crypt_s390_klmd(long func, void* param, const u8* src, long src_len) +{ + register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; + register void* __param asm("1") = param; + register const u8* __src asm("2") = src; + register long __src_len asm("3") = src_len; + int ret; + + ret = 0; + __asm__ __volatile__ ( + "0: .insn rre,0xB93F0000,%1,%1 \n" /* KLMD opcode */ + "1: brc 1,0b \n" /* handle partical completion */ + __crypt_s390_set_result + "6: \n" + __crypt_s390_fixup + : "+d" (ret), "+a" (__src), [result] "+d" (__src_len) + : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), + "a" (__param) + : "cc", "memory" + ); + if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){ + ret = src_len - ret; + } + return ret; +} + +/* + * Executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) operation + * of the CPU. + * @param func: the function code passed to KM; see crypt_s390_klmd_func + * @param param: address of parameter block; see POP for details on each func + * @param src: address of source memory area + * @param src_len: length of src operand in bytes + * @returns < zero for failure, 0 for the query func, number of processed bytes + * for digest funcs + */ +static inline int +crypt_s390_kmac(long func, void* param, const u8* src, long src_len) +{ + register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; + register void* __param asm("1") = param; + register const u8* __src asm("2") = src; + register long __src_len asm("3") = src_len; + int ret; + + ret = 0; + __asm__ __volatile__ ( + "0: .insn rre,0xB91E0000,%5,%5 \n" /* KMAC opcode */ + "1: brc 1,0b \n" /* handle partical completion */ + __crypt_s390_set_result + "6: \n" + __crypt_s390_fixup + : "+d" (ret), "+a" (__src), [result] "+d" (__src_len) + : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), + "a" (__param) + : "cc", "memory" + ); + if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){ + ret = src_len - ret; + } + return ret; +} + +/** + * Tests if a specific crypto function is implemented on the machine. + * @param func: the function code of the specific function; 0 if op in general + * @return 1 if func available; 0 if func or op in general not available + */ +static inline int +crypt_s390_func_available(int func) +{ + int ret; + + struct crypt_s390_query_status status = { + .high = 0, + .low = 0 + }; + switch (func & CRYPT_S390_OP_MASK){ + case CRYPT_S390_KM: + ret = crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0); + break; + case CRYPT_S390_KMC: + ret = crypt_s390_kmc(KMC_QUERY, &status, NULL, NULL, 0); + break; + case CRYPT_S390_KIMD: + ret = crypt_s390_kimd(KIMD_QUERY, &status, NULL, 0); + break; + case CRYPT_S390_KLMD: + ret = crypt_s390_klmd(KLMD_QUERY, &status, NULL, 0); + break; + case CRYPT_S390_KMAC: + ret = crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0); + break; + default: + ret = 0; + return ret; + } + if (ret >= 0){ + func &= CRYPT_S390_FUNC_MASK; + func &= 0x7f; //mask modifier bit + if (func < 64){ + ret = (status.high >> (64 - func - 1)) & 0x1; + } else { + ret = (status.low >> (128 - func - 1)) & 0x1; + } + } else { + ret = 0; + } + return ret; +} + +#endif // _CRYPTO_ARCH_S390_CRYPT_S390_H diff --git a/arch/s390/crypto/crypt_s390_query.c b/arch/s390/crypto/crypt_s390_query.c new file mode 100644 index 00000000000..0fa6bdf197c --- /dev/null +++ b/arch/s390/crypto/crypt_s390_query.c @@ -0,0 +1,113 @@ +/* + * Cryptographic API. + * + * Support for s390 cryptographic instructions. + * Testing module for querying processor crypto capabilities. + * + * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Thomas Spatzier (tspat@de.ibm.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. + * + */ +#include +#include +#include +#include +#include "crypt_s390.h" + +static void query_available_functions(void) +{ + printk(KERN_INFO "#####################\n"); + + /* query available KM functions */ + printk(KERN_INFO "KM_QUERY: %d\n", + crypt_s390_func_available(KM_QUERY)); + printk(KERN_INFO "KM_DEA: %d\n", + crypt_s390_func_available(KM_DEA_ENCRYPT)); + printk(KERN_INFO "KM_TDEA_128: %d\n", + crypt_s390_func_available(KM_TDEA_128_ENCRYPT)); + printk(KERN_INFO "KM_TDEA_192: %d\n", + crypt_s390_func_available(KM_TDEA_192_ENCRYPT)); + + /* query available KMC functions */ + printk(KERN_INFO "KMC_QUERY: %d\n", + crypt_s390_func_available(KMC_QUERY)); + printk(KERN_INFO "KMC_DEA: %d\n", + crypt_s390_func_available(KMC_DEA_ENCRYPT)); + printk(KERN_INFO "KMC_TDEA_128: %d\n", + crypt_s390_func_available(KMC_TDEA_128_ENCRYPT)); + printk(KERN_INFO "KMC_TDEA_192: %d\n", + crypt_s390_func_available(KMC_TDEA_192_ENCRYPT)); + + /* query available KIMD fucntions */ + printk(KERN_INFO "KIMD_QUERY: %d\n", + crypt_s390_func_available(KIMD_QUERY)); + printk(KERN_INFO "KIMD_SHA_1: %d\n", + crypt_s390_func_available(KIMD_SHA_1)); + + /* query available KLMD functions */ + printk(KERN_INFO "KLMD_QUERY: %d\n", + crypt_s390_func_available(KLMD_QUERY)); + printk(KERN_INFO "KLMD_SHA_1: %d\n", + crypt_s390_func_available(KLMD_SHA_1)); + + /* query available KMAC functions */ + printk(KERN_INFO "KMAC_QUERY: %d\n", + crypt_s3990_func_available(KMAC_QUERY)); + printk(KERN_INFO "KMAC_DEA: %d\n", + crypt_s390_func_available(KMAC_DEA)); + printk(KERN_INFO "KMAC_TDEA_128: %d\n", + crypt_s390_func_available(KMAC_TDEA_128)); + printk(KERN_INFO "KMAC_TDEA_192: %d\n", + crypt_s390_func_available(KMAC_TDEA_192)); +} + +static int init(void) +{ + struct crypt_s390_query_status status = { + .high = 0, + .low = 0 + }; + + printk(KERN_INFO "crypt_s390: querying available crypto functions\n"); + crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0); + printk(KERN_INFO "KM:\t%016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + status.high = status.low = 0; + crypt_s390_kmc(KMC_QUERY, &status, NULL, NULL, 0); + printk(KERN_INFO "KMC:\t%016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + status.high = status.low = 0; + crypt_s390_kimd(KIMD_QUERY, &status, NULL, 0); + printk(KERN_INFO "KIMD:\t%016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + status.high = status.low = 0; + crypt_s390_klmd(KLMD_QUERY, &status, NULL, 0); + printk(KERN_INFO "KLMD:\t%016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + status.high = status.low = 0; + crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0); + printk(KERN_INFO "KMAC:\t%016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + + query_available_functions(); + return -ECANCELED; +} + +static void __exit cleanup(void) +{ +} + +module_init(init); +module_exit(cleanup); + +MODULE_LICENSE("GPL"); diff --git a/arch/s390/crypto/crypt_z990.h b/arch/s390/crypto/crypt_z990.h deleted file mode 100644 index 4df660b99e5..00000000000 --- a/arch/s390/crypto/crypt_z990.h +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Cryptographic API. - * - * Support for z990 cryptographic instructions. - * - * Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation - * Author(s): Thomas Spatzier (tspat@de.ibm.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. - * - */ -#ifndef _CRYPTO_ARCH_S390_CRYPT_Z990_H -#define _CRYPTO_ARCH_S390_CRYPT_Z990_H - -#include - -#define CRYPT_Z990_OP_MASK 0xFF00 -#define CRYPT_Z990_FUNC_MASK 0x00FF - - -/*z990 cryptographic operations*/ -enum crypt_z990_operations { - CRYPT_Z990_KM = 0x0100, - CRYPT_Z990_KMC = 0x0200, - CRYPT_Z990_KIMD = 0x0300, - CRYPT_Z990_KLMD = 0x0400, - CRYPT_Z990_KMAC = 0x0500 -}; - -/*function codes for KM (CIPHER MESSAGE) instruction*/ -enum crypt_z990_km_func { - KM_QUERY = CRYPT_Z990_KM | 0, - KM_DEA_ENCRYPT = CRYPT_Z990_KM | 1, - KM_DEA_DECRYPT = CRYPT_Z990_KM | 1 | 0x80, //modifier bit->decipher - KM_TDEA_128_ENCRYPT = CRYPT_Z990_KM | 2, - KM_TDEA_128_DECRYPT = CRYPT_Z990_KM | 2 | 0x80, - KM_TDEA_192_ENCRYPT = CRYPT_Z990_KM | 3, - KM_TDEA_192_DECRYPT = CRYPT_Z990_KM | 3 | 0x80, -}; - -/*function codes for KMC (CIPHER MESSAGE WITH CHAINING) instruction*/ -enum crypt_z990_kmc_func { - KMC_QUERY = CRYPT_Z990_KMC | 0, - KMC_DEA_ENCRYPT = CRYPT_Z990_KMC | 1, - KMC_DEA_DECRYPT = CRYPT_Z990_KMC | 1 | 0x80, //modifier bit->decipher - KMC_TDEA_128_ENCRYPT = CRYPT_Z990_KMC | 2, - KMC_TDEA_128_DECRYPT = CRYPT_Z990_KMC | 2 | 0x80, - KMC_TDEA_192_ENCRYPT = CRYPT_Z990_KMC | 3, - KMC_TDEA_192_DECRYPT = CRYPT_Z990_KMC | 3 | 0x80, -}; - -/*function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) instruction*/ -enum crypt_z990_kimd_func { - KIMD_QUERY = CRYPT_Z990_KIMD | 0, - KIMD_SHA_1 = CRYPT_Z990_KIMD | 1, -}; - -/*function codes for KLMD (COMPUTE LAST MESSAGE DIGEST) instruction*/ -enum crypt_z990_klmd_func { - KLMD_QUERY = CRYPT_Z990_KLMD | 0, - KLMD_SHA_1 = CRYPT_Z990_KLMD | 1, -}; - -/*function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) instruction*/ -enum crypt_z990_kmac_func { - KMAC_QUERY = CRYPT_Z990_KMAC | 0, - KMAC_DEA = CRYPT_Z990_KMAC | 1, - KMAC_TDEA_128 = CRYPT_Z990_KMAC | 2, - KMAC_TDEA_192 = CRYPT_Z990_KMAC | 3 -}; - -/*status word for z990 crypto instructions' QUERY functions*/ -struct crypt_z990_query_status { - u64 high; - u64 low; -}; - -/* - * Standard fixup and ex_table sections for crypt_z990 inline functions. - * label 0: the z990 crypto operation - * label 1: just after 1 to catch illegal operation exception on non-z990 - * label 6: the return point after fixup - * label 7: set error value if exception _in_ crypto operation - * label 8: set error value if illegal operation exception - * [ret] is the variable to receive the error code - * [ERR] is the error code value - */ -#ifndef __s390x__ -#define __crypt_z990_fixup \ - ".section .fixup,\"ax\" \n" \ - "7: lhi %0,%h[e1] \n" \ - " bras 1,9f \n" \ - " .long 6b \n" \ - "8: lhi %0,%h[e2] \n" \ - " bras 1,9f \n" \ - " .long 6b \n" \ - "9: l 1,0(1) \n" \ - " br 1 \n" \ - ".previous \n" \ - ".section __ex_table,\"a\" \n" \ - " .align 4 \n" \ - " .long 0b,7b \n" \ - " .long 1b,8b \n" \ - ".previous" -#else /* __s390x__ */ -#define __crypt_z990_fixup \ - ".section .fixup,\"ax\" \n" \ - "7: lhi %0,%h[e1] \n" \ - " jg 6b \n" \ - "8: lhi %0,%h[e2] \n" \ - " jg 6b \n" \ - ".previous\n" \ - ".section __ex_table,\"a\" \n" \ - " .align 8 \n" \ - " .quad 0b,7b \n" \ - " .quad 1b,8b \n" \ - ".previous" -#endif /* __s390x__ */ - -/* - * Standard code for setting the result of z990 crypto instructions. - * %0: the register which will receive the result - * [result]: the register containing the result (e.g. second operand length - * to compute number of processed bytes]. - */ -#ifndef __s390x__ -#define __crypt_z990_set_result \ - " lr %0,%[result] \n" -#else /* __s390x__ */ -#define __crypt_z990_set_result \ - " lgr %0,%[result] \n" -#endif - -/* - * Executes the KM (CIPHER MESSAGE) operation of the z990 CPU. - * @param func: the function code passed to KM; see crypt_z990_km_func - * @param param: address of parameter block; see POP for details on each func - * @param dest: address of destination memory area - * @param src: address of source memory area - * @param src_len: length of src operand in bytes - * @returns < zero for failure, 0 for the query func, number of processed bytes - * for encryption/decryption funcs - */ -static inline int -crypt_z990_km(long func, void* param, u8* dest, const u8* src, long src_len) -{ - register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK; - register void* __param asm("1") = param; - register u8* __dest asm("4") = dest; - register const u8* __src asm("2") = src; - register long __src_len asm("3") = src_len; - int ret; - - ret = 0; - __asm__ __volatile__ ( - "0: .insn rre,0xB92E0000,%1,%2 \n" //KM opcode - "1: brc 1,0b \n" //handle partial completion - __crypt_z990_set_result - "6: \n" - __crypt_z990_fixup - : "+d" (ret), "+a" (__dest), "+a" (__src), - [result] "+d" (__src_len) - : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), - "a" (__param) - : "cc", "memory" - ); - if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){ - ret = src_len - ret; - } - return ret; -} - -/* - * Executes the KMC (CIPHER MESSAGE WITH CHAINING) operation of the z990 CPU. - * @param func: the function code passed to KM; see crypt_z990_kmc_func - * @param param: address of parameter block; see POP for details on each func - * @param dest: address of destination memory area - * @param src: address of source memory area - * @param src_len: length of src operand in bytes - * @returns < zero for failure, 0 for the query func, number of processed bytes - * for encryption/decryption funcs - */ -static inline int -crypt_z990_kmc(long func, void* param, u8* dest, const u8* src, long src_len) -{ - register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK; - register void* __param asm("1") = param; - register u8* __dest asm("4") = dest; - register const u8* __src asm("2") = src; - register long __src_len asm("3") = src_len; - int ret; - - ret = 0; - __asm__ __volatile__ ( - "0: .insn rre,0xB92F0000,%1,%2 \n" //KMC opcode - "1: brc 1,0b \n" //handle partial completion - __crypt_z990_set_result - "6: \n" - __crypt_z990_fixup - : "+d" (ret), "+a" (__dest), "+a" (__src), - [result] "+d" (__src_len) - : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), - "a" (__param) - : "cc", "memory" - ); - if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){ - ret = src_len - ret; - } - return ret; -} - -/* - * Executes the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) operation - * of the z990 CPU. - * @param func: the function code passed to KM; see crypt_z990_kimd_func - * @param param: address of parameter block; see POP for details on each func - * @param src: address of source memory area - * @param src_len: length of src operand in bytes - * @returns < zero for failure, 0 for the query func, number of processed bytes - * for digest funcs - */ -static inline int -crypt_z990_kimd(long func, void* param, const u8* src, long src_len) -{ - register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK; - register void* __param asm("1") = param; - register const u8* __src asm("2") = src; - register long __src_len asm("3") = src_len; - int ret; - - ret = 0; - __asm__ __volatile__ ( - "0: .insn rre,0xB93E0000,%1,%1 \n" //KIMD opcode - "1: brc 1,0b \n" /*handle partical completion of kimd*/ - __crypt_z990_set_result - "6: \n" - __crypt_z990_fixup - : "+d" (ret), "+a" (__src), [result] "+d" (__src_len) - : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), - "a" (__param) - : "cc", "memory" - ); - if (ret >= 0 && (func & CRYPT_Z990_FUNC_MASK)){ - ret = src_len - ret; - } - return ret; -} - -/* - * Executes the KLMD (COMPUTE LAST MESSAGE DIGEST) operation of the z990 CPU. - * @param func: the function code passed to KM; see crypt_z990_klmd_func - * @param param: address of parameter block; see POP for details on each func - * @param src: address of source memory area - * @param src_len: length of src operand in bytes - * @returns < zero for failure, 0 for the query func, number of processed bytes - * for digest funcs - */ -static inline int -crypt_z990_klmd(long func, void* param, const u8* src, long src_len) -{ - register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK; - register void* __param asm("1") = param; - register const u8* __src asm("2") = src; - register long __src_len asm("3") = src_len; - int ret; - - ret = 0; - __asm__ __volatile__ ( - "0: .insn rre,0xB93F0000,%1,%1 \n" //KLMD opcode - "1: brc 1,0b \n" /*handle partical completion of klmd*/ - __crypt_z990_set_result - "6: \n" - __crypt_z990_fixup - : "+d" (ret), "+a" (__src), [result] "+d" (__src_len) - : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), - "a" (__param) - : "cc", "memory" - ); - if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){ - ret = src_len - ret; - } - return ret; -} - -/* - * Executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) operation - * of the z990 CPU. - * @param func: the function code passed to KM; see crypt_z990_klmd_func - * @param param: address of parameter block; see POP for details on each func - * @param src: address of source memory area - * @param src_len: length of src operand in bytes - * @returns < zero for failure, 0 for the query func, number of processed bytes - * for digest funcs - */ -static inline int -crypt_z990_kmac(long func, void* param, const u8* src, long src_len) -{ - register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK; - register void* __param asm("1") = param; - register const u8* __src asm("2") = src; - register long __src_len asm("3") = src_len; - int ret; - - ret = 0; - __asm__ __volatile__ ( - "0: .insn rre,0xB91E0000,%5,%5 \n" //KMAC opcode - "1: brc 1,0b \n" /*handle partical completion of klmd*/ - __crypt_z990_set_result - "6: \n" - __crypt_z990_fixup - : "+d" (ret), "+a" (__src), [result] "+d" (__src_len) - : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), - "a" (__param) - : "cc", "memory" - ); - if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){ - ret = src_len - ret; - } - return ret; -} - -/** - * Tests if a specific z990 crypto function is implemented on the machine. - * @param func: the function code of the specific function; 0 if op in general - * @return 1 if func available; 0 if func or op in general not available - */ -static inline int -crypt_z990_func_available(int func) -{ - int ret; - - struct crypt_z990_query_status status = { - .high = 0, - .low = 0 - }; - switch (func & CRYPT_Z990_OP_MASK){ - case CRYPT_Z990_KM: - ret = crypt_z990_km(KM_QUERY, &status, NULL, NULL, 0); - break; - case CRYPT_Z990_KMC: - ret = crypt_z990_kmc(KMC_QUERY, &status, NULL, NULL, 0); - break; - case CRYPT_Z990_KIMD: - ret = crypt_z990_kimd(KIMD_QUERY, &status, NULL, 0); - break; - case CRYPT_Z990_KLMD: - ret = crypt_z990_klmd(KLMD_QUERY, &status, NULL, 0); - break; - case CRYPT_Z990_KMAC: - ret = crypt_z990_kmac(KMAC_QUERY, &status, NULL, 0); - break; - default: - ret = 0; - return ret; - } - if (ret >= 0){ - func &= CRYPT_Z990_FUNC_MASK; - func &= 0x7f; //mask modifier bit - if (func < 64){ - ret = (status.high >> (64 - func - 1)) & 0x1; - } else { - ret = (status.low >> (128 - func - 1)) & 0x1; - } - } else { - ret = 0; - } - return ret; -} - - -#endif // _CRYPTO_ARCH_S390_CRYPT_Z990_H diff --git a/arch/s390/crypto/crypt_z990_query.c b/arch/s390/crypto/crypt_z990_query.c deleted file mode 100644 index 7133983d138..00000000000 --- a/arch/s390/crypto/crypt_z990_query.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Cryptographic API. - * - * Support for z990 cryptographic instructions. - * Testing module for querying processor crypto capabilities. - * - * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Thomas Spatzier (tspat@de.ibm.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. - * - */ -#include -#include -#include -#include -#include "crypt_z990.h" - -static void -query_available_functions(void) -{ - printk(KERN_INFO "#####################\n"); - //query available KM functions - printk(KERN_INFO "KM_QUERY: %d\n", - crypt_z990_func_available(KM_QUERY)); - printk(KERN_INFO "KM_DEA: %d\n", - crypt_z990_func_available(KM_DEA_ENCRYPT)); - printk(KERN_INFO "KM_TDEA_128: %d\n", - crypt_z990_func_available(KM_TDEA_128_ENCRYPT)); - printk(KERN_INFO "KM_TDEA_192: %d\n", - crypt_z990_func_available(KM_TDEA_192_ENCRYPT)); - //query available KMC functions - printk(KERN_INFO "KMC_QUERY: %d\n", - crypt_z990_func_available(KMC_QUERY)); - printk(KERN_INFO "KMC_DEA: %d\n", - crypt_z990_func_available(KMC_DEA_ENCRYPT)); - printk(KERN_INFO "KMC_TDEA_128: %d\n", - crypt_z990_func_available(KMC_TDEA_128_ENCRYPT)); - printk(KERN_INFO "KMC_TDEA_192: %d\n", - crypt_z990_func_available(KMC_TDEA_192_ENCRYPT)); - //query available KIMD fucntions - printk(KERN_INFO "KIMD_QUERY: %d\n", - crypt_z990_func_available(KIMD_QUERY)); - printk(KERN_INFO "KIMD_SHA_1: %d\n", - crypt_z990_func_available(KIMD_SHA_1)); - //query available KLMD functions - printk(KERN_INFO "KLMD_QUERY: %d\n", - crypt_z990_func_available(KLMD_QUERY)); - printk(KERN_INFO "KLMD_SHA_1: %d\n", - crypt_z990_func_available(KLMD_SHA_1)); - //query available KMAC functions - printk(KERN_INFO "KMAC_QUERY: %d\n", - crypt_z990_func_available(KMAC_QUERY)); - printk(KERN_INFO "KMAC_DEA: %d\n", - crypt_z990_func_available(KMAC_DEA)); - printk(KERN_INFO "KMAC_TDEA_128: %d\n", - crypt_z990_func_available(KMAC_TDEA_128)); - printk(KERN_INFO "KMAC_TDEA_192: %d\n", - crypt_z990_func_available(KMAC_TDEA_192)); -} - -static int -init(void) -{ - struct crypt_z990_query_status status = { - .high = 0, - .low = 0 - }; - - printk(KERN_INFO "crypt_z990: querying available crypto functions\n"); - crypt_z990_km(KM_QUERY, &status, NULL, NULL, 0); - printk(KERN_INFO "KM: %016llx %016llx\n", - (unsigned long long) status.high, - (unsigned long long) status.low); - status.high = status.low = 0; - crypt_z990_kmc(KMC_QUERY, &status, NULL, NULL, 0); - printk(KERN_INFO "KMC: %016llx %016llx\n", - (unsigned long long) status.high, - (unsigned long long) status.low); - status.high = status.low = 0; - crypt_z990_kimd(KIMD_QUERY, &status, NULL, 0); - printk(KERN_INFO "KIMD: %016llx %016llx\n", - (unsigned long long) status.high, - (unsigned long long) status.low); - status.high = status.low = 0; - crypt_z990_klmd(KLMD_QUERY, &status, NULL, 0); - printk(KERN_INFO "KLMD: %016llx %016llx\n", - (unsigned long long) status.high, - (unsigned long long) status.low); - status.high = status.low = 0; - crypt_z990_kmac(KMAC_QUERY, &status, NULL, 0); - printk(KERN_INFO "KMAC: %016llx %016llx\n", - (unsigned long long) status.high, - (unsigned long long) status.low); - - query_available_functions(); - return -1; -} - -static void __exit -cleanup(void) -{ -} - -module_init(init); -module_exit(cleanup); - -MODULE_LICENSE("GPL"); diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c new file mode 100644 index 00000000000..a38bb2a3eef --- /dev/null +++ b/arch/s390/crypto/des_s390.c @@ -0,0 +1,284 @@ +/* + * Cryptographic API. + * + * s390 implementation of the DES Cipher Algorithm. + * + * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Thomas Spatzier (tspat@de.ibm.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. + * + */ +#include +#include +#include +#include +#include +#include +#include "crypt_s390.h" +#include "crypto_des.h" + +#define DES_BLOCK_SIZE 8 +#define DES_KEY_SIZE 8 + +#define DES3_128_KEY_SIZE (2 * DES_KEY_SIZE) +#define DES3_128_BLOCK_SIZE DES_BLOCK_SIZE + +#define DES3_192_KEY_SIZE (3 * DES_KEY_SIZE) +#define DES3_192_BLOCK_SIZE DES_BLOCK_SIZE + +struct crypt_s390_des_ctx { + u8 iv[DES_BLOCK_SIZE]; + u8 key[DES_KEY_SIZE]; +}; + +struct crypt_s390_des3_128_ctx { + u8 iv[DES_BLOCK_SIZE]; + u8 key[DES3_128_KEY_SIZE]; +}; + +struct crypt_s390_des3_192_ctx { + u8 iv[DES_BLOCK_SIZE]; + u8 key[DES3_192_KEY_SIZE]; +}; + +static int +des_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +{ + struct crypt_s390_des_ctx *dctx; + int ret; + + dctx = ctx; + //test if key is valid (not a weak key) + ret = crypto_des_check_key(key, keylen, flags); + if (ret == 0){ + memcpy(dctx->key, key, keylen); + } + return ret; +} + + +static void +des_encrypt(void *ctx, u8 *dst, const u8 *src) +{ + struct crypt_s390_des_ctx *dctx; + + dctx = ctx; + crypt_s390_km(KM_DEA_ENCRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); +} + +static void +des_decrypt(void *ctx, u8 *dst, const u8 *src) +{ + struct crypt_s390_des_ctx *dctx; + + dctx = ctx; + crypt_s390_km(KM_DEA_DECRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); +} + +static struct crypto_alg des_alg = { + .cra_name = "des", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crypt_s390_des_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(des_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = DES_KEY_SIZE, + .cia_max_keysize = DES_KEY_SIZE, + .cia_setkey = des_setkey, + .cia_encrypt = des_encrypt, + .cia_decrypt = des_decrypt } } +}; + +/* + * RFC2451: + * + * For DES-EDE3, there is no known need to reject weak or + * complementation keys. Any weakness is obviated by the use of + * multiple keys. + * + * However, if the two independent 64-bit keys are equal, + * then the DES3 operation is simply the same as DES. + * Implementers MUST reject keys that exhibit this property. + * + */ +static int +des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +{ + int i, ret; + struct crypt_s390_des3_128_ctx *dctx; + const u8* temp_key = key; + + dctx = ctx; + if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE))) { + + *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED; + return -EINVAL; + } + for (i = 0; i < 2; i++, temp_key += DES_KEY_SIZE) { + ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags); + if (ret < 0) + return ret; + } + memcpy(dctx->key, key, keylen); + return 0; +} + +static void +des3_128_encrypt(void *ctx, u8 *dst, const u8 *src) +{ + struct crypt_s390_des3_128_ctx *dctx; + + dctx = ctx; + crypt_s390_km(KM_TDEA_128_ENCRYPT, dctx->key, dst, (void*)src, + DES3_128_BLOCK_SIZE); +} + +static void +des3_128_decrypt(void *ctx, u8 *dst, const u8 *src) +{ + struct crypt_s390_des3_128_ctx *dctx; + + dctx = ctx; + crypt_s390_km(KM_TDEA_128_DECRYPT, dctx->key, dst, (void*)src, + DES3_128_BLOCK_SIZE); +} + +static struct crypto_alg des3_128_alg = { + .cra_name = "des3_ede128", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = DES3_128_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crypt_s390_des3_128_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(des3_128_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = DES3_128_KEY_SIZE, + .cia_max_keysize = DES3_128_KEY_SIZE, + .cia_setkey = des3_128_setkey, + .cia_encrypt = des3_128_encrypt, + .cia_decrypt = des3_128_decrypt } } +}; + +/* + * RFC2451: + * + * For DES-EDE3, there is no known need to reject weak or + * complementation keys. Any weakness is obviated by the use of + * multiple keys. + * + * However, if the first two or last two independent 64-bit keys are + * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the + * same as DES. Implementers MUST reject keys that exhibit this + * property. + * + */ +static int +des3_192_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +{ + int i, ret; + struct crypt_s390_des3_192_ctx *dctx; + const u8* temp_key; + + dctx = ctx; + temp_key = key; + if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) && + memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2], + DES_KEY_SIZE))) { + + *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED; + return -EINVAL; + } + for (i = 0; i < 3; i++, temp_key += DES_KEY_SIZE) { + ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags); + if (ret < 0){ + return ret; + } + } + memcpy(dctx->key, key, keylen); + return 0; +} + +static void +des3_192_encrypt(void *ctx, u8 *dst, const u8 *src) +{ + struct crypt_s390_des3_192_ctx *dctx; + + dctx = ctx; + crypt_s390_km(KM_TDEA_192_ENCRYPT, dctx->key, dst, (void*)src, + DES3_192_BLOCK_SIZE); +} + +static void +des3_192_decrypt(void *ctx, u8 *dst, const u8 *src) +{ + struct crypt_s390_des3_192_ctx *dctx; + + dctx = ctx; + crypt_s390_km(KM_TDEA_192_DECRYPT, dctx->key, dst, (void*)src, + DES3_192_BLOCK_SIZE); +} + +static struct crypto_alg des3_192_alg = { + .cra_name = "des3_ede", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = DES3_192_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crypt_s390_des3_192_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = DES3_192_KEY_SIZE, + .cia_max_keysize = DES3_192_KEY_SIZE, + .cia_setkey = des3_192_setkey, + .cia_encrypt = des3_192_encrypt, + .cia_decrypt = des3_192_decrypt } } +}; + + + +static int +init(void) +{ + int ret; + + if (!crypt_s390_func_available(KM_DEA_ENCRYPT) || + !crypt_s390_func_available(KM_TDEA_128_ENCRYPT) || + !crypt_s390_func_available(KM_TDEA_192_ENCRYPT)){ + return -ENOSYS; + } + + ret = 0; + ret |= (crypto_register_alg(&des_alg) == 0)? 0:1; + ret |= (crypto_register_alg(&des3_128_alg) == 0)? 0:2; + ret |= (crypto_register_alg(&des3_192_alg) == 0)? 0:4; + if (ret){ + crypto_unregister_alg(&des3_192_alg); + crypto_unregister_alg(&des3_128_alg); + crypto_unregister_alg(&des_alg); + return -EEXIST; + } + + printk(KERN_INFO "crypt_s390: des_s390 loaded.\n"); + return 0; +} + +static void __exit +fini(void) +{ + crypto_unregister_alg(&des3_192_alg); + crypto_unregister_alg(&des3_128_alg); + crypto_unregister_alg(&des_alg); +} + +module_init(init); +module_exit(fini); + +MODULE_ALIAS("des"); +MODULE_ALIAS("des3_ede"); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms"); diff --git a/arch/s390/crypto/des_z990.c b/arch/s390/crypto/des_z990.c deleted file mode 100644 index 813cf37b117..00000000000 --- a/arch/s390/crypto/des_z990.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Cryptographic API. - * - * z990 implementation of the DES Cipher Algorithm. - * - * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Thomas Spatzier (tspat@de.ibm.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. - * - */ -#include -#include -#include -#include -#include -#include -#include "crypt_z990.h" -#include "crypto_des.h" - -#define DES_BLOCK_SIZE 8 -#define DES_KEY_SIZE 8 - -#define DES3_128_KEY_SIZE (2 * DES_KEY_SIZE) -#define DES3_128_BLOCK_SIZE DES_BLOCK_SIZE - -#define DES3_192_KEY_SIZE (3 * DES_KEY_SIZE) -#define DES3_192_BLOCK_SIZE DES_BLOCK_SIZE - -struct crypt_z990_des_ctx { - u8 iv[DES_BLOCK_SIZE]; - u8 key[DES_KEY_SIZE]; -}; - -struct crypt_z990_des3_128_ctx { - u8 iv[DES_BLOCK_SIZE]; - u8 key[DES3_128_KEY_SIZE]; -}; - -struct crypt_z990_des3_192_ctx { - u8 iv[DES_BLOCK_SIZE]; - u8 key[DES3_192_KEY_SIZE]; -}; - -static int -des_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) -{ - struct crypt_z990_des_ctx *dctx; - int ret; - - dctx = ctx; - //test if key is valid (not a weak key) - ret = crypto_des_check_key(key, keylen, flags); - if (ret == 0){ - memcpy(dctx->key, key, keylen); - } - return ret; -} - - -static void -des_encrypt(void *ctx, u8 *dst, const u8 *src) -{ - struct crypt_z990_des_ctx *dctx; - - dctx = ctx; - crypt_z990_km(KM_DEA_ENCRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); -} - -static void -des_decrypt(void *ctx, u8 *dst, const u8 *src) -{ - struct crypt_z990_des_ctx *dctx; - - dctx = ctx; - crypt_z990_km(KM_DEA_DECRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); -} - -static struct crypto_alg des_alg = { - .cra_name = "des", - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = DES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypt_z990_des_ctx), - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(des_alg.cra_list), - .cra_u = { .cipher = { - .cia_min_keysize = DES_KEY_SIZE, - .cia_max_keysize = DES_KEY_SIZE, - .cia_setkey = des_setkey, - .cia_encrypt = des_encrypt, - .cia_decrypt = des_decrypt } } -}; - -/* - * RFC2451: - * - * For DES-EDE3, there is no known need to reject weak or - * complementation keys. Any weakness is obviated by the use of - * multiple keys. - * - * However, if the two independent 64-bit keys are equal, - * then the DES3 operation is simply the same as DES. - * Implementers MUST reject keys that exhibit this property. - * - */ -static int -des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) -{ - int i, ret; - struct crypt_z990_des3_128_ctx *dctx; - const u8* temp_key = key; - - dctx = ctx; - if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE))) { - - *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED; - return -EINVAL; - } - for (i = 0; i < 2; i++, temp_key += DES_KEY_SIZE) { - ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags); - if (ret < 0) - return ret; - } - memcpy(dctx->key, key, keylen); - return 0; -} - -static void -des3_128_encrypt(void *ctx, u8 *dst, const u8 *src) -{ - struct crypt_z990_des3_128_ctx *dctx; - - dctx = ctx; - crypt_z990_km(KM_TDEA_128_ENCRYPT, dctx->key, dst, (void*)src, - DES3_128_BLOCK_SIZE); -} - -static void -des3_128_decrypt(void *ctx, u8 *dst, const u8 *src) -{ - struct crypt_z990_des3_128_ctx *dctx; - - dctx = ctx; - crypt_z990_km(KM_TDEA_128_DECRYPT, dctx->key, dst, (void*)src, - DES3_128_BLOCK_SIZE); -} - -static struct crypto_alg des3_128_alg = { - .cra_name = "des3_ede128", - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = DES3_128_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypt_z990_des3_128_ctx), - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(des3_128_alg.cra_list), - .cra_u = { .cipher = { - .cia_min_keysize = DES3_128_KEY_SIZE, - .cia_max_keysize = DES3_128_KEY_SIZE, - .cia_setkey = des3_128_setkey, - .cia_encrypt = des3_128_encrypt, - .cia_decrypt = des3_128_decrypt } } -}; - -/* - * RFC2451: - * - * For DES-EDE3, there is no known need to reject weak or - * complementation keys. Any weakness is obviated by the use of - * multiple keys. - * - * However, if the first two or last two independent 64-bit keys are - * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the - * same as DES. Implementers MUST reject keys that exhibit this - * property. - * - */ -static int -des3_192_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) -{ - int i, ret; - struct crypt_z990_des3_192_ctx *dctx; - const u8* temp_key; - - dctx = ctx; - temp_key = key; - if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) && - memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2], - DES_KEY_SIZE))) { - - *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED; - return -EINVAL; - } - for (i = 0; i < 3; i++, temp_key += DES_KEY_SIZE) { - ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags); - if (ret < 0){ - return ret; - } - } - memcpy(dctx->key, key, keylen); - return 0; -} - -static void -des3_192_encrypt(void *ctx, u8 *dst, const u8 *src) -{ - struct crypt_z990_des3_192_ctx *dctx; - - dctx = ctx; - crypt_z990_km(KM_TDEA_192_ENCRYPT, dctx->key, dst, (void*)src, - DES3_192_BLOCK_SIZE); -} - -static void -des3_192_decrypt(void *ctx, u8 *dst, const u8 *src) -{ - struct crypt_z990_des3_192_ctx *dctx; - - dctx = ctx; - crypt_z990_km(KM_TDEA_192_DECRYPT, dctx->key, dst, (void*)src, - DES3_192_BLOCK_SIZE); -} - -static struct crypto_alg des3_192_alg = { - .cra_name = "des3_ede", - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = DES3_192_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypt_z990_des3_192_ctx), - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list), - .cra_u = { .cipher = { - .cia_min_keysize = DES3_192_KEY_SIZE, - .cia_max_keysize = DES3_192_KEY_SIZE, - .cia_setkey = des3_192_setkey, - .cia_encrypt = des3_192_encrypt, - .cia_decrypt = des3_192_decrypt } } -}; - - - -static int -init(void) -{ - int ret; - - if (!crypt_z990_func_available(KM_DEA_ENCRYPT) || - !crypt_z990_func_available(KM_TDEA_128_ENCRYPT) || - !crypt_z990_func_available(KM_TDEA_192_ENCRYPT)){ - return -ENOSYS; - } - - ret = 0; - ret |= (crypto_register_alg(&des_alg) == 0)? 0:1; - ret |= (crypto_register_alg(&des3_128_alg) == 0)? 0:2; - ret |= (crypto_register_alg(&des3_192_alg) == 0)? 0:4; - if (ret){ - crypto_unregister_alg(&des3_192_alg); - crypto_unregister_alg(&des3_128_alg); - crypto_unregister_alg(&des_alg); - return -EEXIST; - } - - printk(KERN_INFO "crypt_z990: des_z990 loaded.\n"); - return 0; -} - -static void __exit -fini(void) -{ - crypto_unregister_alg(&des3_192_alg); - crypto_unregister_alg(&des3_128_alg); - crypto_unregister_alg(&des_alg); -} - -module_init(init); -module_exit(fini); - -MODULE_ALIAS("des"); -MODULE_ALIAS("des3_ede"); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms"); diff --git a/arch/s390/crypto/sha1_s390.c b/arch/s390/crypto/sha1_s390.c new file mode 100644 index 00000000000..98c896b86dc --- /dev/null +++ b/arch/s390/crypto/sha1_s390.c @@ -0,0 +1,167 @@ +/* + * Cryptographic API. + * + * s390 implementation of the SHA1 Secure Hash Algorithm. + * + * Derived from cryptoapi implementation, adapted for in-place + * scatterlist interface. Originally based on the public domain + * implementation written by Steve Reid. + * + * s390 Version: + * Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation + * Author(s): Thomas Spatzier (tspat@de.ibm.com) + * + * Derived from "crypto/sha1.c" + * Copyright (c) Alan Smithee. + * Copyright (c) Andrew McDonald + * Copyright (c) Jean-Francois Dive + * + * 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 "crypt_s390.h" + +#define SHA1_DIGEST_SIZE 20 +#define SHA1_BLOCK_SIZE 64 + +struct crypt_s390_sha1_ctx { + u64 count; + u32 state[5]; + u32 buf_len; + u8 buffer[2 * SHA1_BLOCK_SIZE]; +}; + +static void +sha1_init(void *ctx) +{ + static const struct crypt_s390_sha1_ctx initstate = { + .state = { + 0x67452301, + 0xEFCDAB89, + 0x98BADCFE, + 0x10325476, + 0xC3D2E1F0 + }, + }; + memcpy(ctx, &initstate, sizeof(initstate)); +} + +static void +sha1_update(void *ctx, const u8 *data, unsigned int len) +{ + struct crypt_s390_sha1_ctx *sctx; + long imd_len; + + sctx = ctx; + sctx->count += len * 8; //message bit length + + //anything in buffer yet? -> must be completed + if (sctx->buf_len && (sctx->buf_len + len) >= SHA1_BLOCK_SIZE) { + //complete full block and hash + memcpy(sctx->buffer + sctx->buf_len, data, + SHA1_BLOCK_SIZE - sctx->buf_len); + crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, + SHA1_BLOCK_SIZE); + data += SHA1_BLOCK_SIZE - sctx->buf_len; + len -= SHA1_BLOCK_SIZE - sctx->buf_len; + sctx->buf_len = 0; + } + + //rest of data contains full blocks? + imd_len = len & ~0x3ful; + if (imd_len){ + crypt_s390_kimd(KIMD_SHA_1, sctx->state, data, imd_len); + data += imd_len; + len -= imd_len; + } + //anything left? store in buffer + if (len){ + memcpy(sctx->buffer + sctx->buf_len , data, len); + sctx->buf_len += len; + } +} + + +static void +pad_message(struct crypt_s390_sha1_ctx* sctx) +{ + int index; + + index = sctx->buf_len; + sctx->buf_len = (sctx->buf_len < 56)? + SHA1_BLOCK_SIZE:2 * SHA1_BLOCK_SIZE; + //start pad with 1 + sctx->buffer[index] = 0x80; + //pad with zeros + index++; + memset(sctx->buffer + index, 0x00, sctx->buf_len - index); + //append length + memcpy(sctx->buffer + sctx->buf_len - 8, &sctx->count, + sizeof sctx->count); +} + +/* Add padding and return the message digest. */ +static void +sha1_final(void* ctx, u8 *out) +{ + struct crypt_s390_sha1_ctx *sctx = ctx; + + //must perform manual padding + pad_message(sctx); + crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, sctx->buf_len); + //copy digest to out + memcpy(out, sctx->state, SHA1_DIGEST_SIZE); + /* Wipe context */ + memset(sctx, 0, sizeof *sctx); +} + +static struct crypto_alg alg = { + .cra_name = "sha1", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = SHA1_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crypt_s390_sha1_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .digest = { + .dia_digestsize = SHA1_DIGEST_SIZE, + .dia_init = sha1_init, + .dia_update = sha1_update, + .dia_final = sha1_final } } +}; + +static int +init(void) +{ + int ret = -ENOSYS; + + if (crypt_s390_func_available(KIMD_SHA_1)){ + ret = crypto_register_alg(&alg); + if (ret == 0){ + printk(KERN_INFO "crypt_s390: sha1_s390 loaded.\n"); + } + } + return ret; +} + +static void __exit +fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_ALIAS("sha1"); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm"); diff --git a/arch/s390/crypto/sha1_z990.c b/arch/s390/crypto/sha1_z990.c deleted file mode 100644 index 298174ddf5b..00000000000 --- a/arch/s390/crypto/sha1_z990.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Cryptographic API. - * - * z990 implementation of the SHA1 Secure Hash Algorithm. - * - * Derived from cryptoapi implementation, adapted for in-place - * scatterlist interface. Originally based on the public domain - * implementation written by Steve Reid. - * - * s390 Version: - * Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation - * Author(s): Thomas Spatzier (tspat@de.ibm.com) - * - * Derived from "crypto/sha1.c" - * Copyright (c) Alan Smithee. - * Copyright (c) Andrew McDonald - * Copyright (c) Jean-Francois Dive - * - * 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 "crypt_z990.h" - -#define SHA1_DIGEST_SIZE 20 -#define SHA1_BLOCK_SIZE 64 - -struct crypt_z990_sha1_ctx { - u64 count; - u32 state[5]; - u32 buf_len; - u8 buffer[2 * SHA1_BLOCK_SIZE]; -}; - -static void -sha1_init(void *ctx) -{ - static const struct crypt_z990_sha1_ctx initstate = { - .state = { - 0x67452301, - 0xEFCDAB89, - 0x98BADCFE, - 0x10325476, - 0xC3D2E1F0 - }, - }; - memcpy(ctx, &initstate, sizeof(initstate)); -} - -static void -sha1_update(void *ctx, const u8 *data, unsigned int len) -{ - struct crypt_z990_sha1_ctx *sctx; - long imd_len; - - sctx = ctx; - sctx->count += len * 8; //message bit length - - //anything in buffer yet? -> must be completed - if (sctx->buf_len && (sctx->buf_len + len) >= SHA1_BLOCK_SIZE) { - //complete full block and hash - memcpy(sctx->buffer + sctx->buf_len, data, - SHA1_BLOCK_SIZE - sctx->buf_len); - crypt_z990_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, - SHA1_BLOCK_SIZE); - data += SHA1_BLOCK_SIZE - sctx->buf_len; - len -= SHA1_BLOCK_SIZE - sctx->buf_len; - sctx->buf_len = 0; - } - - //rest of data contains full blocks? - imd_len = len & ~0x3ful; - if (imd_len){ - crypt_z990_kimd(KIMD_SHA_1, sctx->state, data, imd_len); - data += imd_len; - len -= imd_len; - } - //anything left? store in buffer - if (len){ - memcpy(sctx->buffer + sctx->buf_len , data, len); - sctx->buf_len += len; - } -} - - -static void -pad_message(struct crypt_z990_sha1_ctx* sctx) -{ - int index; - - index = sctx->buf_len; - sctx->buf_len = (sctx->buf_len < 56)? - SHA1_BLOCK_SIZE:2 * SHA1_BLOCK_SIZE; - //start pad with 1 - sctx->buffer[index] = 0x80; - //pad with zeros - index++; - memset(sctx->buffer + index, 0x00, sctx->buf_len - index); - //append length - memcpy(sctx->buffer + sctx->buf_len - 8, &sctx->count, - sizeof sctx->count); -} - -/* Add padding and return the message digest. */ -static void -sha1_final(void* ctx, u8 *out) -{ - struct crypt_z990_sha1_ctx *sctx = ctx; - - //must perform manual padding - pad_message(sctx); - crypt_z990_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, sctx->buf_len); - //copy digest to out - memcpy(out, sctx->state, SHA1_DIGEST_SIZE); - /* Wipe context */ - memset(sctx, 0, sizeof *sctx); -} - -static struct crypto_alg alg = { - .cra_name = "sha1", - .cra_flags = CRYPTO_ALG_TYPE_DIGEST, - .cra_blocksize = SHA1_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypt_z990_sha1_ctx), - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(alg.cra_list), - .cra_u = { .digest = { - .dia_digestsize = SHA1_DIGEST_SIZE, - .dia_init = sha1_init, - .dia_update = sha1_update, - .dia_final = sha1_final } } -}; - -static int -init(void) -{ - int ret = -ENOSYS; - - if (crypt_z990_func_available(KIMD_SHA_1)){ - ret = crypto_register_alg(&alg); - if (ret == 0){ - printk(KERN_INFO "crypt_z990: sha1_z990 loaded.\n"); - } - } - return ret; -} - -static void __exit -fini(void) -{ - crypto_unregister_alg(&alg); -} - -module_init(init); -module_exit(fini); - -MODULE_ALIAS("sha1"); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm"); diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 0c495fe8311..0cb2995bf21 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -632,13 +632,13 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_MD4 is not set # CONFIG_CRYPTO_MD5 is not set # CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA1_Z990 is not set +# CONFIG_CRYPTO_SHA1_S390 is not set # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set # CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_DES_Z990 is not set +# CONFIG_CRYPTO_DES_S390 is not set # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_SERPENT is not set -- cgit v1.2.3 From 0a497c17fee428604e06320272ff74415eacdc31 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Fri, 6 Jan 2006 00:19:18 -0800 Subject: [PATCH] s390: sha256 support Add support for the hardware accelerated sha256 crypto algorithm. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/crypto/Makefile | 1 + arch/s390/crypto/crypt_s390.h | 2 + arch/s390/crypto/crypt_s390_query.c | 6 +- arch/s390/crypto/sha256_s390.c | 151 ++++++++++++++++++++++++++++++++++++ arch/s390/defconfig | 1 + 5 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 arch/s390/crypto/sha256_s390.c (limited to 'arch') diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile index 50843f8d095..3fccf61ee1d 100644 --- a/arch/s390/crypto/Makefile +++ b/arch/s390/crypto/Makefile @@ -3,6 +3,7 @@ # obj-$(CONFIG_CRYPTO_SHA1_S390) += sha1_s390.o +obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o des_check_key.o obj-$(CONFIG_CRYPTO_TEST) += crypt_s390_query.o diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h index 4d24f668975..b70a410ac31 100644 --- a/arch/s390/crypto/crypt_s390.h +++ b/arch/s390/crypto/crypt_s390.h @@ -61,6 +61,7 @@ enum crypt_s390_kmc_func { enum crypt_s390_kimd_func { KIMD_QUERY = CRYPT_S390_KIMD | 0, KIMD_SHA_1 = CRYPT_S390_KIMD | 1, + KIMD_SHA_256 = CRYPT_S390_KIMD | 2, }; /* function codes for KLMD (COMPUTE LAST MESSAGE DIGEST) @@ -69,6 +70,7 @@ enum crypt_s390_kimd_func { enum crypt_s390_klmd_func { KLMD_QUERY = CRYPT_S390_KLMD | 0, KLMD_SHA_1 = CRYPT_S390_KLMD | 1, + KLMD_SHA_256 = CRYPT_S390_KLMD | 2, }; /* function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) diff --git a/arch/s390/crypto/crypt_s390_query.c b/arch/s390/crypto/crypt_s390_query.c index 0fa6bdf197c..67081b81a4a 100644 --- a/arch/s390/crypto/crypt_s390_query.c +++ b/arch/s390/crypto/crypt_s390_query.c @@ -48,16 +48,20 @@ static void query_available_functions(void) crypt_s390_func_available(KIMD_QUERY)); printk(KERN_INFO "KIMD_SHA_1: %d\n", crypt_s390_func_available(KIMD_SHA_1)); + printk(KERN_INFO "KIMD_SHA_256: %d\n", + crypt_s390_func_available(KIMD_SHA_256)); /* query available KLMD functions */ printk(KERN_INFO "KLMD_QUERY: %d\n", crypt_s390_func_available(KLMD_QUERY)); printk(KERN_INFO "KLMD_SHA_1: %d\n", crypt_s390_func_available(KLMD_SHA_1)); + printk(KERN_INFO "KLMD_SHA_256: %d\n", + crypt_s390_func_available(KLMD_SHA_256)); /* query available KMAC functions */ printk(KERN_INFO "KMAC_QUERY: %d\n", - crypt_s3990_func_available(KMAC_QUERY)); + crypt_s390_func_available(KMAC_QUERY)); printk(KERN_INFO "KMAC_DEA: %d\n", crypt_s390_func_available(KMAC_DEA)); printk(KERN_INFO "KMAC_TDEA_128: %d\n", diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c new file mode 100644 index 00000000000..b75bdbd476c --- /dev/null +++ b/arch/s390/crypto/sha256_s390.c @@ -0,0 +1,151 @@ +/* + * Cryptographic API. + * + * s390 implementation of the SHA256 Secure Hash Algorithm. + * + * s390 Version: + * Copyright (C) 2005 IBM Deutschland GmbH, IBM Corporation + * Author(s): Jan Glauber (jang@de.ibm.com) + * + * Derived from "crypto/sha256.c" + * and "arch/s390/crypto/sha1_s390.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. + * + */ +#include +#include +#include + +#include "crypt_s390.h" + +#define SHA256_DIGEST_SIZE 32 +#define SHA256_BLOCK_SIZE 64 + +struct s390_sha256_ctx { + u64 count; + u32 state[8]; + u8 buf[2 * SHA256_BLOCK_SIZE]; +}; + +static void sha256_init(void *ctx) +{ + struct s390_sha256_ctx *sctx = ctx; + + sctx->state[0] = 0x6a09e667; + sctx->state[1] = 0xbb67ae85; + sctx->state[2] = 0x3c6ef372; + sctx->state[3] = 0xa54ff53a; + sctx->state[4] = 0x510e527f; + sctx->state[5] = 0x9b05688c; + sctx->state[6] = 0x1f83d9ab; + sctx->state[7] = 0x5be0cd19; + sctx->count = 0; + memset(sctx->buf, 0, sizeof(sctx->buf)); +} + +static void sha256_update(void *ctx, const u8 *data, unsigned int len) +{ + struct s390_sha256_ctx *sctx = ctx; + unsigned int index; + + /* how much is already in the buffer? */ + index = sctx->count / 8 & 0x3f; + + /* update message bit length */ + sctx->count += len * 8; + + /* process one block */ + if ((index + len) >= SHA256_BLOCK_SIZE) { + memcpy(sctx->buf + index, data, SHA256_BLOCK_SIZE - index); + crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf, + SHA256_BLOCK_SIZE); + data += SHA256_BLOCK_SIZE - index; + len -= SHA256_BLOCK_SIZE - index; + } + + /* anything left? */ + if (len) + memcpy(sctx->buf + index , data, len); +} + +static void pad_message(struct s390_sha256_ctx* sctx) +{ + int index, end; + + index = sctx->count / 8 & 0x3f; + end = index < 56 ? SHA256_BLOCK_SIZE : 2 * SHA256_BLOCK_SIZE; + + /* start pad with 1 */ + sctx->buf[index] = 0x80; + + /* pad with zeros */ + index++; + memset(sctx->buf + index, 0x00, end - index - 8); + + /* append message length */ + memcpy(sctx->buf + end - 8, &sctx->count, sizeof sctx->count); + + sctx->count = end * 8; +} + +/* Add padding and return the message digest */ +static void sha256_final(void* ctx, u8 *out) +{ + struct s390_sha256_ctx *sctx = ctx; + + /* must perform manual padding */ + pad_message(sctx); + + crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf, + sctx->count / 8); + + /* copy digest to out */ + memcpy(out, sctx->state, SHA256_DIGEST_SIZE); + + /* wipe context */ + memset(sctx, 0, sizeof *sctx); +} + +static struct crypto_alg alg = { + .cra_name = "sha256", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = SHA256_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct s390_sha256_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .digest = { + .dia_digestsize = SHA256_DIGEST_SIZE, + .dia_init = sha256_init, + .dia_update = sha256_update, + .dia_final = sha256_final } } +}; + +static int init(void) +{ + int ret; + + if (!crypt_s390_func_available(KIMD_SHA_256)) + return -ENOSYS; + + ret = crypto_register_alg(&alg); + if (ret != 0) + printk(KERN_INFO "crypt_s390: sha256_s390 couldn't be loaded."); + return ret; +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_ALIAS("sha256"); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm"); diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 0cb2995bf21..fd00a9f53d5 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -634,6 +634,7 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA1_S390 is not set # CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA256_S390 is not set # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set -- cgit v1.2.3 From bf754ae8ef8bc443c067601d9401103e4001e7c5 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Fri, 6 Jan 2006 00:19:18 -0800 Subject: [PATCH] s390: aes support Add support for the hardware accelerated AES crypto algorithm. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/crypto/Makefile | 1 + arch/s390/crypto/aes_s390.c | 248 ++++++++++++++++++++++++++++++++++++ arch/s390/crypto/crypt_s390.h | 40 ++++-- arch/s390/crypto/crypt_s390_query.c | 12 ++ arch/s390/defconfig | 1 + 5 files changed, 288 insertions(+), 14 deletions(-) create mode 100644 arch/s390/crypto/aes_s390.c (limited to 'arch') diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile index 3fccf61ee1d..bfe2541dc5c 100644 --- a/arch/s390/crypto/Makefile +++ b/arch/s390/crypto/Makefile @@ -5,5 +5,6 @@ obj-$(CONFIG_CRYPTO_SHA1_S390) += sha1_s390.o obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o des_check_key.o +obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o obj-$(CONFIG_CRYPTO_TEST) += crypt_s390_query.o diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c new file mode 100644 index 00000000000..7a1033d8e00 --- /dev/null +++ b/arch/s390/crypto/aes_s390.c @@ -0,0 +1,248 @@ +/* + * Cryptographic API. + * + * s390 implementation of the AES Cipher Algorithm. + * + * s390 Version: + * Copyright (C) 2005 IBM Deutschland GmbH, IBM Corporation + * Author(s): Jan Glauber (jang@de.ibm.com) + * + * Derived from "crypto/aes.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. + * + */ + +#include +#include +#include +#include "crypt_s390.h" + +#define AES_MIN_KEY_SIZE 16 +#define AES_MAX_KEY_SIZE 32 + +/* data block size for all key lengths */ +#define AES_BLOCK_SIZE 16 + +int has_aes_128 = 0; +int has_aes_192 = 0; +int has_aes_256 = 0; + +struct s390_aes_ctx { + u8 iv[AES_BLOCK_SIZE]; + u8 key[AES_MAX_KEY_SIZE]; + int key_len; +}; + +static int aes_set_key(void *ctx, const u8 *in_key, unsigned int key_len, + u32 *flags) +{ + struct s390_aes_ctx *sctx = ctx; + + switch (key_len) { + case 16: + if (!has_aes_128) + goto fail; + break; + case 24: + if (!has_aes_192) + goto fail; + + break; + case 32: + if (!has_aes_256) + goto fail; + break; + default: + /* invalid key length */ + goto fail; + break; + } + + sctx->key_len = key_len; + memcpy(sctx->key, in_key, key_len); + return 0; +fail: + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; +} + +static void aes_encrypt(void *ctx, u8 *out, const u8 *in) +{ + const struct s390_aes_ctx *sctx = ctx; + + switch (sctx->key_len) { + case 16: + crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, + AES_BLOCK_SIZE); + break; + case 24: + crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, + AES_BLOCK_SIZE); + break; + case 32: + crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, + AES_BLOCK_SIZE); + break; + } +} + +static void aes_decrypt(void *ctx, u8 *out, const u8 *in) +{ + const struct s390_aes_ctx *sctx = ctx; + + switch (sctx->key_len) { + case 16: + crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, + AES_BLOCK_SIZE); + break; + case 24: + crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, + AES_BLOCK_SIZE); + break; + case 32: + crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, + AES_BLOCK_SIZE); + break; + } +} + +static unsigned int aes_encrypt_ecb(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) +{ + struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); + + switch (sctx->key_len) { + case 16: + crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, nbytes); + break; + case 24: + crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, nbytes); + break; + case 32: + crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, nbytes); + break; + } + return nbytes & ~(AES_BLOCK_SIZE - 1); +} + +static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) +{ + struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); + + switch (sctx->key_len) { + case 16: + crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, nbytes); + break; + case 24: + crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, nbytes); + break; + case 32: + crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, nbytes); + break; + } + return nbytes & ~(AES_BLOCK_SIZE - 1); +} + +static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) +{ + struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); + + memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE); + switch (sctx->key_len) { + case 16: + crypt_s390_kmc(KMC_AES_128_ENCRYPT, &sctx->iv, out, in, nbytes); + break; + case 24: + crypt_s390_kmc(KMC_AES_192_ENCRYPT, &sctx->iv, out, in, nbytes); + break; + case 32: + crypt_s390_kmc(KMC_AES_256_ENCRYPT, &sctx->iv, out, in, nbytes); + break; + } + memcpy(desc->info, &sctx->iv, AES_BLOCK_SIZE); + + return nbytes & ~(AES_BLOCK_SIZE - 1); +} + +static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) +{ + struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); + + memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE); + switch (sctx->key_len) { + case 16: + crypt_s390_kmc(KMC_AES_128_DECRYPT, &sctx->iv, out, in, nbytes); + break; + case 24: + crypt_s390_kmc(KMC_AES_192_DECRYPT, &sctx->iv, out, in, nbytes); + break; + case 32: + crypt_s390_kmc(KMC_AES_256_DECRYPT, &sctx->iv, out, in, nbytes); + break; + } + return nbytes & ~(AES_BLOCK_SIZE - 1); +} + + +static struct crypto_alg aes_alg = { + .cra_name = "aes", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct s390_aes_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), + .cra_u = { + .cipher = { + .cia_min_keysize = AES_MIN_KEY_SIZE, + .cia_max_keysize = AES_MAX_KEY_SIZE, + .cia_setkey = aes_set_key, + .cia_encrypt = aes_encrypt, + .cia_decrypt = aes_decrypt, + .cia_encrypt_ecb = aes_encrypt_ecb, + .cia_decrypt_ecb = aes_decrypt_ecb, + .cia_encrypt_cbc = aes_encrypt_cbc, + .cia_decrypt_cbc = aes_decrypt_cbc, + } + } +}; + +static int __init aes_init(void) +{ + int ret; + + if (crypt_s390_func_available(KM_AES_128_ENCRYPT)) + has_aes_128 = 1; + if (crypt_s390_func_available(KM_AES_192_ENCRYPT)) + has_aes_192 = 1; + if (crypt_s390_func_available(KM_AES_256_ENCRYPT)) + has_aes_256 = 1; + + if (!has_aes_128 && !has_aes_192 && !has_aes_256) + return -ENOSYS; + + ret = crypto_register_alg(&aes_alg); + if (ret != 0) + printk(KERN_INFO "crypt_s390: aes_s390 couldn't be loaded.\n"); + return ret; +} + +static void __exit aes_fini(void) +{ + crypto_unregister_alg(&aes_alg); +} + +module_init(aes_init); +module_exit(aes_fini); + +MODULE_ALIAS("aes"); + +MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm"); +MODULE_LICENSE("GPL"); + diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h index b70a410ac31..d6712cfa6de 100644 --- a/arch/s390/crypto/crypt_s390.h +++ b/arch/s390/crypto/crypt_s390.h @@ -33,26 +33,38 @@ enum crypt_s390_operations { * 0x80 is the decipher modifier bit */ enum crypt_s390_km_func { - KM_QUERY = CRYPT_S390_KM | 0, - KM_DEA_ENCRYPT = CRYPT_S390_KM | 1, - KM_DEA_DECRYPT = CRYPT_S390_KM | 1 | 0x80, - KM_TDEA_128_ENCRYPT = CRYPT_S390_KM | 2, - KM_TDEA_128_DECRYPT = CRYPT_S390_KM | 2 | 0x80, - KM_TDEA_192_ENCRYPT = CRYPT_S390_KM | 3, - KM_TDEA_192_DECRYPT = CRYPT_S390_KM | 3 | 0x80, + KM_QUERY = CRYPT_S390_KM | 0x0, + KM_DEA_ENCRYPT = CRYPT_S390_KM | 0x1, + KM_DEA_DECRYPT = CRYPT_S390_KM | 0x1 | 0x80, + KM_TDEA_128_ENCRYPT = CRYPT_S390_KM | 0x2, + KM_TDEA_128_DECRYPT = CRYPT_S390_KM | 0x2 | 0x80, + KM_TDEA_192_ENCRYPT = CRYPT_S390_KM | 0x3, + KM_TDEA_192_DECRYPT = CRYPT_S390_KM | 0x3 | 0x80, + KM_AES_128_ENCRYPT = CRYPT_S390_KM | 0x12, + KM_AES_128_DECRYPT = CRYPT_S390_KM | 0x12 | 0x80, + KM_AES_192_ENCRYPT = CRYPT_S390_KM | 0x13, + KM_AES_192_DECRYPT = CRYPT_S390_KM | 0x13 | 0x80, + KM_AES_256_ENCRYPT = CRYPT_S390_KM | 0x14, + KM_AES_256_DECRYPT = CRYPT_S390_KM | 0x14 | 0x80, }; /* function codes for KMC (CIPHER MESSAGE WITH CHAINING) * instruction */ enum crypt_s390_kmc_func { - KMC_QUERY = CRYPT_S390_KMC | 0, - KMC_DEA_ENCRYPT = CRYPT_S390_KMC | 1, - KMC_DEA_DECRYPT = CRYPT_S390_KMC | 1 | 0x80, - KMC_TDEA_128_ENCRYPT = CRYPT_S390_KMC | 2, - KMC_TDEA_128_DECRYPT = CRYPT_S390_KMC | 2 | 0x80, - KMC_TDEA_192_ENCRYPT = CRYPT_S390_KMC | 3, - KMC_TDEA_192_DECRYPT = CRYPT_S390_KMC | 3 | 0x80, + KMC_QUERY = CRYPT_S390_KMC | 0x0, + KMC_DEA_ENCRYPT = CRYPT_S390_KMC | 0x1, + KMC_DEA_DECRYPT = CRYPT_S390_KMC | 0x1 | 0x80, + KMC_TDEA_128_ENCRYPT = CRYPT_S390_KMC | 0x2, + KMC_TDEA_128_DECRYPT = CRYPT_S390_KMC | 0x2 | 0x80, + KMC_TDEA_192_ENCRYPT = CRYPT_S390_KMC | 0x3, + KMC_TDEA_192_DECRYPT = CRYPT_S390_KMC | 0x3 | 0x80, + KMC_AES_128_ENCRYPT = CRYPT_S390_KMC | 0x12, + KMC_AES_128_DECRYPT = CRYPT_S390_KMC | 0x12 | 0x80, + KMC_AES_192_ENCRYPT = CRYPT_S390_KMC | 0x13, + KMC_AES_192_DECRYPT = CRYPT_S390_KMC | 0x13 | 0x80, + KMC_AES_256_ENCRYPT = CRYPT_S390_KMC | 0x14, + KMC_AES_256_DECRYPT = CRYPT_S390_KMC | 0x14 | 0x80, }; /* function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) diff --git a/arch/s390/crypto/crypt_s390_query.c b/arch/s390/crypto/crypt_s390_query.c index 67081b81a4a..def02bdc44a 100644 --- a/arch/s390/crypto/crypt_s390_query.c +++ b/arch/s390/crypto/crypt_s390_query.c @@ -32,6 +32,12 @@ static void query_available_functions(void) crypt_s390_func_available(KM_TDEA_128_ENCRYPT)); printk(KERN_INFO "KM_TDEA_192: %d\n", crypt_s390_func_available(KM_TDEA_192_ENCRYPT)); + printk(KERN_INFO "KM_AES_128: %d\n", + crypt_s390_func_available(KM_AES_128_ENCRYPT)); + printk(KERN_INFO "KM_AES_192: %d\n", + crypt_s390_func_available(KM_AES_192_ENCRYPT)); + printk(KERN_INFO "KM_AES_256: %d\n", + crypt_s390_func_available(KM_AES_256_ENCRYPT)); /* query available KMC functions */ printk(KERN_INFO "KMC_QUERY: %d\n", @@ -42,6 +48,12 @@ static void query_available_functions(void) crypt_s390_func_available(KMC_TDEA_128_ENCRYPT)); printk(KERN_INFO "KMC_TDEA_192: %d\n", crypt_s390_func_available(KMC_TDEA_192_ENCRYPT)); + printk(KERN_INFO "KMC_AES_128: %d\n", + crypt_s390_func_available(KMC_AES_128_ENCRYPT)); + printk(KERN_INFO "KMC_AES_192: %d\n", + crypt_s390_func_available(KMC_AES_192_ENCRYPT)); + printk(KERN_INFO "KMC_AES_256: %d\n", + crypt_s390_func_available(KMC_AES_256_ENCRYPT)); /* query available KIMD fucntions */ printk(KERN_INFO "KIMD_QUERY: %d\n", diff --git a/arch/s390/defconfig b/arch/s390/defconfig index fd00a9f53d5..f195c7ea1d7 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -644,6 +644,7 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_SERPENT is not set # CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_AES_S390 is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set # CONFIG_CRYPTO_TEA is not set -- cgit v1.2.3 From 8129ee164267dc030b8e1d541ee3643c0b9f2fa1 Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Fri, 6 Jan 2006 00:19:20 -0800 Subject: [PATCH] s390: qdio V=V pass-through New feature V=V qdio pass-through. QDIO and HiperSockets processing in z/VM V=V guest environments (as well as V=R with z/VM running in LPAR mode) requires shadowing of all QDIO architecture queue elements. Especially the shadowing of SBALs and SLSBs structures in the hypervisor, and the need to issue SIGA SYNC operations to observe state changes, eventually causes significant CPU processing overhead in the hypervisor. The QDIO pass-through support for V=V guests avoids the shadowing of SBALs and SLSBs. This significantly reduces the hypervisor overhead for QDIO based I/O. Signed-off-by: Frank Pavlic Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/Kconfig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 477ac2758bd..1846fbfd6bf 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -240,8 +240,8 @@ config MACHCHK_WARNING config QDIO tristate "QDIO support" ---help--- - This driver provides the Queued Direct I/O base support for the - IBM S/390 (G5 and G6) and eServer zSeries (z800, z890, z900 and z990). + This driver provides the Queued Direct I/O base support for + IBM mainframes. For details please refer to the documentation provided by IBM at @@ -263,7 +263,8 @@ config QDIO_DEBUG bool "Extended debugging information" depends on QDIO help - Say Y here to get extended debugging output in /proc/s390dbf/qdio... + Say Y here to get extended debugging output in + /sys/kernel/debug/s390dbf/qdio... Warning: this option reduces the performance of the QDIO module. If unsure, say N. -- cgit v1.2.3 From 347a8dc3b815f0c0fa62a1df075184ffe4cbdcf1 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Fri, 6 Jan 2006 00:19:28 -0800 Subject: [PATCH] s390: cleanup Kconfig Sanitize some s390 Kconfig options. We have ARCH_S390, ARCH_S390X, ARCH_S390_31, 64BIT, S390_SUPPORT and COMPAT. Replace these 6 options by S390, 64BIT and COMPAT. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/Kconfig | 27 +++++++-------------------- arch/s390/Makefile | 6 ++---- arch/s390/appldata/appldata_base.c | 8 ++++---- arch/s390/crypto/crypt_s390.h | 10 +++++----- arch/s390/defconfig | 4 +--- arch/s390/kernel/Makefile | 15 +++++---------- arch/s390/kernel/cpcmd.c | 16 ++++++++-------- arch/s390/kernel/entry64.S | 18 +++++++++--------- arch/s390/kernel/head.S | 4 ++-- arch/s390/kernel/module.c | 12 ++++++------ arch/s390/kernel/process.c | 12 ++++++------ arch/s390/kernel/ptrace.c | 24 ++++++++++++------------ arch/s390/kernel/reipl_diag.c | 2 +- arch/s390/kernel/setup.c | 14 +++++++------- arch/s390/kernel/signal.c | 2 +- arch/s390/kernel/smp.c | 8 ++++---- arch/s390/kernel/sys_s390.c | 12 +++++------- arch/s390/kernel/traps.c | 10 +++++----- arch/s390/kernel/vmlinux.lds.S | 2 +- arch/s390/lib/Makefile | 5 ++--- arch/s390/lib/spinlock.c | 2 +- arch/s390/mm/extmem.c | 2 +- arch/s390/mm/fault.c | 18 +++++++++--------- arch/s390/mm/init.c | 8 ++++---- arch/s390/mm/mmap.c | 2 +- 25 files changed, 109 insertions(+), 134 deletions(-) (limited to 'arch') diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 1846fbfd6bf..6fe532d8241 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -23,14 +23,14 @@ config GENERIC_BUST_SPINLOCK mainmenu "Linux Kernel Configuration" -config ARCH_S390 +config S390 bool default y config UID16 bool default y - depends on ARCH_S390X = 'n' + depends on !64BIT source "init/Kconfig" @@ -38,20 +38,12 @@ menu "Base setup" comment "Processor type and features" -config ARCH_S390X +config 64BIT bool "64 bit kernel" help Select this option if you have a 64 bit IBM zSeries machine and want to use the 64 bit addressing mode. -config 64BIT - def_bool ARCH_S390X - -config ARCH_S390_31 - bool - depends on ARCH_S390X = 'n' - default y - config SMP bool "Symmetric multi-processing support" ---help--- @@ -101,20 +93,15 @@ config MATHEMU on older S/390 machines. Say Y unless you know your machine doesn't need this. -config S390_SUPPORT +config COMPAT bool "Kernel support for 31 bit emulation" - depends on ARCH_S390X + depends on 64BIT help Select this option if you want to enable your system kernel to handle system-calls from ELF binaries for 31 bit ESA. This option (and some other stuff like libraries and such) is needed for executing 31 bit applications. It is safe to say "Y". -config COMPAT - bool - depends on S390_SUPPORT - default y - config SYSVIPC_COMPAT bool depends on COMPAT && SYSVIPC @@ -122,7 +109,7 @@ config SYSVIPC_COMPAT config BINFMT_ELF32 tristate "Kernel support for 31 bit ELF binaries" - depends on S390_SUPPORT + depends on COMPAT help This allows you to run 32-bit Linux/ELF binaries on your zSeries in 64 bit mode. Everybody wants this; say Y. @@ -135,7 +122,7 @@ choice config MARCH_G5 bool "S/390 model G5 and G6" - depends on ARCH_S390_31 + depends on !64BIT help Select this to build a 31 bit kernel that works on all S/390 and zSeries machines. diff --git a/arch/s390/Makefile b/arch/s390/Makefile index 73a09a6ee6c..6c6b197898d 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -13,16 +13,14 @@ # Copyright (C) 1994 by Linus Torvalds # -ifdef CONFIG_ARCH_S390_31 +ifndef CONFIG_64BIT LDFLAGS := -m elf_s390 CFLAGS += -m31 AFLAGS += -m31 UTS_MACHINE := s390 STACK_SIZE := 8192 CHECKFLAGS += -D__s390__ -endif - -ifdef CONFIG_ARCH_S390X +else LDFLAGS := -m elf64_s390 MODFLAGS += -fpic -D__PIC__ CFLAGS += -m64 diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index dee6ab54984..d06a8d71c71 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -40,7 +40,7 @@ #define TOD_MICRO 0x01000 /* nr. of TOD clock units for 1 microsecond */ -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT #define APPLDATA_START_INTERVAL_REC 0x00 /* Function codes for */ #define APPLDATA_STOP_REC 0x01 /* DIAG 0xDC */ @@ -54,13 +54,13 @@ #define APPLDATA_GEN_EVENT_RECORD 0x82 #define APPLDATA_START_CONFIG_REC 0x83 -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ /* * Parameter list for DIAGNOSE X'DC' */ -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT struct appldata_parameter_list { u16 diag; /* The DIAGNOSE code X'00DC' */ u8 function; /* The function code for the DIAGNOSE */ @@ -82,7 +82,7 @@ struct appldata_parameter_list { u64 product_id_addr; u64 buffer_addr; }; -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ /* * /proc entries (sysctl) diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h index d6712cfa6de..d1c259a7fe3 100644 --- a/arch/s390/crypto/crypt_s390.h +++ b/arch/s390/crypto/crypt_s390.h @@ -112,7 +112,7 @@ struct crypt_s390_query_status { * [ret] is the variable to receive the error code * [ERR] is the error code value */ -#ifndef __s390x__ +#ifndef CONFIG_64BIT #define __crypt_s390_fixup \ ".section .fixup,\"ax\" \n" \ "7: lhi %0,%h[e1] \n" \ @@ -129,7 +129,7 @@ struct crypt_s390_query_status { " .long 0b,7b \n" \ " .long 1b,8b \n" \ ".previous" -#else /* __s390x__ */ +#else /* CONFIG_64BIT */ #define __crypt_s390_fixup \ ".section .fixup,\"ax\" \n" \ "7: lhi %0,%h[e1] \n" \ @@ -142,7 +142,7 @@ struct crypt_s390_query_status { " .quad 0b,7b \n" \ " .quad 1b,8b \n" \ ".previous" -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */ /* * Standard code for setting the result of s390 crypto instructions. @@ -150,10 +150,10 @@ struct crypt_s390_query_status { * [result]: the register containing the result (e.g. second operand length * to compute number of processed bytes]. */ -#ifndef __s390x__ +#ifndef CONFIG_64BIT #define __crypt_s390_set_result \ " lr %0,%[result] \n" -#else /* __s390x__ */ +#else /* CONFIG_64BIT */ #define __crypt_s390_set_result \ " lgr %0,%[result] \n" #endif diff --git a/arch/s390/defconfig b/arch/s390/defconfig index f195c7ea1d7..7d23edc6fac 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -6,7 +6,7 @@ CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_ARCH_S390=y +CONFIG_S390=y CONFIG_UID16=y # @@ -89,9 +89,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # # Processor type and features # -# CONFIG_ARCH_S390X is not set # CONFIG_64BIT is not set -CONFIG_ARCH_S390_31=y CONFIG_SMP=y CONFIG_NR_CPUS=32 CONFIG_HOTPLUG_CPU=y diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 7434c32bc63..4865e4b4946 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -8,31 +8,26 @@ 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 +obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) +obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) + extra-y += head.o init_task.o vmlinux.lds obj-$(CONFIG_MODULES) += s390_ksyms.o module.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_S390_SUPPORT) += compat_linux.o compat_signal.o \ +obj-$(CONFIG_COMPAT) += compat_linux.o compat_signal.o \ compat_ioctl.o compat_wrapper.o \ compat_exec_domain.o obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o -obj-$(CONFIG_ARCH_S390_31) += entry.o reipl.o -obj-$(CONFIG_ARCH_S390X) += entry64.o reipl64.o - obj-$(CONFIG_VIRT_TIMER) += vtime.o # Kexec part S390_KEXEC_OBJS := machine_kexec.o crash.o -ifeq ($(CONFIG_ARCH_S390X),y) -S390_KEXEC_OBJS += relocate_kernel64.o -else -S390_KEXEC_OBJS += relocate_kernel.o -endif +S390_KEXEC_OBJS += $(if $(CONFIG_64BIT),relocate_kernel64.o,relocate_kernel.o) obj-$(CONFIG_KEXEC) += $(S390_KEXEC_OBJS) - # # This is just to get the dependencies... # diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c index d47fecb42cc..4ef44e536b2 100644 --- a/arch/s390/kernel/cpcmd.c +++ b/arch/s390/kernel/cpcmd.c @@ -39,7 +39,7 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) if (response != NULL && rlen > 0) { memset(response, 0, rlen); -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT asm volatile ( "lra 2,0(%2)\n" "lr 4,%3\n" "o 4,%6\n" @@ -55,7 +55,7 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) : "a" (cpcmd_buf), "d" (cmdlen), "a" (response), "d" (rlen), "m" (mask) : "cc", "2", "3", "4", "5" ); -#else /* CONFIG_ARCH_S390X */ +#else /* CONFIG_64BIT */ asm volatile ( "lrag 2,0(%2)\n" "lgr 4,%3\n" "o 4,%6\n" @@ -73,11 +73,11 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) : "a" (cpcmd_buf), "d" (cmdlen), "a" (response), "d" (rlen), "m" (mask) : "cc", "2", "3", "4", "5" ); -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ EBCASC(response, rlen); } else { return_len = 0; -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT asm volatile ( "lra 2,0(%1)\n" "lr 3,%2\n" "diag 2,3,0x8\n" @@ -85,7 +85,7 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) : "=d" (return_code) : "a" (cpcmd_buf), "d" (cmdlen) : "2", "3" ); -#else /* CONFIG_ARCH_S390X */ +#else /* CONFIG_64BIT */ asm volatile ( "lrag 2,0(%1)\n" "lgr 3,%2\n" "sam31\n" @@ -95,7 +95,7 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) : "=d" (return_code) : "a" (cpcmd_buf), "d" (cmdlen) : "2", "3" ); -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ } spin_unlock_irqrestore(&cpcmd_lock, flags); if (response_code != NULL) @@ -105,7 +105,7 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) EXPORT_SYMBOL(__cpcmd); -#ifdef CONFIG_ARCH_S390X +#ifdef CONFIG_64BIT int cpcmd(const char *cmd, char *response, int rlen, int *response_code) { char *lowbuf; @@ -129,4 +129,4 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code) } EXPORT_SYMBOL(cpcmd); -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 4eb71ffcf48..369ab4413ec 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -213,7 +213,7 @@ sysc_nr_ok: mvc SP_ARGS(8,%r15),SP_R7(%r15) sysc_do_restart: larl %r10,sys_call_table -#ifdef CONFIG_S390_SUPPORT +#ifdef CONFIG_COMPAT tm __TI_flags+5(%r9),(_TIF_31BIT>>16) # running in 31 bit mode ? jno sysc_noemu larl %r10,sys_call_table_emu # use 31 bit emulation system calls @@ -361,7 +361,7 @@ sys_clone_glue: la %r2,SP_PTREGS(%r15) # load pt_regs jg sys_clone # branch to sys_clone -#ifdef CONFIG_S390_SUPPORT +#ifdef CONFIG_COMPAT sys32_clone_glue: la %r2,SP_PTREGS(%r15) # load pt_regs jg sys32_clone # branch to sys32_clone @@ -383,7 +383,7 @@ sys_execve_glue: bnz 0(%r12) # it did fail -> store result in gpr2 b 6(%r12) # SKIP STG 2,SP_R2(15) in # system_call/sysc_tracesys -#ifdef CONFIG_S390_SUPPORT +#ifdef CONFIG_COMPAT sys32_execve_glue: la %r2,SP_PTREGS(%r15) # load pt_regs lgr %r12,%r14 # save return address @@ -398,7 +398,7 @@ sys_sigreturn_glue: la %r2,SP_PTREGS(%r15) # load pt_regs as parameter jg sys_sigreturn # branch to sys_sigreturn -#ifdef CONFIG_S390_SUPPORT +#ifdef CONFIG_COMPAT sys32_sigreturn_glue: la %r2,SP_PTREGS(%r15) # load pt_regs as parameter jg sys32_sigreturn # branch to sys32_sigreturn @@ -408,7 +408,7 @@ sys_rt_sigreturn_glue: la %r2,SP_PTREGS(%r15) # load pt_regs as parameter jg sys_rt_sigreturn # branch to sys_sigreturn -#ifdef CONFIG_S390_SUPPORT +#ifdef CONFIG_COMPAT sys32_rt_sigreturn_glue: la %r2,SP_PTREGS(%r15) # load pt_regs as parameter jg sys32_rt_sigreturn # branch to sys32_sigreturn @@ -429,7 +429,7 @@ sys_sigsuspend_glue: la %r14,6(%r14) # skip store of return value jg sys_sigsuspend # branch to sys_sigsuspend -#ifdef CONFIG_S390_SUPPORT +#ifdef CONFIG_COMPAT sys32_sigsuspend_glue: llgfr %r4,%r4 # unsigned long lgr %r5,%r4 # move mask back @@ -449,7 +449,7 @@ sys_rt_sigsuspend_glue: la %r14,6(%r14) # skip store of return value jg sys_rt_sigsuspend # branch to sys_rt_sigsuspend -#ifdef CONFIG_S390_SUPPORT +#ifdef CONFIG_COMPAT sys32_rt_sigsuspend_glue: llgfr %r3,%r3 # size_t lgr %r4,%r3 # move sigsetsize parameter @@ -464,7 +464,7 @@ sys_sigaltstack_glue: la %r4,SP_PTREGS(%r15) # load pt_regs as parameter jg sys_sigaltstack # branch to sys_sigreturn -#ifdef CONFIG_S390_SUPPORT +#ifdef CONFIG_COMPAT sys32_sigaltstack_glue: la %r4,SP_PTREGS(%r15) # load pt_regs as parameter jg sys32_sigaltstack_wrapper # branch to sys_sigreturn @@ -1009,7 +1009,7 @@ sys_call_table: #include "syscalls.S" #undef SYSCALL -#ifdef CONFIG_S390_SUPPORT +#ifdef CONFIG_COMPAT #define SYSCALL(esa,esame,emu) .long emu .globl sys_call_table_emu diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index d31a97c89f6..ea88d066bf0 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -30,7 +30,7 @@ #include #include -#ifdef CONFIG_ARCH_S390X +#ifdef CONFIG_64BIT #define ARCH_OFFSET 4 #else #define ARCH_OFFSET 0 @@ -539,7 +539,7 @@ ipl_devno: .word 0 .endm -#ifdef CONFIG_ARCH_S390X +#ifdef CONFIG_64BIT #include "head64.S" #else #include "head31.S" diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index 607d506689c..c271cdab58e 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c @@ -37,11 +37,11 @@ #define DEBUGP(fmt , ...) #endif -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT #define PLT_ENTRY_SIZE 12 -#else /* CONFIG_ARCH_S390X */ +#else /* CONFIG_64BIT */ #define PLT_ENTRY_SIZE 20 -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ void *module_alloc(unsigned long size) { @@ -294,17 +294,17 @@ apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, unsigned int *ip; ip = me->module_core + me->arch.plt_offset + info->plt_offset; -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT ip[0] = 0x0d105810; /* basr 1,0; l 1,6(1); br 1 */ ip[1] = 0x100607f1; ip[2] = val; -#else /* CONFIG_ARCH_S390X */ +#else /* CONFIG_64BIT */ ip[0] = 0x0d10e310; /* basr 1,0; lg 1,10(1); br 1 */ ip[1] = 0x100a0004; ip[2] = 0x07f10000; ip[3] = (unsigned int) (val >> 32); ip[4] = (unsigned int) val; -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ info->plt_initialized = 1; } if (r_type == R_390_PLTOFF16 || diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 78b64fe5e7c..a942bf2d58e 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -235,7 +235,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, /* Save access registers to new thread structure. */ save_access_regs(&p->thread.acrs[0]); -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT /* * save fprs to current->thread.fp_regs to merge them with * the emulated registers and then copy the result to the child. @@ -247,7 +247,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, /* Set a new TLS ? */ if (clone_flags & CLONE_SETTLS) p->thread.acrs[0] = regs->gprs[6]; -#else /* CONFIG_ARCH_S390X */ +#else /* CONFIG_64BIT */ /* Save the fpu registers to new thread structure. */ save_fp_regs(&p->thread.fp_regs); p->thread.user_seg = __pa((unsigned long) p->mm->pgd) | _REGION_TABLE; @@ -260,7 +260,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, p->thread.acrs[1] = (unsigned int) regs->gprs[6]; } } -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ /* start new process with ar4 pointing to the correct address space */ p->thread.mm_segment = get_fs(); /* Don't copy debug registers */ @@ -339,16 +339,16 @@ out: */ int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) { -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT /* * save fprs to current->thread.fp_regs to merge them with * the emulated registers and then copy the result to the dump. */ save_fp_regs(¤t->thread.fp_regs); memcpy(fpregs, ¤t->thread.fp_regs, sizeof(s390_fp_regs)); -#else /* CONFIG_ARCH_S390X */ +#else /* CONFIG_64BIT */ save_fp_regs(fpregs); -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ return 1; } diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 06afa3103ac..8ecda6d66de 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -42,7 +42,7 @@ #include #include -#ifdef CONFIG_S390_SUPPORT +#ifdef CONFIG_COMPAT #include "compat_ptrace.h" #endif @@ -59,7 +59,7 @@ FixPerRegisters(struct task_struct *task) if (per_info->single_step) { per_info->control_regs.bits.starting_addr = 0; -#ifdef CONFIG_S390_SUPPORT +#ifdef CONFIG_COMPAT if (test_thread_flag(TIF_31BIT)) per_info->control_regs.bits.ending_addr = 0x7fffffffUL; else @@ -112,7 +112,7 @@ ptrace_disable(struct task_struct *child) clear_single_step(child); } -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT # define __ADDR_MASK 3 #else # define __ADDR_MASK 7 @@ -138,7 +138,7 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data) * an alignment of 4. Programmers from hell... */ mask = __ADDR_MASK; -#ifdef CONFIG_ARCH_S390X +#ifdef CONFIG_64BIT if (addr >= (addr_t) &dummy->regs.acrs && addr < (addr_t) &dummy->regs.orig_gpr2) mask = 3; @@ -160,7 +160,7 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data) * access registers are stored in the thread structure */ offset = addr - (addr_t) &dummy->regs.acrs; -#ifdef CONFIG_ARCH_S390X +#ifdef CONFIG_64BIT /* * Very special case: old & broken 64 bit gdb reading * from acrs[15]. Result is a 64 bit value. Read the @@ -218,7 +218,7 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) * an alignment of 4. Programmers from hell indeed... */ mask = __ADDR_MASK; -#ifdef CONFIG_ARCH_S390X +#ifdef CONFIG_64BIT if (addr >= (addr_t) &dummy->regs.acrs && addr < (addr_t) &dummy->regs.orig_gpr2) mask = 3; @@ -231,13 +231,13 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) * psw and gprs are stored on the stack */ if (addr == (addr_t) &dummy->regs.psw.mask && -#ifdef CONFIG_S390_SUPPORT +#ifdef CONFIG_COMPAT data != PSW_MASK_MERGE(PSW_USER32_BITS, data) && #endif data != PSW_MASK_MERGE(PSW_USER_BITS, data)) /* Invalid psw mask. */ return -EINVAL; -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT if (addr == (addr_t) &dummy->regs.psw.addr) /* I'd like to reject addresses without the high order bit but older gdb's rely on it */ @@ -250,7 +250,7 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) * access registers are stored in the thread structure */ offset = addr - (addr_t) &dummy->regs.acrs; -#ifdef CONFIG_ARCH_S390X +#ifdef CONFIG_64BIT /* * Very special case: old & broken 64 bit gdb writing * to acrs[15] with a 64 bit value. Ignore the lower @@ -357,7 +357,7 @@ do_ptrace_normal(struct task_struct *child, long request, long addr, long data) return ptrace_request(child, request, addr, data); } -#ifdef CONFIG_S390_SUPPORT +#ifdef CONFIG_COMPAT /* * Now the fun part starts... a 31 bit program running in the * 31 bit emulation tracing another program. PTRACE_PEEKTEXT, @@ -629,7 +629,7 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) return peek_user(child, addr, data); if (request == PTRACE_POKEUSR && addr == PT_IEEE_IP) return poke_user(child, addr, data); -#ifdef CONFIG_S390_SUPPORT +#ifdef CONFIG_COMPAT if (request == PTRACE_PEEKUSR && addr == PT32_IEEE_IP && test_thread_flag(TIF_31BIT)) return peek_user_emu31(child, addr, data); @@ -695,7 +695,7 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) /* Do requests that differ for 31/64 bit */ default: -#ifdef CONFIG_S390_SUPPORT +#ifdef CONFIG_COMPAT if (test_thread_flag(TIF_31BIT)) return do_ptrace_emu31(child, request, addr, data); #endif diff --git a/arch/s390/kernel/reipl_diag.c b/arch/s390/kernel/reipl_diag.c index 83cb42bc0b7..1f33951ba43 100644 --- a/arch/s390/kernel/reipl_diag.c +++ b/arch/s390/kernel/reipl_diag.c @@ -26,7 +26,7 @@ void reipl_diag(void) " st %%r4,%0\n" " st %%r5,%1\n" ".section __ex_table,\"a\"\n" -#ifdef __s390x__ +#ifdef CONFIG_64BIT " .align 8\n" " .quad 0b, 0b\n" #else diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 31e7b19348b..b03847d100d 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -427,7 +427,7 @@ setup_lowcore(void) __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE; lc->current_task = (unsigned long) init_thread_union.thread_info.task; lc->thread_info = (unsigned long) &init_thread_union; -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT if (MACHINE_HAS_IEEE) { lc->extended_save_area_addr = (__u32) __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0); @@ -562,21 +562,21 @@ setup_arch(char **cmdline_p) /* * print what head.S has found out about the machine */ -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT printk((MACHINE_IS_VM) ? "We are running under VM (31 bit mode)\n" : "We are running native (31 bit mode)\n"); printk((MACHINE_HAS_IEEE) ? "This machine has an IEEE fpu\n" : "This machine has no IEEE fpu\n"); -#else /* CONFIG_ARCH_S390X */ +#else /* CONFIG_64BIT */ printk((MACHINE_IS_VM) ? "We are running under VM (64 bit mode)\n" : "We are running native (64 bit mode)\n"); -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ ROOT_DEV = Root_RAM0; -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT memory_end = memory_size & ~0x400000UL; /* align memory end to 4MB */ /* * We need some free virtual space to be able to do vmalloc. @@ -585,9 +585,9 @@ setup_arch(char **cmdline_p) */ if (memory_end > 1920*1024*1024) memory_end = 1920*1024*1024; -#else /* CONFIG_ARCH_S390X */ +#else /* CONFIG_64BIT */ memory_end = memory_size & ~0x200000UL; /* detected in head.s */ -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ init_mm.start_code = PAGE_OFFSET; init_mm.end_code = (unsigned long) &_etext; diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index 13592d00a10..6ae4a77270b 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -501,7 +501,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) if (signr > 0) { /* Whee! Actually deliver the signal. */ -#ifdef CONFIG_S390_SUPPORT +#ifdef CONFIG_COMPAT if (test_thread_flag(TIF_31BIT)) { extern void handle_signal32(unsigned long sig, struct k_sigaction *ka, diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index bd5b311006b..e10f4ca0049 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -402,7 +402,7 @@ static void smp_ext_bitcall_others(ec_bit_sig sig) } } -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT /* * this function sends a 'purge tlb' signal to another CPU. */ @@ -416,7 +416,7 @@ void smp_ptlb_all(void) on_each_cpu(smp_ptlb_callback, NULL, 0, 1); } EXPORT_SYMBOL(smp_ptlb_all); -#endif /* ! CONFIG_ARCH_S390X */ +#endif /* ! CONFIG_64BIT */ /* * this function sends a 'reschedule' IPI to another CPU. @@ -783,7 +783,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) if (stack == 0ULL) panic("smp_boot_cpus failed to allocate memory\n"); lowcore_ptr[i]->panic_stack = stack + (PAGE_SIZE); -#ifndef __s390x__ +#ifndef CONFIG_64BIT if (MACHINE_HAS_IEEE) { lowcore_ptr[i]->extended_save_area_addr = (__u32) __get_free_pages(GFP_KERNEL,0); @@ -793,7 +793,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) } #endif } -#ifndef __s390x__ +#ifndef CONFIG_64BIT if (MACHINE_HAS_IEEE) ctl_set_bit(14, 29); /* enable extended save area */ #endif diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c index efe6b83b53f..6a63553493c 100644 --- a/arch/s390/kernel/sys_s390.c +++ b/arch/s390/kernel/sys_s390.c @@ -26,9 +26,7 @@ #include #include #include -#ifdef CONFIG_ARCH_S390X #include -#endif /* CONFIG_ARCH_S390X */ #include #include @@ -121,7 +119,7 @@ out: return error; } -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT struct sel_arg_struct { unsigned long n; fd_set *inp, *outp, *exp; @@ -138,7 +136,7 @@ asmlinkage long old_select(struct sel_arg_struct __user *arg) return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); } -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ /* * sys_ipc() is the de-multiplexer for the SysV IPC calls.. @@ -211,7 +209,7 @@ asmlinkage long sys_ipc(uint call, int first, unsigned long second, return -EINVAL; } -#ifdef CONFIG_ARCH_S390X +#ifdef CONFIG_64BIT asmlinkage long s390x_newuname(struct new_utsname __user *name) { int ret = sys_newuname(name); @@ -235,12 +233,12 @@ asmlinkage long s390x_personality(unsigned long personality) return ret; } -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ /* * Wrapper function for sys_fadvise64/fadvise64_64 */ -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT asmlinkage long s390_fadvise64(int fd, u32 offset_high, u32 offset_low, size_t len, int advice) diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index c5bd36fae56..95d10996861 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -67,13 +67,13 @@ extern pgm_check_handler_t do_monitor_call; #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; }) -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT #define FOURLONG "%08lx %08lx %08lx %08lx\n" static int kstack_depth_to_print = 12; -#else /* CONFIG_ARCH_S390X */ +#else /* CONFIG_64BIT */ #define FOURLONG "%016lx %016lx %016lx %016lx\n" static int kstack_depth_to_print = 20; -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ /* * For show_trace we have tree different stack to consider: @@ -702,12 +702,12 @@ 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; -#ifdef CONFIG_ARCH_S390X +#ifdef CONFIG_64BIT pgm_check_table[0x38] = &do_dat_exception; pgm_check_table[0x39] = &do_dat_exception; pgm_check_table[0x3A] = &do_dat_exception; pgm_check_table[0x3B] = &do_dat_exception; -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ pgm_check_table[0x15] = &operand_exception; pgm_check_table[0x1C] = &space_switch_exception; pgm_check_table[0x1D] = &hfp_sqrt_exception; diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index 89fdb3808bc..9289face302 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -5,7 +5,7 @@ #include #include -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390") OUTPUT_ARCH(s390) ENTRY(_start) diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile index b701efa1f00..d9b97b3c597 100644 --- a/arch/s390/lib/Makefile +++ b/arch/s390/lib/Makefile @@ -4,6 +4,5 @@ EXTRA_AFLAGS := -traditional -lib-y += delay.o string.o -lib-$(CONFIG_ARCH_S390_31) += uaccess.o spinlock.o -lib-$(CONFIG_ARCH_S390X) += uaccess64.o spinlock.o +lib-y += delay.o string.o spinlock.o +lib-y += $(if $(CONFIG_64BIT),uaccess64.o,uaccess.o) diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c index 2dc14e9c832..68d79c50208 100644 --- a/arch/s390/lib/spinlock.c +++ b/arch/s390/lib/spinlock.c @@ -29,7 +29,7 @@ __setup("spin_retry=", spin_retry_setup); static inline void _diag44(void) { -#ifdef __s390x__ +#ifdef CONFIG_64BIT if (MACHINE_HAS_DIAG44) #endif asm volatile("diag 0,0,0x44"); diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c index 506a33b51e4..a9566bcab68 100644 --- a/arch/s390/mm/extmem.c +++ b/arch/s390/mm/extmem.c @@ -143,7 +143,7 @@ dcss_diag (__u8 func, void *parameter, rx = (unsigned long) parameter; ry = (unsigned long) func; __asm__ __volatile__( -#ifdef CONFIG_ARCH_S390X +#ifdef CONFIG_64BIT " sam31\n" // switch to 31 bit " diag %0,%1,0x64\n" " sam64\n" // switch back to 64 bit diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index fb2607c369e..81ade401b07 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -31,17 +31,17 @@ #include #include -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT #define __FAIL_ADDR_MASK 0x7ffff000 #define __FIXUP_MASK 0x7fffffff #define __SUBCODE_MASK 0x0200 #define __PF_RES_FIELD 0ULL -#else /* CONFIG_ARCH_S390X */ +#else /* CONFIG_64BIT */ #define __FAIL_ADDR_MASK -4096L #define __FIXUP_MASK ~0L #define __SUBCODE_MASK 0x0600 #define __PF_RES_FIELD 0x8000000000000000ULL -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ #ifdef CONFIG_SYSCTL extern int sysctl_userprocess_debug; @@ -393,11 +393,11 @@ int pfault_init(void) "2:\n" ".section __ex_table,\"a\"\n" " .align 4\n" -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT " .long 0b,1b\n" -#else /* CONFIG_ARCH_S390X */ +#else /* CONFIG_64BIT */ " .quad 0b,1b\n" -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ ".previous" : "=d" (rc) : "a" (&refbk), "m" (refbk) : "cc" ); __ctl_set_bit(0, 9); @@ -417,11 +417,11 @@ void pfault_fini(void) "0:\n" ".section __ex_table,\"a\"\n" " .align 4\n" -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT " .long 0b,0b\n" -#else /* CONFIG_ARCH_S390X */ +#else /* CONFIG_64BIT */ " .quad 0b,0b\n" -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ ".previous" : : "a" (&refbk), "m" (refbk) : "cc" ); } diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index 6ec5cd981e7..df953383724 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -44,7 +44,7 @@ void diag10(unsigned long addr) { if (addr >= 0x7ff00000) return; -#ifdef __s390x__ +#ifdef CONFIG_64BIT asm volatile ( " sam31\n" " diag %0,%0,0x10\n" @@ -106,7 +106,7 @@ extern unsigned long __initdata zholes_size[]; * paging_init() sets up the page tables */ -#ifndef CONFIG_ARCH_S390X +#ifndef CONFIG_64BIT void __init paging_init(void) { pgd_t * pg_dir; @@ -175,7 +175,7 @@ void __init paging_init(void) return; } -#else /* CONFIG_ARCH_S390X */ +#else /* CONFIG_64BIT */ void __init paging_init(void) { pgd_t * pg_dir; @@ -256,7 +256,7 @@ void __init paging_init(void) return; } -#endif /* CONFIG_ARCH_S390X */ +#endif /* CONFIG_64BIT */ void __init mem_init(void) { diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c index fb187e5a54b..356257c171d 100644 --- a/arch/s390/mm/mmap.c +++ b/arch/s390/mm/mmap.c @@ -50,7 +50,7 @@ static inline unsigned long mmap_base(void) static inline int mmap_is_legacy(void) { -#ifdef CONFIG_ARCH_S390X +#ifdef CONFIG_64BIT /* * Force standard allocation for 64 bit programs. */ -- cgit v1.2.3 From 7ed40918a386afc2e14a6d3da563ea6d13686c25 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 6 Jan 2006 08:43:16 -0800 Subject: x86: remove bogus 'pci=usepirqmask' suggestion when no irq is defined This was harmless, but for the case of a device that had no irq pre-defined we would incorrectly suggest that "usepirqmask" might make a difference. It never would, and the message was just confusing people. Reported in the dmesg of Etienne Lorrain. Signed-off-by: Linus Torvalds --- arch/i386/pci/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index 19e6f4871d1..ee8e01697d9 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -846,7 +846,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) * reported by the device if possible. */ newirq = dev->irq; - if (!((1 << newirq) & mask)) { + if (newirq && !((1 << newirq) & mask)) { if ( pci_probe & PCI_USE_PIRQ_MASK) newirq = 0; else printk(KERN_WARNING "PCI: IRQ %i for device %s doesn't match PIRQ mask - try pci=usepirqmask\n", newirq, pci_name(dev)); } -- cgit v1.2.3 From 20ede2741551d4a1d24313292beb0da915a55911 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Thu, 5 Jan 2006 12:10:52 -0500 Subject: gitignore: ignore shared objects Many arches make shared objects for VDSOs. Generally exclude them. Signed-off-by: Brian Gerst Signed-off-by: Sam Ravnborg --- arch/x86_64/ia32/.gitignore | 1 - 1 file changed, 1 deletion(-) delete mode 100644 arch/x86_64/ia32/.gitignore (limited to 'arch') diff --git a/arch/x86_64/ia32/.gitignore b/arch/x86_64/ia32/.gitignore deleted file mode 100644 index 48ab174fe5f..00000000000 --- a/arch/x86_64/ia32/.gitignore +++ /dev/null @@ -1 +0,0 @@ -vsyscall*.so -- cgit v1.2.3