diff -Nru a/CREDITS b/CREDITS --- a/CREDITS Tue Mar 18 08:47:34 2003 +++ b/CREDITS Fri Mar 21 22:39:54 2003 @@ -1210,6 +1210,10 @@ S: Atlanta, Georgia 30332 S: USA +N: Brad Hards +E: bradh@frogmouth.net +D: Various USB bits, other minor patches + N: Angelo Haritsis E: ah@computer.org D: kernel patches (serial, watchdog) diff -Nru a/Documentation/IPMI.txt b/Documentation/IPMI.txt --- a/Documentation/IPMI.txt Tue Dec 31 05:00:18 2002 +++ b/Documentation/IPMI.txt Wed Mar 26 00:05:10 2003 @@ -5,6 +5,18 @@ +The Intelligent Platform Management Interface, or IPMI, is a +standard for controlling intelligent devices that monitor a system. +It provides for dynamic discovery of sensors in the system and the +ability to monitor the sensors and be informed when the sensor's +values change or go outside certain boundaries. It also has a +standardized database for field-replacable units (FRUs) and a watchdog +timer. + +To use this, you need an interface to an IPMI controller in your +system (called a Baseboard Management Controller, or BMC) and +management software that can use the IPMI system. + This document describes how to use the IPMI driver for Linux. If you are not familiar with IPMI itself, see the web site at http://www.intel.com/design/servers/ipmi/index.htm. IPMI is a big diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt --- a/Documentation/kernel-parameters.txt Tue Mar 18 08:49:00 2003 +++ b/Documentation/kernel-parameters.txt Thu Mar 27 21:15:25 2003 @@ -207,6 +207,12 @@ chandev= [HW,NET] Generic channel device initialisation + clock= [BUGS=IA-32, HW] gettimeofday timesource override. + Forces specified timesource (if avaliable) to be used + when calculating gettimeofday(). If specicified timesource + is not avalible, it defaults to PIT. + Format: { pit | tsc | cyclone | ... } + cm206= [HW,CD] Format: { auto | [,][] } @@ -389,6 +395,10 @@ Format: Run specified binary instead of /sbin/init as init process. + + initcall_debug [KNL] Trace initcalls as they are executed. Useful + for working out where the kernel is dying during + startup. initrd= [BOOT] Specify the location of the initial ramdisk diff -Nru a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt --- a/Documentation/networking/bonding.txt Tue Mar 11 10:20:18 2003 +++ b/Documentation/networking/bonding.txt Fri Mar 28 21:14:07 2003 @@ -7,6 +7,7 @@ - Constantine Gavrilov - Chad N. Tindel - Janice Girouard + - Jay Vosburgh Note : ------ @@ -199,28 +200,42 @@ parameters be specified, otherwise serious network degradation will occur during link failures. +max_bonds + + Specifies the number of bonding devices to create for this + instance of the bonding driver. E.g., if max_bonds is 3, and + the bonding driver is not already loaded, then bond0, bond1 + and bond2 will be created. The default value is 1. + mode - Specifies one of four bonding policies. The default is round-robin. - Possible values are: - - 0 Round-robin policy: Transmit in a sequential order from the - first available slave through the last. This mode provides - load balancing and fault tolerance. - - 1 Active-backup policy: Only one slave in the bond is active. A - different slave becomes active if, and only if, the active slave - fails. The bond's MAC address is externally visible on only - one port (network adapter) to avoid confusing the switch. - This mode provides fault tolerance. - - - 2 XOR policy: Transmit based on [(source MAC address XOR'd with - destination MAC address) modula slave count]. This selects the - same slave for each destination MAC address. This mode provides - load balancing and fault tolerance. - 3 Broadcast policy: transmits everything on all slave interfaces. - This mode provides fault tolerance. + Specifies one of four bonding policies. The default is +round-robin (balance-rr). Possible values are (you can use either the +text or numeric option): + + balance-rr or 0 + Round-robin policy: Transmit in a sequential order + from the first available slave through the last. This + mode provides load balancing and fault tolerance. + + active-backup or 1 + Active-backup policy: Only one slave in the bond is + active. A different slave becomes active if, and only + if, the active slave fails. The bond's MAC address is + externally visible on only one port (network adapter) + to avoid confusing the switch. This mode provides + fault tolerance. + + balance-xor or 2 + XOR policy: Transmit based on [(source MAC address + XOR'd with destination MAC address) modula slave + count]. This selects the same slave for each + destination MAC address. This mode provides load + balancing and fault tolerance. + + broadcast or 3 + Broadcast policy: transmits everything on all slave + interfaces. This mode provides fault tolerance. miimon @@ -229,6 +244,27 @@ 100 is a good starting point. See High Availability section for additional information. The default value is 0. +use_carrier + + Specifies whether or not miimon should use MII or ETHTOOL + ioctls vs. netif_carrier_ok() to determine the link status. + The MII or ETHTOOL ioctls are less efficient and utilize a + deprecated calling sequence within the kernel. The + netif_carrier_ok() relies on the device driver to maintain its + state with netif_carrier_on/off; at this writing, most, but + not all, device drivers support this facility. + + If bonding insists that the link is up when it should not be, + it may be that your network device driver does not support + netif_carrier_on/off. This is because the default state for + netif_carrier is "carrier on." In this case, disabling + use_carrier will cause bonding to revert to the MII / ETHTOOL + ioctl method to determine the link state. + + A value of 1 enables the use of netif_carrier_ok(), a value of + 0 will use the deprecated MII / ETHTOOL ioctls. The default + value is 1. + downdelay Specifies the delay time in milli-seconds to disable a link after a @@ -277,14 +313,17 @@ multicast - Integer value for the mode of operation for multicast support. + Option specifying the mode of operation for multicast support. Possible values are: - 0 Disabled (no multicast support) + disabled or 0 + Disabled (no multicast support) - 1 Enabled on active slave only, useful in active-backup mode + active or 1 + Enabled on active slave only, useful in active-backup mode - 2 Enabled on all slaves, this is the default + all or 2 + Enabled on all slaves, this is the default Configuring Multiple Bonds @@ -321,7 +360,52 @@ alias bond0 bonding options bond0 arp_interval=60 arp_ip_target=192.168.0.100 +Potential Problems When Using ARP Monitor +========================================= + +1. Driver support +The ARP monitor relies on the network device driver to maintain two +statistics: the last receive time (dev->last_rx), and the last +transmit time (dev->trans_start). If the network device driver does +not update one or both of these, then the typical result will be that, +upon startup, all links in the bond will immediately be declared down, +and remain that way. A network monitoring tool (tcpdump, e.g.) will +show ARP requests and replies being sent and received on the bonding +device. + +The possible resolutions for this are to (a) fix the device driver, or +(b) discontinue the ARP monitor (using miimon as an alternative, for +example). + +2. Adventures in Routing + +When bonding is set up with the ARP monitor, it is important that the +slave devices not have routes that supercede routes of the master (or, +generally, not have routes at all). For example, suppose the bonding +device bond0 has two slaves, eth0 and eth1, and the routing table is +as follows: + +Kernel IP routing table +Destination Gateway Genmask Flags MSS Window irtt Iface +10.0.0.0 0.0.0.0 255.255.0.0 U 40 0 0 eth0 +10.0.0.0 0.0.0.0 255.255.0.0 U 40 0 0 eth1 +10.0.0.0 0.0.0.0 255.255.0.0 U 40 0 0 bond0 +127.0.0.0 0.0.0.0 255.0.0.0 U 40 0 0 lo + +In this case, the ARP monitor (and ARP itself) may become confused, +because ARP requests will be sent on one interface (bond0), but the +corresponding reply will arrive on a different interface (eth0). This +reply looks to ARP as an unsolicited ARP reply (because ARP matches +replies on an interface basis), and is discarded. This will likely +still update the receive/transmit times in the driver, but will lose +packets. + +The resolution here is simply to insure that slaves do not have routes +of their own, and if for some reason they must, those routes do not +supercede routes of their master. This should generally be the case, +but unusual configurations or errant manual or automatic static route +additions may cause trouble. Switch Configuration ==================== @@ -462,7 +546,7 @@ If not explicitly configured with ifconfig, the MAC address of the bonding device is taken from its first slave device. This MAC address is then passed to all following slaves and remains persistent (even if - the first slave is removed) until the bonding device is brought + the the first slave is removed) until the bonding device is brought down or reconfigured. If you wish to change the MAC address, you can set it with ifconfig: @@ -606,12 +690,16 @@ To use this mode, pass "mode=1" to the module at load time : + # modprobe bonding miimon=100 mode=active-backup + + or: + # modprobe bonding miimon=100 mode=1 Or, put in your /etc/modules.conf : alias bond0 bonding - options bond0 miimon=100 mode=1 + options bond0 miimon=100 mode=active-backup Example 1: Using multiple host and multiple switches to build a "no single point of failure" solution. @@ -698,7 +786,7 @@ Examples : # modprobe bonding miimon=100 mode=1 downdelay=2000 updelay=5000 - # modprobe bonding miimon=100 mode=0 downdelay=0 updelay=5000 + # modprobe bonding miimon=100 mode=balance-rr downdelay=0 updelay=5000 Promiscuous Sniffing notes diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS Sat Mar 22 20:13:39 2003 +++ b/MAINTAINERS Fri Mar 21 22:38:09 2003 @@ -1869,11 +1869,12 @@ W: http://www.kroah.com/linux-usb/ USB CDC ETHERNET DRIVER -P: Brad Hards -M: bradh@frogmouth.net +P: Greg Kroah-Hartman +M: greg@kroah.com L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net S: Maintained +W: http://www.kroah.com/linux-usb/ USB EHCI DRIVER P: David Brownell diff -Nru a/Makefile b/Makefile --- a/Makefile Mon Mar 24 13:57:16 2003 +++ b/Makefile Sun Mar 30 04:33:50 2003 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 5 SUBLEVEL = 66 -EXTRAVERSION = +EXTRAVERSION = -bk5 # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff -Nru a/arch/alpha/kernel/err_titan.c b/arch/alpha/kernel/err_titan.c --- a/arch/alpha/kernel/err_titan.c Thu Jan 16 16:01:37 2003 +++ b/arch/alpha/kernel/err_titan.c Fri Mar 7 09:24:50 2003 @@ -22,8 +22,10 @@ static int titan_parse_c_misc(u64 c_misc, int print) { +#ifdef CONFIG_VERBOSE_MCHECK char *src; int nxs = 0; +#endif int status = MCHK_DISPOSITION_REPORT; #define TITAN__CCHIP_MISC__NXM (1UL << 28) @@ -263,11 +265,11 @@ static int titan_parse_p_agperror(int which, u64 agperror, int print) { + int status = MCHK_DISPOSITION_REPORT; +#ifdef CONFIG_VERBOSE_MCHECK int cmd, len; unsigned long addr; - int status = MCHK_DISPOSITION_REPORT; -#ifdef CONFIG_VERBOSE_MCHECK char *agperror_cmd[] = { "Read (low-priority)", "Read (high-priority)", "Write (low-priority)", "Write (high-priority)", @@ -575,14 +577,14 @@ static int privateer_process_680_frame(struct el_common *mchk_header, int print) { + int status = MCHK_DISPOSITION_UNKNOWN_ERROR; +#ifdef CONFIG_VERBOSE_MCHECK struct el_PRIVATEER_envdata_mcheck *emchk = (struct el_PRIVATEER_envdata_mcheck *) ((unsigned long)mchk_header + mchk_header->sys_offset); - int status = MCHK_DISPOSITION_UNKNOWN_ERROR; /* TODO - catagorize errors, for now, no error */ -#ifdef CONFIG_VERBOSE_MCHECK if (!print) return status; diff -Nru a/arch/alpha/kernel/module.c b/arch/alpha/kernel/module.c --- a/arch/alpha/kernel/module.c Mon Jan 13 09:46:25 2003 +++ b/arch/alpha/kernel/module.c Sun Mar 23 16:17:40 2003 @@ -199,7 +199,9 @@ case R_ALPHA_NONE: break; case R_ALPHA_REFQUAD: - *(u64 *)location = value; + /* BUG() can produce misaligned relocations. */ + ((u32 *)location)[0] = value; + ((u32 *)location)[1] = value >> 32; break; case R_ALPHA_GPREL32: value -= gp; diff -Nru a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c --- a/arch/alpha/kernel/pci.c Sun Mar 16 14:16:29 2003 +++ b/arch/alpha/kernel/pci.c Sun Mar 23 17:35:08 2003 @@ -285,7 +285,7 @@ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); /* Move up the chain of bridges. */ dev = dev->bus->self; - } while (dev->bus->self); + } while (dev->bus->parent); *pinp = pin; /* The slot is the slot of the last bridge. */ @@ -410,10 +410,8 @@ if (pci_probe_only) pcibios_claim_console_setup(); - else /* FIXME: `else' will be removed when - pci_assign_unassigned_resources() is able to work - correctly with [partially] allocated PCI tree. */ - pci_assign_unassigned_resources(); + + pci_assign_unassigned_resources(); pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq); } diff -Nru a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c --- a/arch/alpha/kernel/smp.c Sun Mar 2 18:13:32 2003 +++ b/arch/alpha/kernel/smp.c Sat Mar 22 16:02:37 2003 @@ -112,7 +112,7 @@ static void __init wait_boot_cpu_to_stop(int cpuid) { - long stop = jiffies + 10*HZ; + unsigned long stop = jiffies + 10*HZ; while (time_before(jiffies, stop)) { if (!smp_secondary_alive) @@ -349,7 +349,7 @@ { struct percpu_struct *cpu; struct pcb_struct *hwpcb, *ipcb; - long timeout; + unsigned long timeout; cpu = (struct percpu_struct *) ((char*)hwrpb @@ -428,7 +428,7 @@ smp_boot_one_cpu(int cpuid) { struct task_struct *idle; - long timeout; + unsigned long timeout; /* Cook up an idler for this guy. Note that the address we give to kernel_thread is irrelevant -- it's going to start @@ -816,7 +816,7 @@ int wait, unsigned long to_whom) { struct smp_call_struct data; - long timeout; + unsigned long timeout; int num_cpus_to_call; data.func = func; diff -Nru a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c --- a/arch/alpha/kernel/sys_nautilus.c Sun Mar 2 17:34:25 2003 +++ b/arch/alpha/kernel/sys_nautilus.c Mon Mar 24 12:08:43 2003 @@ -183,14 +183,17 @@ extern void free_reserved_mem(void *, void *); +static struct resource irongate_mem = { + .name = "Irongate PCI MEM", + .flags = IORESOURCE_MEM, +}; + void __init nautilus_init_pci(void) { struct pci_controller *hose = hose_head; struct pci_bus *bus; struct pci_dev *irongate; - unsigned long saved_io_start, saved_io_end; - unsigned long saved_mem_start, saved_mem_end; unsigned long bus_align, bus_size, pci_mem; unsigned long memtop = max_low_pfn << PAGE_SHIFT; @@ -199,50 +202,41 @@ hose->bus = bus; hose->last_busno = bus->subordinate; - /* We're going to size the root bus, so we must - - have a non-NULL PCI device associated with the bus - - preserve hose resources. */ irongate = pci_find_slot(0, 0); bus->self = irongate; - saved_io_start = bus->resource[0]->start; - saved_io_end = bus->resource[0]->end; - saved_mem_start = bus->resource[1]->start; - saved_mem_end = bus->resource[1]->end; + bus->resource[1] = &irongate_mem; pci_bus_size_bridges(bus); - /* Don't care about IO. */ - bus->resource[0]->start = saved_io_start; - bus->resource[0]->end = saved_io_end; + /* IO port range. */ + bus->resource[0]->start = 0; + bus->resource[0]->end = 0xffff; + /* Set up PCI memory range - limit is hardwired to 0xffffffff, + base must be at aligned to 16Mb. */ bus_align = bus->resource[1]->start; bus_size = bus->resource[1]->end + 1 - bus_align; - /* Align to 16Mb. */ if (bus_align < 0x1000000UL) bus_align = 0x1000000UL; - /* Restore hose MEM resource. */ - bus->resource[1]->start = saved_mem_start; - bus->resource[1]->end = saved_mem_end; - pci_mem = (0x100000000UL - bus_size) & -bus_align; + bus->resource[1]->start = pci_mem; + bus->resource[1]->end = 0xffffffffUL; + if (request_resource(&iomem_resource, bus->resource[1]) < 0) + printk(KERN_ERR "Failed to request MEM on hose 0\n"); + if (pci_mem < memtop && pci_mem > alpha_mv.min_mem_address) { free_reserved_mem(__va(alpha_mv.min_mem_address), __va(pci_mem)); - printk("nautilus_init_arch: %ldk freed\n", + printk("nautilus_init_pci: %ldk freed\n", (pci_mem - alpha_mv.min_mem_address) >> 10); } - alpha_mv.min_mem_address = pci_mem; if ((IRONGATE0->dev_vendor >> 16) > 0x7006) /* Albacore? */ IRONGATE0->pci_mem = pci_mem; pci_bus_assign_resources(bus); - - /* To break the loop in common_swizzle() */ - bus->self = NULL; - pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq); } diff -Nru a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c --- a/arch/arm/kernel/apm.c Thu Mar 6 07:59:42 2003 +++ b/arch/arm/kernel/apm.c Wed Mar 26 05:00:46 2003 @@ -552,8 +552,6 @@ MODULE_DESCRIPTION("Advanced Power Management"); MODULE_LICENSE("GPL"); -EXPORT_NO_SYMBOLS; - #ifndef MODULE static int __init apm_setup(char *str) { diff -Nru a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c --- a/arch/arm/kernel/armksyms.c Wed Jan 1 06:34:04 2003 +++ b/arch/arm/kernel/armksyms.c Tue Mar 25 17:10:26 2003 @@ -69,6 +69,7 @@ extern void __udivsi3(void); extern void __umodsi3(void); extern void abort(void); +extern void do_div64(void); extern void ret_from_exception(void); extern void fpundefinstr(void); @@ -234,6 +235,7 @@ EXPORT_SYMBOL_NOVERS(__udivmoddi4); EXPORT_SYMBOL_NOVERS(__udivsi3); EXPORT_SYMBOL_NOVERS(__umodsi3); +EXPORT_SYMBOL_NOVERS(do_div64); /* bitops */ EXPORT_SYMBOL(_set_bit_le); diff -Nru a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S --- a/arch/arm/kernel/entry-armv.S Thu Mar 6 07:52:20 2003 +++ b/arch/arm/kernel/entry-armv.S Wed Mar 26 05:14:18 2003 @@ -997,11 +997,11 @@ * previous and next are guaranteed not to be the same. */ ENTRY(__switch_to) - add ip, r0, #TI_CPU_SAVE - ldr r2, [r1, #TI_CPU_DOMAIN]! + add ip, r1, #TI_CPU_SAVE + ldr r3, [r2, #TI_CPU_DOMAIN]! stmia ip, {r4 - sl, fp, sp, lr} @ Store most regs on stack - mcr p15, 0, r2, c3, c0 @ Set domain register - ldmib r1, {r4 - sl, fp, sp, pc} @ Load all regs saved previously + mcr p15, 0, r3, c3, c0, 0 @ Set domain register + ldmib r2, {r4 - sl, fp, sp, pc} @ Load all regs saved previously __INIT /* diff -Nru a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S --- a/arch/arm/kernel/entry-common.S Thu Mar 6 05:18:11 2003 +++ b/arch/arm/kernel/entry-common.S Wed Mar 26 05:13:45 2003 @@ -75,7 +75,6 @@ * This is how we return from a fork. */ ENTRY(ret_from_fork) - ldr r0, [r0, #TI_TASK] bl schedule_tail get_thread_info tsk ldr r1, [tsk, #TI_FLAGS] @ check for syscall tracing diff -Nru a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile --- a/arch/arm/lib/Makefile Sat Dec 14 04:38:56 2002 +++ b/arch/arm/lib/Makefile Tue Mar 25 17:10:27 2003 @@ -13,7 +13,7 @@ strnlen_user.o strchr.o strrchr.o testchangebit.o \ testclearbit.o testsetbit.o uaccess.o getuser.o \ putuser.o ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ - ucmpdi2.o udivdi3.o lib1funcs.o + ucmpdi2.o udivdi3.o lib1funcs.o div64.o obj-m := obj-n := diff -Nru a/arch/arm/lib/div64.S b/arch/arm/lib/div64.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/lib/div64.S Tue Mar 25 17:10:27 2003 @@ -0,0 +1,42 @@ +#include + +ql .req r0 @ quotient low +qh .req r1 @ quotient high +dl .req r3 @ divisor low +dh .req r2 @ divisor high +nl .req r4 @ dividend low +nh .req r5 @ dividend high + +ENTRY(do_div64) + stmfd sp!, {r4, r5, lr} + mov nl, r0 + movs nh, r1 @ if high bits are zero + movne lr, #33 + moveq lr, #1 @ only divide low bits + moveq nh, r0 + +1: cmp nh, dh + bls 2f + add lr, lr, #1 + movs dh, dh, lsl #1 @ left justify divisor + bpl 1b + +2: movs nh, r1 + moveq dl, dh + moveq dh, #0 + movne dl, #0 + mov ql, #0 + mov qh, #0 +3: subs ip, nl, dl @ trial subtraction + sbcs ip, nh, dh + movcs nh, ip @ only update if successful + subcs nl, nl, dl @ (repeat the subtraction) + adcs ql, ql, ql @ C=1 if successful, shift into + adc qh, qh, qh @ quotient + movs dh, dh, lsr #1 @ shift base high part right + mov dl, dl, rrx @ shift base low part right + subs lr, lr, #1 + bne 3b + + mov r2, nl + ldmfd sp!, {r4, r5, pc} diff -Nru a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c --- a/arch/arm/mach-footbridge/dc21285.c Sun Nov 17 07:31:09 2002 +++ b/arch/arm/mach-footbridge/dc21285.c Wed Mar 26 07:30:03 2003 @@ -25,10 +25,13 @@ #define MAX_SLOTS 21 -#define PCICMD_ERROR_BITS ((PCI_STATUS_DETECTED_PARITY | \ - PCI_STATUS_REC_MASTER_ABORT | \ - PCI_STATUS_REC_TARGET_ABORT | \ - PCI_STATUS_PARITY) << 16) +#define PCICMD_ABORT ((PCI_STATUS_REC_MASTER_ABORT| \ + PCI_STATUS_REC_TARGET_ABORT)<<16) + +#define PCICMD_ERROR_BITS ((PCI_STATUS_DETECTED_PARITY | \ + PCI_STATUS_REC_MASTER_ABORT | \ + PCI_STATUS_REC_TARGET_ABORT | \ + PCI_STATUS_PARITY) << 16) extern int setup_arm_irq(int, struct irqaction *); extern void pcibios_report_status(u_int status_mask, int warn); @@ -84,6 +87,12 @@ *value = v; + v = *CSR_PCICMD; + if (v & PCICMD_ABORT) { + *CSR_PCICMD = v & (0xffff|PCICMD_ABORT); + return -1; + } + return PCIBIOS_SUCCESSFUL; } @@ -92,6 +101,7 @@ int size, u32 value) { unsigned long addr = dc21285_base_address(bus, devfn); + u32 v; if (addr) switch (size) { @@ -109,6 +119,12 @@ break; } + v = *CSR_PCICMD; + if (v & PCICMD_ABORT) { + *CSR_PCICMD = v & (0xffff|PCICMD_ABORT); + return -1; + } + return PCIBIOS_SUCCESSFUL; } @@ -148,16 +164,16 @@ cmd = cmd & 0xffff; if (status & PCI_STATUS_REC_MASTER_ABORT) { - printk(KERN_DEBUG "PCI: master abort: "); - pcibios_report_status(PCI_STATUS_REC_MASTER_ABORT, 1); - printk("\n"); - + printk(KERN_DEBUG "PCI: master abort, pc=0x%08lx\n", + instruction_pointer(regs)); cmd |= PCI_STATUS_REC_MASTER_ABORT << 16; } if (status & PCI_STATUS_REC_TARGET_ABORT) { printk(KERN_DEBUG "PCI: target abort: "); - pcibios_report_status(PCI_STATUS_SIG_TARGET_ABORT, 1); + pcibios_report_status(PCI_STATUS_REC_MASTER_ABORT | + PCI_STATUS_SIG_TARGET_ABORT | + PCI_STATUS_REC_TARGET_ABORT, 1); printk("\n"); cmd |= PCI_STATUS_REC_TARGET_ABORT << 16; @@ -289,6 +305,38 @@ "%s mode\n", *CSR_CLASSREV & 0xff, cfn_mode ? "central function" : "addin"); + if (footbridge_cfn_mode()) { + /* + * Clear any existing errors - we aren't + * interested in historical data... + */ + *CSR_SA110_CNTL = (*CSR_SA110_CNTL & 0xffffde07) | + SA110_CNTL_RXSERR; + *CSR_PCICMD = (*CSR_PCICMD & 0xffff) | PCICMD_ERROR_BITS; + } + + init_timer(&serr_timer); + init_timer(&perr_timer); + + serr_timer.data = IRQ_PCI_SERR; + serr_timer.function = dc21285_enable_error; + perr_timer.data = IRQ_PCI_PERR; + perr_timer.function = dc21285_enable_error; + + /* + * We don't care if these fail. + */ + request_irq(IRQ_PCI_SERR, dc21285_serr_irq, SA_INTERRUPT, + "PCI system error", &serr_timer); + request_irq(IRQ_PCI_PERR, dc21285_parity_irq, SA_INTERRUPT, + "PCI parity error", &perr_timer); + request_irq(IRQ_PCI_ABORT, dc21285_abort_irq, SA_INTERRUPT, + "PCI abort", NULL); + request_irq(IRQ_DISCARD_TIMER, dc21285_discard_irq, SA_INTERRUPT, + "Discard timer", NULL); + request_irq(IRQ_PCI_DPERR, dc21285_dparity_irq, SA_INTERRUPT, + "PCI data parity", NULL); + if (cfn_mode) { static struct resource csrio; @@ -324,35 +372,5 @@ void __init dc21285_postinit(void) { - if (footbridge_cfn_mode()) { - /* - * Clear any existing errors - we aren't - * interested in historical data... - */ - *CSR_SA110_CNTL = (*CSR_SA110_CNTL & 0xffffde07) | - SA110_CNTL_RXSERR; - *CSR_PCICMD = (*CSR_PCICMD & 0xffff) | PCICMD_ERROR_BITS; - } - - /* - * Initialise PCI error IRQ after we've finished probing - */ - request_irq(IRQ_PCI_ABORT, dc21285_abort_irq, SA_INTERRUPT, "PCI abort", NULL); - request_irq(IRQ_DISCARD_TIMER, dc21285_discard_irq, SA_INTERRUPT, "Discard timer", NULL); - request_irq(IRQ_PCI_DPERR, dc21285_dparity_irq, SA_INTERRUPT, "PCI data parity", NULL); - - init_timer(&serr_timer); - init_timer(&perr_timer); - - serr_timer.data = IRQ_PCI_SERR; - serr_timer.function = dc21285_enable_error; - perr_timer.data = IRQ_PCI_PERR; - perr_timer.function = dc21285_enable_error; - - request_irq(IRQ_PCI_SERR, dc21285_serr_irq, SA_INTERRUPT, - "PCI system error", &serr_timer); - request_irq(IRQ_PCI_PERR, dc21285_parity_irq, SA_INTERRUPT, - "PCI parity error", &perr_timer); - register_isa_ports(DC21285_PCI_MEM, DC21285_PCI_IO, 0); } diff -Nru a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c --- a/arch/arm/mach-sa1100/assabet.c Sun Nov 17 07:31:12 2002 +++ b/arch/arm/mach-sa1100/assabet.c Wed Mar 26 07:52:09 2003 @@ -117,6 +117,8 @@ PGSR = 0; PCFR = 0; PSDR = 0; + PPDR |= PPC_TXD3 | PPC_TXD1; + PPSR |= PPC_TXD3 | PPC_TXD1; sa1100fb_lcd_power = assabet_lcd_power; sa1100fb_backlight_power = assabet_backlight_power; diff -Nru a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c --- a/arch/arm/mach-sa1100/cpu-sa1110.c Thu Mar 6 11:27:04 2003 +++ b/arch/arm/mach-sa1100/cpu-sa1110.c Wed Mar 26 07:35:41 2003 @@ -234,6 +234,8 @@ (sa11x0_ppcr_to_freq(ppcr-1) >= policy->min)) ppcr--; break; + default: + return -EINVAL; } freqs.old = sa11x0_getspeed(); diff -Nru a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types --- a/arch/arm/tools/mach-types Thu Mar 6 06:57:42 2003 +++ b/arch/arm/tools/mach-types Wed Mar 26 05:04:32 2003 @@ -6,7 +6,7 @@ # To add an entry into this database, please see Documentation/arm/README, # or contact rmk@arm.linux.org.uk # -# Last update: Wed Mar 5 22:11:59 2003 +# Last update: Tue Mar 25 16:34:29 2003 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -305,3 +305,11 @@ pxa_whitechapel ARCH_PXA_WHITECHAPEL PXA_WHITECHAPEL 294 nwsc ARCH_NWSC NWSC 295 nwlarm ARCH_NWLARM NWLARM 296 +ixp425_mguard ARCH_IXP425_MGUARD IXP425_MGUARD 297 +pxa_netdcu4 ARCH_PXA_NETDCU4 PXA_NETDCU4 298 +ixdp2401 ARCH_IXDP2401 IXDP2401 299 +ixdp2801 ARCH_IXDP2801 IXDP2801 300 +zodiac ARCH_ZODIAC ZODIAC 301 +armmodul ARCH_ARMMODUL ARMMODUL 302 +ketop SA1100_KETOP KETOP 303 +av7200 ARCH_AV7200 AV7200 304 diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c --- a/arch/i386/kernel/smpboot.c Mon Mar 17 21:31:45 2003 +++ b/arch/i386/kernel/smpboot.c Thu Mar 27 21:15:25 2003 @@ -422,7 +422,7 @@ /* * Synchronize the TSC with the BP */ - if (cpu_has_tsc) + if (cpu_has_tsc && cpu_khz) synchronize_tsc_ap(); } @@ -1114,7 +1114,7 @@ /* * Synchronize the TSC with the AP */ - if (cpu_has_tsc && cpucount) + if (cpu_has_tsc && cpucount && cpu_khz) synchronize_tsc_bp(); } diff -Nru a/arch/i386/kernel/timers/timer.c b/arch/i386/kernel/timers/timer.c --- a/arch/i386/kernel/timers/timer.c Mon Feb 10 06:04:32 2003 +++ b/arch/i386/kernel/timers/timer.c Thu Mar 27 21:15:25 2003 @@ -1,4 +1,6 @@ +#include #include +#include #include /* list of externed timers */ @@ -17,6 +19,17 @@ NULL, }; +static char clock_override[10] __initdata; + +static int __init clock_setup(char* str) +{ + if (str) { + strncpy(clock_override, str,10); + clock_override[9] = '\0'; + } + return 1; +} +__setup("clock=", clock_setup); /* iterates through the list of timers, returning the first * one that initializes successfully. @@ -28,7 +41,7 @@ /* find most preferred working timer */ while (timers[i]) { if (timers[i]->init) - if (timers[i]->init() == 0) + if (timers[i]->init(clock_override) == 0) return timers[i]; ++i; } diff -Nru a/arch/i386/kernel/timers/timer_cyclone.c b/arch/i386/kernel/timers/timer_cyclone.c --- a/arch/i386/kernel/timers/timer_cyclone.c Tue Feb 11 17:46:34 2003 +++ b/arch/i386/kernel/timers/timer_cyclone.c Thu Mar 27 21:15:25 2003 @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -73,7 +74,7 @@ return delay_at_last_interrupt + offset; } -static int init_cyclone(void) +static int __init init_cyclone(char* override) { u32* reg; u32 base; /* saved cyclone base address */ @@ -81,8 +82,11 @@ u32 offset; /* offset from pageaddr to cyclone_timer register */ int i; + /* check clock override */ + if (override[0] && strncmp(override,"cyclone",7)) + return -ENODEV; + /*make sure we're on a summit box*/ - /*XXX need to use proper summit hooks! such as xapic -john*/ if(!use_cyclone) return -ENODEV; printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n"); diff -Nru a/arch/i386/kernel/timers/timer_none.c b/arch/i386/kernel/timers/timer_none.c --- a/arch/i386/kernel/timers/timer_none.c Mon Jan 13 06:55:52 2003 +++ b/arch/i386/kernel/timers/timer_none.c Thu Mar 27 21:15:25 2003 @@ -1,6 +1,7 @@ +#include #include -static int init_none(void) +static int __init init_none(char* override) { return 0; } diff -Nru a/arch/i386/kernel/timers/timer_pit.c b/arch/i386/kernel/timers/timer_pit.c --- a/arch/i386/kernel/timers/timer_pit.c Wed Feb 5 05:04:39 2003 +++ b/arch/i386/kernel/timers/timer_pit.c Thu Mar 27 21:15:25 2003 @@ -17,8 +17,12 @@ extern spinlock_t i8253_lock; #include "do_timer.h" -static int init_pit(void) +static int __init init_pit(char* override) { + /* check clock override */ + if (override[0] && strncmp(override,"pit",3)) + printk(KERN_ERR "Warning: clock= override failed. Defaulting to PIT\n"); + return 0; } diff -Nru a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c --- a/arch/i386/kernel/timers/timer_tsc.c Thu Mar 20 03:11:42 2003 +++ b/arch/i386/kernel/timers/timer_tsc.c Thu Mar 27 21:15:25 2003 @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -244,8 +245,13 @@ #endif -static int init_tsc(void) +static int __init init_tsc(char* override) { + + /* check clock override */ + if (override[0] && strncmp(override,"tsc",3)) + return -ENODEV; + /* * If we have APM enabled or the CPU clock speed is variable * (CPU stops clock on HLT or slows clock to save power) diff -Nru a/arch/i386/mm/boot_ioremap.c b/arch/i386/mm/boot_ioremap.c --- a/arch/i386/mm/boot_ioremap.c Mon Feb 24 23:13:13 2003 +++ b/arch/i386/mm/boot_ioremap.c Thu Mar 27 21:15:34 2003 @@ -19,6 +19,7 @@ #undef CONFIG_X86_PAE #include #include +#include #include #include @@ -48,10 +49,12 @@ { boot_pte_t* pte; int i; + char *vaddr = virtual_source; pte = boot_vaddr_to_pte(virtual_source); for (i=0; i < nrpages; i++, phys_addr += PAGE_SIZE, pte++) { set_pte(pte, pfn_pte(phys_addr>>PAGE_SHIFT, PAGE_KERNEL)); + __flush_tlb_one(&vaddr[i*PAGE_SIZE]); } } diff -Nru a/arch/i386/mm/highmem.c b/arch/i386/mm/highmem.c --- a/arch/i386/mm/highmem.c Mon Oct 28 09:41:27 2002 +++ b/arch/i386/mm/highmem.c Thu Mar 27 21:16:14 2003 @@ -2,8 +2,7 @@ void *kmap(struct page *page) { - if (in_interrupt()) - BUG(); + might_sleep(); if (page < highmem_start_page) return page_address(page); return kmap_high(page); diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig --- a/arch/ppc/Kconfig Sat Mar 8 14:50:37 2003 +++ b/arch/ppc/Kconfig Wed Mar 26 22:00:59 2003 @@ -666,6 +666,52 @@ here. Saying Y here will not hurt performance (on any machine) but will increase the size of the kernel. +config CPU_FREQ + bool "CPU Frequency scaling" + help + Clock scaling allows you to change the clock speed of CPUs on the + fly. This is a nice method to save battery power on notebooks, + because the lower the clock speed, the less power the CPU consumes. + + For more information, take a look at linux/Documentation/cpufreq or + at + + If in doubt, say N. + +config CPU_FREQ_PROC_INTF + bool "/proc/cpufreq interface (DEPRECATED)" + depends on CPU_FREQ && PROC_FS + help + This enables the /proc/cpufreq interface for controlling + CPUFreq. Please note that it is recommended to use the sysfs + interface instead (which is built automatically). + + For details, take a look at linux/Documentation/cpufreq. + + If in doubt, say N. + +config CPU_FREQ_24_API + bool "/proc/sys/cpu/ interface (2.4. / OLD)" + depends on CPU_FREQ + help + This enables the /proc/sys/cpu/ sysctl interface for controlling + CPUFreq, as known from the 2.4.-kernel patches for CPUFreq. 2.5 + uses a sysfs interface instead. Please note that some drivers do + not work well with the 2.4. /proc/sys/cpu sysctl interface, + so if in doubt, say N here. + + For details, take a look at linux/Documentation/cpufreq. + + If in doubt, say N. + +config CPU_FREQ_PMAC + bool "Support for Apple PowerBooks" + depends on CPU_FREQ && ADB_PMU + help + This adds support for frequency switching on Apple PowerBooks, + this currently includes some models of iBook & Titanium + PowerBook. + endmenu menu "General setup" diff -Nru a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile --- a/arch/ppc/kernel/Makefile Wed Mar 19 21:01:42 2003 +++ b/arch/ppc/kernel/Makefile Wed Mar 26 21:44:07 2003 @@ -21,7 +21,7 @@ process.o signal.o ptrace.o align.o \ semaphore.o syscalls.o setup.o \ cputable.o ppc_htab.o -obj-$(CONFIG_6xx) += l2cr.o +obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_PCI) += pci-dma.o diff -Nru a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc/kernel/cpu_setup_6xx.S Wed Mar 26 21:29:35 2003 @@ -0,0 +1,415 @@ +/* + * This file contains low level CPU setup functions. + * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org) + * + * 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 + +_GLOBAL(__setup_cpu_601) + blr +_GLOBAL(__setup_cpu_603) + b setup_common_caches +_GLOBAL(__setup_cpu_604) + mflr r4 + bl setup_common_caches + bl setup_604_hid0 + mtlr r4 + blr +_GLOBAL(__setup_cpu_750) + mflr r4 + bl setup_common_caches + bl setup_750_7400_hid0 + mtlr r4 + blr +_GLOBAL(__setup_cpu_750cx) + mflr r4 + bl setup_common_caches + bl setup_750_7400_hid0 + bl setup_750cx + mtlr r4 + blr +_GLOBAL(__setup_cpu_750fx) + mflr r4 + bl setup_common_caches + bl setup_750_7400_hid0 + bl setup_750fx + mtlr r4 + blr +_GLOBAL(__setup_cpu_7400) + mflr r4 + bl setup_7400_workarounds + bl setup_common_caches + bl setup_750_7400_hid0 + mtlr r4 + blr +_GLOBAL(__setup_cpu_7410) + mflr r4 + bl setup_7410_workarounds + bl setup_common_caches + bl setup_750_7400_hid0 + li r3,0 + mtspr SPRN_L2CR2,r3 + mtlr r4 + blr +_GLOBAL(__setup_cpu_7450) + mflr r4 + bl setup_common_caches + bl setup_745x_specifics + mtlr r4 + blr +_GLOBAL(__setup_cpu_7455) + mflr r4 + bl setup_common_caches + bl setup_745x_specifics + mtlr r4 + blr + +/* Enable caches for 603's, 604, 750 & 7400 */ +setup_common_caches: + mfspr r11,HID0 + andi. r0,r11,HID0_DCE +#ifdef CONFIG_DCACHE_DISABLE + ori r11,r11,HID0_ICE +#else + ori r11,r11,HID0_ICE|HID0_DCE +#endif + ori r8,r11,HID0_ICFI + bne 1f /* don't invalidate the D-cache */ + ori r8,r8,HID0_DCI /* unless it wasn't enabled */ +1: sync + mtspr HID0,r8 /* enable and invalidate caches */ + sync + mtspr HID0,r11 /* enable caches */ + sync + isync + blr + +/* 604, 604e, 604ev, ... + * Enable superscalar execution & branch history table + */ +setup_604_hid0: + mfspr r11,HID0 + ori r11,r11,HID0_SIED|HID0_BHTE + ori r8,r11,HID0_BTCD + sync + mtspr HID0,r8 /* flush branch target address cache */ + sync /* on 604e/604r */ + mtspr HID0,r11 + sync + isync + blr + +/* 7400 <= rev 2.7 and 7410 rev = 1.0 suffer from some + * erratas we work around here. + * Moto MPC710CE.pdf describes them, those are errata + * #3, #4 and #5 + * Note that we assume the firmware didn't choose to + * apply other workarounds (there are other ones documented + * in the .pdf). It appear that Apple firmware only works + * around #3 and with the same fix we use. We may want to + * check if the CPU is using 60x bus mode in which case + * the workaround for errata #4 is useless. Also, we may + * want to explicitely clear HID0_NOPDST as this is not + * needed once we have applied workaround #5 (though it's + * not set by Apple's firmware at least). + */ +setup_7400_workarounds: + mfpvr r3 + rlwinm r3,r3,0,20,31 + cmpwi 0,r3,0x0207 + ble 1f + blr +setup_7410_workarounds: + mfpvr r3 + rlwinm r3,r3,0,20,31 + cmpwi 0,r3,0x0100 + bnelr +1: + mfspr r11,SPRN_MSSSR0 + /* Errata #3: Set L1OPQ_SIZE to 0x10 */ + rlwinm r11,r11,0,9,6 + oris r11,r11,0x0100 + /* Errata #4: Set L2MQ_SIZE to 1 (check for MPX mode first ?) */ + oris r11,r11,0x0002 + /* Errata #5: Set DRLT_SIZE to 0x01 */ + rlwinm r11,r11,0,5,2 + oris r11,r11,0x0800 + sync + mtspr SPRN_MSSSR0,r11 + sync + isync + blr + +/* 740/750/7400/7410 + * Enable Store Gathering (SGE), Address Brodcast (ABE), + * Branch History Table (BHTE), Branch Target ICache (BTIC) + * Dynamic Power Management (DPM), Speculative (SPD) + * Clear Instruction cache throttling (ICTC) + */ +setup_750_7400_hid0: + mfspr r11,HID0 + ori r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC +BEGIN_FTR_SECTION + oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */ +END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM) + li r3,HID0_SPD + andc r11,r11,r3 /* clear SPD: enable speculative */ + li r3,0 + mtspr ICTC,r3 /* Instruction Cache Throttling off */ + isync + mtspr HID0,r11 + sync + isync + blr + +/* 750cx specific + * Looks like we have to disable NAP feature for some PLL settings... + * (waiting for confirmation) + */ +setup_750cx: + mfspr r10, SPRN_HID1 + rlwinm r10,r10,4,28,31 + cmpi cr0,r10,7 + cmpi cr1,r10,9 + cmpi cr2,r10,11 + cror 4*cr0+eq,4*cr0+eq,4*cr1+eq + cror 4*cr0+eq,4*cr0+eq,4*cr2+eq + bnelr + lwz r6,CPU_SPEC_FEATURES(r5) + li r7,CPU_FTR_CAN_NAP + andc r6,r6,r7 + stw r6,CPU_SPEC_FEATURES(r5) + blr + +/* 750fx specific + */ +setup_750fx: + blr + +/* MPC 745x + * Enable Store Gathering (SGE), Branch Folding (FOLD) + * Branch History Table (BHTE), Branch Target ICache (BTIC) + * Dynamic Power Management (DPM), Speculative (SPD) + * Ensure our data cache instructions really operate. + * Timebase has to be running or we wouldn't have made it here, + * just ensure we don't disable it. + * Clear Instruction cache throttling (ICTC) + * Enable L2 HW prefetch + */ +setup_745x_specifics: + /* We check for the presence of an L3 cache setup by + * the firmware. If any, we disable NAP capability as + * it's known to be bogus on rev 2.1 and earlier + */ + mfspr r11,SPRN_L3CR + andis. r11,r11,L3CR_L3E@h + beq 1f + lwz r6,CPU_SPEC_FEATURES(r5) + andi. r0,r6,CPU_FTR_L3_DISABLE_NAP + beq 1f + li r7,CPU_FTR_CAN_NAP + andc r6,r6,r7 + stw r6,CPU_SPEC_FEATURES(r5) +1: + mfspr r11,HID0 + + /* All of the bits we have to set..... + */ + ori r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_BTIC | HID0_LRSTK +BEGIN_FTR_SECTION + oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */ +END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM) + + /* All of the bits we have to clear.... + */ + li r3,HID0_SPD | HID0_NOPDST | HID0_NOPTI + andc r11,r11,r3 /* clear SPD: enable speculative */ + li r3,0 + + mtspr ICTC,r3 /* Instruction Cache Throttling off */ + isync + mtspr HID0,r11 + sync + isync + + /* Enable L2 HW prefetch + */ + mfspr r3,SPRN_MSSCR0 + ori r3,r3,3 + sync + mtspr SPRN_MSSCR0,r3 + sync + isync + blr + +/* Definitions for the table use to save CPU states */ +#define CS_HID0 0 +#define CS_HID1 4 +#define CS_MSSCR0 8 +#define CS_MSSSR0 12 +#define CS_ICTRL 16 +#define CS_LDSTCR 20 +#define CS_LDSTDB 24 +#define CS_SIZE 28 + + .data + .balign 4 +cpu_state_storage: + .space CS_SIZE + .text + +/* Called in normal context to backup CPU 0 state. This + * does not include cache settings. This function is also + * called for machine sleep. This does not include the MMU + * setup, BATs, etc... but rather the "special" registers + * like HID0, HID1, MSSCR0, etc... + */ +_GLOBAL(__save_cpu_setup) + /* Get storage ptr */ + lis r5,cpu_state_storage@h + ori r5,r5,cpu_state_storage@l + + /* Save HID0 (common to all CONFIG_6xx cpus) */ + mfspr r3,SPRN_HID0 + stw r3,CS_HID0(r5) + + /* Now deal with CPU type dependent registers */ + mfspr r3,PVR + srwi r3,r3,16 + cmpli cr0,r3,0x8000 /* 7450 */ + cmpli cr1,r3,0x000c /* 7400 */ + cmpli cr2,r3,0x800c /* 7410 */ + cmpli cr3,r3,0x8001 /* 7455 */ + cmpli cr4,r3,0x8002 /* 7457 */ + cmpli cr5,r3,0x7000 /* 750FX */ + /* cr1 is 7400 || 7410 */ + cror 4*cr1+eq,4*cr1+eq,4*cr2+eq + /* cr0 is 74xx */ + cror 4*cr0+eq,4*cr0+eq,4*cr3+eq + cror 4*cr0+eq,4*cr0+eq,4*cr4+eq + cror 4*cr0+eq,4*cr0+eq,4*cr1+eq + bne 1f + /* Backup 74xx specific regs */ + mfspr r4,SPRN_MSSCR0 + stw r4,CS_MSSCR0(r5) + mfspr r4,SPRN_MSSSR0 + stw r4,CS_MSSSR0(r5) + beq cr1,1f + /* Backup 745x specific registers */ + mfspr r4,SPRN_HID1 + stw r4,CS_HID1(r5) + mfspr r4,SPRN_ICTRL + stw r4,CS_ICTRL(r5) + mfspr r4,SPRN_LDSTCR + stw r4,CS_LDSTCR(r5) + mfspr r4,SPRN_LDSTDB + stw r4,CS_LDSTDB(r5) +1: + bne cr5,1f + /* Backup 750FX specific registers */ + mfspr r4,SPRN_HID1 + stw r4,CS_HID1(r5) +1: + blr + +/* Called with no MMU context (typically MSR:IR/DR off) to + * restore CPU state as backed up by the previous + * function. This does not include cache setting + */ +_GLOBAL(__restore_cpu_setup) + /* Get storage ptr */ + lis r5,(cpu_state_storage-KERNELBASE)@h + ori r5,r5,cpu_state_storage@l + + /* Restore HID0 */ + lwz r3,CS_HID0(r5) + sync + isync + mtspr SPRN_HID0,r3 + sync + isync + + /* Now deal with CPU type dependent registers */ + mfspr r3,PVR + srwi r3,r3,16 + cmpli cr0,r3,0x8000 /* 7450 */ + cmpli cr1,r3,0x000c /* 7400 */ + cmpli cr2,r3,0x800c /* 7410 */ + cmpli cr3,r3,0x8001 /* 7455 */ + cmpli cr4,r3,0x8002 /* 7457 */ + cmpli cr5,r3,0x7000 /* 750FX */ + /* cr1 is 7400 || 7410 */ + cror 4*cr1+eq,4*cr1+eq,4*cr2+eq + /* cr0 is 74xx */ + cror 4*cr0+eq,4*cr0+eq,4*cr3+eq + cror 4*cr0+eq,4*cr0+eq,4*cr4+eq + cror 4*cr0+eq,4*cr0+eq,4*cr1+eq + bne 2f + /* Restore 74xx specific regs */ + lwz r4,CS_MSSCR0(r5) + sync + mtspr SPRN_MSSCR0,r4 + sync + isync + lwz r4,CS_MSSSR0(r5) + sync + mtspr SPRN_MSSSR0,r4 + sync + isync + bne cr2,1f + /* Clear 7410 L2CR2 */ + li r4,0 + mtspr SPRN_L2CR2,r4 +1: beq cr1,2f + /* Restore 745x specific registers */ + lwz r4,CS_HID1(r5) + sync + mtspr SPRN_HID1,r4 + isync + sync + lwz r4,CS_ICTRL(r5) + sync + mtspr SPRN_ICTRL,r4 + isync + sync + lwz r4,CS_LDSTCR(r5) + sync + mtspr SPRN_LDSTCR,r4 + isync + sync + lwz r4,CS_LDSTDB(r5) + sync + mtspr SPRN_LDSTDB,r4 + isync + sync +2: bne cr5,1f + /* Restore 750FX specific registers + * that is restore PLL config & switch + * to PLL 0 + */ + lwz r4,CS_HID1(r5) + rlwinm r5,r4,0,16,14 + mtspr SPRN_HID1,r5 + /* Wait for PLL to stabilize */ + mftbl r5 +3: mftbl r6 + sub r6,r6,r5 + cmpli cr0,r6,10000 + ble 3b + /* Setup final PLL */ + mtspr SPRN_HID1,r4 +1: + blr + diff -Nru a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S --- a/arch/ppc/kernel/head.S Sat Feb 15 04:10:22 2003 +++ b/arch/ppc/kernel/head.S Wed Mar 26 21:44:08 2003 @@ -890,7 +890,7 @@ */ mfmsr r5 oris r5,r5,MSR_VEC@h - mtmsr r5 /* enable use of AltiVec now */ + MTMSRD(r5) /* enable use of AltiVec now */ isync /* * For SMP, we don't do lazy AltiVec switching because it just gets too @@ -962,7 +962,7 @@ mfmsr r5 oris r5,r5,MSR_VEC@h SYNC - mtmsr r5 /* enable use of AltiVec now */ + MTMSRD(r5) /* enable use of AltiVec now */ isync cmpi 0,r3,0 beqlr- /* if no previous owner, done */ @@ -999,7 +999,7 @@ ori r5,r5,MSR_FP SYNC_601 ISYNC_601 - mtmsr r5 /* enable use of fpu now */ + MTMSRD(r5) /* enable use of fpu now */ SYNC_601 isync cmpi 0,r3,0 @@ -1191,6 +1191,8 @@ MTMSRD(r0) isync #endif + /* Copy some CPU settings from CPU 0 */ + bl __restore_cpu_setup lis r3,-KERNELBASE@h mr r4,r24 @@ -1236,248 +1238,21 @@ #endif /* CONFIG_SMP */ /* - * Enable caches and 604-specific features if necessary. + * Those generic dummy functions are kept for CPUs not + * included in CONFIG_6xx */ -_GLOBAL(__setup_cpu_601) - blr -_GLOBAL(__setup_cpu_603) - b setup_common_caches -_GLOBAL(__setup_cpu_604) - mflr r4 - bl setup_common_caches - bl setup_604_hid0 - mtlr r4 - blr -_GLOBAL(__setup_cpu_750) - mflr r4 - bl setup_common_caches - bl setup_750_7400_hid0 - mtlr r4 - blr -_GLOBAL(__setup_cpu_750cx) - mflr r4 - bl setup_common_caches - bl setup_750_7400_hid0 - bl setup_750cx - mtlr r4 - blr -_GLOBAL(__setup_cpu_750fx) - mflr r4 - bl setup_common_caches - bl setup_750_7400_hid0 - bl setup_750fx - mtlr r4 - blr -_GLOBAL(__setup_cpu_7400) - mflr r4 - bl setup_7400_workarounds - bl setup_common_caches - bl setup_750_7400_hid0 - mtlr r4 - blr -_GLOBAL(__setup_cpu_7410) - mflr r4 - bl setup_7410_workarounds - bl setup_common_caches - bl setup_750_7400_hid0 - li r3,0 - mtspr SPRN_L2CR2,r3 - mtlr r4 - blr -_GLOBAL(__setup_cpu_7450) - mflr r4 - bl setup_common_caches - bl setup_745x_specifics - mtlr r4 - blr -_GLOBAL(__setup_cpu_7455) - mflr r4 - bl setup_common_caches - bl setup_745x_specifics - mtlr r4 - blr _GLOBAL(__setup_cpu_power3) blr _GLOBAL(__setup_cpu_generic) blr -/* Enable caches for 603's, 604, 750 & 7400 */ -setup_common_caches: - mfspr r11,HID0 - andi. r0,r11,HID0_DCE -#ifdef CONFIG_DCACHE_DISABLE - ori r11,r11,HID0_ICE -#else - ori r11,r11,HID0_ICE|HID0_DCE -#endif - ori r8,r11,HID0_ICFI - bne 1f /* don't invalidate the D-cache */ - ori r8,r8,HID0_DCI /* unless it wasn't enabled */ -1: sync - mtspr HID0,r8 /* enable and invalidate caches */ - sync - mtspr HID0,r11 /* enable caches */ - sync - isync - blr - -/* 604, 604e, 604ev, ... - * Enable superscalar execution & branch history table - */ -setup_604_hid0: - mfspr r11,HID0 - ori r11,r11,HID0_SIED|HID0_BHTE - ori r8,r11,HID0_BTCD - sync - mtspr HID0,r8 /* flush branch target address cache */ - sync /* on 604e/604r */ - mtspr HID0,r11 - sync - isync - blr - -/* 7400 <= rev 2.7 and 7410 rev = 1.0 suffer from some - * errata we work around here. - * Moto MPC710CE.pdf describes them, those are errata - * #3, #4 and #5 - * Note that we assume the firmware didn't choose to - * apply other workarounds (there are other ones documented - * in the .pdf). It appear that Apple firmware only works - * around #3 and with the same fix we use. We may want to - * check if the CPU is using 60x bus mode in which case - * the workaround for errata #4 is useless. Also, we may - * want to explicitely clear HID0_NOPDST as this is not - * needed once we have applied workaround #5 (though it's - * not set by Apple's firmware at least). - */ -setup_7400_workarounds: - mfpvr r3 - rlwinm r3,r3,0,20,31 - cmpwi 0,r3,0x0207 - ble 1f - blr -setup_7410_workarounds: - mfpvr r3 - rlwinm r3,r3,0,20,31 - cmpwi 0,r3,0x0100 - bnelr -1: - mfspr r11,SPRN_MSSSR0 - /* Errata #3: Set L1OPQ_SIZE to 0x10 */ - rlwinm r11,r11,0,9,6 - oris r11,r11,0x0100 - /* Errata #4: Set L2MQ_SIZE to 1 (check for MPX mode first ?) */ - oris r11,r11,0x0002 - /* Errata #5: Set DRLT_SIZE to 0x01 */ - rlwinm r11,r11,0,5,2 - oris r11,r11,0x0800 - sync - mtspr SPRN_MSSSR0,r11 - sync - isync - blr - -/* 740/750/7400/7410 - * Enable Store Gathering (SGE), Address Brodcast (ABE), - * Branch History Table (BHTE), Branch Target ICache (BTIC) - * Dynamic Power Management (DPM), Speculative (SPD) - * Clear Instruction cache throttling (ICTC) - */ -setup_750_7400_hid0: - mfspr r11,HID0 - ori r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC -BEGIN_FTR_SECTION - oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */ -END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM) - li r3,HID0_SPD - andc r11,r11,r3 /* clear SPD: enable speculative */ - li r3,0 - mtspr ICTC,r3 /* Instruction Cache Throttling off */ - isync - mtspr HID0,r11 - sync - isync - blr - -/* 750cx specific - * Looks like we have to disable NAP feature for some PLL settings... - * (waiting for confirmation) - */ -setup_750cx: - mfspr r10, SPRN_HID1 - rlwinm r10,r10,4,28,31 - cmpi cr0,r10,7 - cmpi cr1,r10,9 - cmpi cr2,r10,11 - cror 4*cr0+eq,4*cr0+eq,4*cr1+eq - cror 4*cr0+eq,4*cr0+eq,4*cr2+eq - bnelr - lwz r6,CPU_SPEC_FEATURES(r5) - li r7,CPU_FTR_CAN_NAP - andc r6,r6,r7 - stw r6,CPU_SPEC_FEATURES(r5) +#ifndef CONFIG_6xx +_GLOBAL(__save_cpu_setup) blr - -/* 750fx specific - */ -setup_750fx: +_GLOBAL(__restore_cpu_setup) blr +#endif /* CONFIG_6xx */ -/* MPC 745x - * Enable Store Gathering (SGE), Branch Folding (FOLD) - * Branch History Table (BHTE), Branch Target ICache (BTIC) - * Dynamic Power Management (DPM), Speculative (SPD) - * Ensure our data cache instructions really operate. - * Timebase has to be running or we wouldn't have made it here, - * just ensure we don't disable it. - * Clear Instruction cache throttling (ICTC) - * Enable L2 HW prefetch - */ -setup_745x_specifics: - /* We check for the presence of an L3 cache setup by - * the firmware. If any, we disable NAP capability as - * it's known to be bogus on rev 2.1 and earlier - */ - mfspr r11,SPRN_L3CR - andis. r11,r11,L3CR_L3E@h - beq 1f - lwz r6,CPU_SPEC_FEATURES(r5) - andi. r0,r6,CPU_FTR_L3_DISABLE_NAP - beq 1f - li r7,CPU_FTR_CAN_NAP - andc r6,r6,r7 - stw r6,CPU_SPEC_FEATURES(r5) -1: - mfspr r11,HID0 - - /* All of the bits we have to set..... - */ - ori r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_BTIC | HID0_LRSTK -BEGIN_FTR_SECTION - oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */ -END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM) - - /* All of the bits we have to clear.... - */ - li r3,HID0_SPD | HID0_NOPDST | HID0_NOPTI - andc r11,r11,r3 /* clear SPD: enable speculative */ - li r3,0 - - mtspr ICTC,r3 /* Instruction Cache Throttling off */ - isync - mtspr HID0,r11 - sync - isync - - /* Enable L2 HW prefetch - */ - mfspr r3,SPRN_MSSCR0 - ori r3,r3,3 - sync - mtspr SPRN_MSSCR0,r3 - sync - isync - blr /* * Load stuff into the MMU. Intended to be called with diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S --- a/arch/ppc/kernel/misc.S Wed Feb 19 03:47:25 2003 +++ b/arch/ppc/kernel/misc.S Wed Mar 26 22:08:18 2003 @@ -201,6 +201,60 @@ mr r4,r24 bctr +#ifdef CONFIG_CPU_FREQ_PMAC + +/* This gets called by via-pmu.c to switch the PLL selection + * on 750fx CPU. This function should really be moved to some + * other place (as most of the cpufreq code in via-pmu + */ +_GLOBAL(low_choose_750fx_pll) + /* Clear MSR:EE */ + mfmsr r7 + rlwinm r0,r7,0,17,15 + mtmsr r0 + + /* If switching to PLL1, disable HID0:BTIC */ + cmpli cr0,r3,0 + beq 1f + mfspr r5,HID0 + rlwinm r5,r5,0,27,25 + sync + mtspr HID0,r5 + isync + sync + +1: + /* Calc new HID1 value */ + mfspr r4,SPRN_HID1 /* Build a HID1:PS bit from parameter */ + rlwinm r5,r3,16,15,15 /* Clear out HID1:PS from value read */ + rlwinm r4,r4,0,16,14 /* Could have I used rlwimi here ? */ + or r4,r4,r5 + mtspr SPRN_HID1,r4 + + /* Store new HID1 image */ + rlwinm r6,r1,0,0,18 + lwz r6,TI_CPU(r6) + slwi r6,r6,2 + addis r6,r6,nap_save_hid1@ha + stw r4,nap_save_hid1@l(r6) + + /* If switching to PLL0, enable HID0:BTIC */ + cmpli cr0,r3,0 + bne 1f + mfspr r5,HID0 + ori r5,r5,HID0_BTIC + sync + mtspr HID0,r5 + isync + sync + +1: + /* Return */ + mtmsr r7 + blr + +#endif /* CONFIG_CPU_FREQ_PMAC */ + /* void local_save_flags_ptr(unsigned long *flags) */ _GLOBAL(local_save_flags_ptr) mfmsr r4 @@ -351,7 +405,16 @@ sync /* Flush to memory before changing mapping */ tlbia isync /* Flush shadow TLB */ -#else /* ! defined(CONFIG_40x) */ +#elif defined(CONFIG_440) + lis r3,0 + sync +1: + tlbwe r3,r3,PPC440_TLB_PAGEID + addi r3,r3,1 + cmpwi 0,r3,61 + ble 1b + isync +#else /* !(CONFIG_40x || CONFIG_440) */ #if defined(CONFIG_SMP) rlwinm r8,r1,0,0,18 lwz r8,TI_CPU(r8) @@ -392,7 +455,7 @@ * Flush MMU TLB for a particular address */ _GLOBAL(_tlbie) -#ifdef CONFIG_40x +#if defined(CONFIG_40x) tlbsx. r3, 0, r3 bne 10f sync @@ -402,7 +465,31 @@ tlbwe r3, r3, TLB_TAG isync 10: -#else /* ! CONFIG_40x */ +#elif defined(CONFIG_440) + mfspr r4,SPRN_MMUCR /* Get MMUCR */ + lis r5,PPC440_MMUCR_STS@h + ori r5,r5,PPC440_MMUCR_TID@l /* Create mask */ + andc r4,r4,r5 /* Clear out TID/STS bits */ + mfspr r5,SPRN_PID /* Get PID */ + or r4,r4,r5 /* Set TID bits */ + mfmsr r6 /* Get MSR */ + andi. r6,r6,MSR_IS@l /* TS=1? */ + beq 11f /* If not, leave STS=0 */ + oris r4,r4,PPC440_MMUCR_STS@h /* Set STS=1 */ +11: mtspr SPRN_MMUCR, r4 /* Put MMUCR */ + + tlbsx. r3, 0, r3 + bne 10f + sync + /* There are only 64 TLB entries, so r3 < 64, + * which means bit 22, is clear. Since 22 is + * the V bit in the TLB_PAGEID, loading this + * value will invalidate the TLB entry. + */ + tlbwe r3, r3, PPC440_TLB_PAGEID + isync +10: +#else /* !(CONFIG_40x || CONFIG_440) */ #if defined(CONFIG_SMP) rlwinm r8,r1,0,0,18 lwz r8,TI_CPU(r8) @@ -569,22 +656,18 @@ blr #ifdef CONFIG_NOT_COHERENT_CACHE -/* This is a bad one....It is used by 'consistent_sync' functions when - * there isn't any handle on the virtual address needed by the usual - * cache flush instructions. On the MPC8xx, we can use the cache line - * flush command, on others all we can do is read enough data to completely - * reload the cache, flushing old data out. - */ - -/* Cache organization. The 4xx has a 8K (128 line) cache, and the 8xx - * has 1, 2, 4, 8K variants. For now, cover worst case. When we can - * deteremine actual size, we will use that later. +/* + * 40x cores have 8K or 16K dcache and 32 byte line size. + * 440 has a 32K dcache and 32 byte line size. + * 8xx has 1, 2, 4, 8K variants. + * For now, cover the worst case of the 440. + * Must be called with external interrupts disabled. */ -#define CACHE_NWAYS 2 -#define CACHE_NLINES 128 +#define CACHE_NWAYS 64 +#define CACHE_NLINES 16 _GLOBAL(flush_dcache_all) - li r4, (CACHE_NWAYS * CACHE_NLINES) + li r4, (2 * CACHE_NWAYS * CACHE_NLINES) mtctr r4 lis r5, KERNELBASE@h 1: lwz r3, 0(r5) /* Load one word from every line */ diff -Nru a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c --- a/arch/ppc/kernel/smp.c Wed Jan 15 20:14:49 2003 +++ b/arch/ppc/kernel/smp.c Wed Mar 26 21:44:08 2003 @@ -68,6 +68,9 @@ static int __smp_call_function(void (*func) (void *info), void *info, int wait, int target); +/* Low level assembly function used to backup CPU 0 state */ +extern void __save_cpu_setup(void); + /* Since OpenPIC has only 4 IPIs, we use slightly different message numbers. * * Make sure this matches openpic_request_IPIs in open_pic.c, or what shows up @@ -348,6 +351,9 @@ /* Probe platform for CPUs: always linear. */ num_cpus = smp_ops->probe(); cpu_possible_map = (1 << num_cpus)-1; + + /* Backup CPU 0 state */ + __save_cpu_setup(); if (smp_ops->space_timers) smp_ops->space_timers(num_cpus); diff -Nru a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile --- a/arch/ppc/platforms/Makefile Sat Mar 22 17:18:48 2003 +++ b/arch/ppc/platforms/Makefile Wed Mar 26 22:00:59 2003 @@ -19,12 +19,14 @@ obj-$(CONFIG_ALL_PPC) += pmac_pic.o pmac_setup.o pmac_time.o \ pmac_feature.o pmac_pci.o chrp_setup.o\ chrp_time.o chrp_pci.o prep_pci.o \ - prep_time.o prep_setup.o + prep_time.o prep_setup.o pmac_sleep.o ifeq ($(CONFIG_ALL_PPC),y) obj-$(CONFIG_NVRAM) += pmac_nvram.o endif obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o -obj-$(CONFIG_PMAC_PBOOK) += sleep.o +ifeq ($(CONFIG_ALL_PPC),y) +obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o +endif obj-$(CONFIG_PPC_RTAS) += error_log.o proc_rtas.o obj-$(CONFIG_PREP_RESIDUAL) += residual.o obj-$(CONFIG_ADIR) += adir_setup.o adir_pic.o adir_pci.o diff -Nru a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc/platforms/pmac_cpufreq.c Thu Mar 27 01:38:08 2003 @@ -0,0 +1,345 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG_FREQ + +extern void low_choose_750fx_pll(int pll); +extern void low_sleep_handler(void); +extern void openpic_sleep_save_intrs(void); +extern void openpic_sleep_restore_intrs(void); +extern void enable_kernel_altivec(void); +extern void enable_kernel_fp(void); + +static unsigned int low_freq; +static unsigned int hi_freq; +static unsigned int cur_freq; +static int cpufreq_uses_pmu; + +#define PMAC_CPU_LOW_SPEED 1 +#define PMAC_CPU_HIGH_SPEED 0 + +static inline void +wakeup_decrementer(void) +{ + set_dec(tb_ticks_per_jiffy); + /* No currently-supported powerbook has a 601, + * so use get_tbl, not native + */ + last_jiffy_stamp(0) = tb_last_stamp = get_tbl(); +} + +#ifdef DEBUG_FREQ +static inline void +debug_calc_bogomips(void) +{ + /* This will cause a recalc of bogomips and display the + * result. We backup/restore the value to avoid affecting the + * core cpufreq framework's own calculation. + */ + extern void calibrate_delay(void); + + unsigned long save_lpj = loops_per_jiffy; + calibrate_delay(); + loops_per_jiffy = save_lpj; +} +#endif + +/* Switch CPU speed under 750FX CPU control + */ +static int __pmac +cpu_750fx_cpu_speed(int low_speed) +{ +#ifdef DEBUG_FREQ + printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); +#endif + low_choose_750fx_pll(low_speed); +#ifdef DEBUG_FREQ + printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); + debug_calc_bogomips(); +#endif + + return 0; +} + +/* Switch CPU speed under PMU control + */ +static int __pmac +pmu_set_cpu_speed(unsigned int low_speed) +{ + struct adb_request req; + unsigned long save_l2cr; + unsigned long save_l3cr; + +#ifdef DEBUG_FREQ + printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); +#endif + /* Disable all interrupt sources on openpic */ + openpic_sleep_save_intrs(); + + /* Make sure the PMU is idle */ + pmu_suspend(); + + /* Make sure the decrementer won't interrupt us */ + asm volatile("mtdec %0" : : "r" (0x7fffffff)); + /* Make sure any pending DEC interrupt occuring while we did + * the above didn't re-enable the DEC */ + mb(); + asm volatile("mtdec %0" : : "r" (0x7fffffff)); + + /* We can now disable MSR_EE */ + local_irq_disable(); + + /* Giveup the FPU & vec */ + enable_kernel_fp(); + +#ifdef CONFIG_ALTIVEC + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC) + enable_kernel_altivec(); +#endif /* CONFIG_ALTIVEC */ + + /* Save & disable L2 and L3 caches */ + save_l3cr = _get_L3CR(); /* (returns -1 if not available) */ + save_l2cr = _get_L2CR(); /* (returns -1 if not available) */ + if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0) + _set_L3CR(save_l3cr & 0x7fffffff); + if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0) + _set_L2CR(save_l2cr & 0x7fffffff); + + /* Send the new speed command. My assumption is that this command + * will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep + */ + pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed); + while (!req.complete) + pmu_poll(); + + pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1); + + low_sleep_handler(); + + pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0); + + /* Restore L2 cache */ + if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0) + _set_L2CR(save_l2cr); + /* Restore L3 cache */ + if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0) + _set_L3CR(save_l3cr); + + /* Restore userland MMU context */ + set_context(current->active_mm->context, current->active_mm->pgd); + +#ifdef DEBUG_FREQ + printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); +#endif + + /* Restore decrementer */ + wakeup_decrementer(); + + /* Restore interrupts */ + openpic_sleep_restore_intrs(); + + pmu_resume(); + + /* Let interrupts flow again ... */ + local_irq_enable(); + +#ifdef DEBUG_FREQ + debug_calc_bogomips(); +#endif + + return 0; +} + +static int __pmac +do_set_cpu_speed(int speed_mode) +{ + struct cpufreq_freqs freqs; + int rc; + + freqs.old = cur_freq; + freqs.new = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq; + freqs.cpu = CPUFREQ_ALL_CPUS; + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + if (cpufreq_uses_pmu) + rc = pmu_set_cpu_speed(speed_mode); + else + rc = cpu_750fx_cpu_speed(speed_mode); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + cur_freq = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq; + + return rc; +} + +static int __pmac +pmac_cpufreq_verify(struct cpufreq_policy *policy) +{ + if (!policy) + return -EINVAL; + + policy->cpu = 0; /* UP only */ + + cpufreq_verify_within_limits(policy, low_freq, hi_freq); + + if ((policy->min > low_freq) && + (policy->max < hi_freq)) + policy->max = hi_freq; + + return 0; +} + +static int __pmac +pmac_cpufreq_setpolicy(struct cpufreq_policy *policy) +{ + int rc; + + if (!policy) + return -EINVAL; + if (policy->min > low_freq) + rc = do_set_cpu_speed(PMAC_CPU_HIGH_SPEED); + else if (policy->max < hi_freq) + rc = do_set_cpu_speed(PMAC_CPU_LOW_SPEED); + else if (policy->policy == CPUFREQ_POLICY_POWERSAVE) + rc = do_set_cpu_speed(PMAC_CPU_LOW_SPEED); + else + rc = do_set_cpu_speed(PMAC_CPU_HIGH_SPEED); + + return rc; +} + +unsigned int __pmac +pmac_get_one_cpufreq(int i) +{ + /* Supports only one CPU for now */ + return (i == 0) ? cur_freq : 0; +} + + +/* Currently, we support the following machines: + * + * - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz) + * - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz) + * - iBook2 500 (PMU based, 400Mhz & 500Mhz) + * - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage) + */ +static int __init +pmac_cpufreq_setup(void) +{ + struct device_node *cpunode; + struct cpufreq_driver *driver; + u32 *value; + int has_freq_ctl = 0; + int rc; + + memset(&driver, 0, sizeof(driver)); + + /* Assume only one CPU */ + cpunode = find_type_devices("cpu"); + if (!cpunode) + goto out; + + /* Get current cpu clock freq */ + value = (u32 *)get_property(cpunode, "clock-frequency", NULL); + if (!value) + goto out; + cur_freq = (*value) / 1000; + + /* Check for tibook 800Mhz or 1Ghz */ + if (machine_is_compatible("PowerBook3,4") || machine_is_compatible("PowerBook3,5")) { + value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL); + if (!value) + goto out; + low_freq = (*value) / 1000; + + value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL); + if (!value) + goto out; + hi_freq = (*value) / 1000; + has_freq_ctl = 1; + cpufreq_uses_pmu = 1; + } + /* Else check for iBook2 500 */ + else if (machine_is_compatible("PowerBook4,1")) { + /* We only know about 500Mhz model */ + if (cur_freq < 450000 || cur_freq > 550000) + goto out; + hi_freq = cur_freq; + low_freq = 400000; + has_freq_ctl = 1; + cpufreq_uses_pmu = 1; + } + /* Else check for TiPb 500 */ + else if (machine_is_compatible("PowerBook3,2")) { + /* We only know about 500Mhz model */ + if (cur_freq < 450000 || cur_freq > 550000) + goto out; + hi_freq = cur_freq; + low_freq = 300000; + has_freq_ctl = 1; + cpufreq_uses_pmu = 1; + } + /* Else check for 750FX */ + else if (PVR_VER(mfspr(PVR)) == 0x7000) { + if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) + goto out; + hi_freq = cur_freq; + value = (u32 *)get_property(cpunode, "reduced-clock-frequency", NULL); + if (!value) + goto out; + low_freq = (*value) / 1000; + cpufreq_uses_pmu = 0; + has_freq_ctl = 1; + } +out: + if (!has_freq_ctl) + return -ENODEV; + + /* initialization of main "cpufreq" code*/ + driver = kmalloc(sizeof(struct cpufreq_driver) + + NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL); + if (!driver) + return -ENOMEM; + + driver->policy = (struct cpufreq_policy *) (driver + 1); + + driver->verify = &pmac_cpufreq_verify; + driver->setpolicy = &pmac_cpufreq_setpolicy; + driver->init = NULL; + driver->exit = NULL; + strncpy(driver->name, "powermac", CPUFREQ_NAME_LEN); + + driver->policy[0].cpu = 0; + driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL; + driver->policy[0].cpuinfo.min_freq = low_freq; + driver->policy[0].min = low_freq; + driver->policy[0].max = cur_freq; + driver->policy[0].cpuinfo.max_freq = cur_freq; + driver->policy[0].policy = (cur_freq == low_freq) ? + CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE; + + rc = cpufreq_register_driver(driver); + if (rc) + kfree(driver); + return rc; +} + +__initcall(pmac_cpufreq_setup); + diff -Nru a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c --- a/arch/ppc/platforms/pmac_feature.c Tue Feb 25 10:47:17 2003 +++ b/arch/ppc/platforms/pmac_feature.c Wed Mar 26 22:21:30 2003 @@ -14,6 +14,8 @@ * - Replace mdelay with some schedule loop if possible * - Shorten some obfuscated delays on some routines (like modem * power) + * - Refcount some clocks (see darwin) + * - Split split split... * */ #include @@ -25,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -34,8 +38,10 @@ #include #include #include +#include #include #include +#include #undef DEBUG_FEATURE @@ -46,7 +52,8 @@ #endif /* Exported from arch/ppc/kernel/idle.c */ -extern unsigned long powersave_nap; +extern int powersave_nap; +extern int powersave_lowspeed; /* * We use a single global lock to protect accesses. Each driver has @@ -57,53 +64,13 @@ #define LOCK(flags) spin_lock_irqsave(&feature_lock, flags); #define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags); + /* - * Helper functions regarding the various flavors of mac-io + * Instance of some macio stuffs */ - -#define MAX_MACIO_CHIPS 2 +struct macio_chip macio_chips[MAX_MACIO_CHIPS] __pmacdata; -enum { - macio_unknown = 0, - macio_grand_central, - macio_ohare, - macio_ohareII, - macio_heathrow, - macio_gatwick, - macio_paddington, - macio_keylargo, - macio_pangea -}; - -static const char* macio_names[] __pmacdata = -{ - "Unknown", - "Grand Central", - "OHare", - "OHareII", - "Heathrow", - "Gatwick", - "Paddington", - "Keylargo", - "Pangea" -}; - -static struct macio_chip -{ - struct device_node* of_node; - int type; - int rev; - volatile u32* base; - unsigned long flags; -} macio_chips[MAX_MACIO_CHIPS] __pmacdata; - -#define MACIO_FLAG_SCCA_ON 0x00000001 -#define MACIO_FLAG_SCCB_ON 0x00000002 -#define MACIO_FLAG_SCC_LOCKED 0x00000004 -#define MACIO_FLAG_AIRPORT_ON 0x00000010 -#define MACIO_FLAG_FW_SUPPORTED 0x00000020 - -static struct macio_chip* __pmac +struct macio_chip* __pmac macio_find(struct device_node* child, int type) { while(child) { @@ -118,15 +85,21 @@ return NULL; } -#define MACIO_FCR32(macio, r) ((macio)->base + ((r) >> 2)) -#define MACIO_FCR8(macio, r) (((volatile u8*)((macio)->base)) + (r)) +static const char* macio_names[] __pmacdata = +{ + "Unknown", + "Grand Central", + "OHare", + "OHareII", + "Heathrow", + "Gatwick", + "Paddington", + "Keylargo", + "Pangea", + "Intrepid" +}; + -#define MACIO_IN32(r) (in_le32(MACIO_FCR32(macio,r))) -#define MACIO_OUT32(r,v) (out_le32(MACIO_FCR32(macio,r), (v))) -#define MACIO_BIS(r,v) (MACIO_OUT32((r), MACIO_IN32(r) | (v))) -#define MACIO_BIC(r,v) (MACIO_OUT32((r), MACIO_IN32(r) & ~(v))) -#define MACIO_IN8(r) (in_8(MACIO_FCR8(macio,r))) -#define MACIO_OUT8(r,v) (out_8(MACIO_FCR8(macio,r), (v))) /* * Uninorth reg. access. Note that Uni-N regs are big endian @@ -196,7 +169,7 @@ unsigned long chan_mask; unsigned long fcr; unsigned long flags; - int htw; + int htw, trans; unsigned long rmask; macio = macio_find(node, 0); @@ -211,6 +184,9 @@ htw = (macio->type == macio_heathrow || macio->type == macio_paddington || macio->type == macio_gatwick); + /* On these machines, the HRW_SCC_TRANS_EN_N bit mustn't be touched */ + trans = (pmac_mb.model_id != PMAC_TYPE_YOSEMITE && + pmac_mb.model_id != PMAC_TYPE_YIKES); if (value) { #ifdef CONFIG_ADB_PMU if ((param & 0xfff) == PMAC_SCC_IRDA) @@ -222,7 +198,13 @@ if (!(fcr & OH_SCC_ENABLE)) { fcr |= OH_SCC_ENABLE; if (htw) { - fcr &= ~HRW_SCC_TRANS_EN_N; + /* Side effect: this will also power up the + * modem, but it's too messy to figure out on which + * ports this controls the tranceiver and on which + * it controls the modem + */ + if (trans) + fcr &= ~HRW_SCC_TRANS_EN_N; MACIO_OUT32(OHARE_FCR, fcr); fcr |= (rmask = HRW_RESET_SCC); MACIO_OUT32(OHARE_FCR, fcr); @@ -258,7 +240,7 @@ MACIO_OUT32(OHARE_FCR, fcr); if ((fcr & (OH_SCCA_IO | OH_SCCB_IO)) == 0) { fcr &= ~OH_SCC_ENABLE; - if (htw) + if (htw && trans) fcr |= HRW_SCC_TRANS_EN_N; MACIO_OUT32(OHARE_FCR, fcr); } @@ -330,9 +312,9 @@ if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) return -EPERM; - if (value) { + if (value == 1) { MACIO_BIC(OHARE_FCR, OH_IOBUS_ENABLE); - } else { + } else if (value == 0) { MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); } @@ -522,7 +504,7 @@ return 0; } -static u32 save_fcr[5] __pmacdata; +static u32 save_fcr[6] __pmacdata; static u32 save_mbcr __pmacdata; static u32 save_gpio_levels[2] __pmacdata; static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT] __pmacdata; @@ -586,6 +568,7 @@ /* This seems to be necessary as well or the fan * keeps coming up and battery drains fast */ MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE); + MACIO_BIC(HEATHROW_FCR, HRW_IDE0_RESET_N); /* Make sure eth is down even if module or sleep * won't work properly */ MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET); @@ -750,7 +733,13 @@ struct macio_chip* macio; u8 gpio; unsigned long flags; - + + /* Hack for internal USB modem */ + if (node == NULL) { + if (macio_chips[0].type != macio_keylargo) + return -ENODEV; + node = macio_chips[0].of_node; + } macio = macio_find(node, 0); if (!macio) return -ENODEV; @@ -791,8 +780,96 @@ } static int __pmac +pangea_modem_enable(struct device_node* node, int param, int value) +{ + struct macio_chip* macio; + u8 gpio; + unsigned long flags; + + /* Hack for internal USB modem */ + if (node == NULL) { + if (macio_chips[0].type != macio_pangea && + macio_chips[0].type != macio_intrepid) + return -ENODEV; + node = macio_chips[0].of_node; + } + macio = macio_find(node, 0); + if (!macio) + return -ENODEV; + gpio = MACIO_IN8(KL_GPIO_MODEM_RESET); + gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE; + gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA; + + if (!value) { + LOCK(flags); + MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); + UNLOCK(flags); + (void)MACIO_IN8(KL_GPIO_MODEM_RESET); + mdelay(250); + } + LOCK(flags); + if (value) { + MACIO_OUT8(KL_GPIO_MODEM_POWER, + KEYLARGO_GPIO_OUTPUT_ENABLE); + UNLOCK(flags); + (void)MACIO_IN32(KEYLARGO_FCR2); + mdelay(250); + } else { + MACIO_OUT8(KL_GPIO_MODEM_POWER, + KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); + UNLOCK(flags); + } + if (value) { + LOCK(flags); + MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); + (void)MACIO_IN8(KL_GPIO_MODEM_RESET); + UNLOCK(flags); mdelay(250); LOCK(flags); + MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); + (void)MACIO_IN8(KL_GPIO_MODEM_RESET); + UNLOCK(flags); mdelay(250); LOCK(flags); + MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); + (void)MACIO_IN8(KL_GPIO_MODEM_RESET); + UNLOCK(flags); mdelay(250); + } + return 0; +} + +static int __pmac +core99_ata100_enable(struct device_node* node, int value) +{ + unsigned long flags; + struct pci_dev *pdev = NULL; + u8 pbus, pid; + + if (uninorth_rev < 0x24) + return -ENODEV; + + LOCK(flags); + if (value) + UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100); + else + UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100); + (void)UN_IN(UNI_N_CLOCK_CNTL); + UNLOCK(flags); + udelay(20); + + if (value) { + if (pci_device_from_OF_node(node, &pbus, &pid) == 0) + pdev = pci_find_slot(pbus, pid); + if (pdev == NULL) + return 0; + pci_enable_device(pdev); + pci_set_master(pdev); + } + return 0; +} + +static int __pmac core99_ide_enable(struct device_node* node, int param, int value) { + /* Bus ID 0 to 2 are KeyLargo based IDE, busID 3 is U2 + * based ata-100 + */ switch(param) { case 0: return simple_feature_tweak(node, macio_unknown, @@ -803,6 +880,8 @@ case 2: return simple_feature_tweak(node, macio_unknown, KEYLARGO_FCR1, KL1_UIDE_ENABLE, value); + case 3: + return core99_ata100_enable(node, value); default: return -ENODEV; } @@ -850,7 +929,8 @@ struct macio_chip* macio; macio = &macio_chips[0]; - if (macio->type != macio_keylargo && macio->type != macio_pangea) + if (macio->type != macio_keylargo && macio->type != macio_pangea && + macio->type != macio_intrepid) return -ENODEV; LOCK(flags); @@ -987,27 +1067,40 @@ static int __pmac core99_reset_cpu(struct device_node* node, int param, int value) { - const int reset_lines[] = { KL_GPIO_RESET_CPU0, - KL_GPIO_RESET_CPU1, - KL_GPIO_RESET_CPU2, - KL_GPIO_RESET_CPU3 }; - int reset_io; + unsigned int reset_io = 0; unsigned long flags; struct macio_chip* macio; + struct device_node* np; + const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0, + KL_GPIO_RESET_CPU1, + KL_GPIO_RESET_CPU2, + KL_GPIO_RESET_CPU3 }; macio = &macio_chips[0]; - if (macio->type != macio_keylargo && macio->type != macio_pangea) + if (macio->type != macio_keylargo) return -ENODEV; - if (param > 3 || param < 0) + + np = find_path_device("/cpus"); + if (np == NULL) return -ENODEV; - - reset_io = reset_lines[param]; + for (np = np->child; np != NULL; np = np->sibling) { + u32* num = (u32 *)get_property(np, "reg", NULL); + u32* rst = (u32 *)get_property(np, "soft-reset", NULL); + if (num == NULL || rst == NULL) + continue; + if (param == *num) { + reset_io = *rst; + break; + } + } + if (np == NULL || reset_io == 0) + reset_io = dflt_reset_lines[param]; LOCK(flags); MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); (void)MACIO_IN8(reset_io); udelay(1); - MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); + MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTOUT_DATA | KEYLARGO_GPIO_OUTPUT_ENABLE); (void)MACIO_IN8(reset_io); UNLOCK(flags); @@ -1025,15 +1118,19 @@ u32 reg; macio = &macio_chips[0]; - if (macio->type != macio_keylargo && macio->type != macio_pangea) + if (macio->type != macio_keylargo && macio->type != macio_pangea && + macio->type != macio_intrepid) return -ENODEV; - + + /* XXX Fix handling of 3rd USB controller in Intrepid, move the + * port connect stuff (KL4_*) to the sleep code eventually + */ prop = (char *)get_property(node, "AAPL,clock-id", NULL); if (!prop) return -ENODEV; - if (strncmp(prop, "usb0u048", strlen("usb0u048")) == 0) + if (strncmp(prop, "usb0u048", 8) == 0) number = 0; - else if (strncmp(prop, "usb1u148", strlen("usb1u148")) == 0) + else if (strncmp(prop, "usb1u148", 8) == 0) number = 2; else return -ENODEV; @@ -1104,7 +1201,8 @@ struct macio_chip* macio; macio = &macio_chips[0]; - if (macio->type != macio_keylargo && macio->type != macio_pangea) + if (macio->type != macio_keylargo && macio->type != macio_pangea && + macio->type != macio_intrepid) return -ENODEV; if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED)) return -ENODEV; @@ -1133,7 +1231,8 @@ if ((pmac_mb.board_flags & PMAC_MB_HAS_FW_POWER) == 0) return -ENODEV; macio = &macio_chips[0]; - if (macio->type != macio_keylargo && macio->type != macio_pangea) + if (macio->type != macio_keylargo && macio->type != macio_pangea && + macio->type != macio_intrepid) return -ENODEV; if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED)) return -ENODEV; @@ -1172,23 +1271,24 @@ } static void __pmac -keylargo_shutdown(struct macio_chip* macio, int restart) +keylargo_shutdown(struct macio_chip* macio, int sleep_mode) { u32 temp; - mdelay(1); - MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND); - (void)MACIO_IN32(KEYLARGO_FCR0); - mdelay(100); + if (sleep_mode) { + mdelay(1); + MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND); + (void)MACIO_IN32(KEYLARGO_FCR0); + mdelay(1); + } MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | KL0_SCC_CELL_ENABLE | KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE); - - (void)MACIO_IN32(KEYLARGO_FCR0); udelay(10); + MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK); - (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10); + MACIO_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_IDE_ENABLE); MACIO_BIC(KEYLARGO_FCR1, KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT | @@ -1199,27 +1299,33 @@ KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N | KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N | KL1_UIDE_ENABLE); - (void)MACIO_IN32(KEYLARGO_FCR1); udelay(10); MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); - udelay(10); MACIO_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE); - udelay(10); + temp = MACIO_IN32(KEYLARGO_FCR3); - if (macio->rev >= 2) - temp |= (KL3_SHUTDOWN_PLL2X | KL3_SHUTDOWN_PLL_TOTAL); - + if (macio->rev >= 2) { + temp |= KL3_SHUTDOWN_PLL2X; + if (sleep_mode) + temp |= KL3_SHUTDOWN_PLL_TOTAL; + } + temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 | - KL3_SHUTDOWN_PLLKW35 | KL3_SHUTDOWN_PLLKW12; + KL3_SHUTDOWN_PLLKW35; + if (sleep_mode) + temp |= KL3_SHUTDOWN_PLLKW12; temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE - | KL3_CLK31_ENABLE | KL3_TIMER_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE - | KL3_I2S0_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE); + | KL3_CLK31_ENABLE | KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE); + if (sleep_mode) + temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE); MACIO_OUT32(KEYLARGO_FCR3, temp); - (void)MACIO_IN32(KEYLARGO_FCR3); udelay(10); + + /* Flush posted writes & wait a bit */ + (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1); } static void __pmac -pangea_shutdown(struct macio_chip* macio, int restart) +pangea_shutdown(struct macio_chip* macio, int sleep_mode) { u32 temp; @@ -1227,10 +1333,6 @@ KL0_SCC_CELL_ENABLE | KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE); - (void)MACIO_IN32(KEYLARGO_FCR0); udelay(10); - MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK); - (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10); - MACIO_BIC(KEYLARGO_FCR1, KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT | KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE | @@ -1238,18 +1340,54 @@ KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE | KL1_UIDE_ENABLE); - (void)MACIO_IN32(KEYLARGO_FCR1); udelay(10); + if (pmac_mb.board_flags & PMAC_MB_MOBILE) + MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N); MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); - udelay(10); + temp = MACIO_IN32(KEYLARGO_FCR3); temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 | KL3_SHUTDOWN_PLLKW35; - temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE - | KL3_CLK31_ENABLE | KL3_TIMER_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE - | KL3_I2S0_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE); + temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | KL3_CLK31_ENABLE + | KL3_I2S0_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE); + if (sleep_mode) + temp &= ~(KL3_VIA_CLK16_ENABLE | KL3_TIMER_CLK18_ENABLE); MACIO_OUT32(KEYLARGO_FCR3, temp); - (void)MACIO_IN32(KEYLARGO_FCR3); udelay(10); + + /* Flush posted writes & wait a bit */ + (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1); +} + +static void __pmac +intrepid_shutdown(struct macio_chip* macio, int sleep_mode) +{ + u32 temp; + + MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | + KL0_SCC_CELL_ENABLE | + KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE); + + MACIO_BIC(KEYLARGO_FCR1, + KL1_USB2_CELL_ENABLE | + KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | + KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | + KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE); + if (pmac_mb.board_flags & PMAC_MB_MOBILE) + MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N); + + MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); + + temp = MACIO_IN32(KEYLARGO_FCR3); + temp |= KL3_IT_SHUTDOWN_PLL1 | KL3_IT_SHUTDOWN_PLL2 | + KL3_IT_SHUTDOWN_PLL3; + temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | + KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE); + if (sleep_mode) + temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_IT_VIA_CLK32_ENABLE); + MACIO_OUT32(KEYLARGO_FCR3, temp); + + /* Flush posted writes & wait a bit */ + (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1); } static int __pmac @@ -1259,7 +1397,8 @@ int i; macio = &macio_chips[0]; - if (macio->type != macio_keylargo && macio->type != macio_pangea) + if (macio->type != macio_keylargo && macio->type != macio_pangea && + macio->type != macio_intrepid) return -ENODEV; /* We power off the wireless slot in case it was not done @@ -1275,7 +1414,11 @@ } /* We make sure int. modem is off (in case driver lost it) */ - core99_modem_enable(macio->of_node, 0, 0); + if (macio->type == macio_keylargo) + core99_modem_enable(macio->of_node, 0, 0); + else + pangea_modem_enable(macio->of_node, 0, 0); + /* We make sure the sound is off as well */ core99_sound_chip_enable(macio->of_node, 0, 0); @@ -1292,12 +1435,15 @@ save_gpio_normal[i] = MACIO_IN8(KEYLARGO_GPIO_0+i); /* Save the FCRs */ - save_mbcr = MACIO_IN32(KEYLARGO_MBCR); + if (macio->type == macio_keylargo) + save_mbcr = MACIO_IN32(KEYLARGO_MBCR); save_fcr[0] = MACIO_IN32(KEYLARGO_FCR0); save_fcr[1] = MACIO_IN32(KEYLARGO_FCR1); save_fcr[2] = MACIO_IN32(KEYLARGO_FCR2); save_fcr[3] = MACIO_IN32(KEYLARGO_FCR3); save_fcr[4] = MACIO_IN32(KEYLARGO_FCR4); + if (macio->type == macio_pangea || macio->type == macio_intrepid) + save_fcr[5] = MACIO_IN32(KEYLARGO_FCR5); /* Save state & config of DBDMA channels */ dbdma_save(macio, save_dbdma); @@ -1306,9 +1452,11 @@ * Turn off as much as we can */ if (macio->type == macio_pangea) - pangea_shutdown(macio, 0); + pangea_shutdown(macio, 1); + else if (macio->type == macio_intrepid) + intrepid_shutdown(macio, 1); else if (macio->type == macio_keylargo) - keylargo_shutdown(macio, 0); + keylargo_shutdown(macio, 1); /* * Put the host bridge to sleep @@ -1338,7 +1486,8 @@ int i; macio = &macio_chips[0]; - if (macio->type != macio_keylargo && macio->type != macio_pangea) + if (macio->type != macio_keylargo && macio->type != macio_pangea && + macio->type != macio_intrepid) return -ENODEV; /* @@ -1352,9 +1501,11 @@ /* * Restore KeyLargo */ - - MACIO_OUT32(KEYLARGO_MBCR, save_mbcr); - (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10); + + if (macio->type == macio_keylargo) { + MACIO_OUT32(KEYLARGO_MBCR, save_mbcr); + (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10); + } MACIO_OUT32(KEYLARGO_FCR0, save_fcr[0]); (void)MACIO_IN32(KEYLARGO_FCR0); udelay(10); MACIO_OUT32(KEYLARGO_FCR1, save_fcr[1]); @@ -1365,6 +1516,10 @@ (void)MACIO_IN32(KEYLARGO_FCR3); udelay(10); MACIO_OUT32(KEYLARGO_FCR4, save_fcr[4]); (void)MACIO_IN32(KEYLARGO_FCR4); udelay(10); + if (macio->type == macio_pangea || macio->type == macio_intrepid) { + MACIO_OUT32(KEYLARGO_FCR5, save_fcr[5]); + (void)MACIO_IN32(KEYLARGO_FCR5); udelay(10); + } dbdma_restore(macio, save_dbdma); @@ -1390,6 +1545,21 @@ static int __pmac core99_sleep_state(struct device_node* node, int param, int value) { + /* Param == 1 means to enter the "fake sleep" mode that is + * used for CPU speed switch + */ + if (param == 1) { + if (value == 1) { + UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING); + UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_IDLE2); + } else { + UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL); + udelay(10); + UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING); + udelay(10); + } + return 0; + } if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) return -EPERM; if (value == 1) @@ -1400,55 +1570,6 @@ } static int __pmac -pangea_modem_enable(struct device_node* node, int param, int value) -{ - struct macio_chip* macio; - u8 gpio; - unsigned long flags; - - macio = macio_find(node, 0); - if (!macio) - return -ENODEV; - gpio = MACIO_IN8(KL_GPIO_MODEM_RESET); - gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE; - gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA; - - if (!value) { - LOCK(flags); - MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); - UNLOCK(flags); - (void)MACIO_IN8(KL_GPIO_MODEM_RESET); - mdelay(250); - } - LOCK(flags); - if (value) { - MACIO_OUT8(KL_GPIO_MODEM_POWER, - KEYLARGO_GPIO_OUTPUT_ENABLE); - UNLOCK(flags); - (void)MACIO_IN32(KEYLARGO_FCR2); - mdelay(250); - } else { - MACIO_OUT8(KL_GPIO_MODEM_POWER, - KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); - UNLOCK(flags); - } - if (value) { - LOCK(flags); - MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); - (void)MACIO_IN8(KL_GPIO_MODEM_RESET); - UNLOCK(flags); mdelay(250); LOCK(flags); - MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); - (void)MACIO_IN8(KL_GPIO_MODEM_RESET); - UNLOCK(flags); mdelay(250); LOCK(flags); - MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); - (void)MACIO_IN8(KL_GPIO_MODEM_RESET); - UNLOCK(flags); mdelay(250); - } - return 0; -} - - -static int __pmac generic_get_mb_info(struct device_node* node, int param, int value) { switch(param) { @@ -1561,6 +1682,26 @@ { 0, NULL } }; +/* RackMac + */ +static struct feature_table_entry rackmac_features[] __pmacdata = { + { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, + { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, + { PMAC_FTR_IDE_RESET, core99_ide_reset }, + { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable }, + { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset }, + { PMAC_FTR_USB_ENABLE, core99_usb_enable }, + { PMAC_FTR_1394_ENABLE, core99_firewire_enable }, + { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power }, + { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, +#ifdef CONFIG_SMP + { PMAC_FTR_RESET_CPU, core99_reset_cpu }, +#endif /* CONFIG_SMP */ + { PMAC_FTR_READ_GPIO, core99_read_gpio }, + { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, + { 0, NULL } +}; + /* Pangea features */ static struct feature_table_entry pangea_features[] __pmacdata = { @@ -1580,6 +1721,26 @@ { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, { 0, NULL } }; + +/* Intrepid features + */ +static struct feature_table_entry intrepid_features[] __pmacdata = { + { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, + { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable }, + { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, + { PMAC_FTR_IDE_RESET, core99_ide_reset }, + { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable }, + { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset }, + { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable }, + { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable }, + { PMAC_FTR_USB_ENABLE, core99_usb_enable }, + { PMAC_FTR_1394_ENABLE, core99_firewire_enable }, + { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power }, + { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, + { PMAC_FTR_READ_GPIO, core99_read_gpio }, + { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, + { 0, NULL } +}; static struct pmac_mb_def pmac_mb_defs[] __pmacdata = { /* Warning: ordering is important as some models may claim @@ -1611,11 +1772,11 @@ }, { "AAPL,3400/2400", "PowerBook 3400", PMAC_TYPE_HOOPER, ohare_features, - PMAC_MB_CAN_SLEEP + PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE }, { "AAPL,3500", "PowerBook 3500", PMAC_TYPE_KANGA, ohare_features, - PMAC_MB_CAN_SLEEP + PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE }, { "AAPL,Gossamer", "PowerMac G3 (Gossamer)", PMAC_TYPE_GOSSAMER, heathrow_desktop_features, @@ -1627,11 +1788,11 @@ }, { "AAPL,PowerBook1998", "PowerBook Wallstreet", PMAC_TYPE_WALLSTREET, heathrow_laptop_features, - PMAC_MB_CAN_SLEEP + PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE }, - { "AAPL,PowerBook1,1", "PowerBook 101 (Lombard)", + { "PowerBook1,1", "PowerBook 101 (Lombard)", PMAC_TYPE_101_PBOOK, paddington_features, - PMAC_MB_CAN_SLEEP + PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE }, { "iMac,1", "iMac (first generation)", PMAC_TYPE_ORIG_IMAC, paddington_features, @@ -1641,13 +1802,21 @@ PMAC_TYPE_PANGEA_IMAC, pangea_features, PMAC_MB_CAN_SLEEP }, - { "PowerBook4,2", "iBook 2 with 14\" LCD", + { "PowerBook4,3", "iBook 2 rev. 2", PMAC_TYPE_IBOOK2, pangea_features, - PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER + PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE + }, + { "PowerBook4,2", "iBook 2", + PMAC_TYPE_IBOOK2, pangea_features, + PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE }, { "PowerBook4,1", "iBook 2", PMAC_TYPE_IBOOK2, pangea_features, - PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER + PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE + }, + { "PowerMac4,4", "eMac", + PMAC_TYPE_EMAC, core99_features, + PMAC_MB_CAN_SLEEP }, { "PowerMac4,2", "Flat panel iMac", PMAC_TYPE_FLAT_PANEL_IMAC, pangea_features, @@ -1663,34 +1832,35 @@ }, { "PowerBook2,1", "iBook (first generation)", PMAC_TYPE_ORIG_IBOOK, core99_features, - PMAC_MB_CAN_SLEEP + PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE }, { "PowerMac3,1", "PowerMac G4 AGP Graphics", PMAC_TYPE_SAWTOOTH, core99_features, - 0 + PMAC_MB_OLD_CORE99 }, { "PowerMac3,2", "PowerMac G4 AGP Graphics", PMAC_TYPE_SAWTOOTH, core99_features, - 0 + PMAC_MB_OLD_CORE99 }, { "PowerMac3,3", "PowerMac G4 AGP Graphics", PMAC_TYPE_SAWTOOTH, core99_features, - 0 + PMAC_MB_OLD_CORE99 }, { "PowerMac2,1", "iMac FireWire", PMAC_TYPE_FW_IMAC, core99_features, - PMAC_MB_CAN_SLEEP + PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99 }, { "PowerMac2,2", "iMac FireWire", PMAC_TYPE_FW_IMAC, core99_features, - PMAC_MB_CAN_SLEEP + PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99 }, { "PowerBook2,2", "iBook FireWire", PMAC_TYPE_FW_IBOOK, core99_features, - PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER + PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE }, { "PowerMac5,1", "PowerMac G4 Cube", PMAC_TYPE_CUBE, core99_features, + PMAC_MB_OLD_CORE99 }, { "PowerMac3,4", "PowerMac G4 Silver", PMAC_TYPE_QUICKSILVER, core99_features, @@ -1702,19 +1872,31 @@ }, { "PowerBook3,1", "PowerBook Pismo", PMAC_TYPE_PISMO, core99_features, - PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER + PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE }, { "PowerBook3,2", "PowerBook Titanium", PMAC_TYPE_TITANIUM, core99_features, - PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER + PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE }, { "PowerBook3,3", "PowerBook Titanium II", PMAC_TYPE_TITANIUM2, core99_features, - PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER + PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE }, { "PowerBook3,4", "PowerBook Titanium III", PMAC_TYPE_TITANIUM3, core99_features, - PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER + PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE + }, + { "PowerBook3,5", "PowerBook Titanium IV", + PMAC_TYPE_TITANIUM4, core99_features, + PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE + }, + { "RackMac1,1", "XServe", + PMAC_TYPE_RACKMAC, rackmac_features, + 0, + }, + { "PowerMac3,6", "PowerMac G4 Windtunnel", + PMAC_TYPE_WINDTUNNEL, rackmac_features, + 0, }, }; @@ -1758,8 +1940,22 @@ { int i; struct macio_chip* macio = &macio_chips[0]; - - /* Lookup known motherboard type in device-tree */ + const char* model = NULL; + struct device_node *dt; + + /* Lookup known motherboard type in device-tree. First try an + * exact match on the "model" property, then try a "compatible" + * match is none is found. + */ + dt = find_devices("device-tree"); + if (dt != NULL) + model = (const char *) get_property(dt, "model", NULL); + for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) { + if (strcmp(model, pmac_mb_defs[i].model_string) == 0) { + pmac_mb = pmac_mb_defs[i]; + goto found; + } + } for(i=0; i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) { if (machine_is_compatible(pmac_mb_defs[i].model_string)) { pmac_mb = pmac_mb_defs[i]; @@ -1797,6 +1993,11 @@ pmac_mb.model_name = "Unknown Pangea-based"; pmac_mb.features = pangea_features; break; + case macio_intrepid: + pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PANGEA; + pmac_mb.model_name = "Unknown Pangea-based"; + pmac_mb.features = intrepid_features; + break; default: return -ENODEV; } @@ -1815,6 +2016,7 @@ iounmap(mach_id_ptr); } +#ifdef CONFIG_6xx /* Set default value of powersave_nap on machines that support it. * It appears that uninorth rev 3 has a problem with it, we don't * enable it on those. In theory, the flush-on-lock property is @@ -1823,7 +2025,6 @@ */ while (uninorth_base && uninorth_rev > 3) { struct device_node* np = find_path_device("/cpus"); - u32 pvr = mfspr(PVR); if (!np || !np->child) { printk(KERN_WARNING "Can't find CPU(s) in device tree !\n"); break; @@ -1835,14 +2036,23 @@ /* Nap mode not supported if flush-on-lock property is present */ if (get_property(np, "flush-on-lock", NULL)) break; - /* Some 7450 may have problem with NAP mode too ... */ - if (((pvr >> 16) == 0x8000) && ((pvr & 0xffff) < 0x0201)) - break; powersave_nap = 1; printk(KERN_INFO "Processor NAP mode on idle enabled.\n"); break; } + /* On CPUs that support it (750FX), lowspeed by default during + * NAP mode + */ + powersave_lowspeed = 1; +#endif /* CONFIG_6xx */ + + /* Check for "mobile" machine */ + if (model && (strncmp(model, "PowerBook", 9) == 0 + || strncmp(model, "iBook", 5) == 0)) + pmac_mb.board_flags |= PMAC_MB_MOBILE; + + printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name); return 0; } @@ -1857,7 +2067,7 @@ /* Locate core99 Uni-N */ uninorth_node = find_devices("uni-n"); if (uninorth_node && uninorth_node->n_addrs > 0) { - uninorth_base = ioremap(uninorth_node->addrs[0].address, 0x1000); + uninorth_base = ioremap(uninorth_node->addrs[0].address, 0x4000); uninorth_rev = in_be32(UN_REG(UNI_N_VERSION)); } else uninorth_node = NULL; @@ -1867,15 +2077,23 @@ printk(KERN_INFO "Found Uninorth memory controller & host bridge, revision: %d\n", uninorth_rev); + printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base); /* Set the arbitrer QAck delay according to what Apple does */ - if (uninorth_rev < 0x10) { + if (uninorth_rev < 0x11) { actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK; actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 : UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT; UN_OUT(UNI_N_ARB_CTRL, actrl); } + + /* Some more magic as done by them in recent MacOS X on UniNorth + * revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI + * memory timeout + */ + if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || uninorth_rev == 0xc0) + UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff); } static void __init @@ -1917,11 +2135,14 @@ u32* did = (u32 *)get_property(node, "device-id", NULL); if (*did == 0x00000025) type = macio_pangea; + if (*did == 0x0000003e) + type = macio_intrepid; } macio_chips[i].of_node = node; macio_chips[i].type = type; macio_chips[i].base = base; macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON; + macio_chips[i].name = macio_names[type]; revp = (u32 *)get_property(node, "revision-id", NULL); if (revp) macio_chips[i].rev = *revp; @@ -2011,7 +2232,8 @@ } if (macio_chips[0].type == macio_keylargo || - macio_chips[0].type == macio_pangea) { + macio_chips[0].type == macio_pangea || + macio_chips[0].type == macio_intrepid) { /* Enable GMAC for now for PCI probing. It will be disabled * later on after PCI probe */ @@ -2042,6 +2264,17 @@ np = np->next; } + /* Enable ATA-100 before PCI probe. */ + np = find_devices("ata-6"); + while(np) { + if (np->parent + && device_is_compatible(np->parent, "uni-north") + && device_is_compatible(np, "kauai-ata")) { + core99_ata100_enable(np, 1); + } + np = np->next; + } + /* Switch airport off */ np = find_devices("radio"); while(np) { @@ -2079,9 +2312,6 @@ initial_serial_shutdown(np); np = np->next; } - - /* Let hardware settle down */ - mdelay(10); } void __init diff -Nru a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c --- a/arch/ppc/platforms/pmac_setup.c Sat Mar 22 17:21:25 2003 +++ b/arch/ppc/platforms/pmac_setup.c Wed Mar 26 22:00:59 2003 @@ -225,6 +225,20 @@ return 0; } +int __openfirmware +pmac_show_percpuinfo(struct seq_file *m, int i) +{ +#ifdef CONFIG_CPU_FREQ_PMAC + extern unsigned int pmac_get_one_cpufreq(int i); + unsigned int freq = pmac_get_one_cpufreq(i); + if (freq != 0) { + seq_printf(m, "clock\t\t: %dMHz\n", freq/1000); + return 0; + } +#endif /* CONFIG_CPU_FREQ_PMAC */ + return of_show_percpuinfo(m, i); +} + static volatile u32 *sysctrl_regs; void __init @@ -604,7 +618,7 @@ ppc_md.setup_arch = pmac_setup_arch; ppc_md.show_cpuinfo = pmac_show_cpuinfo; - ppc_md.show_percpuinfo = of_show_percpuinfo; + ppc_md.show_percpuinfo = pmac_show_percpuinfo; ppc_md.irq_cannonicalize = NULL; ppc_md.init_IRQ = pmac_pic_init; ppc_md.get_irq = pmac_get_irq; /* Changed later on ... */ diff -Nru a/arch/ppc/platforms/pmac_sleep.S b/arch/ppc/platforms/pmac_sleep.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc/platforms/pmac_sleep.S Wed Mar 26 21:44:08 2003 @@ -0,0 +1,375 @@ +/* + * This file contains sleep low-level functions for PowerBook G3. + * Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org) + * and Paul Mackerras (paulus@samba.org). + * + * 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 + +#define MAGIC 0x4c617273 /* 'Lars' */ + +/* + * Structure for storing CPU registers on the stack. + */ +#define SL_SP 0 +#define SL_PC 4 +#define SL_MSR 8 +#define SL_SDR1 0xc +#define SL_SPRG0 0x10 /* 4 sprg's */ +#define SL_DBAT0 0x20 +#define SL_IBAT0 0x28 +#define SL_DBAT1 0x30 +#define SL_IBAT1 0x38 +#define SL_DBAT2 0x40 +#define SL_IBAT2 0x48 +#define SL_DBAT3 0x50 +#define SL_IBAT3 0x58 +#define SL_TB 0x60 +#define SL_R2 0x68 +#define SL_CR 0x6c +#define SL_R12 0x70 /* r12 to r31 */ +#define SL_SIZE (SL_R12 + 80) + + .section .text + .align 5 + +#if defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_CPU_FREQ_PMAC) + +/* This gets called by via-pmu.c late during the sleep process. + * The PMU was already send the sleep command and will shut us down + * soon. We need to save all that is needed and setup the wakeup + * vector that will be called by the ROM on wakeup + */ +_GLOBAL(low_sleep_handler) + mflr r0 + stw r0,4(r1) + stwu r1,-SL_SIZE(r1) + mfcr r0 + stw r0,SL_CR(r1) + stw r2,SL_R2(r1) + stmw r12,SL_R12(r1) + + /* Save MSR & SDR1 */ + mfmsr r4 + stw r4,SL_MSR(r1) + mfsdr1 r4 + stw r4,SL_SDR1(r1) + + /* Get a stable timebase and save it */ +1: mftbu r4 + stw r4,SL_TB(r1) + mftb r5 + stw r5,SL_TB+4(r1) + mftbu r3 + cmpw r3,r4 + bne 1b + + /* Save SPRGs */ + mfsprg r4,0 + stw r4,SL_SPRG0(r1) + mfsprg r4,1 + stw r4,SL_SPRG0+4(r1) + mfsprg r4,2 + stw r4,SL_SPRG0+8(r1) + mfsprg r4,3 + stw r4,SL_SPRG0+12(r1) + + /* Save BATs */ + mfdbatu r4,0 + stw r4,SL_DBAT0(r1) + mfdbatl r4,0 + stw r4,SL_DBAT0+4(r1) + mfdbatu r4,1 + stw r4,SL_DBAT1(r1) + mfdbatl r4,1 + stw r4,SL_DBAT1+4(r1) + mfdbatu r4,2 + stw r4,SL_DBAT2(r1) + mfdbatl r4,2 + stw r4,SL_DBAT2+4(r1) + mfdbatu r4,3 + stw r4,SL_DBAT3(r1) + mfdbatl r4,3 + stw r4,SL_DBAT3+4(r1) + mfibatu r4,0 + stw r4,SL_IBAT0(r1) + mfibatl r4,0 + stw r4,SL_IBAT0+4(r1) + mfibatu r4,1 + stw r4,SL_IBAT1(r1) + mfibatl r4,1 + stw r4,SL_IBAT1+4(r1) + mfibatu r4,2 + stw r4,SL_IBAT2(r1) + mfibatl r4,2 + stw r4,SL_IBAT2+4(r1) + mfibatu r4,3 + stw r4,SL_IBAT3(r1) + mfibatl r4,3 + stw r4,SL_IBAT3+4(r1) + + /* Backup various CPU config stuffs */ + bl __save_cpu_setup + + /* The ROM can wake us up via 2 different vectors: + * - On wallstreet & lombard, we must write a magic + * value 'Lars' at address 4 and a pointer to a + * memory location containing the PC to resume from + * at address 0. + * - On Core99, we must store the wakeup vector at + * address 0x80 and eventually it's parameters + * at address 0x84. I've have some trouble with those + * parameters however and I no longer use them. + */ + lis r5,grackle_wake_up@ha + addi r5,r5,grackle_wake_up@l + tophys(r5,r5) + stw r5,SL_PC(r1) + lis r4,KERNELBASE@h + tophys(r5,r1) + addi r5,r5,SL_PC + lis r6,MAGIC@ha + addi r6,r6,MAGIC@l + stw r5,0(r4) + stw r6,4(r4) + /* Setup stuffs at 0x80-0x84 for Core99 */ + lis r3,core99_wake_up@ha + addi r3,r3,core99_wake_up@l + tophys(r3,r3) + stw r3,0x80(r4) + stw r5,0x84(r4) + /* Store a pointer to our backup storage into + * a kernel global + */ + lis r3,sleep_storage@ha + addi r3,r3,sleep_storage@l + stw r5,0(r3) + +BEGIN_FTR_SECTION + DSSALL + sync +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) + +/* + * Flush the L1 data cache by reading the first 128kB of RAM + * and then flushing the same area with the dcbf instruction. + * The L2 cache has already been disabled. + */ + li r4,0x1000 /* 128kB / 32B */ + mtctr r4 + lis r4,KERNELBASE@h +1: + lwz r0,0(r4) + addi r4,r4,0x0020 /* Go to start of next cache line */ + bdnz 1b + sync + + li r4,0x1000 /* 128kB / 32B */ + mtctr r4 + lis r4,KERNELBASE@h +1: + dcbf r0,r4 + addi r4,r4,0x0020 /* Go to start of next cache line */ + bdnz 1b + sync + +/* + * Set the HID0 and MSR for sleep. + */ + mfspr r2,HID0 + rlwinm r2,r2,0,10,7 /* clear doze, nap */ + oris r2,r2,HID0_SLEEP@h + sync + mtspr HID0,r2 + sync + +/* This loop puts us back to sleep in case we have a spurrious + * wakeup so that the host bridge properly stays asleep. The + * CPU will be turned off, either after a known time (about 1 + * second) on wallstreet & lombard, or as soon as the CPU enters + * SLEEP mode on core99 + */ + mfmsr r2 + oris r2,r2,MSR_POW@h +1: sync + mtmsr r2 + isync + b 1b + +/* + * Here is the resume code. + */ + + +/* + * Core99 machines resume here + * r4 has the physical address of SL_PC(sp) (unused) + */ +_GLOBAL(core99_wake_up) + /* Make sure HID0 no longer contains any sleep bit */ + mfspr r3,HID0 + rlwinm r3,r3,0,11,7 /* clear SLEEP, NAP, DOZE bits */ + mtspr HID0,r3 + sync + isync + + /* Won't that cause problems on CPU that doesn't support it ? */ + lis r3, 0 + mtspr SPRN_MMCR0, r3 + + /* sanitize MSR */ + mfmsr r3 + ori r3,r3,MSR_EE|MSR_IP + xori r3,r3,MSR_EE|MSR_IP + sync + isync + mtmsr r3 + sync + isync + + /* Recover sleep storage */ + lis r3,sleep_storage@ha + addi r3,r3,sleep_storage@l + tophys(r3,r3) + lwz r1,0(r3) + + /* Pass thru to older resume code ... */ +/* + * Here is the resume code for older machines. + * r1 has the physical address of SL_PC(sp). + */ + +grackle_wake_up: + /* Enable and then Flash inval the instruction & data cache */ + mfspr r3,HID0 + ori r3,r3, HID0_ICE|HID0_ICFI|HID0_DCE|HID0_DCI + sync + isync + mtspr HID0,r3 + xori r3,r3, HID0_ICFI|HID0_DCI + mtspr HID0,r3 + sync + + /* Restore the kernel's segment registers before + * we do any r1 memory access as we are not sure they + * are in a sane state above the first 256Mb region + */ + li r0,16 /* load up segment register values */ + mtctr r0 /* for context 0 */ + lis r3,0x2000 /* Ku = 1, VSID = 0 */ + li r4,0 +3: mtsrin r3,r4 + addi r3,r3,0x111 /* increment VSID */ + addis r4,r4,0x1000 /* address of next segment */ + bdnz 3b + + subi r1,r1,SL_PC + + /* Restore various CPU config stuffs */ + bl __restore_cpu_setup + + /* Restore the BATs, and SDR1. Then we can turn on the MMU. */ + lwz r4,SL_SDR1(r1) + mtsdr1 r4 + lwz r4,SL_SPRG0(r1) + mtsprg 0,r4 + lwz r4,SL_SPRG0+4(r1) + mtsprg 1,r4 + lwz r4,SL_SPRG0+8(r1) + mtsprg 2,r4 + lwz r4,SL_SPRG0+12(r1) + mtsprg 3,r4 + + lwz r4,SL_DBAT0(r1) + mtdbatu 0,r4 + lwz r4,SL_DBAT0+4(r1) + mtdbatl 0,r4 + lwz r4,SL_DBAT1(r1) + mtdbatu 1,r4 + lwz r4,SL_DBAT1+4(r1) + mtdbatl 1,r4 + lwz r4,SL_DBAT2(r1) + mtdbatu 2,r4 + lwz r4,SL_DBAT2+4(r1) + mtdbatl 2,r4 + lwz r4,SL_DBAT3(r1) + mtdbatu 3,r4 + lwz r4,SL_DBAT3+4(r1) + mtdbatl 3,r4 + lwz r4,SL_IBAT0(r1) + mtibatu 0,r4 + lwz r4,SL_IBAT0+4(r1) + mtibatl 0,r4 + lwz r4,SL_IBAT1(r1) + mtibatu 1,r4 + lwz r4,SL_IBAT1+4(r1) + mtibatl 1,r4 + lwz r4,SL_IBAT2(r1) + mtibatu 2,r4 + lwz r4,SL_IBAT2+4(r1) + mtibatl 2,r4 + lwz r4,SL_IBAT3(r1) + mtibatu 3,r4 + lwz r4,SL_IBAT3+4(r1) + mtibatl 3,r4 + + /* Flush all TLBs */ + lis r4,0x1000 +1: addic. r4,r4,-0x1000 + tlbie r4 + blt 1b + sync + + /* restore the MSR and turn on the MMU */ + lwz r3,SL_MSR(r1) + bl turn_on_mmu + + /* get back the stack pointer */ + tovirt(r1,r1) + + /* Restore TB */ + li r3,0 + mttbl r3 + lwz r3,SL_TB(r1) + lwz r4,SL_TB+4(r1) + mttbu r3 + mttbl r4 + + /* Restore the callee-saved registers and return */ + lwz r0,SL_CR(r1) + mtcr r0 + lwz r2,SL_R2(r1) + lmw r12,SL_R12(r1) + addi r1,r1,SL_SIZE + lwz r0,4(r1) + mtlr r0 + blr + +turn_on_mmu: + mflr r4 + tovirt(r4,r4) + mtsrr0 r4 + mtsrr1 r3 + sync + isync + rfi + +#endif /* defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_CPU_FREQ) */ + + + .data + .globl sleep_storage +sleep_storage: + .long 0 diff -Nru a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c --- a/arch/ppc/platforms/pmac_smp.c Sun Sep 15 21:52:02 2002 +++ b/arch/ppc/platforms/pmac_smp.c Wed Mar 26 21:44:08 2003 @@ -106,14 +106,16 @@ volatile static long int core99_l3_cache; static void __init -core99_init_caches(void) +core99_init_caches(int cpu) { - int cpu = smp_processor_id(); - + /* Check cache presence on cpu 0, we assume all CPUs have + * same features here. We also assume that if we don't have + * L2CR, we don't have L3CR neither + */ if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR)) return; - if (cpu == 0){ + if (cpu == 0) { core99_l2_cache = _get_L2CR(); printk("CPU0: L2CR is %lx\n", core99_l2_cache); } else { @@ -137,106 +139,6 @@ } } -/* Some CPU registers have to be saved from the first CPU and - * applied to others. Note that we override what is setup by - * the cputable intentionally. - */ - -#define reg_hid0 0 -#define reg_hid1 1 -#define reg_msscr0 2 -#define reg_msssr0 3 -#define reg_ictrl 4 -#define reg_ldstcr 5 -#define reg_ldstdb 6 -#define reg_count 7 - -static unsigned long cpu_regs[reg_count]; - -static void __pmac -cpu_setup_grab(void) -{ - unsigned int pvers = mfspr(SPRN_PVR)>>16; - - /* Read cache setting of CPU 0 */ - core99_init_caches(); - - /* 7400/7410/7450 */ - if (pvers == 0x8000 || pvers == 0x000c || pvers == 0x800c) { - cpu_regs[reg_hid0] = mfspr(SPRN_HID0); - cpu_regs[reg_msscr0] = mfspr(SPRN_MSSCR0); - cpu_regs[reg_msssr0] = mfspr(SPRN_MSSSR0); - } - /* 7450 only */ - if (pvers == 0x8000) { - cpu_regs[reg_hid1] = mfspr(SPRN_HID1); - cpu_regs[reg_ictrl] = mfspr(SPRN_ICTRL); - cpu_regs[reg_ldstcr] = mfspr(SPRN_LDSTCR); - cpu_regs[reg_ldstdb] = mfspr(SPRN_LDSTDB); - } - flush_dcache_range((unsigned long)cpu_regs, (unsigned long)&cpu_regs[reg_count]); -} - -static void __pmac -cpu_setup_apply(int cpu_nr) -{ - unsigned int pvers = mfspr(SPRN_PVR)>>16; - - /* Apply cache setting from CPU 0 */ - core99_init_caches(); - - /* 7400/7410/7450 */ - if (pvers == 0x8000 || pvers == 0x000c || pvers == 0x800c) { - unsigned long tmp; - __asm__ __volatile__ ( - "lwz %0,4*"stringify(reg_hid0)"(%1)\n" - "sync\n" - "mtspr "stringify(SPRN_HID0)", %0\n" - "isync;sync\n" - "lwz %0, 4*"stringify(reg_msscr0)"(%1)\n" - "sync\n" - "mtspr "stringify(SPRN_MSSCR0)", %0\n" - "isync;sync\n" -// "lwz %0, "stringify(reg_msssr0)"(%1)\n" -// "sync\n" -// "mtspr "stringify(SPRN_MSSSR0)", %0\n" -// "isync;sync\n" - : "=&r" (tmp) : "r" (cpu_regs)); - } - /* 7410 only */ - if (pvers == 0x800c) { - unsigned long tmp; - __asm__ __volatile__ ( - "li %0, 0\n" - "sync\n" - "mtspr "stringify(SPRN_L2CR2)", %0\n" - "isync;sync\n" - : "=&r" (tmp)); - } - /* 7450 only */ - if (pvers == 0x8000) { - unsigned long tmp; - __asm__ __volatile__ ( - "lwz %0, 4*"stringify(reg_hid1)"(%1)\n" - "sync\n" - "mtspr "stringify(SPRN_HID1)", %0\n" - "isync;sync\n" - "lwz %0, 4*"stringify(reg_ictrl)"(%1)\n" - "sync\n" - "mtspr "stringify(SPRN_ICTRL)", %0\n" - "isync;sync\n" - "lwz %0, 4*"stringify(reg_ldstcr)"(%1)\n" - "sync\n" - "mtspr "stringify(SPRN_LDSTCR)", %0\n" - "isync;sync\n" - "lwz %0, 4*"stringify(reg_ldstdb)"(%1)\n" - "sync\n" - "mtspr "stringify(SPRN_LDSTDB)", %0\n" - "isync;sync\n" - : "=&r" (tmp) : "r" (cpu_regs)); - } -} - /* * Set and clear IPIs for powersurge. */ @@ -501,7 +403,7 @@ /* reset the entry point so if we get another intr we won't * try to startup again */ out_be32(psurge_start, 0x100); - if (request_irq(30, psurge_primary_intr, 0, "primary IPI", 0)) + if (request_irq(30, psurge_primary_intr, SA_INTERRUPT, "primary IPI", 0)) printk(KERN_ERR "Couldn't get primary IPI interrupt"); } @@ -526,8 +428,10 @@ openpic_request_IPIs(); for (i = 1; i < ncpus; ++i) smp_hw_index[i] = i; +#ifdef CONFIG_6xx powersave_nap = 0; - cpu_setup_grab(); +#endif + core99_init_caches(0); } return ncpus; @@ -593,7 +497,7 @@ { /* Setup some registers */ if (cpu_nr != 0) - cpu_setup_apply(cpu_nr); + core99_init_caches(cpu_nr); /* Setup openpic */ do_openpic_setup_cpu(); @@ -605,20 +509,20 @@ /* PowerSurge-style Macs */ struct smp_ops_t psurge_smp_ops __pmacdata = { - smp_psurge_message_pass, - smp_psurge_probe, - smp_psurge_kick_cpu, - smp_psurge_setup_cpu, - .give_timebase = smp_generic_give_timebase, - .take_timebase = smp_generic_take_timebase, + .message_pass = smp_psurge_message_pass, + .probe = smp_psurge_probe, + .kick_cpu = smp_psurge_kick_cpu, + .setup_cpu = smp_psurge_setup_cpu, + .give_timebase = smp_generic_give_timebase, + .take_timebase = smp_generic_take_timebase, }; /* Core99 Macs (dual G4s) */ struct smp_ops_t core99_smp_ops __pmacdata = { - smp_openpic_message_pass, - smp_core99_probe, - smp_core99_kick_cpu, - smp_core99_setup_cpu, - .give_timebase = smp_generic_give_timebase, - .take_timebase = smp_generic_take_timebase, + .message_pass = smp_openpic_message_pass, + .probe = smp_core99_probe, + .kick_cpu = smp_core99_kick_cpu, + .setup_cpu = smp_core99_setup_cpu, + .give_timebase = smp_generic_give_timebase, + .take_timebase = smp_generic_take_timebase, }; diff -Nru a/arch/ppc/platforms/pmac_time.c b/arch/ppc/platforms/pmac_time.c --- a/arch/ppc/platforms/pmac_time.c Wed Feb 5 05:04:38 2003 +++ b/arch/ppc/platforms/pmac_time.c Thu Mar 27 02:14:36 2003 @@ -202,6 +202,8 @@ printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n", tb_ticks_per_jiffy, dstart - dend); + iounmap((void*)via); + return 1; } diff -Nru a/arch/ppc/platforms/sleep.S b/arch/ppc/platforms/sleep.S --- a/arch/ppc/platforms/sleep.S Sun Sep 15 21:52:02 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,444 +0,0 @@ -/* - * This file contains sleep low-level functions for PowerBook G3. - * Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org) - * and Paul Mackerras (paulus@samba.org). - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - */ - -#include -#include -#include -#include - -#define MAGIC 0x4c617273 /* 'Lars' */ - -/* - * Structure for storing CPU registers on the stack. - */ -#define SL_SP 0 -#define SL_PC 4 -#define SL_MSR 8 -#define SL_SDR1 0xc -#define SL_SPRG0 0x10 /* 4 sprg's */ -#define SL_DBAT0 0x20 -#define SL_IBAT0 0x28 -#define SL_DBAT1 0x30 -#define SL_IBAT1 0x38 -#define SL_DBAT2 0x40 -#define SL_IBAT2 0x48 -#define SL_DBAT3 0x50 -#define SL_IBAT3 0x58 -#define SL_TB 0x60 -#define SL_HID0 0x68 -#define SL_HID1 0x6c -#define SL_MSSCR0 0x70 -#define SL_MSSSR0 0x74 -#define SL_ICTRL 0x78 -#define SL_LDSTCR 0x7c -#define SL_LDSTDB 0x80 -#define SL_R2 0x84 -#define SL_CR 0x88 -#define SL_R12 0x8c /* r12 to r31 */ -#define SL_SIZE (SL_R12 + 80) - - .text - .align 5 - -/* This gets called by via-pmu.c late during the sleep process. - * The PMU was already send the sleep command and will shut us down - * soon. We need to save all that is needed and setup the wakeup - * vector that will be called by the ROM on wakeup - */ -_GLOBAL(low_sleep_handler) - mflr r0 - stw r0,4(r1) - stwu r1,-SL_SIZE(r1) - mfcr r0 - stw r0,SL_CR(r1) - stw r2,SL_R2(r1) - stmw r12,SL_R12(r1) - - /* Save MSR & SDR1 */ - mfmsr r4 - stw r4,SL_MSR(r1) - mfsdr1 r4 - stw r4,SL_SDR1(r1) - - /* Get a stable timebase and save it */ -1: mftbu r4 - stw r4,SL_TB(r1) - mftb r5 - stw r5,SL_TB+4(r1) - mftbu r3 - cmpw r3,r4 - bne 1b - - /* Save SPRGs */ - mfsprg r4,0 - stw r4,SL_SPRG0(r1) - mfsprg r4,1 - stw r4,SL_SPRG0+4(r1) - mfsprg r4,2 - stw r4,SL_SPRG0+8(r1) - mfsprg r4,3 - stw r4,SL_SPRG0+12(r1) - - /* Save BATs */ - mfdbatu r4,0 - stw r4,SL_DBAT0(r1) - mfdbatl r4,0 - stw r4,SL_DBAT0+4(r1) - mfdbatu r4,1 - stw r4,SL_DBAT1(r1) - mfdbatl r4,1 - stw r4,SL_DBAT1+4(r1) - mfdbatu r4,2 - stw r4,SL_DBAT2(r1) - mfdbatl r4,2 - stw r4,SL_DBAT2+4(r1) - mfdbatu r4,3 - stw r4,SL_DBAT3(r1) - mfdbatl r4,3 - stw r4,SL_DBAT3+4(r1) - mfibatu r4,0 - stw r4,SL_IBAT0(r1) - mfibatl r4,0 - stw r4,SL_IBAT0+4(r1) - mfibatu r4,1 - stw r4,SL_IBAT1(r1) - mfibatl r4,1 - stw r4,SL_IBAT1+4(r1) - mfibatu r4,2 - stw r4,SL_IBAT2(r1) - mfibatl r4,2 - stw r4,SL_IBAT2+4(r1) - mfibatu r4,3 - stw r4,SL_IBAT3(r1) - mfibatl r4,3 - stw r4,SL_IBAT3+4(r1) - - /* Save HID0 */ - mfspr r4,HID0 - stw r4,SL_HID0(r1) - - /* Save 7400/7410/7450 specific registers */ - mfspr r3,PVR - srwi r3,r3,16 - cmpli cr0,r3,0x8000 - cmpli cr1,r3,0x000c - cmpli cr2,r3,0x800c - cror 4*cr1+eq,4*cr1+eq,4*cr2+eq - cror 4*cr0+eq,4*cr0+eq,4*cr1+eq - bne 1f - mfspr r4,SPRN_MSSCR0 - stw r4,SL_MSSCR0(r1) - mfspr r4,SPRN_MSSSR0 - stw r4,SL_MSSSR0(r1) - /* Save 7450 specific registers */ - beq cr1,1f - mfspr r4,HID1 - stw r4,SL_HID1(r1) - mfspr r4,SPRN_ICTRL - stw r4,SL_ICTRL(r1) - mfspr r4,SPRN_LDSTCR - stw r4,SL_LDSTCR(r1) - mfspr r4,SPRN_LDSTDB - stw r4,SL_LDSTDB(r1) -1: - /* The ROM can wake us up via 2 different vectors: - * - On wallstreet & lombard, we must write a magic - * value 'Lars' at address 4 and a pointer to a - * memory location containing the PC to resume from - * at address 0. - * - On Core99, we must store the wakeup vector at - * address 0x80 and eventually it's parameters - * at address 0x84. I've have some trouble with those - * parameters however and I no longer use them. - */ - lis r5,grackle_wake_up@ha - addi r5,r5,grackle_wake_up@l - tophys(r5,r5) - stw r5,SL_PC(r1) - lis r4,KERNELBASE@h - tophys(r5,r1) - addi r5,r5,SL_PC - lis r6,MAGIC@ha - addi r6,r6,MAGIC@l - stw r5,0(r4) - stw r6,4(r4) - /* Setup stuffs at 0x80-0x84 for Core99 */ - lis r3,core99_wake_up@ha - addi r3,r3,core99_wake_up@l - tophys(r3,r3) - stw r3,0x80(r4) - stw r5,0x84(r4) - /* Store a pointer to our backup storage into - * a kernel global - */ - lis r3,sleep_storage@ha - addi r3,r3,sleep_storage@l - stw r5,0(r3) - - -/* - * Flush the L1 data cache by reading the first 128kB of RAM - * and then flushing the same area with the dcbf instruction. - * The L2 cache has already been disabled. - */ - li r4,0x1000 /* 128kB / 32B */ - mtctr r4 - lis r4,KERNELBASE@h -1: - lwz r0,0(r4) - addi r4,r4,0x0020 /* Go to start of next cache line */ - bdnz 1b - sync - - li r4,0x1000 /* 128kB / 32B */ - mtctr r4 - lis r4,KERNELBASE@h -1: - dcbf r0,r4 - addi r4,r4,0x0020 /* Go to start of next cache line */ - bdnz 1b - sync - -/* - * Set the HID0 and MSR for sleep. - */ - mfspr r2,HID0 - rlwinm r2,r2,0,10,7 /* clear doze, nap */ - oris r2,r2,HID0_SLEEP@h - sync - mtspr HID0,r2 - sync - -/* This loop puts us back to sleep in case we have a spurrious - * wakeup so that the host bridge properly stays asleep. The - * CPU will be turned off, either after a known time (about 1 - * second) on wallstreet & lombard, or as soon as the CPU enters - * SLEEP mode on core99 - */ - mfmsr r2 - oris r2,r2,MSR_POW@h -1: sync - mtmsr r2 - isync - b 1b - -/* - * Here is the resume code. - */ - - -/* - * Core99 machines resume here - * r4 has the physical address of SL_PC(sp) (unused) - */ -_GLOBAL(core99_wake_up) - /* Make sure HID0 no longer contains any sleep bit */ - mfspr r3,HID0 - rlwinm r3,r3,0,11,7 /* clear SLEEP, NAP, DOZE bits */ - mtspr HID0,r3 - sync - isync - - /* Won't that cause problems on CPU that doesn't support it ? */ - lis r3, 0 - mtspr SPRN_MMCR0, r3 - - /* sanitize MSR */ - mfmsr r3 - ori r3,r3,MSR_EE|MSR_IP - xori r3,r3,MSR_EE|MSR_IP - sync - isync - mtmsr r3 - sync - isync - - /* Recover sleep storage */ - lis r3,sleep_storage@ha - addi r3,r3,sleep_storage@l - tophys(r3,r3) - lwz r1,0(r3) - - /* Pass thru to older resume code ... */ -/* - * Here is the resume code for older machines. - * r1 has the physical address of SL_PC(sp). - */ - -grackle_wake_up: - /* Enable and then Flash inval the instruction & data cache */ - mfspr r3,HID0 - ori r3,r3, HID0_ICE|HID0_ICFI|HID0_DCE|HID0_DCI - sync - isync - mtspr HID0,r3 - xori r3,r3, HID0_ICFI|HID0_DCI - mtspr HID0,r3 - sync - - /* Restore the kernel's segment registers before - * we do any r1 memory access as we are not sure they - * are in a sane state above the first 256Mb region - */ - li r0,16 /* load up segment register values */ - mtctr r0 /* for context 0 */ - lis r3,0x2000 /* Ku = 1, VSID = 0 */ - li r4,0 -3: mtsrin r3,r4 - addi r3,r3,0x111 /* increment VSID */ - addis r4,r4,0x1000 /* address of next segment */ - bdnz 3b - - /* Restore the remaining bits of the HID0 register. */ - subi r1,r1,SL_PC - lwz r3,SL_HID0(r1) - sync - isync - mtspr HID0,r3 - sync - isync - - /* Restore 7400/7410/7450 specific registers */ - mfspr r3,PVR - srwi r3,r3,16 - cmpli cr0,r3,0x8000 - cmpli cr1,r3,0x000c - cmpli cr2,r3,0x800c - cror 4*cr1+eq,4*cr1+eq,4*cr2+eq - cror 4*cr0+eq,4*cr0+eq,4*cr1+eq - bne 1f - lwz r4,SL_MSSCR0(r1) - sync - mtspr SPRN_MSSCR0,r4 - sync - isync - lwz r4,SL_MSSSR0(r1) - sync - mtspr SPRN_MSSSR0,r4 - sync - isync - bne cr2,1f - li r4,0 - mtspr SPRN_L2CR2,r4 - /* Restore 7450 specific registers */ - beq cr1,1f - lwz r4,SL_HID1(r1) - sync - mtspr HID1,r4 - isync - sync - lwz r4,SPRN_ICTRL(r1) - sync - mtspr SPRN_ICTRL,r4 - isync - sync - lwz r4,SPRN_LDSTCR(r1) - sync - mtspr SPRN_LDSTCR,r4 - isync - sync - lwz r4,SL_LDSTDB(r1) - sync - mtspr SPRN_LDSTDB,r4 - isync - sync -1: - /* Restore the BATs, and SDR1. Then we can turn on the MMU. */ - lwz r4,SL_SDR1(r1) - mtsdr1 r4 - lwz r4,SL_SPRG0(r1) - mtsprg 0,r4 - lwz r4,SL_SPRG0+4(r1) - mtsprg 1,r4 - lwz r4,SL_SPRG0+8(r1) - mtsprg 2,r4 - lwz r4,SL_SPRG0+12(r1) - mtsprg 3,r4 - - lwz r4,SL_DBAT0(r1) - mtdbatu 0,r4 - lwz r4,SL_DBAT0+4(r1) - mtdbatl 0,r4 - lwz r4,SL_DBAT1(r1) - mtdbatu 1,r4 - lwz r4,SL_DBAT1+4(r1) - mtdbatl 1,r4 - lwz r4,SL_DBAT2(r1) - mtdbatu 2,r4 - lwz r4,SL_DBAT2+4(r1) - mtdbatl 2,r4 - lwz r4,SL_DBAT3(r1) - mtdbatu 3,r4 - lwz r4,SL_DBAT3+4(r1) - mtdbatl 3,r4 - lwz r4,SL_IBAT0(r1) - mtibatu 0,r4 - lwz r4,SL_IBAT0+4(r1) - mtibatl 0,r4 - lwz r4,SL_IBAT1(r1) - mtibatu 1,r4 - lwz r4,SL_IBAT1+4(r1) - mtibatl 1,r4 - lwz r4,SL_IBAT2(r1) - mtibatu 2,r4 - lwz r4,SL_IBAT2+4(r1) - mtibatl 2,r4 - lwz r4,SL_IBAT3(r1) - mtibatu 3,r4 - lwz r4,SL_IBAT3+4(r1) - mtibatl 3,r4 - - /* Flush all TLBs */ - lis r4,0x1000 -1: addic. r4,r4,-0x1000 - tlbie r4 - blt 1b - sync - - /* restore the MSR and turn on the MMU */ - lwz r3,SL_MSR(r1) - bl turn_on_mmu - - /* get back the stack pointer */ - tovirt(r1,r1) - - /* Restore TB */ - li r3,0 - mttbl r3 - lwz r3,SL_TB(r1) - lwz r4,SL_TB+4(r1) - mttbu r3 - mttbl r4 - - /* Restore the callee-saved registers and return */ - lwz r0,SL_CR(r1) - mtcr r0 - lwz r2,SL_R2(r1) - lmw r12,SL_R12(r1) - addi r1,r1,SL_SIZE - lwz r0,4(r1) - mtlr r0 - blr - -turn_on_mmu: - mflr r4 - tovirt(r4,r4) - mtsrr0 r4 - mtsrr1 r3 - sync - isync - rfi - - .data - .globl sleep_storage -sleep_storage: - .long 0 diff -Nru a/arch/ppc/platforms/spruce_setup.c b/arch/ppc/platforms/spruce_setup.c --- a/arch/ppc/platforms/spruce_setup.c Tue Feb 11 15:48:53 2003 +++ b/arch/ppc/platforms/spruce_setup.c Thu Mar 27 02:17:35 2003 @@ -133,8 +133,8 @@ #endif /* Identify the system */ - printk("System Identification: IBM Spruce\n"); - printk("IBM Spruce port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n"); + printk(KERN_INFO "System Identification: IBM Spruce\n"); + printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n"); } static void diff -Nru a/arch/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c --- a/arch/ppc/syslib/prom_init.c Thu Feb 13 18:50:29 2003 +++ b/arch/ppc/syslib/prom_init.c Thu Mar 27 02:19:22 2003 @@ -275,7 +275,7 @@ { phandle node; ihandle ih; - int i; + int i, j; char type[16], *path; static unsigned char default_colors[] = { 0x00, 0x00, 0x00, @@ -335,26 +335,23 @@ break; } -try_again: - /* - * Open the first display and set its colormap. - */ - if (prom_num_displays > 0) { - path = prom_display_paths[0]; + for (j=0; j 0) - prom_disp_node = prom_display_nodes[0]; - else + if (--prom_num_displays > 0) { + prom_disp_node = prom_display_nodes[j]; + j--; + } else prom_disp_node = NULL; - goto try_again; + continue; } else { prom_print("... ok\n"); /* @@ -369,7 +366,7 @@ break; #ifdef CONFIG_LOGO_LINUX_CLUT224 - clut = logo_linux_clut224.clut; + clut = PTRRELOC(logo_linux_clut224.clut); for (i = 0; i < logo_linux_clut224.clutsize; i++, clut += 3) if (prom_set_color(ih, i + 32, clut[0], diff -Nru a/arch/ppc64/Makefile b/arch/ppc64/Makefile --- a/arch/ppc64/Makefile Sat Mar 15 21:52:29 2003 +++ b/arch/ppc64/Makefile Thu Mar 20 13:46:10 2003 @@ -13,10 +13,10 @@ # Adjusted for PPC64 by Tom Gall # -KERNELLOAD = 0xc000000000000000 +KERNELLOAD := 0xc000000000000000 LDFLAGS := -m elf64ppc -LDFLAGS_vmlinux = -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD) +LDFLAGS_vmlinux := -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD) LDFLAGS_BLOB := --format binary --oformat elf64-powerpc CFLAGS += -msoft-float -pipe -Wno-uninitialized -mminimal-toc \ -mtraceback=full -mcpu=power4 @@ -29,21 +29,19 @@ core-$(CONFIG_XMON) += arch/ppc64/xmon/ drivers-$(CONFIG_OPROFILE) += arch/ppc64/oprofile/ -makeboot =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/ppc64/boot $(1) +boot := arch/ppc64/boot boottarget-$(CONFIG_PPC_PSERIES) := zImage zImage.initrd boottarget-$(CONFIG_PPC_ISERIES) := vmlinux.sminitrd vmlinux.initrd vmlinux.sm $(boottarget-y): vmlinux - $(call makeboot,arch/ppc64/boot/$@) + $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ %_config: arch/ppc64/configs/%_defconfig rm -f .config arch/ppc64/defconfig cp -f arch/ppc64/configs/$(@:config=defconfig) arch/ppc64/defconfig archclean: - $(Q)$(MAKE) -f scripts/Makefile.clean obj=arch/ppc64/boot - -archmrproper: + $(Q)$(MAKE) $(clean)=$(boot) prepare: include/asm-ppc64/offsets.h diff -Nru a/arch/ppc64/boot/Makefile b/arch/ppc64/boot/Makefile --- a/arch/ppc64/boot/Makefile Sun Mar 9 14:15:54 2003 +++ b/arch/ppc64/boot/Makefile Thu Mar 20 13:46:10 2003 @@ -79,7 +79,7 @@ $(obj)/vmlinux.sminitrd: $(obj)/vmlinux.sm $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE $(call if_changed,ramdisk) -$(obj)/sysmap.o: System.map $(obj)/piggyback +$(obj)/sysmap.o: System.map $(obj)/piggyback FORCE $(call if_changed,piggy) addsection = $(BOOTOBJCOPY) $(1) \ @@ -92,7 +92,7 @@ quiet_cmd_piggy = PIGGY $@ cmd_piggy = $(obj)/piggyback $(@:.o=) < $< | $(BOOTAS) -o $@ -$(call gz-sec, $(required)): $(obj)/kernel-%.gz: % +$(call gz-sec, $(required)): $(obj)/kernel-%.gz: % FORCE $(call if_changed,gzip) $(obj)/kernel-initrd.gz: $(obj)/ramdisk.image.gz @@ -101,7 +101,7 @@ $(call src-sec, $(required) $(initrd)): $(obj)/kernel-%.c: $(obj)/kernel-%.gz touch $@ -$(call obj-sec, $(required) $(initrd)): $(obj)/kernel-%.o: $(obj)/kernel-%.c +$(call obj-sec, $(required) $(initrd)): $(obj)/kernel-%.o: $(obj)/kernel-%.c FORCE $(call if_changed_dep,bootcc) $(call addsection, $@) diff -Nru a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c --- a/arch/ppc64/kernel/chrp_setup.c Tue Mar 4 09:23:43 2003 +++ b/arch/ppc64/kernel/chrp_setup.c Mon Mar 24 16:01:56 2003 @@ -71,9 +71,6 @@ extern void init_ras_IRQ(void); extern void find_and_init_phbs(void); -extern void pSeries_pcibios_fixup(void); -extern void pSeries_pcibios_fixup_bus(struct pci_bus *bus); -extern void iSeries_pcibios_fixup(void); extern void pSeries_get_rtc_time(struct rtc_time *rtc_time); extern int pSeries_set_rtc_time(struct rtc_time *rtc_time); @@ -201,7 +198,6 @@ hpte_init_pSeries(); tce_init_pSeries(); - pSeries_pcibios_init_early(); #ifdef CONFIG_SMP smp_init_pSeries(); @@ -243,15 +239,6 @@ ppc_md.get_irq = xics_get_irq; } ppc_md.init_ras_IRQ = init_ras_IRQ; - - #ifndef CONFIG_PPC_ISERIES - ppc_md.pcibios_fixup = pSeries_pcibios_fixup; - ppc_md.pcibios_fixup_bus = pSeries_pcibios_fixup_bus; - #else - ppc_md.pcibios_fixup = NULL; - // ppc_md.pcibios_fixup = iSeries_pcibios_fixup; - #endif - ppc_md.init = chrp_init2; diff -Nru a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c --- a/arch/ppc64/kernel/iSeries_pci.c Sat Dec 7 20:23:44 2002 +++ b/arch/ppc64/kernel/iSeries_pci.c Mon Mar 24 16:01:56 2003 @@ -84,8 +84,6 @@ struct iSeries_Device_Node* get_Device_Node(struct pci_dev* PciDev); unsigned long find_and_init_phbs(void); -void fixup_resources(struct pci_dev *dev); -void iSeries_pcibios_fixup(void); struct pci_controller* alloc_phb(struct device_node *dev, char *model, unsigned int addr_size_words) ; void iSeries_Scan_PHBs_Slots(struct pci_controller* Phb); @@ -275,7 +273,7 @@ return 0; } /*********************************************************************** - * ppc64_pcibios_init + * iSeries_pcibios_init * * Chance to initialize and structures or variable before PCI Bus walk. * @@ -302,9 +300,9 @@ PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_init Exit.\n"); } /*********************************************************************** - * iSeries_pcibios_fixup(void) + * pcibios_final_fixup(void) ***********************************************************************/ -void __init iSeries_pcibios_fixup(void) +void __init pcibios_final_fixup(void) { struct pci_dev* PciDev; struct iSeries_Device_Node* DeviceNode; @@ -328,8 +326,6 @@ iSeries_allocateDeviceBars(PciDev); - PPCDBGCALL(PPCDBG_BUSWALK,dumpPci_Dev(PciDev) ); - iSeries_Device_Information(PciDev,Buffer, sizeof(Buffer) ); printk("%d. %s\n",DeviceCount,Buffer); @@ -345,11 +341,7 @@ mf_displaySrc(0xC9000200); } -/*********************************************************************** - * iSeries_pcibios_fixup_bus(int Bus) - * - ***********************************************************************/ -void iSeries_pcibios_fixup_bus(struct pci_bus* PciBus) +void pcibios_fixup_bus(struct pci_bus* PciBus) { PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_fixup_bus(0x%04X) Entry.\n",PciBus->number); @@ -357,12 +349,12 @@ /*********************************************************************** - * fixup_resources(struct pci_dev *dev) + * pcibios_fixup_resources(struct pci_dev *dev) * ***********************************************************************/ -void fixup_resources(struct pci_dev *PciDev) +void pcibios_fixup_resources(struct pci_dev *PciDev) { - PPCDBG(PPCDBG_BUSWALK,"fixup_resources PciDev %p\n",PciDev); + PPCDBG(PPCDBG_BUSWALK,"pcibios_fixup_resources PciDev %p\n",PciDev); } @@ -910,18 +902,3 @@ } while (CheckReturnCode("WWL",DevNode, Return.rc) != 0); if(Pci_Trace_Flag == 1) PCIFR("WWL: IoAddress 0x%p = 0x%08X",IoAddress, Data); } -/* - * This is called very early before the page table is setup. - * There are warnings here because of type mismatches.. Okay for now. AHT - */ -void -iSeries_pcibios_init_early(void) -{ - //ppc_md.pcibios_read_config_byte = iSeries_Node_read_config_byte; - //ppc_md.pcibios_read_config_word = iSeries_Node_read_config_word; - //ppc_md.pcibios_read_config_dword = iSeries_Node_read_config_dword; - //ppc_md.pcibios_write_config_byte = iSeries_Node_write_config_byte; - //ppc_md.pcibios_write_config_word = iSeries_Node_write_config_word; - //ppc_md.pcibios_write_config_dword = iSeries_Node_write_config_dword; -} - diff -Nru a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c --- a/arch/ppc64/kernel/iSeries_setup.c Sun Sep 15 20:25:22 2002 +++ b/arch/ppc64/kernel/iSeries_setup.c Mon Mar 24 16:01:56 2003 @@ -62,8 +62,6 @@ pte_t * ptep, unsigned hpteflags, unsigned bolted ); extern void ppcdbg_initialize(void); extern void iSeries_pcibios_init(void); -extern void iSeries_pcibios_fixup(void); -extern void iSeries_pcibios_fixup_bus(int); static void iSeries_setup_dprofile(void); /* Global Variables */ @@ -316,9 +314,6 @@ ppc_md.init_ras_IRQ = NULL; ppc_md.get_irq = iSeries_get_irq; ppc_md.init = NULL; - - ppc_md.pcibios_fixup = iSeries_pcibios_fixup; - ppc_md.pcibios_fixup_bus = iSeries_pcibios_fixup_bus; ppc_md.restart = iSeries_restart; ppc_md.power_off = iSeries_power_off; diff -Nru a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c --- a/arch/ppc64/kernel/pSeries_lpar.c Tue Feb 25 02:42:30 2003 +++ b/arch/ppc64/kernel/pSeries_lpar.c Mon Mar 24 16:01:56 2003 @@ -320,7 +320,6 @@ #ifdef CONFIG_SMP smp_init_pSeries(); #endif - pSeries_pcibios_init_early(); /* The keyboard is not useful in the LPAR environment. * Leave all the interfaces NULL. diff -Nru a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c --- a/arch/ppc64/kernel/pSeries_pci.c Tue Mar 4 09:37:25 2003 +++ b/arch/ppc64/kernel/pSeries_pci.c Mon Mar 24 16:01:56 2003 @@ -2,6 +2,7 @@ * pSeries_pci.c * * Copyright (C) 2001 Dave Engebretsen, IBM Corporation + * Copyright (C) 2003 Anton Blanchard , IBM * * pSeries specific routines for PCI. * @@ -51,6 +52,8 @@ static int s7a_workaround; +extern unsigned long pci_probe_only; + static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val) { unsigned long returnval = ~0L; @@ -371,9 +374,6 @@ phb->last_busno += (phb->global_number << 8); } - /* Dump PHB information for Debug */ - PPCDBGCALL(PPCDBG_PHBINIT, dumpPci_Controller(phb)); - return phb; } @@ -423,129 +423,96 @@ return 0; } -void -fixup_resources(struct pci_dev *dev) +void pcibios_name_device(struct pci_dev *dev) { - int i; - struct pci_controller *phb = PCI_GET_PHB_PTR(dev); struct device_node *dn; - /* Add IBM loc code (slot) as a prefix to the device names for service */ + /* + * Add IBM loc code (slot) as a prefix to the device names for service + */ dn = pci_device_to_OF_node(dev); if (dn) { char *loc_code = get_property(dn, "ibm,loc-code", 0); if (loc_code) { int loc_len = strlen(loc_code); if (loc_len < sizeof(dev->dev.name)) { - memmove(dev->dev.name+loc_len+1, dev->dev.name, sizeof(dev->dev.name)-loc_len-1); + memmove(dev->dev.name+loc_len+1, dev->dev.name, + sizeof(dev->dev.name)-loc_len-1); memcpy(dev->dev.name, loc_code, loc_len); dev->dev.name[loc_len] = ' '; dev->dev.name[sizeof(dev->dev.name)-1] = '\0'; } } } +} - PPCDBG(PPCDBG_PHBINIT, "fixup_resources:\n"); - PPCDBG(PPCDBG_PHBINIT, "\tphb = 0x%016LX\n", phb); - PPCDBG(PPCDBG_PHBINIT, "\tphb->pci_io_offset = 0x%016LX\n", phb->pci_io_offset); - PPCDBG(PPCDBG_PHBINIT, "\tphb->pci_mem_offset = 0x%016LX\n", phb->pci_mem_offset); - - PPCDBG(PPCDBG_PHBINIT, "\tdev->dev.name = %s\n", dev->dev.name); - PPCDBG(PPCDBG_PHBINIT, "\tdev->vendor:device = 0x%04X : 0x%04X\n", dev->vendor, dev->device); - - if (phb == NULL) - return; - - for (i = 0; i < DEVICE_COUNT_RESOURCE; ++i) { - PPCDBG(PPCDBG_PHBINIT, "\tdevice %x.%x[%d] (flags %x) [%lx..%lx]\n", - dev->bus->number, dev->devfn, i, - dev->resource[i].flags, - dev->resource[i].start, - dev->resource[i].end); - - if ((dev->resource[i].start == 0) && (dev->resource[i].end == 0)) { - continue; - } - if (dev->resource[i].start > dev->resource[i].end) { - /* Bogus resource. Just clear it out. */ - dev->resource[i].start = dev->resource[i].end = 0; - continue; - } +void __init pcibios_fixup_device_resources(struct pci_dev *dev, + struct pci_bus *bus) +{ + /* Update device resources. */ + struct pci_controller *hose = PCI_GET_PHB_PTR(bus); + int i; + for (i = 0; i < PCI_NUM_RESOURCES; i++) { if (dev->resource[i].flags & IORESOURCE_IO) { - unsigned long offset = (unsigned long)phb->io_base_virt - pci_io_base; + unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base; dev->resource[i].start += offset; dev->resource[i].end += offset; - PPCDBG(PPCDBG_PHBINIT, "\t\t-> now [%lx .. %lx]\n", - dev->resource[i].start, dev->resource[i].end); - } else if (dev->resource[i].flags & IORESOURCE_MEM) { - if (dev->resource[i].start == 0) { - /* Bogus. Probably an unused bridge. */ - dev->resource[i].end = 0; - } else { - dev->resource[i].start += phb->pci_mem_offset; - dev->resource[i].end += phb->pci_mem_offset; - } - PPCDBG(PPCDBG_PHBINIT, "\t\t-> now [%lx..%lx]\n", - dev->resource[i].start, dev->resource[i].end); - - } else { - continue; } + else if (dev->resource[i].flags & IORESOURCE_MEM) { + dev->resource[i].start += hose->pci_mem_offset; + dev->resource[i].end += hose->pci_mem_offset; + } + } +} - /* zap the 2nd function of the winbond chip */ - if (dev->resource[i].flags & IORESOURCE_IO - && dev->bus->number == 0 && dev->devfn == 0x81) - dev->resource[i].flags &= ~IORESOURCE_IO; - } -} - -void __init pSeries_pcibios_fixup_bus(struct pci_bus *bus) +void __init pcibios_fixup_bus(struct pci_bus *bus) { - struct pci_controller *phb = PCI_GET_PHB_PTR(bus); + struct pci_controller *hose = PCI_GET_PHB_PTR(bus); + struct list_head *ln; + + /* XXX or bus->parent? */ + struct pci_dev *dev = bus->self; struct resource *res; int i; - if (bus->parent == NULL) { - /* This is a host bridge - fill in its resources */ - phb->bus = bus; - bus->resource[0] = res = &phb->io_resource; + if (!dev) { + /* Root bus. */ + + hose->bus = bus; + bus->resource[0] = res = &hose->io_resource; if (!res->flags) BUG(); /* No I/O resource for this PHB? */ + if (request_resource(&ioport_resource, res)) + printk(KERN_ERR "Failed to request IO" + "on hose %d\n", 0 /* FIXME */); + for (i = 0; i < 3; ++i) { - res = &phb->mem_resources[i]; - if (!res->flags) { - if (i == 0) - BUG(); /* No memory resource for this PHB? */ - } + res = &hose->mem_resources[i]; + if (!res->flags && i == 0) + BUG(); /* No memory resource for this PHB? */ bus->resource[i+1] = res; + if (res->flags && request_resource(&iomem_resource, res)) + printk(KERN_ERR "Failed to request MEM" + "on hose %d\n", 0 /* FIXME */); } - } else { + } else if (pci_probe_only && + (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { /* This is a subordinate bridge */ + pci_read_bridge_bases(bus); + pcibios_fixup_device_resources(dev, bus); + } - for (i = 0; i < 4; ++i) { - if ((res = bus->resource[i]) == NULL) - continue; - if (!res->flags) - continue; - if (res == pci_find_parent_resource(bus->self, res)) { - /* Transparent resource -- don't try to "fix" it. */ - continue; - } - if (res->flags & IORESOURCE_IO) { - unsigned long offset = (unsigned long)phb->io_base_virt - pci_io_base; - res->start += offset; - res->end += offset; - } else if (phb->pci_mem_offset - && (res->flags & IORESOURCE_MEM)) { - if (res->start < phb->pci_mem_offset) { - res->start += phb->pci_mem_offset; - res->end += phb->pci_mem_offset; - } - } - } + /* XXX Need to check why Alpha doesnt do this - Anton */ + if (!pci_probe_only) + return; + + for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) { + struct pci_dev *dev = pci_dev_b(ln); + if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) + pcibios_fixup_device_resources(dev, bus); } } @@ -562,19 +529,20 @@ } } -void __init -pSeries_pcibios_fixup(void) +extern void chrp_request_regions(void); + +void __init pcibios_final_fixup(void) { struct pci_dev *dev; - PPCDBG(PPCDBG_PHBINIT, "pSeries_pcibios_fixup: start\n"); - check_s7a(); - - pci_for_each_dev(dev) { + + pci_for_each_dev(dev) pci_read_irq_line(dev); - PPCDBGCALL(PPCDBG_PHBINIT, dumpPci_Dev(dev) ); - } + + chrp_request_regions(); + pci_fix_bus_sysdata(); + create_tce_tables(); } /*********************************************************************** @@ -595,14 +563,4 @@ node=node->parent; } return NULL; -} - -/* - * This is called very early before the page table is setup. - */ -void -pSeries_pcibios_init_early(void) -{ - ppc_md.pcibios_read_config = rtas_read_config; - ppc_md.pcibios_write_config = rtas_write_config; } diff -Nru a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c --- a/arch/ppc64/kernel/pci.c Sun Mar 16 14:16:32 2003 +++ b/arch/ppc64/kernel/pci.c Mon Mar 24 19:22:52 2003 @@ -2,6 +2,9 @@ * Port for PPC64 David Engebretsen, IBM Corp. * Contains common pci routines for ppc64 platform, pSeries and iSeries brands. * + * Copyright (C) 2003 Anton Blanchard , IBM + * Rework, based on alpha PCI code. + * * 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 @@ -30,31 +33,37 @@ #include #include #include -#include #include "pci.h" +unsigned long pci_probe_only = 1; +unsigned long pci_assign_all_buses = 0; + +unsigned int pcibios_assign_all_busses(void) +{ + return pci_assign_all_buses; +} + /* pci_io_base -- the base address from which io bars are offsets. * This is the lowest I/O base address (so bar values are always positive), * and it *must* be the start of ISA space if an ISA bus exists because * ISA drivers use hard coded offsets. If no ISA bus exists a dummy * page is mapped and isa_io_limit prevents access to it. */ -unsigned long isa_io_base = 0; /* NULL if no ISA bus */ -unsigned long pci_io_base = 0; +unsigned long isa_io_base; /* NULL if no ISA bus */ +unsigned long pci_io_base; -static void pcibios_fixup_resources(struct pci_dev* dev); +void pcibios_name_device(struct pci_dev* dev); +void pcibios_final_fixup(void); static void fixup_broken_pcnet32(struct pci_dev* dev); static void fixup_windbond_82c105(struct pci_dev* dev); -void fixup_resources(struct pci_dev* dev); -void iSeries_pcibios_init(void); +void iSeries_pcibios_init(void); -struct pci_controller* hose_head; -struct pci_controller** hose_tail = &hose_head; +struct pci_controller *hose_head; +struct pci_controller **hose_tail = &hose_head; -int global_phb_number = 0; /* Global phb counter */ -struct pci_controller *phbtab[PCI_MAX_PHB]; +int global_phb_number; /* Global phb counter */ /* Cached ISA bridge dev. */ struct pci_dev *ppc64_isabridge_dev = NULL; @@ -62,8 +71,8 @@ struct pci_fixup pcibios_fixups[] = { { PCI_FIXUP_HEADER, PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32 }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, fixup_windbond_82c105 }, - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources }, - { 0 } + { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device }, + { 0 } }; static void fixup_broken_pcnet32(struct pci_dev* dev) @@ -81,14 +90,21 @@ * p610. We should probably be more careful in case * someone tries to plug in a similar adapter. */ + int i; unsigned int reg; printk("Using INTC for W82c105 IDE controller.\n"); pci_read_config_dword(dev, 0x40, ®); /* Enable LEGIRQ to use INTC instead of ISA interrupts */ pci_write_config_dword(dev, 0x40, reg | (1<<11)); -} + for (i = 0; i < DEVICE_COUNT_RESOURCE; ++i) { + /* zap the 2nd function of the winbond chip */ + if (dev->resource[i].flags & IORESOURCE_IO + && dev->bus->number == 0 && dev->devfn == 0x81) + dev->resource[i].flags &= ~IORESOURCE_IO; + } +} /* Given an mmio phys address, find a pci device that implements * this address. This is of course expensive, but only used @@ -127,12 +143,30 @@ return NULL; } -static void -pcibios_fixup_resources(struct pci_dev* dev) +void __devinit +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, + struct resource *res) { - fixup_resources(dev); + unsigned long offset = 0; + struct pci_controller *hose = PCI_GET_PHB_PTR(dev); + + if (!hose) + return; + + if (res->flags & IORESOURCE_IO) + offset = (unsigned long)hose->io_base_virt - pci_io_base; + + if (res->flags & IORESOURCE_MEM) + offset = hose->pci_mem_offset; + + region->start = res->start - offset; + region->end = res->end - offset; } +#ifdef CONFIG_HOTPLUG +EXPORT_SYMBOL(pcibios_resource_to_bus); +#endif + /* * We need to avoid collisions with `mirrored' VGA ports * and other strange ISA hardware, so we always want the @@ -146,180 +180,38 @@ * but we want to try to avoid allocating at 0x2900-0x2bff * which might have be mirrored at 0x0100-0x03ff.. */ -void -pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size, unsigned long align) { struct pci_dev *dev = data; + struct pci_controller *hose = PCI_GET_PHB_PTR(dev); + unsigned long start = res->start; + unsigned long alignto; if (res->flags & IORESOURCE_IO) { - unsigned long start = res->start; - - if (size > 0x100) { - printk(KERN_ERR "PCI: Can not align I/O Region %s %s because size %ld is too large.\n", - dev->slot_name, res->name, size); - } - - if (start & 0x300) { + unsigned long offset = (unsigned long)hose->io_base_virt - + pci_io_base; + /* Make sure we start at our min on all hoses */ + if (start - offset < PCIBIOS_MIN_IO) + start = PCIBIOS_MIN_IO + offset; + + /* + * Put everything into 0x00-0xff region modulo 0x400 + */ + if (start & 0x300) start = (start + 0x3ff) & ~0x3ff; - res->start = start; - } - } -} -/* - * Handle resources of PCI devices. If the world were perfect, we could - * just allocate all the resource regions and do nothing more. It isn't. - * On the other hand, we cannot just re-allocate all devices, as it would - * require us to know lots of host bridge internals. So we attempt to - * keep as much of the original configuration as possible, but tweak it - * when it's found to be wrong. - * - * Known BIOS problems we have to work around: - * - I/O or memory regions not configured - * - regions configured, but not enabled in the command register - * - bogus I/O addresses above 64K used - * - expansion ROMs left enabled (this may sound harmless, but given - * the fact the PCI specs explicitly allow address decoders to be - * shared between expansion ROMs and other resource regions, it's - * at least dangerous) - * - * Our solution: - * (1) Allocate resources for all buses behind PCI-to-PCI bridges. - * This gives us fixed barriers on where we can allocate. - * (2) Allocate resources for all enabled devices. If there is - * a collision, just mark the resource as unallocated. Also - * disable expansion ROMs during this step. - * (3) Try to allocate resources for disabled devices. If the - * resources were assigned correctly, everything goes well, - * if they weren't, they won't disturb allocation of other - * resources. - * (4) Assign new addresses to resources which were either - * not configured at all or misconfigured. If explicitly - * requested by the user, configure expansion ROM address - * as well. - */ + } else if (res->flags & IORESOURCE_MEM) { + /* Make sure we start at our min on all hoses */ + if (start - hose->pci_mem_offset < PCIBIOS_MIN_MEM) + start = PCIBIOS_MIN_MEM + hose->pci_mem_offset; -static void __init -pcibios_allocate_bus_resources(struct list_head *bus_list) -{ - struct list_head *ln; - struct pci_bus *bus; - int i; - struct resource *res, *pr; - - /* Depth-First Search on bus tree */ - for (ln=bus_list->next; ln != bus_list; ln=ln->next) { - bus = pci_bus_b(ln); - for (i = 0; i < 4; ++i) { - if ((res = bus->resource[i]) == NULL || !res->flags) - continue; - if (bus->parent == NULL) - pr = (res->flags & IORESOURCE_IO)? - &ioport_resource: &iomem_resource; - else - pr = pci_find_parent_resource(bus->self, res); - - if (pr == res) - continue; /* transparent bus or undefined */ - if (pr && request_resource(pr, res) == 0) - continue; - printk(KERN_ERR "PCI: Cannot allocate resource region " - "%d of PCI bridge %x\n", i, bus->number); - printk(KERN_ERR "PCI: resource is %lx..%lx (%lx), parent %p\n", - res->start, res->end, res->flags, pr); - } - pcibios_allocate_bus_resources(&bus->children); + /* Align to multiple of size of minimum base. */ + alignto = max(0x1000UL, align); + start = ALIGN(start, alignto); } -} - -static void __init -pcibios_allocate_resources(int pass) -{ - struct pci_dev *dev; - int idx, disabled; - u16 command; - struct resource *r, *pr; - pci_for_each_dev(dev) { - pci_read_config_word(dev, PCI_COMMAND, &command); - for(idx = 0; idx < 6; idx++) { - r = &dev->resource[idx]; - if (r->parent) /* Already allocated */ - continue; - if (!r->start) /* Address not assigned at all */ - continue; - - if (r->flags & IORESOURCE_IO) - disabled = !(command & PCI_COMMAND_IO); - else - disabled = !(command & PCI_COMMAND_MEMORY); - if (pass == disabled) { - PPCDBG(PPCDBG_PHBINIT, - "PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n", - r->start, r->end, r->flags, disabled, pass); - pr = pci_find_parent_resource(dev, r); - if (!pr || request_resource(pr, r) < 0) { - PPCDBG(PPCDBG_PHBINIT, - "PCI: Cannot allocate resource region %d of device %s, pr = 0x%lx\n", idx, dev->slot_name, pr); - if(pr) { - PPCDBG(PPCDBG_PHBINIT, - "PCI: Cannot allocate resource 0x%lx\n", request_resource(pr,r)); - } - /* We'll assign a new address later */ - r->end -= r->start; - r->start = 0; - } - } - } - if (!pass) { - r = &dev->resource[PCI_ROM_RESOURCE]; - if (r->flags & PCI_ROM_ADDRESS_ENABLE) { - /* Turn the ROM off, leave the resource region, but keep it unregistered. */ - u32 reg; - r->flags &= ~PCI_ROM_ADDRESS_ENABLE; - pci_read_config_dword(dev, dev->rom_base_reg, ®); - pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE); - } - } - } -} - -static void __init -pcibios_assign_resources(void) -{ - struct pci_dev *dev; - int idx; - struct resource *r; - - pci_for_each_dev(dev) { - int class = dev->class >> 8; - - /* Don't touch classless devices and host bridges */ - if (!class || class == PCI_CLASS_BRIDGE_HOST) - continue; - - for (idx = 0; idx < 6; idx++) { - r = &dev->resource[idx]; - - /* - * We shall assign a new address to this resource, - * either because the BIOS (sic) forgot to do so - * or because we have decided the old address was - * unusable for some reason. - */ - if (!r->start && r->end) - pci_assign_resource(dev, idx); - } - -#if 0 /* don't assign ROMs */ - r = &dev->resource[PCI_ROM_RESOURCE]; - r->end -= r->start; - r->start = 0; - if (r->end) - pci_assign_resource(dev, PCI_ROM_RESOURCE); -#endif - } + res->start = start; } /* @@ -358,20 +250,49 @@ else memcpy(hose->what,model,7); hose->type = controller_type; - hose->global_number = global_phb_number; - phbtab[global_phb_number++] = hose; + hose->global_number = global_phb_number++; *hose_tail = hose; hose_tail = &hose->next; return hose; } -static int __init -pcibios_init(void) +static void __init pcibios_claim_one_bus(struct pci_bus *b) +{ + struct list_head *ld; + struct pci_bus *child_bus; + + for (ld = b->devices.next; ld != &b->devices; ld = ld->next) { + struct pci_dev *dev = pci_dev_b(ld); + int i; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + struct resource *r = &dev->resource[i]; + + if (r->parent || !r->start || !r->flags) + continue; + pci_claim_resource(dev, i); + } + } + + list_for_each_entry(child_bus, &b->children, node) + pcibios_claim_one_bus(child_bus); +} + +static void __init pcibios_claim_of_setup(void) +{ + struct list_head *lb; + + for (lb = pci_root_buses.next; lb != &pci_root_buses; lb = lb->next) { + struct pci_bus *b = pci_bus_b(lb); + pcibios_claim_one_bus(b); + } +} + +static int __init pcibios_init(void) { struct pci_controller *hose; struct pci_bus *bus; - int next_busno; #ifdef CONFIG_PPC_ISERIES iSeries_pcibios_init(); @@ -379,38 +300,26 @@ //ppc64_boot_msg(0x40, "PCI Probe"); printk("PCI: Probing PCI hardware\n"); - PPCDBG(PPCDBG_BUSWALK,"PCI: Probing PCI hardware\n"); /* Scan all of the recorded PCI controllers. */ - for (next_busno = 0, hose = hose_head; hose; hose = hose->next) { + for (hose = hose_head; hose; hose = hose->next) { hose->last_busno = 0xff; - bus = pci_scan_bus(hose->first_busno, hose->ops, hose->arch_data); + bus = pci_scan_bus(hose->first_busno, hose->ops, + hose->arch_data); hose->bus = bus; hose->last_busno = bus->subordinate; - if (next_busno <= hose->last_busno) - next_busno = hose->last_busno+1; } - /* Call machine dependent fixup */ - if (ppc_md.pcibios_fixup) { - ppc_md.pcibios_fixup(); - } - - /* Allocate and assign resources */ - pcibios_allocate_bus_resources(&pci_root_buses); - pcibios_allocate_resources(0); - pcibios_allocate_resources(1); - pcibios_assign_resources(); - -#ifndef CONFIG_PPC_ISERIES - void chrp_request_regions(void); - chrp_request_regions(); + if (pci_probe_only) + pcibios_claim_of_setup(); + else + /* FIXME: `else' will be removed when + pci_assign_unassigned_resources() is able to work + correctly with [partially] allocated PCI tree. */ + pci_assign_unassigned_resources(); - pci_fix_bus_sysdata(); - - create_tce_tables(); - PPCDBG(PPCDBG_BUSWALK,"pSeries create_tce_tables()\n"); -#endif + /* Call machine dependent fixup */ + pcibios_final_fixup(); /* Cache the location of the ISA bridge (if we have one) */ ppc64_isabridge_dev = pci_find_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); @@ -418,7 +327,6 @@ printk("ISA bridge at %s\n", ppc64_isabridge_dev->slot_name); printk("PCI: Probing PCI hardware done\n"); - PPCDBG(PPCDBG_BUSWALK,"PCI: Probing PCI hardware done.\n"); //ppc64_boot_msg(0x41, "PCI Done"); return 0; @@ -426,12 +334,6 @@ subsys_initcall(pcibios_init); -void __init pcibios_fixup_bus(struct pci_bus *bus) -{ - if (ppc_md.pcibios_fixup_bus) - ppc_md.pcibios_fixup_bus(bus); -} - char __init *pcibios_setup(char *str) { return str; @@ -439,35 +341,29 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) { - u16 cmd, old_cmd; - int idx; - struct resource *r; - - PPCDBG(PPCDBG_BUSWALK,"PCI: %s for device %s \n", __FUNCTION__, - dev->slot_name); + u16 cmd, oldcmd; + int i; pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for (idx = 0; idx < 6; idx++) { + oldcmd = cmd; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + struct resource *res = &dev->resource[i]; + /* Only set up the requested stuff */ - if (!(mask & (1<resource[idx]; - if (!r->start && r->end) { - printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) + if (res->flags & IORESOURCE_IO) cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) + if (res->flags & IORESOURCE_MEM) cmd |= PCI_COMMAND_MEMORY; } - if (cmd != old_cmd) { - printk("PCI: Enabling device %s (%04x -> %04x)\n", - dev->slot_name, old_cmd, cmd); - PPCDBG(PPCDBG_BUSWALK,"PCI: Enabling device %s \n", - dev->slot_name); + + if (cmd != oldcmd) { + printk(KERN_DEBUG "PCI: Enabling device: (%s), cmd %x\n", + dev->slot_name, cmd); + /* Enable the appropriate bits in the PCI command register. */ pci_write_config_word(dev, PCI_COMMAND, cmd); } return 0; @@ -608,113 +504,4 @@ vma->vm_end - vma->vm_start, vma->vm_page_prot); return ret; -} - -/***************************************************** - * Dump Resource information - *****************************************************/ -void dumpResources(struct resource* Resource) -{ - if(Resource != NULL) { - int Flags = 0x00000F00 & Resource->flags; - if(Resource->start == 0 && Resource->end == 0) return; - else if(Resource->start == Resource->end ) return; - else { - if (Flags == IORESOURCE_IO) udbg_printf("IO.:"); - else if(Flags == IORESOURCE_MEM) udbg_printf("MEM:"); - else if(Flags == IORESOURCE_IRQ) udbg_printf("IRQ:"); - else udbg_printf("0x%02X:",Resource->flags); - - } - udbg_printf("0x%016LX / 0x%016LX (0x%08X)\n", - Resource->start, Resource->end, Resource->end - Resource->start); - } -} - -int resourceSize(struct resource* Resource) -{ - if(Resource->start == 0 && Resource->end == 0) return 0; - else if(Resource->start == Resource->end ) return 0; - else return (Resource->end-1)-Resource->start; -} - - -/***************************************************** - * Dump PHB information for Debug - *****************************************************/ -void dumpPci_Controller(struct pci_controller* phb) -{ - udbg_printf("\tpci_controller= 0x%016LX\n", phb); - if (phb != NULL) { - udbg_printf("\twhat & type = %s 0x%02X\n ",phb->what,phb->type); - udbg_printf("\tbus = "); - if (phb->bus != NULL) udbg_printf("0x%02X\n", phb->bus->number); - else udbg_printf("\n"); - udbg_printf("\tarch_data = 0x%016LX\n", phb->arch_data); - udbg_printf("\tfirst_busno = 0x%02X\n", phb->first_busno); - udbg_printf("\tlast_busno = 0x%02X\n", phb->last_busno); - udbg_printf("\tio_base_virt* = 0x%016LX\n", phb->io_base_virt); - udbg_printf("\tio_base_phys = 0x%016LX\n", phb->io_base_phys); - udbg_printf("\tpci_mem_offset= 0x%016LX\n", phb->pci_mem_offset); - udbg_printf("\tpci_io_offset = 0x%016LX\n", phb->pci_io_offset); - - udbg_printf("\tResources\n"); - dumpResources(&phb->io_resource); - if (phb->mem_resource_count > 0) dumpResources(&phb->mem_resources[0]); - if (phb->mem_resource_count > 1) dumpResources(&phb->mem_resources[1]); - if (phb->mem_resource_count > 2) dumpResources(&phb->mem_resources[2]); - - udbg_printf("\tglobal_num = 0x%02X\n", phb->global_number); - udbg_printf("\tlocal_num = 0x%02X\n", phb->local_number); - } -} - -/***************************************************** - * Dump PHB information for Debug - *****************************************************/ -void dumpPci_Bus(struct pci_bus* Pci_Bus) -{ - int i; - udbg_printf("\tpci_bus = 0x%016LX \n",Pci_Bus); - if (Pci_Bus != NULL) { - - udbg_printf("\tnumber = 0x%02X \n",Pci_Bus->number); - udbg_printf("\tprimary = 0x%02X \n",Pci_Bus->primary); - udbg_printf("\tsecondary = 0x%02X \n",Pci_Bus->secondary); - udbg_printf("\tsubordinate = 0x%02X \n",Pci_Bus->subordinate); - - for (i=0;i<4;++i) { - if(Pci_Bus->resource[i] == NULL) continue; - if(Pci_Bus->resource[i]->start == 0 && Pci_Bus->resource[i]->end == 0) break; - udbg_printf("\tResources[%d]",i); - dumpResources(Pci_Bus->resource[i]); - } - } -} - -/***************************************************** - * Dump Device information for Debug - *****************************************************/ -void dumpPci_Dev(struct pci_dev* Pci_Dev) -{ - int i; - udbg_printf("\tpci_dev* = 0x%p\n",Pci_Dev); - if ( Pci_Dev == NULL ) return; - udbg_printf("\tname = %s \n",Pci_Dev->dev.name); - udbg_printf("\tbus* = 0x%p\n",Pci_Dev->bus); - udbg_printf("\tsysdata* = 0x%p\n",Pci_Dev->sysdata); - udbg_printf("\tDevice = 0x%4X%02X:%02X.%02X 0x%04X:%04X\n", - PCI_GET_PHB_NUMBER(Pci_Dev), - PCI_GET_BUS_NUMBER(Pci_Dev), - PCI_SLOT(Pci_Dev->devfn), - PCI_FUNC(Pci_Dev->devfn), - Pci_Dev->vendor, - Pci_Dev->device); - udbg_printf("\tHdr/Irq = 0x%02X/0x%02X \n",Pci_Dev->hdr_type,Pci_Dev->irq); - for (i=0;iresource[i].start == 0 && Pci_Dev->resource[i].end == 0) continue; - udbg_printf("\tResources[%d] ",i); - dumpResources(&Pci_Dev->resource[i]); - } - dumpResources(&Pci_Dev->resource[i]); } diff -Nru a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h --- a/arch/ppc64/kernel/pci.h Mon Mar 3 22:12:45 2003 +++ b/arch/ppc64/kernel/pci.h Mon Mar 24 16:01:56 2003 @@ -19,18 +19,14 @@ extern struct pci_controller* hose_head; extern struct pci_controller** hose_tail; -/* PHB's are also in a table. */ -#define PCI_MAX_PHB 64 -extern int global_phb_number; -extern struct pci_controller *phbtab[]; + +extern int global_phb_number; /******************************************************************* * Platform functions that are brand specific implementation. *******************************************************************/ extern unsigned long find_and_init_phbs(void); -extern void ppc64_pcibios_init(void); - extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */ /******************************************************************* @@ -46,10 +42,6 @@ void pci_fix_bus_sysdata(void); struct device_node *fetch_dev_dn(struct pci_dev *dev); -void iSeries_pcibios_init_early(void); -void pSeries_pcibios_init_early(void); -void pSeries_pcibios_init(void); - /******************************************************************* * Helper macros for extracting data from pci structures. * PCI_GET_PHB_PTR(struct pci_dev*) returns the Phb pointer. @@ -59,13 +51,5 @@ #define PCI_GET_PHB_PTR(dev) (((struct device_node *)(dev)->sysdata)->phb) #define PCI_GET_PHB_NUMBER(dev) (((dev)->bus->number&0x00FFFF00)>>8) #define PCI_GET_BUS_NUMBER(dev) ((dev)->bus->number&0x0000FF) - -/******************************************************************* - * Debugging Routines. - *******************************************************************/ -extern void dumpResources(struct resource* Resource); -extern void dumpPci_Controller(struct pci_controller* phb); -extern void dumpPci_Bus(struct pci_bus* Pci_Bus); -extern void dumpPci_Dev(struct pci_dev* Pci_Dev); #endif /* __PPC_KERNEL_PCI_H__ */ diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c --- a/arch/ppc64/kernel/process.c Sat Feb 22 01:05:26 2003 +++ b/arch/ppc64/kernel/process.c Thu Mar 20 08:53:38 2003 @@ -208,6 +208,12 @@ } else { childregs->gpr[1] = usp; p->thread.regs = childregs; + if (clone_flags & CLONE_SETTLS) { + if (test_thread_flag(TIF_32BIT)) + childregs->gpr[2] = childregs->gpr[6]; + else + childregs->gpr[13] = childregs->gpr[6]; + } } childregs->gpr[3] = 0; /* Result from fork() */ sp -= STACK_FRAME_OVERHEAD; @@ -304,7 +310,7 @@ if (clone_flags & (CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) { parent_tidptr = p3; - child_tidptr = p4; + child_tidptr = p5; if (test_thread_flag(TIF_32BIT)) { parent_tidptr &= 0xffffffff; child_tidptr &= 0xffffffff; diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c --- a/arch/ppc64/kernel/prom.c Sun Mar 16 15:51:49 2003 +++ b/arch/ppc64/kernel/prom.c Mon Mar 24 17:04:39 2003 @@ -1270,8 +1270,8 @@ break; #ifdef CONFIG_LOGO_LINUX_CLUT224 - clut = RELOC(RELOC(&logo_linux_clut224)->clut); - for (i = 0; i < logo_linux_clut224.clutsize; i++, clut += 3) + clut = PTRRELOC(RELOC(logo_linux_clut224.clut)); + for (i = 0; i < RELOC(logo_linux_clut224.clutsize); i++, clut += 3) if (prom_set_color(ih, i + 32, clut[0], clut[1], clut[2]) != 0) break; diff -Nru a/arch/ppc64/kernel/stab.c b/arch/ppc64/kernel/stab.c --- a/arch/ppc64/kernel/stab.c Mon Sep 16 00:21:25 2002 +++ b/arch/ppc64/kernel/stab.c Mon Mar 24 21:09:32 2003 @@ -197,11 +197,23 @@ PMC_SW_PROCESSOR(stab_capacity_castouts); + /* + * Never cast out the segment for our kernel stack. Since we + * dont invalidate the ERAT we could have a valid translation + * for the kernel stack during the first part of exception exit + * which gets invalidated due to a tlbie from another cpu at a + * non recoverable point (after setting srr0/1) - Anton + */ castout_entry = get_paca()->xStab_data.next_round_robin; - entry = castout_entry; - castout_entry++; - if (castout_entry >= naca->slb_size) - castout_entry = 1; + do { + entry = castout_entry; + castout_entry++; + if (castout_entry >= naca->slb_size) + castout_entry = 1; + asm volatile("slbmfee %0,%1" : "=r" (esid_data) : "r" (entry)); + } while (esid_data.data.esid == GET_ESID((unsigned long)_get_SP()) && + esid_data.data.v); + get_paca()->xStab_data.next_round_robin = castout_entry; /* slbie not needed as the previous mapping is still valid. */ @@ -346,7 +358,12 @@ void flush_stab(struct task_struct *tsk, struct mm_struct *mm) { if (cpu_has_slb()) { - if (!STAB_PRESSURE && test_thread_flag(TIF_32BIT)) { + /* + * XXX disable 32bit slb invalidate optimisation until we fix + * the issue where a 32bit app execed out of a 64bit app can + * cause segments above 4GB not to be flushed - Anton + */ + if (0 && !STAB_PRESSURE && test_thread_flag(TIF_32BIT)) { union { unsigned long word0; slb_dword0 data; diff -Nru a/arch/sparc/Makefile b/arch/sparc/Makefile --- a/arch/sparc/Makefile Fri Mar 7 13:28:49 2003 +++ b/arch/sparc/Makefile Tue Mar 25 05:14:47 2003 @@ -54,13 +54,16 @@ LIBS_Y := $(patsubst %/, %/lib.a, $(libs-y)) export INIT_Y CORE_Y DRIVERS_Y NET_Y LIBS_Y HEAD_Y -makeboot =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/$(ARCH)/boot $(1) +# Default target +all: image + +boot := arch/sparc/boot image tftpboot.img: vmlinux - $(call makeboot,arch/sparc/boot/$@) + $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ archclean: - $(Q)$(MAKE) -f scripts/Makefile.clean obj=arch/$(ARCH)/boot + $(Q)$(MAKE) $(clean)=$(boot) prepare: include/asm-$(ARCH)/asm_offsets.h @@ -72,3 +75,9 @@ CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h \ arch/$(ARCH)/kernel/asm-offsets.s + +# Don't use tabs in echo arguments. +define archhelp + echo '* image - kernel image ($(boot)/image)' + echo ' tftpboot.img - image prepared for tftp' +endef diff -Nru a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile --- a/arch/sparc/boot/Makefile Sun Mar 9 13:47:41 2003 +++ b/arch/sparc/boot/Makefile Tue Mar 25 05:14:47 2003 @@ -32,7 +32,3 @@ $(obj)/btfix.s: $(obj)/btfixupprep vmlinux FORCE $(call if_changed,btfix) - -archhelp: - @echo '* image - kernel image ($(obj)/image)' - @echo ' tftpboot.img - image prepared for tftp' diff -Nru a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig --- a/arch/sparc64/Kconfig Sat Mar 8 14:50:37 2003 +++ b/arch/sparc64/Kconfig Wed Mar 26 02:27:26 2003 @@ -139,8 +139,8 @@ bool "CPU Frequency scaling" help Clock scaling allows you to change the clock speed of CPUs on the - fly. Currently there is only a sparc64 driver for UltraSPARC-III - processors. + fly. Currently there are only sparc64 drivers for UltraSPARC-III + and UltraSPARC-IIe processors. For details, take a look at linux/Documentation/cpufreq. @@ -161,6 +161,16 @@ depends on CPU_FREQ_TABLE help This adds the CPUFreq driver for UltraSPARC-III processors. + + For details, take a look at linux/Documentation/cpufreq. + + If in doubt, say N. + +config US2E_FREQ + tristate "UltraSPARC-IIe CPU Frequency driver" + depends on CPU_FREQ_TABLE + help + This adds the CPUFreq driver for UltraSPARC-IIe processors. For details, take a look at linux/Documentation/cpufreq. diff -Nru a/arch/sparc64/Makefile b/arch/sparc64/Makefile --- a/arch/sparc64/Makefile Sun Mar 23 00:38:52 2003 +++ b/arch/sparc64/Makefile Wed Mar 26 02:52:44 2003 @@ -71,10 +71,13 @@ # FIXME: is drivers- right? drivers-$(CONFIG_OPROFILE) += arch/sparc64/oprofile/ -makeboot = $(Q)$(MAKE) -f scripts/Makefile.build obj=arch/$(ARCH)/boot $(1) +boot := arch/sparc64/boot image tftpboot.img vmlinux.aout: vmlinux - $(call makeboot,arch/sparc64/boot/$@) + $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ + +archclean: + $(Q)$(MAKE) $(clean)=$(boot) define archhelp echo '* vmlinux - Standard sparc64 kernel' diff -Nru a/arch/sparc64/boot/Makefile b/arch/sparc64/boot/Makefile --- a/arch/sparc64/boot/Makefile Sun Mar 23 00:38:52 2003 +++ b/arch/sparc64/boot/Makefile Wed Mar 26 02:52:44 2003 @@ -8,7 +8,7 @@ ELFTOAOUT := elftoaout host-progs := piggyback -targets := tftpboot.img vmlinux.aout +targets := image tftpboot.img vmlinux.aout quiet_cmd_elftoaout = ELT2AOUT $@ cmd_elftoaout = $(ELFTOAOUT) vmlinux -o $@ diff -Nru a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile --- a/arch/sparc64/kernel/Makefile Sun Mar 9 14:15:54 2003 +++ b/arch/sparc64/kernel/Makefile Wed Mar 26 02:27:26 2003 @@ -21,6 +21,7 @@ obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o +obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o ifdef CONFIG_SUNOS_EMUL obj-y += sys_sunos32.o sunos_ioctl32.o diff -Nru a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c --- a/arch/sparc64/kernel/binfmt_elf32.c Wed Dec 4 11:05:20 2002 +++ b/arch/sparc64/kernel/binfmt_elf32.c Tue Mar 25 05:20:16 2003 @@ -152,7 +152,6 @@ #ifdef CONFIG_BINFMT_ELF32_MODULE #define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE #endif -#define ELF_FLAGS_INIT set_thread_flag(TIF_32BIT) MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit SparcLinux binaries on the Ultra"); MODULE_AUTHOR("Eric Youngdale, David S. Miller, Jakub Jelinek"); diff -Nru a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c --- a/arch/sparc64/kernel/devices.c Mon Aug 19 01:18:52 2002 +++ b/arch/sparc64/kernel/devices.c Wed Mar 26 00:49:46 2003 @@ -17,6 +17,7 @@ #include #include #include +#include /* Used to synchronize acceses to NatSemi SUPER I/O chip configure * operations in asm/ns87303.h @@ -88,7 +89,6 @@ #ifndef CONFIG_SMP { - extern unsigned long up_clock_tick; up_clock_tick = prom_getintdefault(prom_node_cpu, "clock-frequency", 0); diff -Nru a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c --- a/arch/sparc64/kernel/setup.c Tue Mar 4 04:05:17 2003 +++ b/arch/sparc64/kernel/setup.c Wed Mar 26 00:49:46 2003 @@ -44,6 +44,7 @@ #include #include #include +#include #ifdef CONFIG_IP_PNP #include diff -Nru a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c --- a/arch/sparc64/kernel/sparc64_ksyms.c Sun Mar 23 22:06:53 2003 +++ b/arch/sparc64/kernel/sparc64_ksyms.c Wed Mar 26 00:49:46 2003 @@ -55,6 +55,7 @@ #endif #include #include +#include struct poll { int fd; @@ -159,11 +160,7 @@ EXPORT_SYMBOL(smp_call_function); #endif /* CONFIG_SMP */ -/* Uniprocessor clock frequency */ -#ifndef CONFIG_SMP -extern unsigned long up_clock_tick; -EXPORT_SYMBOL(up_clock_tick); -#endif +EXPORT_SYMBOL(sparc64_get_clock_tick); /* semaphores */ EXPORT_SYMBOL(down); diff -Nru a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c --- a/arch/sparc64/kernel/time.c Tue Mar 18 18:04:20 2003 +++ b/arch/sparc64/kernel/time.c Wed Mar 26 00:49:46 2003 @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include @@ -988,6 +990,73 @@ return clock; } +struct freq_table { + unsigned long udelay_val_ref; + unsigned long clock_tick_ref; + unsigned int ref_freq; +}; +static DEFINE_PER_CPU(struct freq_table, sparc64_freq_table) = { 0, 0, 0 }; + +unsigned long sparc64_get_clock_tick(unsigned int cpu) +{ + struct freq_table *ft = &per_cpu(sparc64_freq_table, cpu); + + if (ft->clock_tick_ref) + return ft->clock_tick_ref; +#ifdef CONFIG_SMP + return cpu_data[cpu].clock_tick; +#else + return up_clock_tick; +#endif +} + +#ifdef CONFIG_CPU_FREQ + +static int sparc64_cpufreq_notifier(struct notifier_block *nb, unsigned long val, + void *data) +{ + struct cpufreq_freqs *freq = data; + unsigned int cpu = freq->cpu; + struct freq_table *ft = &per_cpu(sparc64_freq_table, cpu); + +#ifdef CONFIG_SMP + if (!ft->ref_freq) { + ft->ref_freq = freq->old; + ft->udelay_val_ref = cpu_data[cpu].udelay_val; + ft->clock_tick_ref = cpu_data[cpu].clock_tick; + } + if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || + (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) { + cpu_data[cpu].udelay_val = + cpufreq_scale(ft->udelay_val_ref, + ft->ref_freq, + freq->new); + cpu_data[cpu].clock_tick = + cpufreq_scale(ft->clock_tick_ref, + ft->ref_freq, + freq->new); + } +#else + /* In the non-SMP case, kernel/cpufreq.c takes care of adjusting + * loops_per_jiffy. + */ + if (!ft->ref_freq) { + ft->ref_freq = freq->old; + ft->clock_tick_ref = up_clock_tick; + } + if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || + (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) + up_clock_tick = cpufreq_scale(ft->clock_tick_ref, ft->ref_freq, freq->new); +#endif + + return 0; +} + +static struct notifier_block sparc64_cpufreq_notifier_block = { + .notifier_call = sparc64_cpufreq_notifier +}; +#endif + /* The quotient formula is taken from the IA64 port. */ void __init time_init(void) { @@ -996,6 +1065,11 @@ timer_ticks_per_usec_quotient = (((1000000UL << 30) + (clock / 2)) / clock); + +#ifdef CONFIG_CPU_FREQ + cpufreq_register_notifier(&sparc64_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); +#endif } static __inline__ unsigned long do_gettimeoffset(void) diff -Nru a/arch/sparc64/kernel/us2e_cpufreq.c b/arch/sparc64/kernel/us2e_cpufreq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/sparc64/kernel/us2e_cpufreq.c Wed Mar 26 02:27:10 2003 @@ -0,0 +1,398 @@ +/* us2e_cpufreq.c: UltraSPARC-IIe cpu frequency support + * + * Copyright (C) 2003 David S. Miller (davem@redhat.com) + * + * Many thanks to Dominik Brodowski for fixing up the cpufreq + * infrastructure in order to make this driver easier to implement. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static struct cpufreq_driver *cpufreq_us2e_driver; + +struct us2e_freq_percpu_info { + struct cpufreq_frequency_table table[6]; +}; + +/* Indexed by cpu number. */ +static struct us2e_freq_percpu_info *us2e_freq_table; + +#define HBIRD_MEM_CNTL0_ADDR 0x1fe0000f010UL +#define HBIRD_ESTAR_MODE_ADDR 0x1fe0000f080UL + +/* UltraSPARC-IIe has five dividers: 1, 2, 4, 6, and 8. These are controlled + * in the ESTAR mode control register. + */ +#define ESTAR_MODE_DIV_1 0x0000000000000000UL +#define ESTAR_MODE_DIV_2 0x0000000000000001UL +#define ESTAR_MODE_DIV_4 0x0000000000000003UL +#define ESTAR_MODE_DIV_6 0x0000000000000002UL +#define ESTAR_MODE_DIV_8 0x0000000000000004UL +#define ESTAR_MODE_DIV_MASK 0x0000000000000007UL + +#define MCTRL0_SREFRESH_ENAB 0x0000000000010000UL +#define MCTRL0_REFR_COUNT_MASK 0x0000000000007f00UL +#define MCTRL0_REFR_COUNT_SHIFT 8 +#define MCTRL0_REFR_INTERVAL 7800 +#define MCTRL0_REFR_CLKS_P_CNT 64 + +static unsigned long read_hbreg(unsigned long addr) +{ + unsigned long ret; + + __asm__ __volatile__("ldxa [%1] %2, %0" + : "=&r" (ret) + : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)); + return ret; +} + +static void write_hbreg(unsigned long addr, unsigned long val) +{ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "membar #Sync" + : /* no outputs */ + : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E) + : "memory"); + if (addr == HBIRD_ESTAR_MODE_ADDR) { + /* Need to wait 16 clock cycles for the PLL to lock. */ + udelay(1); + } +} + +static void self_refresh_ctl(int enable) +{ + unsigned long mctrl = read_hbreg(HBIRD_MEM_CNTL0_ADDR); + + if (enable) + mctrl |= MCTRL0_SREFRESH_ENAB; + else + mctrl &= ~MCTRL0_SREFRESH_ENAB; + write_hbreg(HBIRD_MEM_CNTL0_ADDR, mctrl); + (void) read_hbreg(HBIRD_MEM_CNTL0_ADDR); +} + +static void frob_mem_refresh(int cpu_slowing_down, + unsigned long clock_tick, + unsigned long old_divisor, unsigned long divisor) +{ + unsigned long old_refr_count, refr_count, mctrl; + + + refr_count = (clock_tick * MCTRL0_REFR_INTERVAL); + refr_count /= (MCTRL0_REFR_CLKS_P_CNT * divisor * 1000000000UL); + + mctrl = read_hbreg(HBIRD_MEM_CNTL0_ADDR); + old_refr_count = (mctrl & MCTRL0_REFR_COUNT_MASK) + >> MCTRL0_REFR_COUNT_SHIFT; + + mctrl &= ~MCTRL0_REFR_COUNT_MASK; + mctrl |= refr_count << MCTRL0_REFR_COUNT_SHIFT; + write_hbreg(HBIRD_MEM_CNTL0_ADDR, mctrl); + mctrl = read_hbreg(HBIRD_MEM_CNTL0_ADDR); + + if (cpu_slowing_down && !(mctrl & MCTRL0_SREFRESH_ENAB)) { + unsigned long usecs; + + /* We have to wait for both refresh counts (old + * and new) to go to zero. + */ + usecs = (MCTRL0_REFR_CLKS_P_CNT * + (refr_count + old_refr_count) * + 1000000UL * + old_divisor) / clock_tick; + udelay(usecs + 1UL); + } +} + +static void us2e_transition(unsigned long estar, unsigned long new_bits, + unsigned long clock_tick, + unsigned long old_divisor, unsigned long divisor) +{ + unsigned long flags; + + local_irq_save(flags); + + estar &= ~ESTAR_MODE_DIV_MASK; + + /* This is based upon the state transition diagram in the IIe manual. */ + if (old_divisor == 2 && divisor == 1) { + self_refresh_ctl(0); + write_hbreg(HBIRD_ESTAR_MODE_ADDR, estar | new_bits); + frob_mem_refresh(0, clock_tick, old_divisor, divisor); + } else if (old_divisor == 1 && divisor == 2) { + frob_mem_refresh(1, clock_tick, old_divisor, divisor); + write_hbreg(HBIRD_ESTAR_MODE_ADDR, estar | new_bits); + self_refresh_ctl(1); + } else if (old_divisor == 1 && divisor > 2) { + us2e_transition(estar, ESTAR_MODE_DIV_2, clock_tick, + 1, 2); + us2e_transition(estar, new_bits, clock_tick, + 2, divisor); + } else if (old_divisor > 2 && divisor == 1) { + us2e_transition(estar, ESTAR_MODE_DIV_2, clock_tick, + old_divisor, 2); + us2e_transition(estar, new_bits, clock_tick, + 2, divisor); + } else if (old_divisor < divisor) { + frob_mem_refresh(0, clock_tick, old_divisor, divisor); + write_hbreg(HBIRD_ESTAR_MODE_ADDR, estar | new_bits); + } else if (old_divisor > divisor) { + write_hbreg(HBIRD_ESTAR_MODE_ADDR, estar | new_bits); + frob_mem_refresh(1, clock_tick, old_divisor, divisor); + } else { + BUG(); + } + + local_irq_restore(flags); +} + +static unsigned long index_to_estar_mode(unsigned int index) +{ + switch (index) { + case 0: + return ESTAR_MODE_DIV_1; + + case 1: + return ESTAR_MODE_DIV_2; + + case 2: + return ESTAR_MODE_DIV_4; + + case 3: + return ESTAR_MODE_DIV_6; + + case 4: + return ESTAR_MODE_DIV_8; + + default: + BUG(); + }; +} + +static unsigned long index_to_divisor(unsigned int index) +{ + switch (index) { + case 0: + return 1; + + case 1: + return 2; + + case 2: + return 4; + + case 3: + return 6; + + case 4: + return 8; + + default: + BUG(); + }; +} + +static unsigned long estar_to_divisor(unsigned long estar) +{ + unsigned long ret; + + switch (estar & ESTAR_MODE_DIV_MASK) { + case ESTAR_MODE_DIV_1: + ret = 1; + break; + case ESTAR_MODE_DIV_2: + ret = 2; + break; + case ESTAR_MODE_DIV_4: + ret = 4; + break; + case ESTAR_MODE_DIV_6: + ret = 6; + break; + case ESTAR_MODE_DIV_8: + ret = 8; + break; + default: + BUG(); + }; + + return ret; +} + +static void us2e_set_cpu_divider_index(unsigned int cpu, unsigned int index) +{ + unsigned long new_bits, new_freq, cpus_allowed; + unsigned long clock_tick, divisor, old_divisor, estar; + struct cpufreq_freqs freqs; + + if (!cpu_online(cpu)) + return; + + cpus_allowed = current->cpus_allowed; + set_cpus_allowed(current, (1UL << cpu)); + + new_freq = clock_tick = sparc64_get_clock_tick(cpu); + new_bits = index_to_estar_mode(index); + divisor = index_to_divisor(index); + new_freq /= divisor; + + estar = read_hbreg(HBIRD_ESTAR_MODE_ADDR); + + old_divisor = estar_to_divisor(estar); + + freqs.old = clock_tick / old_divisor; + freqs.new = new_freq; + freqs.cpu = cpu; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + us2e_transition(estar, new_bits, clock_tick, old_divisor, divisor); + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + set_cpus_allowed(current, cpus_allowed); +} + +static int us2e_freq_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + unsigned int new_index = 0; + + if (cpufreq_frequency_table_target(policy, + &us2e_freq_table[policy->cpu].table[0], + target_freq, + relation, + &new_index)) + return -EINVAL; + + us2e_set_cpu_divider_index(policy->cpu, new_index); + + return 0; +} + +static int us2e_freq_verify(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, + &us2e_freq_table[policy->cpu].table[0]); +} + +static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy) +{ + unsigned int cpu = policy->cpu; + unsigned long clock_tick = sparc64_get_clock_tick(cpu); + struct cpufreq_frequency_table *table = + &us2e_freq_table[cpu].table[0]; + + table[0].index = 0; + table[0].frequency = clock_tick / 1; + table[1].index = 1; + table[1].frequency = clock_tick / 2; + table[2].index = 2; + table[2].frequency = clock_tick / 4; + table[2].index = 3; + table[2].frequency = clock_tick / 6; + table[2].index = 4; + table[2].frequency = clock_tick / 8; + table[2].index = 5; + table[3].frequency = CPUFREQ_TABLE_END; + + policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->cpuinfo.transition_latency = 0; + policy->cur = clock_tick; + + return cpufreq_frequency_table_cpuinfo(policy, table); +} + +static int __exit us2e_freq_cpu_exit(struct cpufreq_policy *policy) +{ + if (cpufreq_us2e_driver) + us2e_set_cpu_divider_index(policy->cpu, 0); + + return 0; +} + +static int __init us2e_freq_init(void) +{ + unsigned long manuf, impl, ver; + int ret; + + __asm__("rdpr %%ver, %0" : "=r" (ver)); + manuf = ((ver >> 48) & 0xffff); + impl = ((ver >> 32) & 0xffff); + + if (manuf == 0x17 && impl == 0x13) { + struct cpufreq_driver *driver; + + ret = -ENOMEM; + driver = kmalloc(sizeof(struct cpufreq_driver), GFP_KERNEL); + if (!driver) + goto err_out; + memset(driver, 0, sizeof(*driver)); + + us2e_freq_table = kmalloc( + (NR_CPUS * sizeof(struct us2e_freq_percpu_info)), + GFP_KERNEL); + if (!us2e_freq_table) + goto err_out; + + memset(us2e_freq_table, 0, + (NR_CPUS * sizeof(struct us2e_freq_percpu_info))); + + driver->verify = us2e_freq_verify; + driver->target = us2e_freq_target; + driver->init = us2e_freq_cpu_init; + driver->exit = us2e_freq_cpu_exit; + driver->owner = THIS_MODULE, + strcpy(driver->name, "UltraSPARC-IIe"); + + cpufreq_us2e_driver = driver; + ret = cpufreq_register_driver(driver); + if (ret) + goto err_out; + + return 0; + +err_out: + if (driver) { + kfree(driver); + cpufreq_us2e_driver = NULL; + } + if (us2e_freq_table) { + kfree(us2e_freq_table); + us2e_freq_table = NULL; + } + return ret; + } + + return -ENODEV; +} + +static void __exit us2e_freq_exit(void) +{ + if (cpufreq_us2e_driver) { + cpufreq_unregister_driver(cpufreq_us2e_driver); + + kfree(cpufreq_us2e_driver); + cpufreq_us2e_driver = NULL; + kfree(us2e_freq_table); + us2e_freq_table = NULL; + } +} + +MODULE_AUTHOR("David S. Miller "); +MODULE_DESCRIPTION("cpufreq driver for UltraSPARC-IIe"); +MODULE_LICENSE("GPL"); + +module_init(us2e_freq_init); +module_exit(us2e_freq_exit); diff -Nru a/arch/sparc64/kernel/us3_cpufreq.c b/arch/sparc64/kernel/us3_cpufreq.c --- a/arch/sparc64/kernel/us3_cpufreq.c Tue Mar 11 16:10:22 2003 +++ b/arch/sparc64/kernel/us3_cpufreq.c Wed Mar 26 00:49:46 2003 @@ -16,14 +16,12 @@ #include #include +#include static struct cpufreq_driver *cpufreq_us3_driver; struct us3_freq_percpu_info { struct cpufreq_frequency_table table[4]; - unsigned long udelay_val_ref; - unsigned long clock_tick_ref; - unsigned int ref_freq; }; /* Indexed by cpu number. */ @@ -56,71 +54,9 @@ : "memory"); } -#ifndef CONFIG_SMP -extern unsigned long up_clock_tick; -unsigned long clock_tick_ref; -unsigned int ref_freq; -#endif - -static __inline__ unsigned long get_clock_tick(unsigned int cpu) -{ -#ifdef CONFIG_SMP - if (us3_freq_table[cpu].clock_tick_ref) - return us3_freq_table[cpu].clock_tick_ref; - return cpu_data[cpu].clock_tick; -#else - if (clock_tick_ref) - return clock_tick_ref; - return up_clock_tick; -#endif -} - -static int us3_cpufreq_notifier(struct notifier_block *nb, unsigned long val, - void *data) -{ - struct cpufreq_freqs *freq = data; -#ifdef CONFIG_SMP - unsigned int cpu = freq->cpu; - - if (!us3_freq_table[cpu].ref_freq) { - us3_freq_table[cpu].ref_freq = freq->old; - us3_freq_table[cpu].udelay_val_ref = cpu_data[cpu].udelay_val; - us3_freq_table[cpu].clock_tick_ref = cpu_data[cpu].clock_tick; - } - if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || - (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) { - cpu_data[cpu].udelay_val = - cpufreq_scale(us3_freq_table[cpu].udelay_val_ref, - us3_freq_table[cpu].ref_freq, - freq->new); - cpu_data[cpu].clock_tick = - cpufreq_scale(us3_freq_table[cpu].clock_tick_ref, - us3_freq_table[cpu].ref_freq, - freq->new); - } -#else - /* In the non-SMP case, kernel/cpufreq.c takes care of adjusting - * loops_per_jiffy. - */ - if (!ref_freq) { - ref_freq = freq->old; - clock_tick_ref = up_clock_tick; - } - if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || - (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) - up_clock_tick = cpufreq_scale(clock_tick_ref, ref_freq, freq->new); -#endif - - return 0; -} - -static struct notifier_block us3_cpufreq_notifier_block = { - .notifier_call = us3_cpufreq_notifier -}; - static unsigned long get_current_freq(unsigned int cpu, unsigned long safari_cfg) { - unsigned long clock_tick = get_clock_tick(cpu); + unsigned long clock_tick = sparc64_get_clock_tick(cpu); unsigned long ret; switch (safari_cfg & SAFARI_CFG_DIV_MASK) { @@ -151,7 +87,7 @@ cpus_allowed = current->cpus_allowed; set_cpus_allowed(current, (1UL << cpu)); - new_freq = get_clock_tick(cpu); + new_freq = sparc64_get_clock_tick(cpu); switch (index) { case 0: new_bits = SAFARI_CFG_DIV_1; @@ -186,17 +122,17 @@ set_cpus_allowed(current, cpus_allowed); } -static int us3freq_target(struct cpufreq_policy *policy, +static int us3_freq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { unsigned int new_index = 0; if (cpufreq_frequency_table_target(policy, - &us3_freq_table[policy->cpu].table[0], - target_freq, - relation, - &new_index)) + &us3_freq_table[policy->cpu].table[0], + target_freq, + relation, + &new_index)) return -EINVAL; us3_set_cpu_divider_index(policy->cpu, new_index); @@ -204,16 +140,16 @@ return 0; } -static int us3freq_verify(struct cpufreq_policy *policy) +static int us3_freq_verify(struct cpufreq_policy *policy) { return cpufreq_frequency_table_verify(policy, &us3_freq_table[policy->cpu].table[0]); } -static int __init us3freq_cpu_init(struct cpufreq_policy *policy) +static int __init us3_freq_cpu_init(struct cpufreq_policy *policy) { unsigned int cpu = policy->cpu; - unsigned long clock_tick = get_clock_tick(cpu); + unsigned long clock_tick = sparc64_get_clock_tick(cpu); struct cpufreq_frequency_table *table = &us3_freq_table[cpu].table[0]; @@ -233,7 +169,7 @@ return cpufreq_frequency_table_cpuinfo(policy, table); } -static int __exit us3freq_cpu_exit(struct cpufreq_policy *policy) +static int __exit us3_freq_cpu_exit(struct cpufreq_policy *policy) { if (cpufreq_us3_driver) us3_set_cpu_divider_index(policy->cpu, 0); @@ -241,7 +177,7 @@ return 0; } -static int __init us3freq_init(void) +static int __init us3_freq_init(void) { unsigned long manuf, impl, ver; int ret; @@ -254,9 +190,6 @@ (impl == CHEETAH_IMPL || impl == CHEETAH_PLUS_IMPL)) { struct cpufreq_driver *driver; - cpufreq_register_notifier(&us3_cpufreq_notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); - ret = -ENOMEM; driver = kmalloc(sizeof(struct cpufreq_driver), GFP_KERNEL); if (!driver) @@ -272,10 +205,10 @@ memset(us3_freq_table, 0, (NR_CPUS * sizeof(struct us3_freq_percpu_info))); - driver->verify = us3freq_verify; - driver->target = us3freq_target; - driver->init = us3freq_cpu_init; - driver->exit = us3freq_cpu_exit; + driver->verify = us3_freq_verify; + driver->target = us3_freq_target; + driver->init = us3_freq_cpu_init; + driver->exit = us3_freq_cpu_exit; driver->owner = THIS_MODULE, strcpy(driver->name, "UltraSPARC-III"); @@ -295,20 +228,16 @@ kfree(us3_freq_table); us3_freq_table = NULL; } - cpufreq_unregister_notifier(&us3_cpufreq_notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); return ret; } return -ENODEV; } -static void __exit us3freq_exit(void) +static void __exit us3_freq_exit(void) { if (cpufreq_us3_driver) { cpufreq_unregister_driver(cpufreq_us3_driver); - cpufreq_unregister_notifier(&us3_cpufreq_notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); kfree(cpufreq_us3_driver); cpufreq_us3_driver = NULL; @@ -321,5 +250,5 @@ MODULE_DESCRIPTION("cpufreq driver for UltraSPARC-III"); MODULE_LICENSE("GPL"); -module_init(us3freq_init); -module_exit(us3freq_exit); +module_init(us3_freq_init); +module_exit(us3_freq_exit); diff -Nru a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile --- a/arch/sparc64/lib/Makefile Mon Mar 3 00:49:24 2003 +++ b/arch/sparc64/lib/Makefile Tue Mar 25 07:03:45 2003 @@ -11,4 +11,4 @@ VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \ VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o \ dec_and_lock.o U3memcpy.o U3copy_from_user.o U3copy_to_user.o \ - U3copy_in_user.o mcount.o ipcsum.o + U3copy_in_user.o mcount.o ipcsum.o rwsem.o diff -Nru a/arch/sparc64/lib/rwsem.c b/arch/sparc64/lib/rwsem.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/sparc64/lib/rwsem.c Tue Mar 25 07:03:33 2003 @@ -0,0 +1,238 @@ +/* rwsem.c: Don't inline expand these suckers all over the place. + * + * Written by David S. Miller (davem@redhat.com), 2001. + * Derived from asm-i386/rwsem.h + */ + +#include +#include +#include + +extern struct rw_semaphore *FASTCALL(rwsem_down_read_failed(struct rw_semaphore *sem)); +extern struct rw_semaphore *FASTCALL(rwsem_down_write_failed(struct rw_semaphore *sem)); +extern struct rw_semaphore *FASTCALL(rwsem_wake(struct rw_semaphore *)); +extern struct rw_semaphore *FASTCALL(rwsem_downgrade_wake(struct rw_semaphore *)); + +void __down_read(struct rw_semaphore *sem) +{ + __asm__ __volatile__( + "! beginning __down_read\n" + "1:\tlduw [%0], %%g5\n\t" + "add %%g5, 1, %%g7\n\t" + "cas [%0], %%g5, %%g7\n\t" + "cmp %%g5, %%g7\n\t" + "bne,pn %%icc, 1b\n\t" + " add %%g7, 1, %%g7\n\t" + "cmp %%g7, 0\n\t" + "bl,pn %%icc, 3f\n\t" + " membar #StoreLoad | #StoreStore\n" + "2:\n\t" + ".subsection 2\n" + "3:\tmov %0, %%g5\n\t" + "save %%sp, -160, %%sp\n\t" + "mov %%g1, %%l1\n\t" + "mov %%g2, %%l2\n\t" + "mov %%g3, %%l3\n\t" + "call %1\n\t" + " mov %%g5, %%o0\n\t" + "mov %%l1, %%g1\n\t" + "mov %%l2, %%g2\n\t" + "ba,pt %%xcc, 2b\n\t" + " restore %%l3, %%g0, %%g3\n\t" + ".previous\n\t" + "! ending __down_read" + : : "r" (sem), "i" (rwsem_down_read_failed) + : "g5", "g7", "memory", "cc"); +} +EXPORT_SYMBOL(__down_read); + +int __down_read_trylock(struct rw_semaphore *sem) +{ + int result; + + __asm__ __volatile__( + "! beginning __down_read_trylock\n" + "1:\tlduw [%1], %%g5\n\t" + "add %%g5, 1, %%g7\n\t" + "cmp %%g7, 0\n\t" + "bl,pn %%icc, 2f\n\t" + " mov 0, %0\n\t" + "cas [%1], %%g5, %%g7\n\t" + "cmp %%g5, %%g7\n\t" + "bne,pn %%icc, 1b\n\t" + " mov 1, %0\n\t" + "membar #StoreLoad | #StoreStore\n" + "2:\n\t" + "! ending __down_read_trylock" + : "=&r" (result) + : "r" (sem) + : "g5", "g7", "memory", "cc"); + + return result; +} +EXPORT_SYMBOL(__down_read_trylock); + +void __down_write(struct rw_semaphore *sem) +{ + __asm__ __volatile__( + "! beginning __down_write\n\t" + "sethi %%hi(%2), %%g1\n\t" + "or %%g1, %%lo(%2), %%g1\n" + "1:\tlduw [%0], %%g5\n\t" + "add %%g5, %%g1, %%g7\n\t" + "cas [%0], %%g5, %%g7\n\t" + "cmp %%g5, %%g7\n\t" + "bne,pn %%icc, 1b\n\t" + " cmp %%g7, 0\n\t" + "bne,pn %%icc, 3f\n\t" + " membar #StoreLoad | #StoreStore\n" + "2:\n\t" + ".subsection 2\n" + "3:\tmov %0, %%g5\n\t" + "save %%sp, -160, %%sp\n\t" + "mov %%g2, %%l2\n\t" + "mov %%g3, %%l3\n\t" + "call %1\n\t" + " mov %%g5, %%o0\n\t" + "mov %%l2, %%g2\n\t" + "ba,pt %%xcc, 2b\n\t" + " restore %%l3, %%g0, %%g3\n\t" + ".previous\n\t" + "! ending __down_write" + : : "r" (sem), "i" (rwsem_down_write_failed), + "i" (RWSEM_ACTIVE_WRITE_BIAS) + : "g1", "g5", "g7", "memory", "cc"); +} +EXPORT_SYMBOL(__down_write); + +int __down_write_trylock(struct rw_semaphore *sem) +{ + int result; + + __asm__ __volatile__( + "! beginning __down_write_trylock\n\t" + "sethi %%hi(%2), %%g1\n\t" + "or %%g1, %%lo(%2), %%g1\n" + "1:\tlduw [%1], %%g5\n\t" + "cmp %%g5, 0\n\t" + "bne,pn %%icc, 2f\n\t" + " mov 0, %0\n\t" + "add %%g5, %%g1, %%g7\n\t" + "cas [%1], %%g5, %%g7\n\t" + "cmp %%g5, %%g7\n\t" + "bne,pn %%icc, 1b\n\t" + " mov 1, %0\n\t" + "membar #StoreLoad | #StoreStore\n" + "2:\n\t" + "! ending __down_write_trylock" + : "=&r" (result) + : "r" (sem), "i" (RWSEM_ACTIVE_WRITE_BIAS) + : "g1", "g5", "g7", "memory", "cc"); + + return result; +} +EXPORT_SYMBOL(__down_write_trylock); + +void __up_read(struct rw_semaphore *sem) +{ + __asm__ __volatile__( + "! beginning __up_read\n\t" + "1:\tlduw [%0], %%g5\n\t" + "sub %%g5, 1, %%g7\n\t" + "cas [%0], %%g5, %%g7\n\t" + "cmp %%g5, %%g7\n\t" + "bne,pn %%icc, 1b\n\t" + " cmp %%g7, 0\n\t" + "bl,pn %%icc, 3f\n\t" + " membar #StoreLoad | #StoreStore\n" + "2:\n\t" + ".subsection 2\n" + "3:\tsethi %%hi(%2), %%g1\n\t" + "sub %%g7, 1, %%g7\n\t" + "or %%g1, %%lo(%2), %%g1\n\t" + "andcc %%g7, %%g1, %%g0\n\t" + "bne,pn %%icc, 2b\n\t" + " mov %0, %%g5\n\t" + "save %%sp, -160, %%sp\n\t" + "mov %%g2, %%l2\n\t" + "mov %%g3, %%l3\n\t" + "call %1\n\t" + " mov %%g5, %%o0\n\t" + "mov %%l2, %%g2\n\t" + "ba,pt %%xcc, 2b\n\t" + " restore %%l3, %%g0, %%g3\n\t" + ".previous\n\t" + "! ending __up_read" + : : "r" (sem), "i" (rwsem_wake), + "i" (RWSEM_ACTIVE_MASK) + : "g1", "g5", "g7", "memory", "cc"); +} +EXPORT_SYMBOL(__up_read); + +void __up_write(struct rw_semaphore *sem) +{ + __asm__ __volatile__( + "! beginning __up_write\n\t" + "sethi %%hi(%2), %%g1\n\t" + "or %%g1, %%lo(%2), %%g1\n" + "1:\tlduw [%0], %%g5\n\t" + "sub %%g5, %%g1, %%g7\n\t" + "cas [%0], %%g5, %%g7\n\t" + "cmp %%g5, %%g7\n\t" + "bne,pn %%icc, 1b\n\t" + " sub %%g7, %%g1, %%g7\n\t" + "cmp %%g7, 0\n\t" + "bl,pn %%icc, 3f\n\t" + " membar #StoreLoad | #StoreStore\n" + "2:\n\t" + ".subsection 2\n" + "3:\tmov %0, %%g5\n\t" + "save %%sp, -160, %%sp\n\t" + "mov %%g2, %%l2\n\t" + "mov %%g3, %%l3\n\t" + "call %1\n\t" + " mov %%g5, %%o0\n\t" + "mov %%l2, %%g2\n\t" + "ba,pt %%xcc, 2b\n\t" + " restore %%l3, %%g0, %%g3\n\t" + ".previous\n\t" + "! ending __up_write" + : : "r" (sem), "i" (rwsem_wake), + "i" (RWSEM_ACTIVE_WRITE_BIAS) + : "g1", "g5", "g7", "memory", "cc"); +} +EXPORT_SYMBOL(__up_write); + +void __downgrade_write(struct rw_semaphore *sem) +{ + __asm__ __volatile__( + "! beginning __downgrade_write\n\t" + "sethi %%hi(%2), %%g1\n\t" + "or %%g1, %%lo(%2), %%g1\n" + "1:\tlduw [%0], %%g5\n\t" + "sub %%g5, %%g1, %%g7\n\t" + "cas [%0], %%g5, %%g7\n\t" + "cmp %%g5, %%g7\n\t" + "bne,pn %%icc, 1b\n\t" + " sub %%g7, %%g1, %%g7\n\t" + "cmp %%g7, 0\n\t" + "bl,pn %%icc, 3f\n\t" + " membar #StoreLoad | #StoreStore\n" + "2:\n\t" + ".subsection 2\n" + "3:\tmov %0, %%g5\n\t" + "save %%sp, -160, %%sp\n\t" + "mov %%g2, %%l2\n\t" + "mov %%g3, %%l3\n\t" + "call %1\n\t" + " mov %%g5, %%o0\n\t" + "mov %%l2, %%g2\n\t" + "ba,pt %%xcc, 2b\n\t" + " restore %%l3, %%g0, %%g3\n\t" + ".previous\n\t" + "! ending __up_write" + : : "r" (sem), "i" (rwsem_downgrade_wake), + "i" (RWSEM_WAITING_BIAS) + : "g1", "g5", "g7", "memory", "cc"); +} +EXPORT_SYMBOL(__downgrade_write); diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig --- a/arch/x86_64/Kconfig Sat Mar 8 14:50:37 2003 +++ b/arch/x86_64/Kconfig Sun Mar 23 16:25:04 2003 @@ -179,9 +179,7 @@ If you don't know what to do here, say N. -# broken currently config PREEMPT - depends on NOT_WORKING bool "Preemptible Kernel" ---help--- This option reduces the latency of the kernel when reacting to @@ -200,7 +198,7 @@ # someone write a better help text please. config K8_NUMA bool "K8 NUMA support" - depends on SMP && NOT_WORKING + depends on SMP help Enable NUMA (Non Unified Memory Architecture) support for AMD Opteron Multiprocessor systems. The kernel will try to allocate @@ -590,10 +588,8 @@ allocation as well as poisoning memory on free to catch use of freed memory. -# bool ' Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT config MAGIC_SYSRQ bool "Magic SysRq key" - depends on DEBUG_KERNEL help If you say Y here, you will have some control over the system even if the system crashes for example during kernel debugging (e.g., you @@ -639,13 +635,36 @@ config FRAME_POINTER bool "Compile the kernel with frame pointers" - depends on DEBUG_KERNEL help Compile the kernel with frame pointers. This may help for some debugging with external debuggers. Note the standard oops backtracer - doesn't make use of it and the x86-64 kernel doesn't ensure an consistent + doesn't make use of this and the x86-64 kernel doesn't ensure an consistent frame pointer through inline assembly (semaphores etc.) Normally you should say N. + +config IOMMU_DEBUG + bool "Force IOMMU to on" + help + Force the IOMMU to on even when you have less than 4GB of memory and add + debugging code. + Can be disabled at boot time with iommu=noforce. + +config IOMMU_LEAK + bool "IOMMU leak tracing" + depends on DEBUG_KERNEL + help + Add a simple leak tracer to the IOMMU code. This is useful when you + are debugging a buggy device driver that leaks IOMMU mappings. + +config MCE_DEBUG + bool "K8 Machine check debugging mode" + default y + help + Turn on all Machine Check debugging for device driver problems. + This can cause panics, but is useful to find device driver problems. + +#config X86_REMOTE_DEBUG +# bool "kgdb debugging stub" endmenu diff -Nru a/arch/x86_64/Makefile b/arch/x86_64/Makefile --- a/arch/x86_64/Makefile Fri Mar 7 13:28:49 2003 +++ b/arch/x86_64/Makefile Sat Mar 22 09:27:58 2003 @@ -47,6 +47,10 @@ # should lower this a lot and see how much .text is saves CFLAGS += -finline-limit=2000 #CFLAGS += -g +# don't enable this when you use kgdb: +ifneq ($(CONFIG_X86_REMOTE_DEBUG),y) +CFLAGS += -fno-asynchronous-unwind-tables +endif head-y := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o diff -Nru a/arch/x86_64/boot/compressed/misc.c b/arch/x86_64/boot/compressed/misc.c --- a/arch/x86_64/boot/compressed/misc.c Sun Feb 23 00:43:15 2003 +++ b/arch/x86_64/boot/compressed/misc.c Sat Mar 22 10:08:40 2003 @@ -274,7 +274,7 @@ puts(x); puts("\n\n -- System halted"); - while(1); /* Halt */ + while(1); } void setup_normal_output_buffer(void) @@ -429,8 +429,6 @@ else setup_output_buffer_if_we_run_high(mv); makecrc(); - puts("Checking CPU type..."); - check_cpu(); puts(".\nDecompressing Linux..."); gunzip(); puts("done.\nBooting the kernel.\n"); diff -Nru a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S --- a/arch/x86_64/boot/setup.S Wed Mar 5 01:43:54 2003 +++ b/arch/x86_64/boot/setup.S Sat Mar 22 10:08:09 2003 @@ -42,6 +42,7 @@ * if CX/DX have been changed in the e801 call and if so use AX/BX . * Michael Miller, April 2001 * + * Added long mode checking and SSE force. March 2003, Andi Kleen. */ #include @@ -200,10 +201,10 @@ prtsp2: call prtspc # Print double space prtspc: movb $0x20, %al # Print single space (note: fall-thru) -# Part of above routine, this one just prints ascii al -prtchr: pushw %ax +prtchr: + pushw %ax pushw %cx - xorb %bh, %bh + movw $0007,%bx movw $0x01, %cx movb $0x0e, %ah int $0x10 @@ -280,6 +281,75 @@ loader_panic_mess: .string "Wrong loader, giving up..." loader_ok: + /* check for long mode. */ + /* we have to do this before the VESA setup, otherwise the user + can't see the error message. */ + + pushw %ds + movw %cs,%ax + movw %ax,%ds + + /* minimum CPUID flags for x86-64 */ + /* see http://www.x86-64.org/lists/discuss/msg02971.html */ +#define SSE_MASK ((1<<25)|(1<<26)) +#define REQUIRED_MASK1 ((1<<0)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<8)|(1<<11)| \ + (1<<13)|(1<<15)|(1<<24)|(1<<29)) + + pushfl /* standard way to check for cpuid */ + popl %eax + movl %eax,%ebx + xorl $0x200000,%eax + pushl %eax + popfl + pushfl + popl %eax + cmpl %eax,%ebx + jz no_longmode /* cpu has no cpuid */ + movl $0x80000000,%eax + cpuid + cmpl $0x80000001,%eax + jb no_longmode /* no extended cpuid */ + xor %di,%di + cmpl $0x68747541,%ebx /* AuthenticAMD */ + jnz noamd + cmpl $0x69746e65,%edx + jnz noamd + cmpl $0x444d4163,%ecx + jnz noamd + mov $1,%di /* cpu is from AMD */ +noamd: + movl $0x80000001,%eax + cpuid + andl $REQUIRED_MASK1,%edx + xorl $REQUIRED_MASK1,%edx + jnz no_longmode +sse_test: + movl $1,%eax + cpuid + andl $SSE_MASK,%edx + cmpl $SSE_MASK,%edx + je sse_ok + test %di,%di + jz no_longmode /* only try to force SSE on AMD */ + movl $0xc0010015,%ecx /* HWCR */ + rdmsr + btr $15,%eax /* enable SSE */ + wrmsr + xor %di,%di /* don't loop */ + jmp sse_test /* try again */ +no_longmode: + call beep + lea long_mode_panic,%si + call prtstr +no_longmode_loop: + jmp no_longmode_loop +long_mode_panic: + .string "Your CPU does not support long mode. Use a 32bit distribution." + .byte 0 + +sse_ok: + popw %ds + # Get memory size (extended mem, kB) xorl %eax, %eax diff -Nru a/arch/x86_64/ia32/fpu32.c b/arch/x86_64/ia32/fpu32.c --- a/arch/x86_64/ia32/fpu32.c Fri Jan 31 08:17:41 2003 +++ b/arch/x86_64/ia32/fpu32.c Sat Mar 22 11:41:26 2003 @@ -77,17 +77,20 @@ struct _fpxreg *to; struct _fpreg *from; int i; - int err; - __u32 v; + u32 v; + int err = 0; - err = __get_user(fxsave->cwd, &buf->cw); - err |= __get_user(fxsave->swd, &buf->sw); - err |= __get_user(fxsave->twd, &buf->tag); +#define G(num,val) err |= __get_user(val, num + (u32 *)buf) + G(0, fxsave->cwd); + G(1, fxsave->swd); + G(2, fxsave->twd); fxsave->twd = twd_i387_to_fxsr(fxsave->twd); - err |= __get_user(fxsave->rip, &buf->ipoff); - err |= __get_user(fxsave->rdp, &buf->dataoff); - err |= __get_user(v, &buf->cssel); - fxsave->fop = v >> 16; + G(3, fxsave->rip); + G(4, v); + fxsave->fop = v>>16; /* cs ignored */ + G(5, fxsave->rdp); + /* 6: ds ignored */ +#undef G if (err) return -1; @@ -109,21 +112,29 @@ struct _fpreg *to; struct _fpxreg *from; int i; - u32 ds; - int err; + u16 cs,ds; + int err = 0; - err = __put_user((unsigned long)fxsave->cwd | 0xffff0000, &buf->cw); - err |= __put_user((unsigned long)fxsave->swd | 0xffff0000, &buf->sw); - err |= __put_user((u32)fxsave->rip, &buf->ipoff); - err |= __put_user((u32)(regs->cs | ((u32)fxsave->fop << 16)), - &buf->cssel); - err |= __put_user((u32)twd_fxsr_to_i387(fxsave), &buf->tag); - err |= __put_user((u32)fxsave->rdp, &buf->dataoff); - if (tsk == current) - asm("movl %%ds,%0 " : "=r" (ds)); - else /* ptrace. task has stopped. */ + if (tsk == current) { + /* should be actually ds/cs at fpu exception time, + but that information is not available in 64bit mode. */ + asm("movw %%ds,%0 " : "=r" (ds)); + asm("movw %%cs,%0 " : "=r" (cs)); + } else { /* ptrace. task has stopped. */ ds = tsk->thread.ds; - err |= __put_user(ds, &buf->datasel); + cs = regs->cs; + } + +#define P(num,val) err |= __put_user(val, num + (u32 *)buf) + P(0, (u32)fxsave->cwd | 0xffff0000); + P(1, (u32)fxsave->swd | 0xffff0000); + P(2, twd_fxsr_to_i387(fxsave)); + P(3, (u32)fxsave->rip); + P(4, cs | ((u32)fxsave->fop) << 16); + P(5, fxsave->rdp); + P(6, 0xffff0000 | ds); +#undef P + if (err) return -1; @@ -144,9 +155,9 @@ &buf->_fxsr_env[0], sizeof(struct i387_fxsave_struct))) return -1; - } tsk->thread.i387.fxsave.mxcsr &= 0xffbf; - current->used_math = 1; + tsk->used_math = 1; + } return convert_fxsr_from_user(&tsk->thread.i387.fxsave, buf); } @@ -157,12 +168,11 @@ { int err = 0; - if (!tsk->used_math) - return 0; - tsk->used_math = 0; - unlazy_fpu(tsk); + init_fpu(tsk); if (convert_fxsr_to_user(buf, &tsk->thread.i387.fxsave, regs, tsk)) return -1; + if (fsave) + return 0; err |= __put_user(tsk->thread.i387.fxsave.swd, &buf->status); if (fsave) return err ? -1 : 1; diff -Nru a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c --- a/arch/x86_64/ia32/ia32_ioctl.c Tue Feb 25 10:47:17 2003 +++ b/arch/x86_64/ia32/ia32_ioctl.c Sat Mar 22 10:42:58 2003 @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -60,6 +61,8 @@ #include #include #include +#include +#include #if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) /* Ugh. This header really is not clean */ #define min min @@ -2906,35 +2909,28 @@ { typedef struct serial_struct SS; struct serial_struct32 *ss32 = ptr; - int err = 0; + int err; struct serial_struct ss; mm_segment_t oldseg = get_fs(); - set_fs(KERNEL_DS); if (cmd == TIOCSSERIAL) { - err = -EFAULT; if (copy_from_user(&ss, ss32, sizeof(struct serial_struct32))) - goto out; + return -EFAULT; memmove(&ss.iomem_reg_shift, ((char*)&ss.iomem_base)+4, sizeof(SS)-offsetof(SS,iomem_reg_shift)); ss.iomem_base = (void *)((unsigned long)ss.iomem_base & 0xffffffff); } - if (!err) + set_fs(KERNEL_DS); err = sys_ioctl(fd,cmd,(unsigned long)(&ss)); + set_fs(oldseg); if (cmd == TIOCGSERIAL && err >= 0) { - __u32 base; if (__copy_to_user(ss32,&ss,offsetof(SS,iomem_base)) || - __copy_to_user(&ss32->iomem_reg_shift, - &ss.iomem_reg_shift, - sizeof(SS) - offsetof(SS, iomem_reg_shift))) - err = -EFAULT; - if (ss.iomem_base > (unsigned char *)0xffffffff) - base = -1; - else - base = (unsigned long)ss.iomem_base; - err |= __put_user(base, &ss32->iomem_base); + __put_user((unsigned long)ss.iomem_base >> 32 ? + 0xffffffff : (unsigned)(unsigned long)ss.iomem_base, + &ss32->iomem_base) || + __put_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift) || + __put_user(ss.port_high, &ss32->port_high)) + return -EFAULT; } - out: - set_fs(oldseg); return err; } @@ -3045,7 +3041,14 @@ return sys_ioctl(fd, BLKGETSIZE64, arg); } +/* Bluetooth ioctls */ +#define HCIUARTSETPROTO _IOW('U', 200, int) +#define HCIUARTGETPROTO _IOR('U', 201, int) +#define BNEPCONNADD _IOW('B', 200, int) +#define BNEPCONNDEL _IOW('B', 201, int) +#define BNEPGETCONNLIST _IOR('B', 210, int) +#define BNEPGETCONNINFO _IOR('B', 211, int) struct usbdevfs_ctrltransfer32 { __u8 bRequestType; @@ -4093,6 +4096,7 @@ COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC) COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER) COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE) +COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI) /* DEVFS */ COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV) COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK) @@ -4200,6 +4204,17 @@ COMPATIBLE_IOCTL(HCISETACLMTU) COMPATIBLE_IOCTL(HCISETSCOMTU) COMPATIBLE_IOCTL(HCIINQUIRY) +COMPATIBLE_IOCTL(HCIUARTSETPROTO) +COMPATIBLE_IOCTL(HCIUARTGETPROTO) +COMPATIBLE_IOCTL(RFCOMMCREATEDEV) +COMPATIBLE_IOCTL(RFCOMMRELEASEDEV) +COMPATIBLE_IOCTL(RFCOMMGETDEVLIST) +COMPATIBLE_IOCTL(RFCOMMGETDEVINFO) +COMPATIBLE_IOCTL(RFCOMMSTEALDLC) +COMPATIBLE_IOCTL(BNEPCONNADD) +COMPATIBLE_IOCTL(BNEPCONNDEL) +COMPATIBLE_IOCTL(BNEPGETCONNLIST) +COMPATIBLE_IOCTL(BNEPGETCONNINFO) /* Misc. */ COMPATIBLE_IOCTL(0x41545900) /* ATYIO_CLKR */ COMPATIBLE_IOCTL(0x41545901) /* ATYIO_CLKW */ diff -Nru a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c --- a/arch/x86_64/ia32/ia32_signal.c Sat Mar 8 18:05:09 2003 +++ b/arch/x86_64/ia32/ia32_signal.c Sat Mar 22 11:05:44 2003 @@ -47,9 +47,16 @@ { if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t))) return -EFAULT; - if (from->si_code < 0) - return __copy_to_user(to, from, sizeof(siginfo_t)); - else { + if (from->si_code < 0) { + /* the only field that's different is the alignment + of the pointer in sigval_t. Move that 4 bytes down including + padding. */ + memmove(&((siginfo_t32 *)&from)->si_int, + &from->si_int, + sizeof(siginfo_t) - offsetof(siginfo_t, si_int)); + /* last 4 bytes stay the same */ + return __copy_to_user(to, from, sizeof(siginfo_t32)); + } else { int err; /* If you change siginfo_t structure, please be sure @@ -59,7 +66,7 @@ 3 ints plus the relevant union member. */ err = __put_user(from->si_signo, &to->si_signo); err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user((short)from->si_code, &to->si_code); + err |= __put_user(from->si_code, &to->si_code); /* First 32bits of unions are always present. */ err |= __put_user(from->si_pid, &to->si_pid); switch (from->si_code >> 16) { @@ -108,6 +115,7 @@ mm_segment_t seg; if (uss_ptr) { u32 ptr; + memset(&uss,0,sizeof(stack_t)); if (!access_ok(VERIFY_READ,uss_ptr,sizeof(stack_ia32_t)) || __get_user(ptr, &uss_ptr->ss_sp) || __get_user(uss.ss_flags, &uss_ptr->ss_flags) || @@ -340,8 +348,11 @@ tmp = save_i387_ia32(current, fpstate, regs, 0); if (tmp < 0) err = -EFAULT; - else + else { + current->used_math = 0; + stts(); err |= __put_user((u32)(u64)(tmp ? fpstate : NULL), &sc->fpstate); + } /* non-iBCS2 extensions.. */ err |= __put_user(mask, &sc->oldmask); diff -Nru a/arch/x86_64/ia32/ipc32.c b/arch/x86_64/ia32/ipc32.c --- a/arch/x86_64/ia32/ipc32.c Mon Feb 10 17:21:29 2003 +++ b/arch/x86_64/ia32/ipc32.c Sat Mar 22 14:30:49 2003 @@ -187,12 +187,58 @@ } } +static int put_semid(void *user_semid, struct semid64_ds *s, int version) +{ + int err2; + switch (version) { + case IPC_64: { + struct semid64_ds32 *usp64 = (struct semid64_ds32 *) user_semid; + + if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) { + err2 = -EFAULT; + break; + } + err2 = __put_user(s->sem_perm.key, &usp64->sem_perm.key); + err2 |= __put_user(s->sem_perm.uid, &usp64->sem_perm.uid); + err2 |= __put_user(s->sem_perm.gid, &usp64->sem_perm.gid); + err2 |= __put_user(s->sem_perm.cuid, &usp64->sem_perm.cuid); + err2 |= __put_user(s->sem_perm.cgid, &usp64->sem_perm.cgid); + err2 |= __put_user(s->sem_perm.mode, &usp64->sem_perm.mode); + err2 |= __put_user(s->sem_perm.seq, &usp64->sem_perm.seq); + err2 |= __put_user(s->sem_otime, &usp64->sem_otime); + err2 |= __put_user(s->sem_ctime, &usp64->sem_ctime); + err2 |= __put_user(s->sem_nsems, &usp64->sem_nsems); + break; + } + default: { + struct semid_ds32 *usp32 = (struct semid_ds32 *) user_semid; + + if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) { + err2 = -EFAULT; + break; + } + err2 = __put_user(s->sem_perm.key, &usp32->sem_perm.key); + err2 |= __put_user(s->sem_perm.uid, &usp32->sem_perm.uid); + err2 |= __put_user(s->sem_perm.gid, &usp32->sem_perm.gid); + err2 |= __put_user(s->sem_perm.cuid, &usp32->sem_perm.cuid); + err2 |= __put_user(s->sem_perm.cgid, &usp32->sem_perm.cgid); + err2 |= __put_user(s->sem_perm.mode, &usp32->sem_perm.mode); + err2 |= __put_user(s->sem_perm.seq, &usp32->sem_perm.seq); + err2 |= __put_user(s->sem_otime, &usp32->sem_otime); + err2 |= __put_user(s->sem_ctime, &usp32->sem_ctime); + err2 |= __put_user(s->sem_nsems, &usp32->sem_nsems); + break; + } + } + return err2; +} + static int semctl32 (int first, int second, int third, void *uptr) { union semun fourth; u32 pad; - int err = 0, err2; + int err; struct semid64_ds s; mm_segment_t old_fs; int version = ipc_parse_version32(&third); @@ -225,46 +271,10 @@ fourth.__pad = &s; old_fs = get_fs(); set_fs(KERNEL_DS); - err = sys_semctl(first, second|IPC_64, third, fourth); + err = sys_semctl(first, second, third|IPC_64, fourth); set_fs(old_fs); - - if (version == IPC_64) { - struct semid64_ds32 *usp64 = (struct semid64_ds32 *) A(pad); - - if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) { - err = -EFAULT; - break; - } - err2 = __put_user(s.sem_perm.key, &usp64->sem_perm.key); - err2 |= __put_user(s.sem_perm.uid, &usp64->sem_perm.uid); - err2 |= __put_user(s.sem_perm.gid, &usp64->sem_perm.gid); - err2 |= __put_user(s.sem_perm.cuid, &usp64->sem_perm.cuid); - err2 |= __put_user(s.sem_perm.cgid, &usp64->sem_perm.cgid); - err2 |= __put_user(s.sem_perm.mode, &usp64->sem_perm.mode); - err2 |= __put_user(s.sem_perm.seq, &usp64->sem_perm.seq); - err2 |= __put_user(s.sem_otime, &usp64->sem_otime); - err2 |= __put_user(s.sem_ctime, &usp64->sem_ctime); - err2 |= __put_user(s.sem_nsems, &usp64->sem_nsems); - } else { - struct semid_ds32 *usp32 = (struct semid_ds32 *) A(pad); - - if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) { - err = -EFAULT; - break; - } - err2 = __put_user(s.sem_perm.key, &usp32->sem_perm.key); - err2 |= __put_user(s.sem_perm.uid, &usp32->sem_perm.uid); - err2 |= __put_user(s.sem_perm.gid, &usp32->sem_perm.gid); - err2 |= __put_user(s.sem_perm.cuid, &usp32->sem_perm.cuid); - err2 |= __put_user(s.sem_perm.cgid, &usp32->sem_perm.cgid); - err2 |= __put_user(s.sem_perm.mode, &usp32->sem_perm.mode); - err2 |= __put_user(s.sem_perm.seq, &usp32->sem_perm.seq); - err2 |= __put_user(s.sem_otime, &usp32->sem_otime); - err2 |= __put_user(s.sem_ctime, &usp32->sem_ctime); - err2 |= __put_user(s.sem_nsems, &usp32->sem_nsems); - } - if (err2) - err = -EFAULT; + if (!err) + err = put_semid((void *)A(pad), &s, version); break; default: err = -EINVAL; @@ -343,6 +353,7 @@ return err; } + static int msgctl32 (int first, int second, void *uptr) { @@ -387,7 +398,6 @@ set_fs(KERNEL_DS); err = sys_msgctl(first, second|IPC_64, (void *) &m64); set_fs(old_fs); - if (version == IPC_64) { if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) { err = -EFAULT; @@ -608,7 +618,9 @@ if (err2) err = -EFAULT; break; - + default: + err = -EINVAL; + break; } return err; } diff -Nru a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c --- a/arch/x86_64/ia32/ptrace32.c Sat Mar 8 17:56:51 2003 +++ b/arch/x86_64/ia32/ptrace32.c Sat Mar 22 11:10:37 2003 @@ -8,7 +8,7 @@ * This allows to access 64bit processes too; but there is no way to see the extended * register contents. * - * $Id: ptrace32.c,v 1.12 2002/03/24 13:02:02 ak Exp $ + * $Id: ptrace32.c,v 1.16 2003/03/14 16:06:35 ak Exp $ */ #include @@ -22,11 +22,9 @@ #include #include #include -#include -#include #include -#include #include +#include #define R32(l,q) \ case offsetof(struct user32, regs.l): stack[offsetof(struct pt_regs, q)/8] = val; break @@ -39,29 +37,26 @@ switch (regno) { case offsetof(struct user32, regs.fs): if (val && (val & 3) != 3) return -EIO; - child->thread.fs = val; + child->thread.fs = val & 0xffff; break; case offsetof(struct user32, regs.gs): if (val && (val & 3) != 3) return -EIO; - child->thread.gs = val; + child->thread.gs = val & 0xffff; break; case offsetof(struct user32, regs.ds): if (val && (val & 3) != 3) return -EIO; - child->thread.ds = val; + child->thread.ds = val & 0xffff; break; case offsetof(struct user32, regs.es): - if (val && (val & 3) != 3) return -EIO; - child->thread.es = val; + child->thread.es = val & 0xffff; break; - case offsetof(struct user32, regs.ss): if ((val & 3) != 3) return -EIO; - stack[offsetof(struct pt_regs, ss)/8] = val; + stack[offsetof(struct pt_regs, ss)/8] = val & 0xffff; break; - case offsetof(struct user32, regs.cs): if ((val & 3) != 3) return -EIO; - stack[offsetof(struct pt_regs, cs)/8] = val; + stack[offsetof(struct pt_regs, cs)/8] = val & 0xffff; break; R32(ebx, rbx); @@ -79,8 +74,16 @@ stack[offsetof(struct pt_regs, eflags)/8] = val & 0x44dd5; break; - case offsetof(struct user32, u_debugreg[0]) ... offsetof(struct user32, u_debugreg[6]): - child->thread.debugreg[(regno-offsetof(struct user32, u_debugreg[0]))/4] = val; + case offsetof(struct user32, u_debugreg[4]): + case offsetof(struct user32, u_debugreg[5]): + return -EIO; + + case offsetof(struct user32, u_debugreg[0]) ... + offsetof(struct user32, u_debugreg[3]): + case offsetof(struct user32, u_debugreg[6]): + child->thread.debugreg + [(regno-offsetof(struct user32, u_debugreg[0]))/4] + = val; break; case offsetof(struct user32, u_debugreg[7]): @@ -170,11 +173,19 @@ if (child) get_task_struct(child); read_unlock(&tasklist_lock); - *err = ptrace_check_attach(child,0); - if (*err == 0) + if (child) { + *err = -EPERM; + if (child->pid == 1) + goto out; + *err = ptrace_check_attach(child, request == PTRACE_KILL); + if (*err < 0) + goto out; return child; + } + out: put_task_struct(child); return NULL; + } extern asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, unsigned long data); @@ -187,6 +198,9 @@ __u32 val; switch (request) { + default: + return sys_ptrace(request, pid, addr, data); + case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: case PTRACE_POKEDATA: @@ -201,9 +215,6 @@ case PTRACE_GETFPXREGS: break; - default: - ret = sys_ptrace(request, pid, addr, data); - return ret; } child = find_target(request, pid, &ret); @@ -261,7 +272,6 @@ ret = -EIO; break; } - empty_fpu(child); ret = 0; for ( i = 0; i <= 16*4; i += sizeof(u32) ) { ret |= __get_user(tmp, (u32 *) (unsigned long) data); @@ -271,33 +281,47 @@ break; } - case PTRACE_SETFPREGS: - empty_fpu(child); + case PTRACE_GETFPREGS: + ret = -EIO; + if (!access_ok(VERIFY_READ, (void *)(u64)data, + sizeof(struct user_i387_struct))) + break; save_i387_ia32(child, (void *)(u64)data, childregs, 1); ret = 0; break; - case PTRACE_GETFPREGS: - empty_fpu(child); - restore_i387_ia32(child, (void *)(u64)data, 1); + case PTRACE_SETFPREGS: + ret = -EIO; + if (!access_ok(VERIFY_WRITE, (void *)(u64)data, + sizeof(struct user_i387_struct))) + break; ret = 0; + /* don't check EFAULT to be bug-to-bug compatible to i386 */ + restore_i387_ia32(child, (void *)(u64)data, 1); break; case PTRACE_GETFPXREGS: { struct user32_fxsr_struct *u = (void *)(u64)data; - empty_fpu(child); - ret = copy_to_user(u, &child->thread.i387.fxsave, sizeof(*u)); - ret |= __put_user(childregs->cs, &u->fcs); - ret |= __put_user(child->thread.ds, &u->fos); - if (ret) + init_fpu(child); + ret = -EIO; + if (!access_ok(VERIFY_WRITE, u, sizeof(*u))) + break; ret = -EFAULT; + if (__copy_to_user(u, &child->thread.i387.fxsave, sizeof(*u))) + break; + ret = __put_user(childregs->cs, &u->fcs); + ret |= __put_user(child->thread.ds, &u->fos); break; } case PTRACE_SETFPXREGS: { struct user32_fxsr_struct *u = (void *)(u64)data; - empty_fpu(child); - /* no error checking to be bug to bug compatible with i386 */ - copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u)); + unlazy_fpu(child); + ret = -EIO; + if (!access_ok(VERIFY_READ, u, sizeof(*u))) + break; + /* no checking to be bug-to-bug compatible with i386 */ + __copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u)); + child->used_math = 1; child->thread.i387.fxsave.mxcsr &= 0xffbf; ret = 0; break; diff -Nru a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c --- a/arch/x86_64/ia32/sys_ia32.c Sun Mar 23 14:34:05 2003 +++ b/arch/x86_64/ia32/sys_ia32.c Sat Mar 22 14:02:51 2003 @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,7 @@ #define A(__x) ((unsigned long)(__x)) #define AA(__x) ((unsigned long)(__x)) +#define u32_to_ptr(x) ((void *)(u64)(x)) #define ROUND_UP(x,a) ((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1))) #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) @@ -738,7 +740,7 @@ asmlinkage ssize_t sys_writev(unsigned long,const struct iovec *,unsigned long); static struct iovec * -get_compat_iovec(struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type, int *errp) +get_compat_iovec(struct compat_iovec *iov32, struct iovec *iov_buf, u32 *count, int type, int *errp) { int i; u32 buf, len; @@ -747,15 +749,18 @@ /* Get the "struct iovec" from user memory */ - if (!count) + *errp = 0; + if (!*count) return 0; - if (count > UIO_MAXIOV) + *errp = -EINVAL; + if (*count > UIO_MAXIOV) return(struct iovec *)0; - if(verify_area(VERIFY_READ, iov32, sizeof(struct compat_iovec)*count)) + *errp = -EFAULT; + if(verify_area(VERIFY_READ, iov32, sizeof(struct compat_iovec)*(*count))) return(struct iovec *)0; - if (count > UIO_FASTIOV) { + if (*count > UIO_FASTIOV) { *errp = -ENOMEM; - iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL); + iov = kmalloc(*count*sizeof(struct iovec), GFP_KERNEL); if (!iov) return((struct iovec *)0); } else @@ -763,14 +768,19 @@ ivp = iov; totlen = 0; - for (i = 0; i < count; i++) { + for (i = 0; i < *count; i++) { *errp = __get_user(len, &iov32->iov_len) | __get_user(buf, &iov32->iov_base); if (*errp) goto error; *errp = verify_area(type, (void *)A(buf), len); - if (*errp) + if (*errp) { + if (i > 0) { + *count = i; + break; + } goto error; + } /* SuS checks: */ *errp = -EINVAL; if ((int)len < 0) @@ -799,7 +809,7 @@ int ret; mm_segment_t old_fs = get_fs(); - if ((iov = get_compat_iovec(vector, iovstack, count, VERIFY_WRITE, &ret)) == NULL) + if ((iov = get_compat_iovec(vector, iovstack, &count, VERIFY_WRITE, &ret)) == NULL) return ret; set_fs(KERNEL_DS); ret = sys_readv(fd, iov, count); @@ -817,7 +827,7 @@ int ret; mm_segment_t old_fs = get_fs(); - if ((iov = get_compat_iovec(vector, iovstack, count, VERIFY_READ, &ret)) == NULL) + if ((iov = get_compat_iovec(vector, iovstack, &count, VERIFY_READ, &ret)) == NULL) return ret; set_fs(KERNEL_DS); ret = sys_writev(fd, iov, count); @@ -1672,21 +1682,26 @@ return cnt; } -long sys32_execve(char *name, u32 argv, u32 envp, struct pt_regs regs) +asmlinkage long sys32_execve(char *name, u32 argv, u32 envp, struct pt_regs regs) { mm_segment_t oldseg; - char **buf; - int na,ne; + char **buf = NULL; + int na = 0,ne = 0; int ret; - unsigned sz; + unsigned sz = 0; + if (argv) { na = nargs(argv, NULL); if (na < 0) return -EFAULT; + } + if (envp) { ne = nargs(envp, NULL); if (ne < 0) return -EFAULT; + } + if (argv || envp) { sz = (na+ne)*sizeof(void *); if (sz > PAGE_SIZE) buf = vmalloc(sz); @@ -1694,14 +1709,19 @@ buf = kmalloc(sz, GFP_KERNEL); if (!buf) return -ENOMEM; + } + if (argv) { ret = nargs(argv, buf); if (ret < 0) goto free; + } + if (envp) { ret = nargs(envp, buf + na); if (ret < 0) goto free; + } name = getname(name); ret = PTR_ERR(name); @@ -1710,7 +1730,7 @@ oldseg = get_fs(); set_fs(KERNEL_DS); - ret = do_execve(name, buf, buf+na, ®s); + ret = do_execve(name, argv ? buf : NULL, envp ? buf+na : NULL, ®s); set_fs(oldseg); if (ret == 0) @@ -1719,10 +1739,12 @@ putname(name); free: + if (argv || envp) { if (sz > PAGE_SIZE) vfree(buf); else kfree(buf); + } return ret; } @@ -2012,12 +2034,8 @@ long sys32_module_warning(void) { - static long warn_time = -(60*HZ); - if (time_before(warn_time + 60*HZ,jiffies) && strcmp(current->comm,"klogd")) { printk(KERN_INFO "%s: 32bit 2.4.x modutils not supported on 64bit kernel\n", current->comm); - warn_time = jiffies; - } return -ENOSYS ; } @@ -2055,6 +2073,7 @@ return err; } + extern long sys_io_setup(unsigned nr_reqs, aio_context_t *ctx); long sys32_io_setup(unsigned nr_reqs, u32 *ctx32p) @@ -2071,48 +2090,47 @@ return ret; } -extern asmlinkage long sys_io_submit(aio_context_t ctx_id, long nr, - struct iocb **iocbpp); - -long sys32_io_submit(aio_context_t ctx_id, unsigned long nr, +asmlinkage long sys32_io_submit(aio_context_t ctx_id, int nr, u32 *iocbpp) { - mm_segment_t oldfs = get_fs(); - int k, err = 0; - struct iocb **iocb64; - if (nr > 128) + struct kioctx *ctx; + long ret = 0; + int i; + + if (unlikely(nr < 0)) + return -EINVAL; + + if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp))))) + return -EFAULT; + + ctx = lookup_ioctx(ctx_id); + if (unlikely(!ctx)) { + pr_debug("EINVAL: io_submit: invalid context id\n"); return -EINVAL; - iocb64 = kmalloc(sizeof(struct iocb *) * nr, GFP_KERNEL); - if (!iocb64) - return -ENOMEM; - for (k = 0; k < nr && !err; k++) { - u64 val1, val2; - u32 iocb32; - struct iocb *iocb; - err = get_user(iocb32, (u32 *)(u64)iocbpp[k]); - iocb64[k] = iocb = (void *)(u64)iocb32; - - if (get_user(val1, &iocb->aio_buf) || - get_user(val2, &iocb->aio_nbytes)) - err = -EFAULT; - else if (!val1) /* should check cmd */ - ; - else if (verify_area(VERIFY_WRITE, (void*)val1, val2)) - err = -EFAULT; - - /* paranoia check - remove it when you are sure they - are not pointers */ - if (get_user(val1, &iocb->aio_reserved2) || val1 || - get_user(val2, &iocb->aio_reserved2) || val2) - err = -EFAULT; } - if (!err) { - set_fs(KERNEL_DS); - err = sys_io_submit(ctx_id, nr, iocb64); - set_fs(oldfs); + + for (i=0; icomm); - warn_time = jiffies; - } return -ENOSYS ; } diff -Nru a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile --- a/arch/x86_64/kernel/Makefile Sun Mar 9 14:15:54 2003 +++ b/arch/x86_64/kernel/Makefile Sun Mar 23 17:29:57 2003 @@ -10,14 +10,13 @@ setup64.o bluesmoke.o bootflag.o e820.o reboot.o obj-$(CONFIG_MTRR) += mtrr/ +obj-$(CONFIG_ACPI) += acpi/ obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o suspend_asm.o -obj-$(CONFIG_ACPI) += acpi.o -obj-$(CONFIG_ACPI_SLEEP) += wakeup.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o diff -Nru a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c --- a/arch/x86_64/kernel/aperture.c Wed Jan 29 08:17:37 2003 +++ b/arch/x86_64/kernel/aperture.c Sat Mar 22 09:40:35 2003 @@ -105,7 +105,8 @@ if (!fix && !fallback_aper_force) return; - printk("Your BIOS is broken and doesn't leave a aperture memory hole\n"); + printk("Your BIOS doesn't leave a aperture memory hole\n"); + printk("Please enable the IOMMU option in the BIOS setup\n"); aper_alloc = allocate_aperture(); if (!aper_alloc) return; diff -Nru a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c --- a/arch/x86_64/kernel/apic.c Sat Mar 8 18:01:10 2003 +++ b/arch/x86_64/kernel/apic.c Sat Mar 22 10:50:30 2003 @@ -408,7 +408,7 @@ if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ apic_write(APIC_ESR, 0); value = apic_read(APIC_ESR); - printk("ESR value before enabling vector: %08x\n", value); + Dprintk("ESR value before enabling vector: %08x\n", value); value = ERROR_APIC_VECTOR; // enables sending errors apic_write_around(APIC_LVTERR, value); @@ -418,7 +418,7 @@ if (maxlvt > 3) apic_write(APIC_ESR, 0); value = apic_read(APIC_ESR); - printk("ESR value after enabling vector: %08x\n", value); + Dprintk("ESR value after enabling vector: %08x\n", value); } else { if (esr_disable) /* @@ -1080,9 +1080,10 @@ if (nmi_watchdog == NMI_LOCAL_APIC) check_nmi_watchdog(); #ifdef CONFIG_X86_IO_APIC - if (smp_found_config) - if (!skip_ioapic_setup && nr_ioapics) + if (smp_found_config && !skip_ioapic_setup && nr_ioapics) setup_IO_APIC(); + else + nr_ioapics = 0; #endif setup_boot_APIC_clock(); diff -Nru a/arch/x86_64/kernel/bluesmoke.c b/arch/x86_64/kernel/bluesmoke.c --- a/arch/x86_64/kernel/bluesmoke.c Sun Mar 2 18:13:32 2003 +++ b/arch/x86_64/kernel/bluesmoke.c Sun Mar 23 09:02:00 2003 @@ -1,65 +1,87 @@ /* - * arch/x86_64/kernel/bluesmoke.c - x86-64 Machine Check Exception Reporting - * - -RED-PEN: need to add power management to restore after S3 wakeup. - + * Machine check handler. + * K8 parts Copyright 2002,2003 Andi Kleen, SuSE Labs. + * Rest from unknown author(s). */ - +#include #include #include #include -#include -#include -#include -#include +#include +#include +#include #include -#include #include -#include -#include -#include +#include +#include +#include -#ifdef CONFIG_X86_MCE +static int mce_disabled __initdata; +static unsigned long mce_cpus; -static int mce_disabled __initdata = 0; +/* + * Machine Check Handler For PII/PIII/K7 + */ static int banks; +static unsigned long ignored_banks, disabled_banks; +/* Machine Check on everything dubious. This is a good setting + for device driver testing. */ +#define K8_DRIVER_DEBUG ((1<<13)-1) +/* Report RAM errors and Hyper Transport Problems, but ignore Device + aborts and GART errors. */ +#define K8_NORMAL_OP 0xff -/* - * Machine Check Handler For Hammer - */ +#ifdef CONFIG_MCE_DEBUG +static u32 k8_nb_flags __initdata = K8_DRIVER_DEBUG; +#else +static u32 k8_nb_flags __initdata = K8_NORMAL_OP; +#endif -static void hammer_machine_check(struct pt_regs * regs, long error_code) +static void generic_machine_check(struct pt_regs * regs, long error_code) { int recover=1; u32 alow, ahigh, high, low; u32 mcgstl, mcgsth; int i; + preempt_disable(); + rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); if(mcgstl&(1<<0)) /* Recoverable ? */ recover=0; printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", smp_processor_id(), mcgsth, mcgstl); - preempt_disable(); - for (i=0;i:%016lx RSP %016lx\n", + regs->cs, regs->rip, regs->rsp); + + for(i=0;ibus->number==0 && PCI_FUNC(dev->devfn)==3 && + PCI_SLOT(dev->devfn) == (24+cpu)) + return dev; + } + return NULL; +} -static void mce_checkregs (void *info) +static void check_k8_nb(void) { - u32 low, high; - int i; + struct pci_dev *nb; + nb = find_k8_nb(); + if (nb == NULL) + return; - for (i=0; irip, regs->rsp); + + others: + generic_machine_check(regs, error_code); + preempt_enable(); +} + +static struct timer_list mcheck_timer; +int mcheck_interval = 30*HZ; -static void mce_timerfunc (unsigned long data) +#ifndef CONFIG_SMP +static void mcheck_timer_handler(unsigned long data) { - on_each_cpu (mce_checkregs, NULL, 1, 1); + k8_machine_check(NULL,0); + mcheck_timer.expires = jiffies + mcheck_interval; + add_timer(&mcheck_timer); +} +#else + +/* SMP needs a process context trampoline because smp_call_function cannot be + called from interrupt context. */ - /* Refresh the timer. */ - mce_timer.expires = jiffies + MCE_RATE; - add_timer (&mce_timer); +static void mcheck_timer_other(void *data) +{ + k8_machine_check(NULL, 0); +} + +static void mcheck_timer_dist(void *data) +{ + smp_call_function(mcheck_timer_other,0,0,0); + k8_machine_check(NULL, 0); + mcheck_timer.expires = jiffies + mcheck_interval; + add_timer(&mcheck_timer); +} + +static void mcheck_timer_handler(unsigned long data) +{ + static DECLARE_WORK(mcheck_work, mcheck_timer_dist, NULL); + schedule_work(&mcheck_work); } #endif +static int nok8 __initdata; + +static void __init k8_mcheck_init(struct cpuinfo_x86 *c) +{ + u64 cap; + int i; + struct pci_dev *nb; + + if (!test_bit(X86_FEATURE_MCE, &c->x86_capability) || + !test_bit(X86_FEATURE_MCA, &c->x86_capability)) + return; + + rdmsrl(MSR_IA32_MCG_CAP, cap); + banks = cap&0xff; + machine_check_vector = k8_machine_check; + for (i = 0; i < banks; i++) { + u64 val = ((1UL<devfn, reg, reg2); + ignored_banks |= (1UL<<4); + } + + set_in_cr4(X86_CR4_MCE); + + if (mcheck_interval && (smp_processor_id() == 0)) { + init_timer(&mcheck_timer); + mcheck_timer.function = (void (*)(unsigned long))mcheck_timer_handler; + mcheck_timer.expires = jiffies + mcheck_interval; + add_timer(&mcheck_timer); + } + + printk(KERN_INFO "Machine Check Reporting enabled for CPU#%d\n", smp_processor_id()); +} /* - * Set up machine check reporting for processors with Intel style MCE + * Set up machine check reporting for Intel processors */ -static void __init hammer_mcheck_init(struct cpuinfo_x86 *c) +static void __init generic_mcheck_init(struct cpuinfo_x86 *c) { u32 l, h; int i; @@ -154,33 +310,36 @@ * Check for MCE support */ - if( !test_bit(X86_FEATURE_MCE, c->x86_capability) ) + if( !test_bit(X86_FEATURE_MCE, &c->x86_capability) ) return; - /* Check for PPro style MCA */ - if( !test_bit(X86_FEATURE_MCA, c->x86_capability) ) + /* + * Check for PPro style MCA + */ + + if( !test_bit(X86_FEATURE_MCA, &c->x86_capability) ) return; /* Ok machine check is available */ - machine_check_vector = hammer_machine_check; + + machine_check_vector = generic_machine_check; wmb(); if(done==0) - printk(KERN_INFO "Machine check architecture supported.\n"); + printk(KERN_INFO "Intel machine check architecture supported.\n"); rdmsr(MSR_IA32_MCG_CAP, l, h); - if(l&(1<<8)) /* Control register present ? */ + if(l&(1<<8)) wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); banks = l&0xff; - for(i=0; ix86_vendor) - { + switch(c->x86_vendor) { case X86_VENDOR_AMD: - hammer_mcheck_init(c); -#ifdef CONFIG_X86_MCE_NONFATAL - if (timerset == 0) { - /* Set the timer to check for non-fatal - errors every MCE_RATE seconds */ - init_timer (&mce_timer); - mce_timer.expires = jiffies + MCE_RATE; - mce_timer.data = 0; - mce_timer.function = &mce_timerfunc; - add_timer (&mce_timer); - timerset = 1; - printk(KERN_INFO "Machine check exception polling timer started.\n"); - } -#endif + if (c->x86 == 15 && !nok8) { + k8_mcheck_init(c); break; - + } + /* FALL THROUGH */ default: + case X86_VENDOR_INTEL: + generic_mcheck_init(c); break; } } @@ -224,16 +375,33 @@ return 0; } + +/* mce=off disable machine check + mce=nok8 disable k8 specific features + mce=disable disable bank NUMBER + mce=enable enable bank number + mce=device Enable device driver test reporting in NB + mce=NUMBER mcheck timer interval number seconds. + Can be also comma separated in a single mce= */ static int __init mcheck_enable(char *str) { - mce_disabled = -1; + char *p; + while ((p = strsep(&str,",")) != NULL) { + if (isdigit(*p)) + mcheck_interval = simple_strtol(p,NULL,0) * HZ; + else if (!strcmp(p,"off")) + mce_disabled = 1; + else if (!strncmp(p,"enable",6)) + disabled_banks &= ~(1< level2_kernel_pgt (so that __va works even before pagetable_init) */ .org 0xb000 +ENTRY(wakeup_level4_pgt) + .quad 0x0000000000102007 /* -> level3_ident_pgt */ + .fill 255,8,0 + .quad 0x000000000010a007 + .fill 254,8,0 + /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ + .quad 0x0000000000103007 /* -> level3_kernel_pgt */ + +.org 0xc000 .data .align 16 @@ -371,3 +380,4 @@ .quad 0 .quad 0 .endr + diff -Nru a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c --- a/arch/x86_64/kernel/head64.c Sun Mar 9 08:28:23 2003 +++ b/arch/x86_64/kernel/head64.c Sat Mar 22 09:11:16 2003 @@ -15,6 +15,7 @@ #include #include #include +#include /* Don't add a printk in there. printk relies on the PDA which is not initialized yet. */ @@ -51,7 +52,7 @@ printk("old bootloader convention, maybe loadlin?\n"); } command_line = (char *) ((u64)(new_data)); - memcpy(saved_command_line, command_line, 2048); + memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); printk("Bootdata ok (command line is %s)\n", saved_command_line); } diff -Nru a/arch/x86_64/kernel/i387.c b/arch/x86_64/kernel/i387.c --- a/arch/x86_64/kernel/i387.c Tue Nov 12 15:35:38 2002 +++ b/arch/x86_64/kernel/i387.c Sat Mar 22 11:34:31 2003 @@ -42,7 +42,7 @@ /* clean state in init */ stts(); - clear_thread_flag(TIF_USEDFPU); + current_thread_info()->status = 0; current->used_math = 0; } @@ -51,13 +51,12 @@ * so initialize it and set the mxcsr to its default. * remeber the current task has used the FPU. */ -void init_fpu(void) +void init_fpu(struct task_struct *child) { - struct task_struct *me = current; - memset(&me->thread.i387.fxsave, 0, sizeof(struct i387_fxsave_struct)); - me->thread.i387.fxsave.cwd = 0x37f; - me->thread.i387.fxsave.mxcsr = 0x1f80; - me->used_math = 1; + memset(&child->thread.i387.fxsave, 0, sizeof(struct i387_fxsave_struct)); + child->thread.i387.fxsave.cwd = 0x37f; + child->thread.i387.fxsave.mxcsr = 0x1f80; + child->used_math = 1; } /* @@ -81,7 +80,7 @@ if (!tsk->used_math) return 0; tsk->used_math = 0; /* trigger finit */ - if (test_thread_flag(TIF_USEDFPU)) { + if (tsk->thread_info->status & TS_USEDFPU) { err = save_i387_checking((struct i387_fxsave_struct *)buf); if (err) return err; stts(); @@ -99,7 +98,7 @@ int get_fpregs(struct user_i387_struct *buf, struct task_struct *tsk) { - empty_fpu(tsk); + init_fpu(tsk); return __copy_to_user((void *)buf, &tsk->thread.i387.fxsave, sizeof(struct user_i387_struct)) ? -EFAULT : 0; } diff -Nru a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c --- a/arch/x86_64/kernel/nmi.c Tue Feb 25 02:43:11 2003 +++ b/arch/x86_64/kernel/nmi.c Sat Mar 22 10:57:48 2003 @@ -25,13 +25,15 @@ #include #include #include +#include +#include extern void default_do_nmi(struct pt_regs *); unsigned int nmi_watchdog = NMI_LOCAL_APIC; static unsigned int nmi_hz = HZ; unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ -extern void show_registers(struct pt_regs *regs); +int nmi_watchdog_disabled; #define K7_EVNTSEL_ENABLE (1 << 22) #define K7_EVNTSEL_INT (1 << 20) @@ -251,15 +253,13 @@ alert_counter[i] = 0; } -void nmi_watchdog_tick (struct pt_regs * regs) +void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason) { + if (nmi_watchdog_disabled) + return; + + int sum, cpu = safe_smp_processor_id(); - /* - * Since current_thread_info()-> is always on the stack, and we - * always switch the stack NMI-atomically, it's safe to use - * smp_processor_id(). - */ - int sum, cpu = smp_processor_id(); sum = read_pda(apic_timer_irqs); if (last_irq_sums[cpu] == sum) { @@ -269,6 +269,10 @@ */ alert_counter[cpu]++; if (alert_counter[cpu] == 5*nmi_hz) { + if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_BAD) { + alert_counter[cpu] = 0; + return; + } spin_lock(&nmi_print_lock); /* * We are in trouble anyway, lets at least try diff -Nru a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c --- a/arch/x86_64/kernel/pci-gart.c Tue Mar 18 13:19:53 2003 +++ b/arch/x86_64/kernel/pci-gart.c Sun Mar 23 16:23:56 2003 @@ -8,7 +8,7 @@ * See Documentation/DMA-mapping.txt for the interface specification. * * Copyright 2002 Andi Kleen, SuSE Labs. - * $Id: pci-gart.c,v 1.12 2002/09/19 19:25:32 ak Exp $ + * $Id: pci-gart.c,v 1.20 2003/03/12 08:23:29 ak Exp $ */ /* @@ -19,9 +19,12 @@ possible future tuning: fast path for sg streaming mappings - more intelligent flush strategy - flush only a single NB? + more intelligent flush strategy - flush only a single NB? flush only when + gart area fills up and alloc_iommu wraps. + don't flush on allocation - need to unmap the gart area first to avoid prefetches + by the CPU move boundary between IOMMU and AGP in GART dynamically - could use exact fit in the gart in alloc_consistent, not order of two. + */ #include @@ -49,7 +52,11 @@ int no_iommu; static int no_agp; +#ifdef CONFIG_IOMMU_DEBUG int force_mmu = 1; +#else +int force_mmu = 0; +#endif extern int fallback_aper_order; extern int fallback_aper_force; @@ -58,10 +65,9 @@ static spinlock_t iommu_bitmap_lock = SPIN_LOCK_UNLOCKED; static unsigned long *iommu_gart_bitmap; /* guarded by iommu_bitmap_lock */ -#define GPTE_MASK 0xfffffff000 #define GPTE_VALID 1 #define GPTE_COHERENT 2 -#define GPTE_ENCODE(x,flag) (((x) & 0xfffffff0) | ((x) >> 28) | GPTE_VALID | (flag)) +#define GPTE_ENCODE(x) (((x) & 0xfffff000) | (((x) >> 32) << 4) | GPTE_VALID | GPTE_COHERENT) #define GPTE_DECODE(x) (((x) & 0xfffff000) | (((u64)(x) & 0xff0) << 28)) #define for_all_nb(dev) \ @@ -72,7 +78,6 @@ #define EMERGENCY_PAGES 32 /* = 128KB */ #ifdef CONFIG_AGP -extern int agp_amdk8_init(void); extern int agp_init(void); #define AGPEXTERN extern #else @@ -130,7 +135,7 @@ { void *memory; int gfp = GFP_ATOMIC; - int order, i; + int i; unsigned long iommu_page; if (hwdev == NULL || hwdev->dma_mask < 0xffffffff || no_iommu) @@ -140,15 +145,15 @@ * First try to allocate continuous and use directly if already * in lowmem. */ - order = get_order(size); - memory = (void *)__get_free_pages(gfp, order); + size = round_up(size, PAGE_SIZE); + memory = (void *)__get_free_pages(gfp, get_order(size)); if (memory == NULL) { return NULL; } else { int high = (unsigned long)virt_to_bus(memory) + size >= 0xffffffff; int mmu = high; - if (force_mmu) + if (force_mmu && !(gfp & GFP_DMA)) mmu = 1; if (no_iommu) { if (high) goto error; @@ -161,19 +166,21 @@ } } - iommu_page = alloc_iommu(1<>= PAGE_SHIFT; + + iommu_page = alloc_iommu(size); if (iommu_page == -1) goto error; /* Fill in the GATT, allocating pages as needed. */ - for (i = 0; i < 1< 0) atomic_inc(&virt_to_page(mem)->count); phys_mem = virt_to_phys(mem); - BUG_ON(phys_mem & ~PTE_MASK); - iommu_gatt_base[iommu_page + i] = GPTE_ENCODE(phys_mem,GPTE_COHERENT); + BUG_ON(phys_mem & ~PHYSICAL_PAGE_MASK); + iommu_gatt_base[iommu_page + i] = GPTE_ENCODE(phys_mem); } flush_gart(); @@ -181,7 +188,7 @@ return memory; error: - free_pages((unsigned long)memory, order); + free_pages((unsigned long)memory, get_order(size)); return NULL; } @@ -193,30 +200,32 @@ void *vaddr, dma_addr_t bus) { u64 pte; - int order = get_order(size); unsigned long iommu_page; int i; + size = round_up(size, PAGE_SIZE); if (bus < iommu_bus_base || bus > iommu_bus_base + iommu_size) { - free_pages((unsigned long)vaddr, order); + free_pages((unsigned long)vaddr, get_order(size)); return; } + size >>= PAGE_SHIFT; iommu_page = (bus - iommu_bus_base) / PAGE_SIZE; - for (i = 0; i < 1<>10); return 0; @@ -530,8 +547,10 @@ off don't use the IOMMU leak turn on simple iommu leak tracing (only when CONFIG_IOMMU_LEAK is on) memaper[=order] allocate an own aperture over RAM with size 32MB^order. + noforce don't force IOMMU usage. Should be fastest. + force Force IOMMU and turn on unmap debugging. */ -__init int iommu_setup(char *opt, char **end) +__init int iommu_setup(char *opt) { int arg; char *p = opt; @@ -552,17 +571,21 @@ fallback_aper_order = arg; } #ifdef CONFIG_IOMMU_LEAK - if (!memcmp(p,"leak", 4)) + if (!memcmp(p,"leak", 4)) { leak_trace = 1; + p += 4; + if (*p == '=') ++p; + if (isdigit(*p) && get_option(&p, &arg)) + iommu_leak_pages = arg; + } else #endif if (isdigit(*p) && get_option(&p, &arg)) iommu_size = arg; do { - if (*p == ' ' || *p == 0) { - *end = p; + if (*p == ' ' || *p == 0) return 0; - } } while (*p++ != ','); } + return 1; } diff -Nru a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c --- a/arch/x86_64/kernel/process.c Sun Mar 9 16:22:16 2003 +++ b/arch/x86_64/kernel/process.c Sat Mar 22 11:30:54 2003 @@ -192,6 +192,8 @@ fs,fsindex,gs,gsindex,shadowgs); printk("CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, es, cr0); printk("CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, cr4); + + show_trace(®s->rsp); } extern void load_gs_index(unsigned); @@ -260,6 +262,14 @@ (((u32)desc->base2) << 24); } +/* + * This gets called before we allocate a new thread and copy + * the current task into it. + */ +void prepare_to_copy(struct task_struct *tsk) +{ + unlazy_fpu(tsk); +} int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, unsigned long unused, @@ -294,9 +304,6 @@ asm("movl %%es,%0" : "=m" (p->thread.es)); asm("movl %%ds,%0" : "=m" (p->thread.ds)); - unlazy_fpu(me); - p->thread.i387 = me->thread.i387; - if (unlikely(me->thread.io_bitmap_ptr != NULL)) { p->thread.io_bitmap_ptr = kmalloc((IO_BITMAP_SIZE+1)*4, GFP_KERNEL); if (!p->thread.io_bitmap_ptr) @@ -314,7 +321,7 @@ err = ia32_child_tls(p, childregs); else #endif - err = do_arch_prctl(p, ARCH_SET_FS, childregs->r10); + err = do_arch_prctl(p, ARCH_SET_FS, childregs->r8); if (err) goto out; } diff -Nru a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c --- a/arch/x86_64/kernel/ptrace.c Sun Mar 9 04:38:18 2003 +++ b/arch/x86_64/kernel/ptrace.c Sat Mar 22 10:22:28 2003 @@ -240,8 +240,8 @@ unsigned long tmp; ret = -EIO; - if ((addr & 3) || addr < 0 || - addr > sizeof(struct user) - 3) + if ((addr & 7) || addr < 0 || + addr > sizeof(struct user) - 7) break; tmp = 0; /* Default return condition */ @@ -250,7 +250,7 @@ if(addr >= (long) &dummy->u_debugreg[0] && addr <= (long) &dummy->u_debugreg[7]){ addr -= (long) &dummy->u_debugreg[0]; - addr = addr >> 2; + addr = addr >> 3; tmp = child->thread.debugreg[addr]; } ret = put_user(tmp,(unsigned long *) data); @@ -268,8 +268,8 @@ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ ret = -EIO; - if ((addr & 3) || addr < 0 || - addr > sizeof(struct user) - 3) + if ((addr & 7) || addr < 0 || + addr > sizeof(struct user) - 7) break; if (addr < sizeof(struct user_regs_struct)) { @@ -290,6 +290,11 @@ if(addr < (long) &dummy->u_debugreg[4] && ((unsigned long) data) >= TASK_SIZE-3) break; + if (addr == (long) &dummy->u_debugreg[6]) { + if (data >> 32) + goto out_tsk; + } + if(addr == (long) &dummy->u_debugreg[7]) { data &= ~DR_CONTROL_RESERVED; for(i=0; i<4; i++) @@ -298,7 +303,7 @@ } addr -= (long) &dummy->u_debugreg; - addr = addr >> 2; + addr = addr >> 3; child->thread.debugreg[addr] = data; ret = 0; } diff -Nru a/arch/x86_64/kernel/reboot.c b/arch/x86_64/kernel/reboot.c --- a/arch/x86_64/kernel/reboot.c Mon Oct 14 02:42:47 2002 +++ b/arch/x86_64/kernel/reboot.c Sat Mar 22 10:30:29 2003 @@ -101,7 +101,6 @@ * Stop all CPUs and turn off local APICs and the IO-APIC, so * other OSs see a clean IRQ state. */ - if (notify_die(DIE_STOP,"cpustop",0,0) != NOTIFY_BAD) smp_send_stop(); disable_IO_APIC(); #endif diff -Nru a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c --- a/arch/x86_64/kernel/setup.c Sat Feb 15 16:47:07 2003 +++ b/arch/x86_64/kernel/setup.c Sun Mar 23 08:46:28 2003 @@ -197,12 +197,15 @@ if (!memcmp(from, "acpi=off", 8)) acpi_disabled = 1; + if (!memcmp(from, "disableapic", 11)) + disable_apic = 1; + if (!memcmp(from, "mem=", 4)) parse_memopt(from+4, &from); #ifdef CONFIG_GART_IOMMU if (!memcmp(from,"iommu=",6)) { - iommu_setup(from+6, &from); + iommu_setup(from+6); } #endif diff -Nru a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c --- a/arch/x86_64/kernel/setup64.c Wed Mar 5 01:43:54 2003 +++ b/arch/x86_64/kernel/setup64.c Sun Mar 23 09:06:01 2003 @@ -40,7 +40,7 @@ char boot_cpu_stack[IRQSTACKSIZE] __cacheline_aligned; unsigned long __supported_pte_mask = ~0UL; -static int do_not_nx = 0; +static int do_not_nx = 1; static int __init nonx_setup(char *str) { @@ -98,6 +98,8 @@ pda->cpudata_offset = 0; pda->kernelstack = (unsigned long)stack_thread_info() - PDA_STACKOFFSET + THREAD_SIZE; + pda->active_mm = &init_mm; + pda->mmu_state = 0; if (cpu == 0) { /* others are initialized in smpboot.c */ @@ -121,8 +123,6 @@ asm volatile("movq %0,%%cr3" :: "r" (__pa(level4))); pda->irqstackptr += IRQSTACKSIZE-64; - pda->active_mm = &init_mm; - pda->mmu_state = 0; } #define EXCEPTION_STK_ORDER 0 /* >= N_EXCEPTION_STACKS*EXCEPTION_STKSZ */ diff -Nru a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c --- a/arch/x86_64/kernel/signal.c Wed Mar 5 01:43:54 2003 +++ b/arch/x86_64/kernel/signal.c Sat Mar 22 10:44:35 2003 @@ -225,6 +225,7 @@ rsp = regs->rsp - 128; /* This is the X/Open sanctioned signal stack switching. */ + /* RED-PEN: redzone on that stack? */ if (ka->sa.sa_flags & SA_ONSTACK) { if (sas_ss_flags(rsp) == 0) rsp = current->sas_ss_sp + current->sas_ss_size; @@ -433,7 +434,8 @@ * have been cleared if the watchpoint triggered * inside the kernel. */ - __asm__("movq %0,%%db7" : : "r" (current->thread.debugreg[7])); + if (current->thread.debugreg[7]) + asm volatile("movq %0,%%db7" : : "r" (current->thread.debugreg[7])); /* Whee! Actually deliver the signal. */ handle_signal(signr, &info, oldset, regs); diff -Nru a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c --- a/arch/x86_64/kernel/smp.c Sun Mar 2 18:13:32 2003 +++ b/arch/x86_64/kernel/smp.c Sat Mar 22 09:34:26 2003 @@ -485,16 +485,16 @@ } } - /* Slow. Should be only used for debugging. */ int slow_smp_processor_id(void) { int stack_location; unsigned long sp = (unsigned long)&stack_location; - int cpu; - unsigned long mask; + int offset = 0, cpu; + + for (offset = 0; (cpu_online_map >> offset); offset = cpu + 1) { + cpu = ffz(~(cpu_online_map >> offset)); - for_each_cpu(cpu, mask) { if (sp >= (u64)cpu_pda[cpu].irqstackptr - IRQSTACKSIZE && sp <= (u64)cpu_pda[cpu].irqstackptr) return cpu; diff -Nru a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c --- a/arch/x86_64/kernel/smpboot.c Tue Feb 25 10:47:32 2003 +++ b/arch/x86_64/kernel/smpboot.c Sat Mar 22 10:45:29 2003 @@ -318,8 +318,6 @@ */ smp_store_cpu_info(cpuid); - notify_die(DIE_CPUINIT, "cpuinit", NULL, 0); - local_irq_disable(); /* @@ -898,6 +896,8 @@ */ if (!skip_ioapic_setup && nr_ioapics) setup_IO_APIC(); + else + nr_ioapics = 0; setup_boot_APIC_clock(); diff -Nru a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c --- a/arch/x86_64/kernel/suspend.c Wed Mar 5 01:43:54 2003 +++ b/arch/x86_64/kernel/suspend.c Sun Mar 23 09:06:01 2003 @@ -28,7 +28,7 @@ #include #include -static struct saved_context saved_context; +struct saved_context saved_context; unsigned long saved_context_eax, saved_context_ebx, saved_context_ecx, saved_context_edx; unsigned long saved_context_esp, saved_context_ebp, saved_context_esi, saved_context_edi; diff -Nru a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c --- a/arch/x86_64/kernel/traps.c Mon Mar 17 21:32:24 2003 +++ b/arch/x86_64/kernel/traps.c Sat Mar 22 11:29:44 2003 @@ -110,7 +110,7 @@ } #endif -static inline unsigned long *in_exception_stack(int cpu, unsigned long stack) +unsigned long *in_exception_stack(int cpu, unsigned long stack) { int k; for (k = 0; k < N_EXCEPTION_STACKS; k++) { @@ -249,7 +249,7 @@ void dump_stack(void) { unsigned long dummy; - show_stack(&dummy); + show_trace(&dummy); } void show_registers(struct pt_regs *regs) @@ -344,7 +344,6 @@ show_registers(regs); bust_spinlocks(0); spin_unlock_irq(&die_lock); - notify_die(DIE_OOPS, (char *)str, regs, err); do_exit(SIGSEGV); } @@ -419,6 +418,8 @@ #define DO_ERROR(trapnr, signr, str, name) \ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ { \ + if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) == NOTIFY_BAD) \ + return; \ do_trap(trapnr, signr, str, regs, error_code, NULL); \ } @@ -430,10 +431,13 @@ info.si_errno = 0; \ info.si_code = sicode; \ info.si_addr = (void *)siaddr; \ + if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) == NOTIFY_BAD) \ + return; \ do_trap(trapnr, signr, str, regs, error_code, &info); \ } DO_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->rip) +DO_ERROR( 3, SIGTRAP, "int3", int3); DO_ERROR( 4, SIGSEGV, "overflow", overflow) DO_ERROR( 5, SIGSEGV, "bounds", bounds) DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->rip) @@ -446,13 +450,6 @@ DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr2()) DO_ERROR(18, SIGSEGV, "reserved", reserved) -asmlinkage void do_int3(struct pt_regs * regs, long error_code) -{ - if (notify_die(DIE_INT3, "int3", regs, error_code) == NOTIFY_BAD) - return; - do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); -} - extern void dump_pagetable(unsigned long); asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) @@ -493,6 +490,8 @@ regs->rip = fixup->fixup; return; } + notify_die(DIE_GPF, "general protection fault", regs, error_code, + 13, SIGSEGV); die("general protection fault", regs, error_code); } } @@ -537,14 +536,14 @@ * so it must be the NMI watchdog. */ if (nmi_watchdog) { - nmi_watchdog_tick(regs); + nmi_watchdog_tick(regs,reason); return; } #endif unknown_nmi_error(reason, regs); return; } - if (notify_die(DIE_NMI, "nmi", regs, reason) == NOTIFY_BAD) + if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_BAD) return; if (reason & 0x80) mem_parity_error(reason, regs); @@ -569,6 +568,7 @@ #ifdef CONFIG_CHECKING { + /* RED-PEN interaction with debugger - could destroy gs */ unsigned long gs; struct x8664_pda *pda = cpu_pda + safe_smp_processor_id(); rdmsrl(MSR_GS_BASE, gs); @@ -583,9 +583,6 @@ conditional_sti(regs); - if (notify_die(DIE_DEBUG, "debug", regs, error_code) == NOTIFY_BAD) - return; - /* Mask out spurious debug traps due to lazy DR7 setting */ if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { if (!tsk->thread.debugreg[7]) { @@ -618,17 +615,22 @@ info.si_signo = SIGTRAP; info.si_errno = 0; info.si_code = TRAP_BRKPT; - info.si_addr = ((regs->cs & 3) == 0) ? (void *)tsk->thread.rip : - (void *)regs->rip; + if ((regs->cs & 3) == 0) + goto clear_dr7; + + info.si_addr = (void *)regs->rip; force_sig_info(SIGTRAP, &info, tsk); clear_dr7: - asm("movq %0,%%db7"::"r"(0UL)); + asm volatile("movq %0,%%db7"::"r"(0UL)); + notify_die(DIE_DEBUG, "debug", regs, error_code, 1, SIGTRAP); return; clear_TF_reenable: set_tsk_thread_flag(tsk, TIF_SINGLESTEP); clear_TF: + /* RED-PEN could cause spurious errors */ + if (notify_die(DIE_DEBUG, "debug2", regs, error_code, 1, SIGTRAP) != NOTIFY_BAD) regs->eflags &= ~TF_MASK; return; } @@ -775,9 +777,9 @@ clts(); /* Allow maths ops (or we recurse) */ if (!me->used_math) - init_fpu(); + init_fpu(me); restore_fpu_checking(&me->thread.i387.fxsave); - set_thread_flag(TIF_USEDFPU); + me->thread_info->status |= TS_USEDFPU; } asmlinkage void math_emulate(void) @@ -787,7 +789,7 @@ void do_call_debug(struct pt_regs *regs) { - notify_die(DIE_CALL, "debug call", regs, 0); + notify_die(DIE_CALL, "debug call", regs, 0, 255, SIGINT); } void __init trap_init(void) @@ -819,8 +821,6 @@ set_intr_gate(KDB_VECTOR, call_debug); - notify_die(DIE_TRAPINIT, "traps initialized", 0, 0); - /* * Should be a barrier for any external CPU state. */ diff -Nru a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c --- a/arch/x86_64/mm/fault.c Wed Jan 22 17:31:58 2003 +++ b/arch/x86_64/mm/fault.c Sat Mar 22 11:12:34 2003 @@ -57,29 +57,41 @@ } } +static int bad_address(void *p) +{ + unsigned long dummy; + return __get_user(dummy, (unsigned long *)p); +} + void dump_pagetable(unsigned long address) { - static char *name[] = { "PML4", "PGD", "PDE", "PTE" }; - int i, shift; - unsigned long page; + pml4_t *pml4; + asm("movq %%cr3,%0" : "=r" (pml4)); + + pml4 = __va((unsigned long)pml4 & PHYSICAL_PAGE_MASK); + pml4 += pml4_index(address); + printk("PML4 %lx ", pml4_val(*pml4)); + if (bad_address(pml4)) goto bad; + if (!pml4_present(*pml4)) goto ret; + + pgd_t *pgd = __pgd_offset_k((pgd_t *)pml4_page(*pml4), address); + if (bad_address(pgd)) goto bad; + printk("PGD %lx ", pgd_val(*pgd)); + if (!pgd_present(*pgd)) goto ret; + + pmd_t *pmd = pmd_offset(pgd, address); + if (bad_address(pmd)) goto bad; + printk("PMD %lx ", pmd_val(*pmd)); + if (!pmd_present(*pmd)) goto ret; - shift = 9+9+9+12; - address &= ~0xFFFF000000000000UL; - asm("movq %%cr3,%0" : "=r" (page)); - for (i = 0; i < 4; i++) { - unsigned long *padr = (unsigned long *) __va(page); - padr += (address >> shift) & 0x1FFU; - if (__get_user(page, padr)) { - printk("%s: bad %p\n", name[i], padr); - break; - } - printk("%s: %016lx ", name[i], page); - if ((page & (1 | (1<<7))) != 1) /* Not present or 2MB page */ - break; - page &= ~0xFFFUL; - shift -= (i == 0) ? 12 : 9; - } + pte_t *pte = pte_offset_kernel(pmd, address); + if (bad_address(pte)) goto bad; + printk("PTE %lx", pte_val(*pte)); +ret: printk("\n"); + return; +bad: + printk("BAD\n"); } int page_fault_trace; diff -Nru a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c --- a/arch/x86_64/mm/ioremap.c Mon Feb 24 23:13:24 2003 +++ b/arch/x86_64/mm/ioremap.c Sat Mar 22 11:29:07 2003 @@ -150,7 +150,7 @@ */ offset = phys_addr & ~PAGE_MASK; phys_addr &= PAGE_MASK; - size = PAGE_ALIGN(last_addr) - phys_addr; + size = PAGE_ALIGN(last_addr+1) - phys_addr; /* * Ok, go for it.. diff -Nru a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c --- a/arch/x86_64/mm/k8topology.c Wed Feb 5 18:46:01 2003 +++ b/arch/x86_64/mm/k8topology.c Sat Mar 22 10:14:05 2003 @@ -21,7 +21,7 @@ #include #include -static int find_northbridge(void) +static __init int find_northbridge(void) { int num; @@ -45,7 +45,8 @@ { unsigned long prevbase; struct node nodes[MAXNODE]; - int nodeid, numnodes, maxnode, i, nb; + int nodeid, i, nb; + int found = 0; nb = find_northbridge(); if (nb < 0) @@ -53,12 +54,13 @@ printk(KERN_INFO "Scanning NUMA topology in Northbridge %d\n", nb); - numnodes = (read_pci_config(0, nb, 0, 0x60 ) >> 4) & 3; + numnodes = (1 << ((read_pci_config(0, nb, 0, 0x60 ) >> 4) & 3)); + + printk(KERN_INFO "Assuming %d nodes\n", numnodes - 1); memset(&nodes,0,sizeof(nodes)); prevbase = 0; - maxnode = -1; - for (i = 0; i < MAXNODE; i++) { + for (i = 0; i < numnodes; i++) { unsigned long base,limit; base = read_pci_config(0, nb, 1, 0x40 + i*8); @@ -66,18 +68,16 @@ nodeid = limit & 3; if (!limit) { - printk(KERN_INFO "Skipping node entry %d (base %lx)\n", i, base); - continue; + printk(KERN_ERR "Skipping node entry %d (base %lx)\n", i, base); + return -1; } if ((base >> 8) & 3 || (limit >> 8) & 3) { printk(KERN_ERR "Node %d using interleaving mode %lx/%lx\n", nodeid, (base>>8)&3, (limit>>8) & 3); return -1; } - if (nodeid > maxnode) - maxnode = nodeid; if ((1UL << nodeid) & nodes_present) { - printk("Node %d already present. Skipping\n", nodeid); + printk(KERN_INFO "Node %d already present. Skipping\n", nodeid); continue; } @@ -98,17 +98,19 @@ base = start; if (limit > end) limit = end; - if (limit == base) + if (limit == base) { + printk(KERN_ERR "Empty node %d\n", nodeid); continue; + } if (limit < base) { - printk(KERN_INFO"Node %d bogus settings %lx-%lx. Ignored.\n", + printk(KERN_ERR "Node %d bogus settings %lx-%lx.\n", nodeid, base, limit); - continue; + return -1; } /* Could sort here, but pun for now. Should not happen anyroads. */ if (prevbase > base) { - printk(KERN_INFO "Node map not sorted %lx,%lx\n", + printk(KERN_ERR "Node map not sorted %lx,%lx\n", prevbase,base); return -1; } @@ -116,23 +118,26 @@ printk(KERN_INFO "Node %d MemBase %016lx Limit %016lx\n", nodeid, base, limit); + found++; + nodes[nodeid].start = base; nodes[nodeid].end = limit; prevbase = base; } - if (maxnode <= 0) + if (!found) return -1; - memnode_shift = compute_hash_shift(nodes,maxnode,end); + memnode_shift = compute_hash_shift(nodes); if (memnode_shift < 0) { printk(KERN_ERR "No NUMA node hash function found. Contact maintainer\n"); return -1; } printk(KERN_INFO "Using node hash shift of %d\n", memnode_shift); - early_for_all_nodes(i) { + for (i = 0; i < numnodes; i++) { + if (nodes[i].start != nodes[i].end) setup_node_bootmem(i, nodes[i].start, nodes[i].end); } diff -Nru a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c --- a/arch/x86_64/mm/numa.c Tue Feb 11 06:01:39 2003 +++ b/arch/x86_64/mm/numa.c Sat Mar 22 10:13:46 2003 @@ -26,11 +26,10 @@ static int numa_off __initdata; unsigned long nodes_present; -int maxnode; static int emunodes __initdata; -int compute_hash_shift(struct node *nodes, int numnodes, u64 maxmem) +int __init compute_hash_shift(struct node *nodes) { int i; int shift = 24; @@ -39,12 +38,16 @@ /* When in doubt use brute force. */ while (shift < 48) { memset(memnodemap,0xff,sizeof(*memnodemap) * NODEMAPSIZE); - early_for_all_nodes (i) { + for (i = 0; i < numnodes; i++) { + if (nodes[i].start == nodes[i].end) + continue; for (addr = nodes[i].start; addr < nodes[i].end; addr += (1UL << shift)) { - if (memnodemap[addr >> shift] != 0xff) { - printk("node %d shift %d addr %Lx conflict %d\n", + if (memnodemap[addr >> shift] != 0xff && + memnodemap[addr >> shift] != i) { + printk(KERN_INFO + "node %d shift %d addr %Lx conflict %d\n", i, shift, addr, memnodemap[addr>>shift]); goto next; } @@ -101,9 +104,8 @@ reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size); reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, bootmap_pages< maxnode) - maxnode = nodeid; + if (nodeid + 1 > numnodes) + numnodes = nodeid + 1; nodes_present |= (1UL << nodeid); } @@ -151,6 +153,7 @@ int i; if (emunodes > MAXNODE) emunodes = MAXNODE; + memset(&nodes, 0, sizeof(nodes)); printk(KERN_INFO "Faking %d nodes of size %ld MB\n", emunodes, nodesize>>20); for (i = 0; i < emunodes; i++) { unsigned long end = (i+1)*nodesize; @@ -160,7 +163,7 @@ nodes[i].end = end; setup_node_bootmem(i, nodes[i].start, nodes[i].end); } - memnode_shift = compute_hash_shift(nodes, emunodes, nodes[i-1].end); + memnode_shift = compute_hash_shift(nodes); return 0; } diff -Nru a/arch/x86_64/pci/irq.c b/arch/x86_64/pci/irq.c --- a/arch/x86_64/pci/irq.c Wed Mar 5 03:54:28 2003 +++ b/arch/x86_64/pci/irq.c Sat Mar 22 11:28:20 2003 @@ -618,11 +618,20 @@ int pirq_enable_irq(struct pci_dev *dev) { u8 pin; + extern int interrupt_line_quirk; pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) { + /* With IDE legacy devices the IRQ lookup failure is not a problem.. */ + if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5)) + return 0; + printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.\n", 'A' + pin - 1, dev->slot_name); } + /* VIA bridges use interrupt line for apic/pci steering across + the V-Link */ + else if (interrupt_line_quirk) + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); return 0; } diff -Nru a/drivers/acorn/char/i2c.c b/drivers/acorn/char/i2c.c --- a/drivers/acorn/char/i2c.c Thu Dec 5 18:56:48 2002 +++ b/drivers/acorn/char/i2c.c Sat Mar 22 23:26:39 2003 @@ -303,11 +303,13 @@ } static struct i2c_adapter ioc_ops = { - .name = "IOC/IOMD", .id = I2C_HW_B_IOC, .algo_data = &ioc_data, .client_register = ioc_client_reg, .client_unregister = ioc_client_unreg + .dev = { + .name = "IOC/IOMD", + }, }; static int __init i2c_ioc_init(void) diff -Nru a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig --- a/drivers/acpi/Kconfig Wed Feb 26 13:48:11 2003 +++ b/drivers/acpi/Kconfig Sat Mar 22 12:01:25 2003 @@ -132,7 +132,7 @@ may be damaged without it. config ACPI_NUMA - bool "NUMA support" if NUMA && (IA64 && !IA64_HP_SIM || X86 && ACPI && !ACPI_HT_ONLY) + bool "NUMA support" if NUMA && (IA64 && !IA64_HP_SIM || X86 && ACPI && !ACPI_HT_ONLY && !X86_64) default y if IA64 && IA64_SGI_SN config ACPI_TOSHIBA diff -Nru a/drivers/atm/iphase.c b/drivers/atm/iphase.c --- a/drivers/atm/iphase.c Sat Jan 11 09:27:18 2003 +++ b/drivers/atm/iphase.c Tue Mar 25 22:40:26 2003 @@ -2893,7 +2893,7 @@ struct tx_buf_desc *buf_desc_ptr; int desc; int comp_code; - int total_len, pad, last; + int total_len; struct cpcs_trailer *trailer; struct ia_vcc *iavcc; @@ -2975,9 +2975,7 @@ /* Figure out the exact length of the packet and padding required to make it aligned on a 48 byte boundary. */ total_len = skb->len + sizeof(struct cpcs_trailer); - last = total_len - (total_len/48)*48; - pad = 48 - last; - total_len = pad + total_len; + total_len = ((total_len + 47) / 48) * 48; IF_TX(printk("ia packet len:%d padding:%d\n", total_len, pad);) /* Put the packet in a tx buffer */ diff -Nru a/drivers/base/base.h b/drivers/base/base.h --- a/drivers/base/base.h Mon Mar 3 10:48:36 2003 +++ b/drivers/base/base.h Tue Mar 25 13:12:05 2003 @@ -1,5 +1,3 @@ -#undef DEBUG - extern struct semaphore device_sem; extern struct semaphore devclass_sem; diff -Nru a/drivers/base/cpu.c b/drivers/base/cpu.c --- a/drivers/base/cpu.c Tue Mar 4 08:13:43 2003 +++ b/drivers/base/cpu.c Tue Mar 25 18:34:37 2003 @@ -48,6 +48,9 @@ int __init cpu_dev_init(void) { - devclass_register(&cpu_devclass); - return driver_register(&cpu_driver); + int error; + if (!(error = devclass_register(&cpu_devclass))) + if ((error = driver_register(&cpu_driver))) + devclass_unregister(&cpu_devclass); + return error; } diff -Nru a/drivers/base/driver.c b/drivers/base/driver.c --- a/drivers/base/driver.c Thu Jan 9 16:32:06 2003 +++ b/drivers/base/driver.c Tue Mar 25 13:12:32 2003 @@ -82,6 +82,7 @@ int driver_register(struct device_driver * drv) { INIT_LIST_HEAD(&drv->devices); + INIT_LIST_HEAD(&drv->class_list); init_MUTEX_LOCKED(&drv->unload_sem); return bus_add_driver(drv); } diff -Nru a/drivers/base/memblk.c b/drivers/base/memblk.c --- a/drivers/base/memblk.c Mon Feb 3 23:46:59 2003 +++ b/drivers/base/memblk.c Tue Mar 25 13:13:58 2003 @@ -47,9 +47,12 @@ } -static int __init register_memblk_type(void) +int __init register_memblk_type(void) { - int error = devclass_register(&memblk_devclass); - return error ? error : driver_register(&memblk_driver); + int error; + if (!(error = devclass_register(&memblk_devclass))) + if (error = driver_register(&memblk_driver)) + devclass_unregister(&memblk_devclass); + return error; } postcore_initcall(register_memblk_type); diff -Nru a/drivers/base/node.c b/drivers/base/node.c --- a/drivers/base/node.c Mon Feb 3 23:46:59 2003 +++ b/drivers/base/node.c Tue Mar 25 13:13:58 2003 @@ -89,9 +89,12 @@ } -static int __init register_node_type(void) +int __init register_node_type(void) { - int error = devclass_register(&node_devclass); - return error ? error : driver_register(&node_driver); + int error; + if (!(error = devclass_register(&node_devclass))) + if (error = driver_register(&node_driver)) + devclass_unregister(&node_devclass); + return error; } postcore_initcall(register_node_type); diff -Nru a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig --- a/drivers/char/drm/Kconfig Sun Feb 9 17:29:49 2003 +++ b/drivers/char/drm/Kconfig Sat Mar 29 22:34:33 2003 @@ -22,7 +22,13 @@ Choose this option if you have a 3dfx Banshee or Voodoo3 (or later), graphics card. If M is selected, the module will be called tdfx. -# tristate ' 3dlabs GMX 2000' CONFIG_DRM_GAMMA +config DRM_GAMMA + tristate "3dlabs GMX 2000" + depends on DRM && n + help + This is the old gamma driver, disabled for now unless somebody + tells me it actually might work. + config DRM_R128 tristate "ATI Rage 128" depends on DRM @@ -60,4 +66,3 @@ Choose this option if you have a Matrox G200, G400 or G450 graphics card. If M is selected, the module will be called mga. AGP support is required for this driver to work. - diff -Nru a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile --- a/drivers/char/drm/Makefile Sat Dec 14 04:38:56 2002 +++ b/drivers/char/drm/Makefile Sat Mar 29 22:34:33 2003 @@ -7,7 +7,7 @@ r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o i810-objs := i810_drv.o i810_dma.o -i830-objs := i830_drv.o i830_dma.o +i830-objs := i830_drv.o i830_dma.o i830_irq.o radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o ffb-objs := ffb_drv.o ffb_context.o diff -Nru a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h --- a/drivers/char/drm/drmP.h Wed Dec 18 09:56:28 2002 +++ b/drivers/char/drm/drmP.h Sat Mar 29 22:34:33 2003 @@ -254,6 +254,7 @@ } \ } \ } while(0) +#define DRM_DROP_MAP(_map) /* Internal types and structures */ #define DRM_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) @@ -268,6 +269,17 @@ (_map) = (_dev)->context_sareas[_ctx]; \ } while(0) +#define LOCK_TEST_WITH_RETURN( dev, filp ) \ +do { \ + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \ + dev->lock.filp != filp ) { \ + DRM_ERROR( "%s called without lock held\n", \ + __FUNCTION__ ); \ + return -EINVAL; \ + } \ +} while (0) + + typedef int drm_ioctl_t( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); @@ -316,7 +328,7 @@ __volatile__ int waiting; /* On kernel DMA queue */ __volatile__ int pending; /* On hardware DMA queue */ wait_queue_head_t dma_wait; /* Processes waiting */ - pid_t pid; /* PID of holding process */ + struct file *filp; /* Pointer to holding file descr */ int context; /* Kernel queue for this buffer */ int while_locked;/* Dispatch this buffer while locked */ enum { @@ -434,7 +446,7 @@ typedef struct drm_lock_data { drm_hw_lock_t *hw_lock; /* Hardware lock */ - pid_t pid; /* PID of lock holder (0=kernel) */ + struct file *filp; /* File descr of lock holder (0=kernel) */ wait_queue_head_t lock_queue; /* Queue of blocked processes */ unsigned long lock_time; /* Time of last lock in jiffies */ } drm_lock_data_t; @@ -516,6 +528,8 @@ drm_map_t *map; } drm_map_list_t; +typedef drm_map_t drm_local_map_t; + #if __HAVE_VBL_IRQ typedef struct drm_vbl_sig { @@ -591,6 +605,7 @@ atomic_t vbl_received; spinlock_t vbl_lock; drm_vbl_sig_t vbl_sigs; + unsigned int vbl_pending; #endif cycles_t ctx_start; cycles_t lck_start; @@ -807,15 +822,15 @@ extern int DRM(dma_setup)(drm_device_t *dev); extern void DRM(dma_takedown)(drm_device_t *dev); extern void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf); -extern void DRM(reclaim_buffers)(drm_device_t *dev, pid_t pid); +extern void DRM(reclaim_buffers)( struct file *filp ); #if __HAVE_OLD_DMA /* GH: This is a dirty hack for now... */ extern void DRM(clear_next_buffer)(drm_device_t *dev); extern int DRM(select_queue)(drm_device_t *dev, void (*wrapper)(unsigned long)); -extern int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *dma); -extern int DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma); +extern int DRM(dma_enqueue)(struct file *filp, drm_dma_t *dma); +extern int DRM(dma_get_buffers)(struct file *filp, drm_dma_t *dma); #endif #if __HAVE_DMA_IRQ extern int DRM(control)( struct inode *inode, struct file *filp, diff -Nru a/drivers/char/drm/drm_agpsupport.h b/drivers/char/drm/drm_agpsupport.h --- a/drivers/char/drm/drm_agpsupport.h Thu Mar 13 16:52:15 2003 +++ b/drivers/char/drm/drm_agpsupport.h Sat Mar 29 22:34:33 2003 @@ -266,12 +266,12 @@ head->cant_use_aperture = head->agp_info.cant_use_aperture; head->page_mask = head->agp_info.page_mask; #endif - - DRM_DEBUG("AGP %d.%d, aperture @ 0x%08lx %ZuMB\n", - head->agp_info.version.major, - head->agp_info.version.minor, - head->agp_info.aper_base, - head->agp_info.aper_size); + + DRM_INFO("AGP %d.%d aperture @ 0x%08lx %ZuMB\n", + head->agp_info.version.major, + head->agp_info.version.minor, + head->agp_info.aper_base, + head->agp_info.aper_size); } return head; } diff -Nru a/drivers/char/drm/drm_bufs.h b/drivers/char/drm/drm_bufs.h --- a/drivers/char/drm/drm_bufs.h Thu Mar 13 16:52:15 2003 +++ b/drivers/char/drm/drm_bufs.h Sat Mar 29 22:34:33 2003 @@ -403,7 +403,7 @@ buf->waiting = 0; buf->pending = 0; init_waitqueue_head( &buf->dma_wait ); - buf->pid = 0; + buf->filp = 0; buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T); buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T), @@ -616,7 +616,7 @@ buf->waiting = 0; buf->pending = 0; init_waitqueue_head( &buf->dma_wait ); - buf->pid = 0; + buf->filp = 0; #if __HAVE_DMA_HISTOGRAM buf->time_queued = 0; buf->time_dispatched = 0; @@ -773,7 +773,7 @@ buf->waiting = 0; buf->pending = 0; init_waitqueue_head( &buf->dma_wait ); - buf->pid = 0; + buf->filp = 0; buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T); buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T), @@ -1011,9 +1011,9 @@ return -EINVAL; } buf = dma->buflist[idx]; - if ( buf->pid != current->pid ) { - DRM_ERROR( "Process %d freeing buffer owned by %d\n", - current->pid, buf->pid ); + if ( buf->filp != filp ) { + DRM_ERROR( "Process %d freeing buffer not owned\n", + current->pid ); return -EINVAL; } DRM(free_buffer)( dev, buf ); diff -Nru a/drivers/char/drm/drm_dma.h b/drivers/char/drm/drm_dma.h --- a/drivers/char/drm/drm_dma.h Thu Mar 13 16:52:15 2003 +++ b/drivers/char/drm/drm_dma.h Sat Mar 29 22:34:33 2003 @@ -188,7 +188,7 @@ buf->waiting = 0; buf->pending = 0; - buf->pid = 0; + buf->filp = 0; buf->used = 0; #if __HAVE_DMA_HISTOGRAM buf->time_completed = get_cycles(); @@ -210,14 +210,16 @@ } #if !__HAVE_DMA_RECLAIM -void DRM(reclaim_buffers)(drm_device_t *dev, pid_t pid) +void DRM(reclaim_buffers)( struct file *filp ) { + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; drm_device_dma_t *dma = dev->dma; int i; if (!dma) return; for (i = 0; i < dma->buf_count; i++) { - if (dma->buflist[i]->pid == pid) { + if (dma->buflist[i]->filp == filp) { switch (dma->buflist[i]->list) { case DRM_LIST_NONE: DRM(free_buffer)(dev, dma->buflist[i]); @@ -318,8 +320,10 @@ } -int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *d) +int DRM(dma_enqueue)(struct file *filp, drm_dma_t *d) { + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; int i; drm_queue_t *q; drm_buf_t *buf; @@ -381,10 +385,10 @@ return -EINVAL; } buf = dma->buflist[ idx ]; - if (buf->pid != current->pid) { + if (buf->filp != filp) { atomic_dec(&q->use_count); - DRM_ERROR("Process %d using buffer owned by %d\n", - current->pid, buf->pid); + DRM_ERROR("Process %d using buffer not owned\n", + current->pid); return -EINVAL; } if (buf->list != DRM_LIST_NONE) { @@ -426,9 +430,11 @@ return 0; } -static int DRM(dma_get_buffers_of_order)(drm_device_t *dev, drm_dma_t *d, +static int DRM(dma_get_buffers_of_order)(struct file *filp, drm_dma_t *d, int order) { + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; int i; drm_buf_t *buf; drm_device_dma_t *dma = dev->dma; @@ -438,13 +444,13 @@ d->flags & _DRM_DMA_WAIT); if (!buf) break; if (buf->pending || buf->waiting) { - DRM_ERROR("Free buffer %d in use by %d (w%d, p%d)\n", + DRM_ERROR("Free buffer %d in use by %x (w%d, p%d)\n", buf->idx, - buf->pid, + buf->filp, buf->waiting, buf->pending); } - buf->pid = current->pid; + buf->filp = filp; if (copy_to_user(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) @@ -461,7 +467,7 @@ } -int DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma) +int DRM(dma_get_buffers)(struct file *filp, drm_dma_t *dma) { int order; int retcode = 0; @@ -470,7 +476,7 @@ order = DRM(order)(dma->request_size); dma->granted_count = 0; - retcode = DRM(dma_get_buffers_of_order)(dev, dma, order); + retcode = DRM(dma_get_buffers_of_order)(filp, dma, order); if (dma->granted_count < dma->request_count && (dma->flags & _DRM_DMA_SMALLER_OK)) { @@ -480,7 +486,7 @@ && tmp_order >= DRM_MIN_ORDER; --tmp_order) { - retcode = DRM(dma_get_buffers_of_order)(dev, dma, + retcode = DRM(dma_get_buffers_of_order)(filp, dma, tmp_order); } } @@ -493,7 +499,7 @@ && tmp_order <= DRM_MAX_ORDER; ++tmp_order) { - retcode = DRM(dma_get_buffers_of_order)(dev, dma, + retcode = DRM(dma_get_buffers_of_order)(filp, dma, tmp_order); } } @@ -540,6 +546,8 @@ spin_lock_init( &dev->vbl_lock ); INIT_LIST_HEAD( &dev->vbl_sigs.head ); + + dev->vbl_pending = 0; #endif /* Before installing handler */ @@ -622,6 +630,7 @@ switch ( vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK ) { case _DRM_VBLANK_RELATIVE: vblwait.request.sequence += atomic_read( &dev->vbl_received ); + vblwait.request.type &= ~_DRM_VBLANK_RELATIVE; case _DRM_VBLANK_ABSOLUTE: break; default: @@ -632,10 +641,38 @@ if ( flags & _DRM_VBLANK_SIGNAL ) { unsigned long irqflags; - drm_vbl_sig_t *vbl_sig = DRM_MALLOC( sizeof( drm_vbl_sig_t ) ); + drm_vbl_sig_t *vbl_sig; + + vblwait.reply.sequence = atomic_read( &dev->vbl_received ); + + spin_lock_irqsave( &dev->vbl_lock, irqflags ); + + /* Check if this task has already scheduled the same signal + * for the same vblank sequence number; nothing to be done in + * that case + */ + list_for_each( ( (struct list_head *) vbl_sig ), &dev->vbl_sigs.head ) { + if (vbl_sig->sequence == vblwait.request.sequence + && vbl_sig->info.si_signo == vblwait.request.signal + && vbl_sig->task == current) + { + spin_unlock_irqrestore( &dev->vbl_lock, irqflags ); + goto done; + } + } + + if ( dev->vbl_pending >= 100 ) { + spin_unlock_irqrestore( &dev->vbl_lock, irqflags ); + return -EBUSY; + } + + dev->vbl_pending++; - if ( !vbl_sig ) + spin_unlock_irqrestore( &dev->vbl_lock, irqflags ); + + if ( !( vbl_sig = DRM_MALLOC( sizeof( drm_vbl_sig_t ) ) ) ) { return -ENOMEM; + } memset( (void *)vbl_sig, 0, sizeof(*vbl_sig) ); @@ -643,9 +680,6 @@ vbl_sig->info.si_signo = vblwait.request.signal; vbl_sig->task = current; - vblwait.reply.sequence = atomic_read( &dev->vbl_received ); - - /* Hook signal entry into list */ spin_lock_irqsave( &dev->vbl_lock, irqflags ); list_add_tail( (struct list_head *) vbl_sig, &dev->vbl_sigs.head ); @@ -659,6 +693,7 @@ vblwait.reply.tval_usec = now.tv_usec; } +done: DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait, sizeof(vblwait) ); @@ -667,25 +702,23 @@ void DRM(vbl_send_signals)( drm_device_t *dev ) { - struct list_head *entry, *tmp; + struct list_head *tmp; drm_vbl_sig_t *vbl_sig; unsigned int vbl_seq = atomic_read( &dev->vbl_received ); unsigned long flags; spin_lock_irqsave( &dev->vbl_lock, flags ); - list_for_each_safe( entry, tmp, &dev->vbl_sigs.head ) { - - vbl_sig = (drm_vbl_sig_t *) entry; - + list_for_each_safe( ( (struct list_head *) vbl_sig ), tmp, &dev->vbl_sigs.head ) { if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) { - - vbl_sig->info.si_code = atomic_read( &dev->vbl_received ); + vbl_sig->info.si_code = vbl_seq; send_sig_info( vbl_sig->info.si_signo, &vbl_sig->info, vbl_sig->task ); - list_del( entry ); + list_del( (struct list_head *) vbl_sig ); + + DRM_FREE( vbl_sig, sizeof(*vbl_sig) ); - DRM_FREE( entry ); + dev->vbl_pending--; } } diff -Nru a/drivers/char/drm/drm_drv.h b/drivers/char/drm/drm_drv.h --- a/drivers/char/drm/drm_drv.h Mon Mar 17 15:42:16 2003 +++ b/drivers/char/drm/drm_drv.h Sat Mar 29 22:34:33 2003 @@ -323,6 +323,8 @@ dev->last_context = 0; dev->last_switch = 0; dev->last_checked = 0; + init_timer( &dev->timer ); + init_waitqueue_head( &dev->context_wait ); dev->ctx_start = 0; dev->lck_start = 0; @@ -494,7 +496,7 @@ #endif if ( dev->lock.hw_lock ) { dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */ - dev->lock.pid = 0; + dev->lock.filp = 0; wake_up_interruptible( &dev->lock.lock_queue ); } up( &dev->struct_sem ); @@ -545,9 +547,7 @@ drm_device_t *dev; int i; -#if __HAVE_CTX_BITMAP int retcode; -#endif DRM_DEBUG( "\n" ); #ifdef MODULE @@ -578,13 +578,9 @@ memset( (void *)dev, 0, sizeof(*dev) ); dev->count_lock = SPIN_LOCK_UNLOCKED; sema_init( &dev->struct_sem, 1 ); - init_timer( &dev->timer ); - init_waitqueue_head( &dev->context_wait ); - if ((DRM(minor)[i] = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0) { - retcode = -EPERM; - goto fail_reg; - } + if ((DRM(minor)[i] = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0) + return -EPERM; dev->device = MKDEV(DRM_MAJOR, DRM(minor)[i] ); dev->name = DRIVER_NAME; @@ -593,8 +589,9 @@ #if __MUST_HAVE_AGP if ( dev->agp == NULL ) { DRM_ERROR( "Cannot initialize the agpgart module.\n" ); - retcode = -ENOMEM; - goto fail; + DRM(stub_unregister)(DRM(minor)[i]); + DRM(takedown)( dev ); + return -ENOMEM; } #endif #if __REALLY_HAVE_MTRR @@ -610,7 +607,9 @@ retcode = DRM(ctxbitmap_init)( dev ); if( retcode ) { DRM_ERROR( "Cannot allocate memory for context bitmap.\n" ); - goto fail; + DRM(stub_unregister)(DRM(minor)[i]); + DRM(takedown)( dev ); + return retcode; } #endif DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n", @@ -625,15 +624,6 @@ DRIVER_POSTINIT(); return 0; - -fail: - DRM(stub_unregister)(DRM(minor)[i]); - DRM(takedown)( dev ); - -fail_reg: - kfree (DRM(device)); - kfree (DRM(minor)); - return retcode; } /* drm_cleanup is called via cleanup_module at module unload time. @@ -740,8 +730,6 @@ return -ENODEV; } - DRM_DEBUG( "open_count = %d\n", dev->open_count ); - retcode = DRM(open_helper)( inode, filp, dev ); if ( !retcode ) { atomic_inc( &dev->counts[_DRM_STAT_OPENS] ); @@ -773,15 +761,15 @@ * Begin inline drm_release */ - DRM_DEBUG( "pid = %d, device = 0x%x, open_count = %d\n", - current->pid, dev->device, dev->open_count ); + DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n", + current->pid, (long)dev->device, dev->open_count ); if ( dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) && - dev->lock.pid == current->pid ) { - DRM_DEBUG( "Process %d dead, freeing lock for context %d\n", - current->pid, - _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) ); + dev->lock.filp == filp ) { + DRM_DEBUG( "File %p released, freeing lock for context %d\n", + filp, + _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) ); #if __HAVE_RELEASE DRIVER_RELEASE(); #endif @@ -797,6 +785,7 @@ else if ( dev->lock.hw_lock ) { /* The lock is required to reclaim buffers */ DECLARE_WAITQUEUE( entry, current ); + add_wait_queue( &dev->lock.lock_queue, &entry ); for (;;) { current->state = TASK_INTERRUPTIBLE; @@ -807,7 +796,7 @@ } if ( DRM(lock_take)( &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT ) ) { - dev->lock.pid = priv->pid; + dev->lock.filp = filp; dev->lock.lock_time = jiffies; atomic_inc( &dev->counts[_DRM_STAT_LOCKS] ); break; /* Got lock */ @@ -831,7 +820,7 @@ } } #elif __HAVE_DMA - DRM(reclaim_buffers)( dev, priv->pid ); + DRM(reclaim_buffers)( filp ); #endif DRM(fasync)( -1, filp, 0 ); @@ -855,7 +844,7 @@ dev->file_last = priv->prev; } up( &dev->struct_sem ); - + DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES ); /* ======================================================== @@ -880,6 +869,7 @@ spin_unlock( &dev->count_lock ); unlock_kernel(); + return retcode; } @@ -899,8 +889,9 @@ atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] ); ++priv->ioctl_count; - DRM_DEBUG( "pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%x, auth=%d\n", - current->pid, cmd, nr, dev->device, priv->authenticated ); + DRM_DEBUG( "pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n", + current->pid, cmd, nr, (long)dev->device, + priv->authenticated ); if ( nr >= DRIVER_IOCTL_COUNT ) { retcode = -EINVAL; @@ -976,7 +967,7 @@ } if ( DRM(lock_take)( &dev->lock.hw_lock->lock, lock.context ) ) { - dev->lock.pid = current->pid; + dev->lock.filp = filp; dev->lock.lock_time = jiffies; atomic_inc( &dev->counts[_DRM_STAT_LOCKS] ); break; /* Got lock */ @@ -1058,7 +1049,7 @@ * agent to request it then we should just be able to * take it immediately and not eat the ioctl. */ - dev->lock.pid = 0; + dev->lock.filp = 0; { __volatile__ unsigned int *plock = &dev->lock.hw_lock->lock; unsigned int old, new, prev, ctx; diff -Nru a/drivers/char/drm/drm_fops.h b/drivers/char/drm/drm_fops.h --- a/drivers/char/drm/drm_fops.h Thu Mar 13 16:52:15 2003 +++ b/drivers/char/drm/drm_fops.h Sat Mar 29 22:34:33 2003 @@ -94,8 +94,8 @@ drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n", - current->pid, dev->device, dev->open_count); + DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n", + current->pid, (long)dev->device, dev->open_count); return 0; } @@ -105,7 +105,7 @@ drm_device_t *dev = priv->dev; int retcode; - DRM_DEBUG("fd = %d, device = 0x%x\n", fd, dev->device); + DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, (long)dev->device); retcode = fasync_helper(fd, filp, on, &dev->buf_async); if (retcode < 0) return retcode; return 0; diff -Nru a/drivers/char/drm/drm_ioctl.h b/drivers/char/drm/drm_ioctl.h --- a/drivers/char/drm/drm_ioctl.h Thu Mar 13 16:52:15 2003 +++ b/drivers/char/drm/drm_ioctl.h Sat Mar 29 22:34:33 2003 @@ -40,6 +40,28 @@ if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p))) return -EFAULT; +#ifdef __alpha__ + { + int domain = p.busnum >> 8; + p.busnum &= 0xff; + + /* + * Find the hose the device is on (the domain number is the + * hose index) and offset the bus by the root bus of that + * hose. + */ + for(dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL); + dev; + dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,dev)) { + struct pci_controller *hose = dev->sysdata; + + if (hose->index == domain) { + p.busnum += hose->bus->number; + break; + } + } + } +#endif dev = pci_find_slot(p.busnum, PCI_DEVFN(p.devnum, p.funcnum)); if (!dev) { DRM_ERROR("pci_find_slot failed for %d:%d:%d\n", @@ -112,7 +134,7 @@ do { struct pci_dev *pci_dev; - int b, d, f; + int domain, b, d, f; char *p; for(p = dev->unique; p && *p && *p != ':'; p++); @@ -124,6 +146,27 @@ f = (int)simple_strtoul(p+1, &p, 10); if (*p) break; + domain = b >> 8; + b &= 0xff; + +#ifdef __alpha__ + /* + * Find the hose the device is on (the domain number is the + * hose index) and offset the bus by the root bus of that + * hose. + */ + for(pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL); + pci_dev; + pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,pci_dev)) { + struct pci_controller *hose = pci_dev->sysdata; + + if (hose->index == domain) { + b += hose->bus->number; + break; + } + } +#endif + pci_dev = pci_find_slot(b, PCI_DEVFN(d,f)); if (pci_dev) { dev->pdev = pci_dev; diff -Nru a/drivers/char/drm/drm_lists.h b/drivers/char/drm/drm_lists.h --- a/drivers/char/drm/drm_lists.h Thu Mar 13 16:52:15 2003 +++ b/drivers/char/drm/drm_lists.h Sat Mar 29 22:34:33 2003 @@ -72,8 +72,8 @@ left = DRM_LEFTCOUNT(bl); if (!left) { - DRM_ERROR("Overflow while adding buffer %d from pid %d\n", - buf->idx, buf->pid); + DRM_ERROR("Overflow while adding buffer %d from filp %p\n", + buf->idx, buf->filp); return -EINVAL; } #if __HAVE_DMA_HISTOGRAM diff -Nru a/drivers/char/drm/drm_lock.h b/drivers/char/drm/drm_lock.h --- a/drivers/char/drm/drm_lock.h Thu Mar 13 16:52:15 2003 +++ b/drivers/char/drm/drm_lock.h Sat Mar 29 22:34:33 2003 @@ -78,7 +78,7 @@ { unsigned int old, new, prev; - dev->lock.pid = 0; + dev->lock.filp = 0; do { old = *lock; new = context | _DRM_LOCK_HELD; @@ -91,19 +91,17 @@ __volatile__ unsigned int *lock, unsigned int context) { unsigned int old, new, prev; - pid_t pid = dev->lock.pid; - dev->lock.pid = 0; + dev->lock.filp = 0; do { old = *lock; new = 0; prev = cmpxchg(lock, old, new); } while (prev != old); if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) { - DRM_ERROR("%d freed heavyweight lock held by %d (pid %d)\n", + DRM_ERROR("%d freed heavyweight lock held by %d\n", context, - _DRM_LOCKING_CONTEXT(old), - pid); + _DRM_LOCKING_CONTEXT(old)); return 1; } wake_up_interruptible(&dev->lock.lock_queue); diff -Nru a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h --- a/drivers/char/drm/drm_os_linux.h Thu Mar 13 16:52:15 2003 +++ b/drivers/char/drm/drm_os_linux.h Sat Mar 29 22:34:33 2003 @@ -2,16 +2,17 @@ #include /* For task queue support */ #include +#define DRMFILE struct file * #define DRM_IOCTL_ARGS struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data #define DRM_ERR(d) -(d) #define DRM_CURRENTPID current->pid #define DRM_UDELAY(d) udelay(d) -#define DRM_READ8(addr) readb(addr) -#define DRM_READ32(addr) readl(addr) -#define DRM_WRITE8(addr, val) writeb(val, addr) -#define DRM_WRITE32(addr, val) writel(val, addr) -#define DRM_READMEMORYBARRIER() mb() -#define DRM_WRITEMEMORYBARRIER() wmb() +#define DRM_READ8(map, offset) readb(((unsigned long)(map)->handle) + (offset)) +#define DRM_READ32(map, offset) readl(((unsigned long)(map)->handle) + (offset)) +#define DRM_WRITE8(map, offset, val) writeb(val, ((unsigned long)(map)->handle) + (offset)) +#define DRM_WRITE32(map, offset, val) writel(val, ((unsigned long)(map)->handle) + (offset)) +#define DRM_READMEMORYBARRIER(map) mb() +#define DRM_WRITEMEMORYBARRIER(map) wmb() #define DRM_DEVICE drm_file_t *priv = filp->private_data; \ drm_device_t *dev = priv->dev @@ -41,7 +42,7 @@ /* malloc/free without the overhead of DRM(alloc) */ #define DRM_MALLOC(x) kmalloc(x, GFP_KERNEL) -#define DRM_FREE(x) kfree(x) +#define DRM_FREE(x,size) kfree(x) #define DRM_GETSAREA() \ do { \ diff -Nru a/drivers/char/drm/drm_proc.h b/drivers/char/drm/drm_proc.h --- a/drivers/char/drm/drm_proc.h Thu Mar 13 16:52:15 2003 +++ b/drivers/char/drm/drm_proc.h Sat Mar 29 22:34:33 2003 @@ -147,10 +147,10 @@ *eof = 0; if (dev->unique) { - DRM_PROC_PRINT("%s 0x%x %s\n", - dev->name, dev->device, dev->unique); + DRM_PROC_PRINT("%s 0x%lx %s\n", + dev->name, (long)dev->device, dev->unique); } else { - DRM_PROC_PRINT("%s 0x%x\n", dev->name, dev->device); + DRM_PROC_PRINT("%s 0x%lx\n", dev->name, (long)dev->device); } if (len > request + offset) return request; diff -Nru a/drivers/char/drm/gamma_dma.c b/drivers/char/drm/gamma_dma.c --- a/drivers/char/drm/gamma_dma.c Thu Mar 13 16:52:15 2003 +++ b/drivers/char/drm/gamma_dma.c Sat Mar 29 22:34:33 2003 @@ -188,7 +188,7 @@ if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("Dispatching buffer %d from pid %d" " \"while locked\", but no lock held\n", - buf->idx, buf->pid); + buf->idx, current->pid); } } else { if (!locked && !gamma_lock_take(&dev->lock.hw_lock->lock, @@ -340,7 +340,8 @@ return retcode; } -static int gamma_dma_priority(drm_device_t *dev, drm_dma_t *d) +static int gamma_dma_priority(struct file *filp, + drm_device_t *dev, drm_dma_t *d) { unsigned long address; unsigned long length; @@ -378,15 +379,15 @@ continue; } buf = dma->buflist[ idx ]; - if (buf->pid != current->pid) { - DRM_ERROR("Process %d using buffer owned by %d\n", - current->pid, buf->pid); + if (buf->filp != filp) { + DRM_ERROR("Process %d using buffer not owned\n", + current->pid); retcode = -EINVAL; goto cleanup; } if (buf->list != DRM_LIST_NONE) { - DRM_ERROR("Process %d using %d's buffer on list %d\n", - current->pid, buf->pid, buf->list); + DRM_ERROR("Process %d using buffer on list %d\n", + current->pid, buf->list); retcode = -EINVAL; goto cleanup; } @@ -478,7 +479,8 @@ return retcode; } -static int gamma_dma_send_buffers(drm_device_t *dev, drm_dma_t *d) +static int gamma_dma_send_buffers(struct file *filp, + drm_device_t *dev, drm_dma_t *d) { DECLARE_WAITQUEUE(entry, current); drm_buf_t *last_buf = NULL; @@ -490,7 +492,7 @@ add_wait_queue(&last_buf->dma_wait, &entry); } - if ((retcode = gamma_dma_enqueue(dev, d))) { + if ((retcode = gamma_dma_enqueue(filp, d))) { if (d->flags & _DRM_DMA_BLOCK) remove_wait_queue(&last_buf->dma_wait, &entry); return retcode; @@ -520,14 +522,13 @@ } } if (retcode) { - DRM_ERROR("ctx%d w%d p%d c%d i%d l%d %d/%d\n", + DRM_ERROR("ctx%d w%d p%d c%ld i%d l%d pid:%d\n", d->context, last_buf->waiting, last_buf->pending, - DRM_WAITCOUNT(dev, d->context), + (long)DRM_WAITCOUNT(dev, d->context), last_buf->idx, last_buf->list, - last_buf->pid, current->pid); } } @@ -560,15 +561,15 @@ if (d.send_count) { if (d.flags & _DRM_DMA_PRIORITY) - retcode = gamma_dma_priority(dev, &d); + retcode = gamma_dma_priority(filp, dev, &d); else - retcode = gamma_dma_send_buffers(dev, &d); + retcode = gamma_dma_send_buffers(filp, dev, &d); } d.granted_count = 0; if (!retcode && d.request_count) { - retcode = gamma_dma_get_buffers(dev, &d); + retcode = gamma_dma_get_buffers(filp, &d); } DRM_DEBUG("%d returning, granted = %d\n", @@ -590,7 +591,7 @@ drm_buf_t *buf; int i; struct list_head *list; - unsigned int *pgt; + unsigned long *pgt; DRM_DEBUG( "%s\n", __FUNCTION__ ); @@ -643,7 +644,7 @@ for (i = 0; i < GLINT_DRI_BUF_COUNT; i++) { buf = dma->buflist[i]; - *pgt = (unsigned int)buf->address + 0x07; + *pgt = (unsigned long)buf->address + 0x07; pgt++; } diff -Nru a/drivers/char/drm/gamma_drv.h b/drivers/char/drm/gamma_drv.h --- a/drivers/char/drm/gamma_drv.h Tue Oct 29 14:29:20 2002 +++ b/drivers/char/drm/gamma_drv.h Sat Mar 29 22:34:33 2003 @@ -42,16 +42,6 @@ drm_map_t *mmio3; } drm_gamma_private_t; -#define LOCK_TEST_WITH_RETURN( dev ) \ -do { \ - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \ - dev->lock.pid != current->pid ) { \ - DRM_ERROR( "%s called without lock held\n", \ - __FUNCTION__ ); \ - return -EINVAL; \ - } \ -} while (0) - /* gamma_dma.c */ extern int gamma_dma_init( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); diff -Nru a/drivers/char/drm/i810.h b/drivers/char/drm/i810.h --- a/drivers/char/drm/i810.h Tue Oct 29 14:29:20 2002 +++ b/drivers/char/drm/i810.h Sat Mar 29 22:34:33 2003 @@ -86,7 +86,7 @@ */ #define __HAVE_RELEASE 1 #define DRIVER_RELEASE() do { \ - i810_reclaim_buffers( dev, priv->pid ); \ + i810_reclaim_buffers( filp ); \ } while (0) /* DMA customization: diff -Nru a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c --- a/drivers/char/drm/i810_dma.c Thu Mar 13 16:52:15 2003 +++ b/drivers/char/drm/i810_dma.c Sat Mar 29 22:34:33 2003 @@ -46,30 +46,10 @@ #define I810_BUF_UNMAPPED 0 #define I810_BUF_MAPPED 1 -#define RING_LOCALS unsigned int outring, ringmask; volatile char *virt; - -#define BEGIN_LP_RING(n) do { \ - if (0) DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__); \ - if (dev_priv->ring.space < n*4) \ - i810_wait_ring(dev, n*4); \ - dev_priv->ring.space -= n*4; \ - outring = dev_priv->ring.tail; \ - ringmask = dev_priv->ring.tail_mask; \ - virt = dev_priv->ring.virtual_start; \ -} while (0) - -#define ADVANCE_LP_RING() do { \ - if (0) DRM_DEBUG("ADVANCE_LP_RING\n"); \ - dev_priv->ring.tail = outring; \ - I810_WRITE(LP_RING + RING_TAIL, outring); \ -} while(0) - -#define OUT_RING(n) do { \ - if (0) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ - *(volatile unsigned int *)(virt + outring) = n; \ - outring += 4; \ - outring &= ringmask; \ -} while (0) +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,2) +#define down_write down +#define up_write up +#endif static inline void i810_print_status_page(drm_device_t *dev) { @@ -178,11 +158,7 @@ if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL; -#if LINUX_VERSION_CODE <= 0x020402 - down( ¤t->mm->mmap_sem ); -#else down_write( ¤t->mm->mmap_sem ); -#endif old_fops = filp->f_op; filp->f_op = &i810_buffer_fops; dev_priv->mmap_buffer = buf; @@ -194,15 +170,12 @@ filp->f_op = old_fops; if ((unsigned long)buf_priv->virtual > -1024UL) { /* Real error */ - DRM_DEBUG("mmap error\n"); + DRM_ERROR("mmap error\n"); retcode = (signed int)buf_priv->virtual; buf_priv->virtual = 0; } -#if LINUX_VERSION_CODE <= 0x020402 - up( ¤t->mm->mmap_sem ); -#else up_write( ¤t->mm->mmap_sem ); -#endif + return retcode; } @@ -213,19 +186,13 @@ if(buf_priv->currently_mapped != I810_BUF_MAPPED) return -EINVAL; -#if LINUX_VERSION_CODE <= 0x020402 - down( ¤t->mm->mmap_sem ); -#else - down_write( ¤t->mm->mmap_sem ); -#endif + + down_write(¤t->mm->mmap_sem); retcode = do_munmap(current->mm, (unsigned long)buf_priv->virtual, (size_t) buf->total); -#if LINUX_VERSION_CODE <= 0x020402 - up( ¤t->mm->mmap_sem ); -#else - up_write( ¤t->mm->mmap_sem ); -#endif + up_write(¤t->mm->mmap_sem); + buf_priv->currently_mapped = I810_BUF_UNMAPPED; buf_priv->virtual = 0; @@ -235,7 +202,6 @@ static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d, struct file *filp) { - drm_file_t *priv = filp->private_data; drm_buf_t *buf; drm_i810_buf_priv_t *buf_priv; int retcode = 0; @@ -250,10 +216,10 @@ retcode = i810_map_buffer(buf, filp); if(retcode) { i810_freelist_put(dev, buf); - DRM_DEBUG("mapbuf failed, retcode %d\n", retcode); + DRM_ERROR("mapbuf failed, retcode %d\n", retcode); return retcode; } - buf->pid = priv->pid; + buf->filp = filp; buf_priv = buf->dev_private; d->granted = 1; d->request_idx = buf->idx; @@ -314,7 +280,7 @@ end = jiffies + (HZ*3); iters++; - if((signed)(end - jiffies) <= 0) { + if(time_before(end, jiffies)) { DRM_ERROR("space: %d wanted %d\n", ring->space, n); DRM_ERROR("lockup\n"); goto out_wait_ring; @@ -882,8 +848,10 @@ } /* Must be called with the lock held */ -void i810_reclaim_buffers(drm_device_t *dev, pid_t pid) +void i810_reclaim_buffers(struct file *filp) { + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; drm_device_dma_t *dma = dev->dma; int i; @@ -897,7 +865,7 @@ drm_buf_t *buf = dma->buflist[ i ]; drm_i810_buf_priv_t *buf_priv = buf->dev_private; - if (buf->pid == pid && buf_priv) { + if (buf->filp == filp && buf_priv) { int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE); diff -Nru a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h --- a/drivers/char/drm/i810_drv.h Sat Nov 16 17:33:53 2002 +++ b/drivers/char/drm/i810_drv.h Sat Mar 29 22:34:33 2003 @@ -88,7 +88,7 @@ unsigned int cmd, unsigned long arg); extern int i810_flush_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern void i810_reclaim_buffers(drm_device_t *dev, pid_t pid); +extern void i810_reclaim_buffers(struct file *filp); extern int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma); @@ -136,6 +136,33 @@ #define I810_READ16(reg) I810_DEREF16(reg) #define I810_WRITE16(reg,val) do { I810_DEREF16(reg) = val; } while (0) +#define I810_VERBOSE 0 +#define RING_LOCALS unsigned int outring, ringmask; \ + volatile char *virt; + +#define BEGIN_LP_RING(n) do { \ + if (I810_VERBOSE) \ + DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__); \ + if (dev_priv->ring.space < n*4) \ + i810_wait_ring(dev, n*4); \ + dev_priv->ring.space -= n*4; \ + outring = dev_priv->ring.tail; \ + ringmask = dev_priv->ring.tail_mask; \ + virt = dev_priv->ring.virtual_start; \ +} while (0) + +#define ADVANCE_LP_RING() do { \ + if (I810_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n"); \ + dev_priv->ring.tail = outring; \ + I810_WRITE(LP_RING + RING_TAIL, outring); \ +} while(0) + +#define OUT_RING(n) do { \ + if (I810_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ + *(volatile unsigned int *)(virt + outring) = n; \ + outring += 4; \ + outring &= ringmask; \ +} while (0) #define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23)) #define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23)) @@ -198,6 +225,7 @@ #define CMD_OP_Z_BUFFER_INFO ((0x0<<29)|(0x16<<23)) #define CMD_OP_DESTBUFFER_INFO ((0x0<<29)|(0x15<<23)) +#define CMD_OP_FRONTBUFFER_INFO ((0x0<<29)|(0x14<<23)) #define BR00_BITBLT_CLIENT 0x40000000 #define BR00_OP_COLOR_BLT 0x10000000 diff -Nru a/drivers/char/drm/i830.h b/drivers/char/drm/i830.h --- a/drivers/char/drm/i830.h Tue Oct 29 14:29:21 2002 +++ b/drivers/char/drm/i830.h Sat Mar 29 22:34:33 2003 @@ -45,22 +45,37 @@ #define DRIVER_NAME "i830" #define DRIVER_DESC "Intel 830M" -#define DRIVER_DATE "20020828" +#define DRIVER_DATE "20021108" +/* Interface history: + * + * 1.1: Original. + * 1.2: ? + * 1.3: New irq emit/wait ioctls. + * New pageflip ioctl. + * New getparam ioctl. + * State for texunits 3&4 in sarea. + * New (alternative) layout for texture state. + */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 2 -#define DRIVER_PATCHLEVEL 1 +#define DRIVER_MINOR 3 +#define DRIVER_PATCHLEVEL 2 #define DRIVER_IOCTLS \ [DRM_IOCTL_NR(DRM_IOCTL_I830_INIT)] = { i830_dma_init, 1, 1 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I830_VERTEX)] = { i830_dma_vertex, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I830_CLEAR)] = { i830_clear_bufs, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I830_FLUSH)] = { i830_flush_ioctl, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I830_GETAGE)] = { i830_getage, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_VERTEX)] = { i830_dma_vertex, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_CLEAR)] = { i830_clear_bufs, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_FLUSH)] = { i830_flush_ioctl, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_GETAGE)] = { i830_getage, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_I830_GETBUF)] = { i830_getbuf, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I830_SWAP)] = { i830_swap_bufs, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I830_COPY)] = { i830_copybuf, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_I830_DOCOPY)] = { i830_docopy, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_I830_SWAP)] = { i830_swap_bufs, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_COPY)] = { i830_copybuf, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_DOCOPY)] = { i830_docopy, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_FLIP)] = { i830_flip_bufs, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_IRQ_EMIT)] = { i830_irq_emit, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_IRQ_WAIT)] = { i830_irq_wait, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_GETPARAM)] = { i830_getparam, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_I830_SETPARAM)] = { i830_setparam, 1, 0 } #define __HAVE_COUNTERS 4 #define __HAVE_COUNTER6 _DRM_STAT_IRQ @@ -72,7 +87,7 @@ */ #define __HAVE_RELEASE 1 #define DRIVER_RELEASE() do { \ - i830_reclaim_buffers( dev, priv->pid ); \ + i830_reclaim_buffers( filp ); \ } while (0) /* DMA customization: @@ -87,10 +102,49 @@ i830_dma_quiescent( dev ); \ } while (0) -/* Don't need an irq any more. The template code will make sure that - * a noop stub is generated for compatibility. + +/* Driver will work either way: IRQ's save cpu time when waiting for + * the card, but are subject to subtle interactions between bios, + * hardware and the driver. */ -#define __HAVE_DMA_IRQ 0 +#define USE_IRQS 0 + + +#if USE_IRQS +#define __HAVE_DMA_IRQ 1 +#define __HAVE_SHARED_IRQ 1 + +#define DRIVER_PREINSTALL() do { \ + drm_i830_private_t *dev_priv = \ + (drm_i830_private_t *)dev->dev_private; \ + \ + I830_WRITE16( I830REG_HWSTAM, 0xffff ); \ + I830_WRITE16( I830REG_INT_MASK_R, 0x0 ); \ + I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 ); \ +} while (0) + + +#define DRIVER_POSTINSTALL() do { \ + drm_i830_private_t *dev_priv = \ + (drm_i830_private_t *)dev->dev_private; \ + I830_WRITE16( I830REG_INT_ENABLE_R, 0x2 ); \ + atomic_set(&dev_priv->irq_received, 0); \ + atomic_set(&dev_priv->irq_emitted, 0); \ + init_waitqueue_head(&dev_priv->irq_queue); \ +} while (0) + + +/* This gets called too late to be useful: dev_priv has already been + * freed. + */ +#define DRIVER_UNINSTALL() do { \ +} while (0) + +#else +#define __HAVE_DMA_IRQ 0 +#endif + + /* Buffer customization: */ diff -Nru a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c --- a/drivers/char/drm/i830_dma.c Thu Mar 13 16:52:15 2003 +++ b/drivers/char/drm/i830_dma.c Sat Mar 29 22:34:33 2003 @@ -37,6 +37,7 @@ #include "i830_drm.h" #include "i830_drv.h" #include /* For task queue support */ +#include /* For FASTCALL on unlock_page() */ #include #define I830_BUF_FREE 2 @@ -46,8 +47,6 @@ #define I830_BUF_UNMAPPED 0 #define I830_BUF_MAPPED 1 -#define RING_LOCALS unsigned int outring, ringmask; volatile char *virt; - #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,2) #define down_write down #define up_write up @@ -60,32 +59,6 @@ #define UnlockPage(page) unlock_page(page) #endif -#define I830_VERBOSE 0 - -#define BEGIN_LP_RING(n) do { \ - if (I830_VERBOSE) \ - printk("BEGIN_LP_RING(%d) in %s\n", \ - n, __FUNCTION__); \ - if (dev_priv->ring.space < n*4) \ - i830_wait_ring(dev, n*4); \ - dev_priv->ring.space -= n*4; \ - outring = dev_priv->ring.tail; \ - ringmask = dev_priv->ring.tail_mask; \ - virt = dev_priv->ring.virtual_start; \ -} while (0) - -#define ADVANCE_LP_RING() do { \ - if (I830_VERBOSE) printk("ADVANCE_LP_RING %x\n", outring); \ - dev_priv->ring.tail = outring; \ - I830_WRITE(LP_RING + RING_TAIL, outring); \ -} while(0) - -#define OUT_RING(n) do { \ - if (I830_VERBOSE) printk(" OUT_RING %x\n", (int)(n)); \ - *(volatile unsigned int *)(virt + outring) = n; \ - outring += 4; \ - outring &= ringmask; \ -} while (0) static inline void i830_print_status_page(drm_device_t *dev) { @@ -237,7 +210,6 @@ static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d, struct file *filp) { - drm_file_t *priv = filp->private_data; drm_buf_t *buf; drm_i830_buf_priv_t *buf_priv; int retcode = 0; @@ -245,7 +217,7 @@ buf = i830_freelist_get(dev); if (!buf) { retcode = -ENOMEM; - DRM_ERROR("retcode=%d\n", retcode); + DRM_DEBUG("retcode=%d\n", retcode); return retcode; } @@ -255,7 +227,7 @@ DRM_ERROR("mapbuf failed, retcode %d\n", retcode); return retcode; } - buf->pid = priv->pid; + buf->filp = filp; buf_priv = buf->dev_private; d->granted = 1; d->request_idx = buf->idx; @@ -279,12 +251,21 @@ dev_priv->ring.Size); } if(dev_priv->hw_status_page != 0UL) { - pci_free_consistent(dev->pdev, PAGE_SIZE, + pci_free_consistent(dev->pdev, PAGE_SIZE, (void *)dev_priv->hw_status_page, dev_priv->dma_status_page); /* Need to rewrite hardware status page */ I830_WRITE(0x02080, 0x1ffff000); } + + /* Disable interrupts here because after dev_private + * is freed, it's too late. + */ + if (dev->irq) { + I830_WRITE16( I830REG_INT_MASK_R, 0xffff ); + I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 ); + } + DRM(free)(dev->dev_private, sizeof(drm_i830_private_t), DRM_MEM_DRIVER); dev->dev_private = NULL; @@ -298,7 +279,7 @@ return 0; } -static int i830_wait_ring(drm_device_t *dev, int n) +int i830_wait_ring(drm_device_t *dev, int n, const char *caller) { drm_i830_private_t *dev_priv = dev->dev_private; drm_i830_ring_buffer_t *ring = &(dev_priv->ring); @@ -324,6 +305,7 @@ goto out_wait_ring; } udelay(1); + dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT; } out_wait_ring: @@ -339,6 +321,9 @@ ring->tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR; ring->space = ring->head - (ring->tail+8); if (ring->space < 0) ring->space += ring->Size; + + if (ring->head == ring->tail) + dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY; } static int i830_freelist_init(drm_device_t *dev, drm_i830_private_t *dev_priv) @@ -453,6 +438,8 @@ dev_priv->back_pitch = init->back_pitch; dev_priv->depth_pitch = init->depth_pitch; + dev_priv->do_boxes = 0; + dev_priv->use_mi_batchbuffer_start = 0; /* Program Hardware Status Page */ dev_priv->hw_status_page = @@ -467,7 +454,7 @@ memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE); DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page); - I830_WRITE(0x02080, dev_priv->dma_status_page); + I830_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page)); DRM_DEBUG("Enabled hardware status page\n"); /* Now we need to init our freelist */ @@ -528,11 +515,7 @@ unsigned int tmp; RING_LOCALS; - BEGIN_LP_RING( I830_CTX_SETUP_SIZE + 2 ); - - OUT_RING( GFX_OP_STIPPLE ); - OUT_RING( 0 ); - + BEGIN_LP_RING( I830_CTX_SETUP_SIZE + 4 ); for ( i = 0 ; i < I830_CTXREG_BLENDCOLR0 ; i++ ) { tmp = code[i]; @@ -570,38 +553,44 @@ ADVANCE_LP_RING(); } -static void i830EmitTexVerified( drm_device_t *dev, - volatile unsigned int *code ) +static void i830EmitTexVerified( drm_device_t *dev, unsigned int *code ) { drm_i830_private_t *dev_priv = dev->dev_private; int i, j = 0; unsigned int tmp; RING_LOCALS; - BEGIN_LP_RING( I830_TEX_SETUP_SIZE ); - - OUT_RING( GFX_OP_MAP_INFO ); - OUT_RING( code[I830_TEXREG_MI1] ); - OUT_RING( code[I830_TEXREG_MI2] ); - OUT_RING( code[I830_TEXREG_MI3] ); - OUT_RING( code[I830_TEXREG_MI4] ); - OUT_RING( code[I830_TEXREG_MI5] ); - - for ( i = 6 ; i < I830_TEX_SETUP_SIZE ; i++ ) { - tmp = code[i]; - OUT_RING( tmp ); - j++; - } + if (code[I830_TEXREG_MI0] == GFX_OP_MAP_INFO || + (code[I830_TEXREG_MI0] & ~(0xf*LOAD_TEXTURE_MAP0)) == + (STATE3D_LOAD_STATE_IMMEDIATE_2|4)) { + + BEGIN_LP_RING( I830_TEX_SETUP_SIZE ); + + OUT_RING( code[I830_TEXREG_MI0] ); /* TM0LI */ + OUT_RING( code[I830_TEXREG_MI1] ); /* TM0S0 */ + OUT_RING( code[I830_TEXREG_MI2] ); /* TM0S1 */ + OUT_RING( code[I830_TEXREG_MI3] ); /* TM0S2 */ + OUT_RING( code[I830_TEXREG_MI4] ); /* TM0S3 */ + OUT_RING( code[I830_TEXREG_MI5] ); /* TM0S4 */ + + for ( i = 6 ; i < I830_TEX_SETUP_SIZE ; i++ ) { + tmp = code[i]; + OUT_RING( tmp ); + j++; + } - if (j & 1) - OUT_RING( 0 ); + if (j & 1) + OUT_RING( 0 ); - ADVANCE_LP_RING(); + ADVANCE_LP_RING(); + } + else + printk("rejected packet %x\n", code[0]); } static void i830EmitTexBlendVerified( drm_device_t *dev, - volatile unsigned int *code, - volatile unsigned int num) + unsigned int *code, + unsigned int num) { drm_i830_private_t *dev_priv = dev->dev_private; int i, j = 0; @@ -611,7 +600,7 @@ if (!num) return; - BEGIN_LP_RING( num ); + BEGIN_LP_RING( num + 1 ); for ( i = 0 ; i < num ; i++ ) { tmp = code[i]; @@ -634,6 +623,8 @@ int i; RING_LOCALS; + return; + BEGIN_LP_RING( 258 ); if(is_shared == 1) { @@ -647,42 +638,41 @@ OUT_RING(palette[i]); } OUT_RING(0); + /* KW: WHERE IS THE ADVANCE_LP_RING? This is effectively a noop! + */ } /* Need to do some additional checking when setting the dest buffer. */ static void i830EmitDestVerified( drm_device_t *dev, - volatile unsigned int *code ) + unsigned int *code ) { drm_i830_private_t *dev_priv = dev->dev_private; unsigned int tmp; RING_LOCALS; - BEGIN_LP_RING( I830_DEST_SETUP_SIZE + 6 ); + BEGIN_LP_RING( I830_DEST_SETUP_SIZE + 10 ); + tmp = code[I830_DESTREG_CBUFADDR]; - if (tmp == dev_priv->front_di1) { - /* Don't use fence when front buffer rendering */ - OUT_RING( CMD_OP_DESTBUFFER_INFO ); - OUT_RING( BUF_3D_ID_COLOR_BACK | - BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) ); - OUT_RING( tmp ); + if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) { + if (((int)outring) & 8) { + OUT_RING(0); + OUT_RING(0); + } OUT_RING( CMD_OP_DESTBUFFER_INFO ); - OUT_RING( BUF_3D_ID_DEPTH | - BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp)); - OUT_RING( dev_priv->zi1 ); - } else if(tmp == dev_priv->back_di1) { - OUT_RING( CMD_OP_DESTBUFFER_INFO ); OUT_RING( BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) | BUF_3D_USE_FENCE); OUT_RING( tmp ); + OUT_RING( 0 ); OUT_RING( CMD_OP_DESTBUFFER_INFO ); OUT_RING( BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE | BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp)); OUT_RING( dev_priv->zi1 ); + OUT_RING( 0 ); } else { DRM_ERROR("bad di1 %x (allow %x or %x)\n", tmp, dev_priv->front_di1, dev_priv->back_di1); @@ -710,21 +700,35 @@ OUT_RING( 0 ); } - OUT_RING( code[I830_DESTREG_SENABLE] ); - OUT_RING( GFX_OP_SCISSOR_RECT ); OUT_RING( code[I830_DESTREG_SR1] ); OUT_RING( code[I830_DESTREG_SR2] ); + OUT_RING( 0 ); ADVANCE_LP_RING(); } +static void i830EmitStippleVerified( drm_device_t *dev, + unsigned int *code ) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + BEGIN_LP_RING( 2 ); + OUT_RING( GFX_OP_STIPPLE ); + OUT_RING( code[1] ); + ADVANCE_LP_RING(); +} + + static void i830EmitState( drm_device_t *dev ) { drm_i830_private_t *dev_priv = dev->dev_private; drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int dirty = sarea_priv->dirty; + DRM_DEBUG("%s %x\n", __FUNCTION__, dirty); + if (dirty & I830_UPLOAD_BUFFERS) { i830EmitDestVerified( dev, sarea_priv->BufferState ); sarea_priv->dirty &= ~I830_UPLOAD_BUFFERS; @@ -758,17 +762,154 @@ } if (dirty & I830_UPLOAD_TEX_PALETTE_SHARED) { - i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1); + i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1); + } else { + if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) { + i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0); + sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0); + } + if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) { + i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0); + sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1); + } + + /* 1.3: + */ +#if 0 + if (dirty & I830_UPLOAD_TEX_PALETTE_N(2)) { + i830EmitTexPalette(dev, sarea_priv->Palette2[0], 0, 0); + sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2); + } + if (dirty & I830_UPLOAD_TEX_PALETTE_N(3)) { + i830EmitTexPalette(dev, sarea_priv->Palette2[1], 1, 0); + sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2); + } +#endif + } + + /* 1.3: + */ + if (dirty & I830_UPLOAD_STIPPLE) { + i830EmitStippleVerified( dev, + sarea_priv->StippleState); + sarea_priv->dirty &= ~I830_UPLOAD_STIPPLE; + } + + if (dirty & I830_UPLOAD_TEX2) { + i830EmitTexVerified( dev, sarea_priv->TexState2 ); + sarea_priv->dirty &= ~I830_UPLOAD_TEX2; + } + + if (dirty & I830_UPLOAD_TEX3) { + i830EmitTexVerified( dev, sarea_priv->TexState3 ); + sarea_priv->dirty &= ~I830_UPLOAD_TEX3; + } + + + if (dirty & I830_UPLOAD_TEXBLEND2) { + i830EmitTexBlendVerified( + dev, + sarea_priv->TexBlendState2, + sarea_priv->TexBlendStateWordsUsed2); + + sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND2; + } + + if (dirty & I830_UPLOAD_TEXBLEND3) { + i830EmitTexBlendVerified( + dev, + sarea_priv->TexBlendState3, + sarea_priv->TexBlendStateWordsUsed3); + sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND3; + } +} + +/* ================================================================ + * Performance monitoring functions + */ + +static void i830_fill_box( drm_device_t *dev, + int x, int y, int w, int h, + int r, int g, int b ) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + u32 color; + unsigned int BR13, CMD; + RING_LOCALS; + + BR13 = (0xF0 << 16) | (dev_priv->pitch * dev_priv->cpp) | (1<<24); + CMD = XY_COLOR_BLT_CMD; + x += dev_priv->sarea_priv->boxes[0].x1; + y += dev_priv->sarea_priv->boxes[0].y1; + + if (dev_priv->cpp == 4) { + BR13 |= (1<<25); + CMD |= (XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB); + color = (((0xff) << 24) | (r << 16) | (g << 8) | b); } else { - if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) { - i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0); - sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0); - } - if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) { - i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0); - sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1); - } + color = (((r & 0xf8) << 8) | + ((g & 0xfc) << 3) | + ((b & 0xf8) >> 3)); } + + BEGIN_LP_RING( 6 ); + OUT_RING( CMD ); + OUT_RING( BR13 ); + OUT_RING( (y << 16) | x ); + OUT_RING( ((y+h) << 16) | (x+w) ); + + if ( dev_priv->current_page == 1 ) { + OUT_RING( dev_priv->front_offset ); + } else { + OUT_RING( dev_priv->back_offset ); + } + + OUT_RING( color ); + ADVANCE_LP_RING(); +} + +static void i830_cp_performance_boxes( drm_device_t *dev ) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + + /* Purple box for page flipping + */ + if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_FLIP ) + i830_fill_box( dev, 4, 4, 8, 8, 255, 0, 255 ); + + /* Red box if we have to wait for idle at any point + */ + if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_WAIT ) + i830_fill_box( dev, 16, 4, 8, 8, 255, 0, 0 ); + + /* Blue box: lost context? + */ + if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_LOST_CONTEXT ) + i830_fill_box( dev, 28, 4, 8, 8, 0, 0, 255 ); + + /* Yellow box for texture swaps + */ + if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_TEXTURE_LOAD ) + i830_fill_box( dev, 40, 4, 8, 8, 255, 255, 0 ); + + /* Green box if hardware never idles (as far as we can tell) + */ + if ( !(dev_priv->sarea_priv->perf_boxes & I830_BOX_RING_EMPTY) ) + i830_fill_box( dev, 64, 4, 8, 8, 0, 255, 0 ); + + + /* Draw bars indicating number of buffers allocated + * (not a great measure, easily confused) + */ + if (dev_priv->dma_used) { + int bar = dev_priv->dma_used / 10240; + if (bar > 100) bar = 100; + if (bar < 1) bar = 1; + i830_fill_box( dev, 4, 16, bar, 4, 196, 128, 128 ); + dev_priv->dma_used = 0; + } + + dev_priv->sarea_priv->perf_boxes = 0; } static void i830_dma_dispatch_clear( drm_device_t *dev, int flags, @@ -786,6 +927,15 @@ unsigned int BR13, CMD, D_CMD; RING_LOCALS; + + if ( dev_priv->current_page == 1 ) { + unsigned int tmp = flags; + + flags &= ~(I830_FRONT | I830_BACK); + if ( tmp & I830_FRONT ) flags |= I830_BACK; + if ( tmp & I830_BACK ) flags |= I830_FRONT; + } + i830_kernel_lost_context(dev); switch(cpp) { @@ -865,13 +1015,17 @@ drm_clip_rect_t *pbox = sarea_priv->boxes; int pitch = dev_priv->pitch; int cpp = dev_priv->cpp; - int ofs = dev_priv->back_offset; int i; unsigned int CMD, BR13; RING_LOCALS; DRM_DEBUG("swapbuffers\n"); + i830_kernel_lost_context(dev); + + if (dev_priv->do_boxes) + i830_cp_performance_boxes( dev ); + switch(cpp) { case 2: BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24); @@ -888,7 +1042,6 @@ break; } - i830_kernel_lost_context(dev); if (nbox > I830_NR_SAREA_CLIPRECTS) nbox = I830_NR_SAREA_CLIPRECTS; @@ -908,23 +1061,72 @@ BEGIN_LP_RING( 8 ); OUT_RING( CMD ); OUT_RING( BR13 ); + OUT_RING( (pbox->y1 << 16) | pbox->x1 ); + OUT_RING( (pbox->y2 << 16) | pbox->x2 ); - OUT_RING( (pbox->y1 << 16) | - pbox->x1 ); - OUT_RING( (pbox->y2 << 16) | - pbox->x2 ); - - OUT_RING( dev_priv->front_offset ); - OUT_RING( (pbox->y1 << 16) | - pbox->x1 ); + if (dev_priv->current_page == 0) + OUT_RING( dev_priv->front_offset ); + else + OUT_RING( dev_priv->back_offset ); + OUT_RING( (pbox->y1 << 16) | pbox->x1 ); OUT_RING( BR13 & 0xffff ); - OUT_RING( ofs ); + + if (dev_priv->current_page == 0) + OUT_RING( dev_priv->back_offset ); + else + OUT_RING( dev_priv->front_offset ); ADVANCE_LP_RING(); } } +static void i830_dma_dispatch_flip( drm_device_t *dev ) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n", + __FUNCTION__, + dev_priv->current_page, + dev_priv->sarea_priv->pf_current_page); + + i830_kernel_lost_context(dev); + + if (dev_priv->do_boxes) { + dev_priv->sarea_priv->perf_boxes |= I830_BOX_FLIP; + i830_cp_performance_boxes( dev ); + } + + + BEGIN_LP_RING( 2 ); + OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); + + BEGIN_LP_RING( 6 ); + OUT_RING( CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP ); + OUT_RING( 0 ); + if ( dev_priv->current_page == 0 ) { + OUT_RING( dev_priv->back_offset ); + dev_priv->current_page = 1; + } else { + OUT_RING( dev_priv->front_offset ); + dev_priv->current_page = 0; + } + OUT_RING(0); + ADVANCE_LP_RING(); + + + BEGIN_LP_RING( 2 ); + OUT_RING( MI_WAIT_FOR_EVENT | + MI_WAIT_FOR_PLANE_A_FLIP ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); + + + dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; +} static void i830_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf, @@ -977,8 +1179,10 @@ sarea_priv->vertex_prim | ((used/4)-2)); - vp[used/4] = MI_BATCH_BUFFER_END; - used += 4; + if (dev_priv->use_mi_batchbuffer_start) { + vp[used/4] = MI_BATCH_BUFFER_END; + used += 4; + } if (used & 4) { vp[used/4] = 0; @@ -1001,11 +1205,21 @@ ADVANCE_LP_RING(); } - BEGIN_LP_RING(2); - OUT_RING( MI_BATCH_BUFFER_START | (2<<6) ); - OUT_RING( start | MI_BATCH_NON_SECURE ); - ADVANCE_LP_RING(); - + if (dev_priv->use_mi_batchbuffer_start) { + BEGIN_LP_RING(2); + OUT_RING( MI_BATCH_BUFFER_START | (2<<6) ); + OUT_RING( start | MI_BATCH_NON_SECURE ); + ADVANCE_LP_RING(); + } + else { + BEGIN_LP_RING(4); + OUT_RING( MI_BATCH_BUFFER ); + OUT_RING( start | MI_BATCH_NON_SECURE ); + OUT_RING( start + used - 4 ); + OUT_RING( 0 ); + ADVANCE_LP_RING(); + } + } while (++i < nbox); } @@ -1043,7 +1257,7 @@ OUT_RING( 0 ); ADVANCE_LP_RING(); - i830_wait_ring( dev, dev_priv->ring.Size - 8 ); + i830_wait_ring( dev, dev_priv->ring.Size - 8, __FUNCTION__ ); } static int i830_flush_queue(drm_device_t *dev) @@ -1060,7 +1274,7 @@ OUT_RING( 0 ); ADVANCE_LP_RING(); - i830_wait_ring( dev, dev_priv->ring.Size - 8 ); + i830_wait_ring( dev, dev_priv->ring.Size - 8, __FUNCTION__ ); for (i = 0; i < dma->buf_count; i++) { drm_buf_t *buf = dma->buflist[ i ]; @@ -1079,8 +1293,10 @@ } /* Must be called with the lock held */ -void i830_reclaim_buffers(drm_device_t *dev, pid_t pid) +void i830_reclaim_buffers( struct file *filp ) { + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; drm_device_dma_t *dma = dev->dma; int i; @@ -1094,7 +1310,7 @@ drm_buf_t *buf = dma->buflist[ i ]; drm_i830_buf_priv_t *buf_priv = buf->dev_private; - if (buf->pid == pid && buf_priv) { + if (buf->filp == filp && buf_priv) { int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, I830_BUF_FREE); @@ -1200,6 +1416,53 @@ return 0; } + + +/* Not sure why this isn't set all the time: + */ +static void i830_do_init_pageflip( drm_device_t *dev ) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + + DRM_DEBUG("%s\n", __FUNCTION__); + dev_priv->page_flipping = 1; + dev_priv->current_page = 0; + dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; +} + +int i830_do_cleanup_pageflip( drm_device_t *dev ) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + + DRM_DEBUG("%s\n", __FUNCTION__); + if (dev_priv->current_page != 0) + i830_dma_dispatch_flip( dev ); + + dev_priv->page_flipping = 0; + return 0; +} + +int i830_flip_bufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i830_private_t *dev_priv = dev->dev_private; + + DRM_DEBUG("%s\n", __FUNCTION__); + + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("i830_flip_buf called without lock held\n"); + return -EINVAL; + } + + if (!dev_priv->page_flipping) + i830_do_init_pageflip( dev ); + + i830_dma_dispatch_flip( dev ); + return 0; +} + int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { @@ -1261,5 +1524,68 @@ int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { + return 0; +} + + + +int i830_getparam( struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i830_private_t *dev_priv = dev->dev_private; + drm_i830_getparam_t param; + int value; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + if (copy_from_user(¶m, (drm_i830_getparam_t *)arg, sizeof(param) )) + return -EFAULT; + + switch( param.param ) { + case I830_PARAM_IRQ_ACTIVE: + value = dev->irq ? 1 : 0; + break; + default: + return -EINVAL; + } + + if ( copy_to_user( param.value, &value, sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return -EFAULT; + } + + return 0; +} + + +int i830_setparam( struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i830_private_t *dev_priv = dev->dev_private; + drm_i830_setparam_t param; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + if (copy_from_user(¶m, (drm_i830_setparam_t *)arg, sizeof(param) )) + return -EFAULT; + + switch( param.param ) { + case I830_SETPARAM_USE_MI_BATCHBUFFER_START: + dev_priv->use_mi_batchbuffer_start = param.value; + break; + default: + return -EINVAL; + } + return 0; } diff -Nru a/drivers/char/drm/i830_drm.h b/drivers/char/drm/i830_drm.h --- a/drivers/char/drm/i830_drm.h Sun Mar 2 23:30:02 2003 +++ b/drivers/char/drm/i830_drm.h Sat Mar 29 22:34:33 2003 @@ -3,6 +3,9 @@ /* WARNING: These defines must be the same as what the Xserver uses. * if you change them, you must change the defines in the Xserver. + * + * KW: Actually, you can't ever change them because doing so would + * break backwards compatibility. */ #ifndef _I830_DEFINES_ @@ -18,14 +21,12 @@ #define I830_NR_TEX_REGIONS 64 #define I830_LOG_MIN_TEX_REGION_SIZE 16 -/* if defining I830_ENABLE_4_TEXTURES, do it in i830_3d_reg.h, too */ -#if !defined(I830_ENABLE_4_TEXTURES) +/* KW: These aren't correct but someone set them to two and then + * released the module. Now we can't change them as doing so would + * break backwards compatibility. + */ #define I830_TEXTURE_COUNT 2 -#define I830_TEXBLEND_COUNT 2 /* always same as TEXTURE_COUNT? */ -#else /* defined(I830_ENABLE_4_TEXTURES) */ -#define I830_TEXTURE_COUNT 4 -#define I830_TEXBLEND_COUNT 4 /* always same as TEXTURE_COUNT? */ -#endif /* I830_ENABLE_4_TEXTURES */ +#define I830_TEXBLEND_COUNT I830_TEXTURE_COUNT #define I830_TEXBLEND_SIZE 12 /* (4 args + op) * 2 + COLOR_FACTOR */ @@ -57,6 +58,7 @@ #define I830_UPLOAD_TEXBLEND_MASK 0xf00000 #define I830_UPLOAD_TEX_PALETTE_N(n) (0x1000000 << (n)) #define I830_UPLOAD_TEX_PALETTE_SHARED 0x4000000 +#define I830_UPLOAD_STIPPLE 0x8000000 /* Indices into buf.Setup where various bits of state are mirrored per * context and per buffer. These can be fired at the card as a unit, @@ -73,7 +75,6 @@ */ #define I830_DESTREG_CBUFADDR 0 -/* Invarient */ #define I830_DESTREG_DBUFADDR 1 #define I830_DESTREG_DV0 2 #define I830_DESTREG_DV1 3 @@ -109,6 +110,13 @@ #define I830_CTXREG_MCSB1 16 #define I830_CTX_SETUP_SIZE 17 +/* 1.3: Stipple state + */ +#define I830_STPREG_ST0 0 +#define I830_STPREG_ST1 1 +#define I830_STP_SETUP_SIZE 2 + + /* Texture state (per tex unit) */ @@ -124,6 +132,18 @@ #define I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS */ #define I830_TEX_SETUP_SIZE 10 +#define I830_TEXREG_TM0LI 0 /* load immediate 2 texture map n */ +#define I830_TEXREG_TM0S0 1 +#define I830_TEXREG_TM0S1 2 +#define I830_TEXREG_TM0S2 3 +#define I830_TEXREG_TM0S3 4 +#define I830_TEXREG_TM0S4 5 +#define I830_TEXREG_NOP0 6 /* noop */ +#define I830_TEXREG_NOP1 7 /* noop */ +#define I830_TEXREG_NOP2 8 /* noop */ +#define __I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS -- shared */ +#define __I830_TEX_SETUP_SIZE 10 + #define I830_FRONT 0x1 #define I830_BACK 0x2 #define I830_DEPTH 0x4 @@ -199,8 +219,35 @@ int ctxOwner; /* last context to upload state */ int vertex_prim; + + int pf_enabled; /* is pageflipping allowed? */ + int pf_active; + int pf_current_page; /* which buffer is being displayed? */ + + int perf_boxes; /* performance boxes to be displayed */ + + /* Here's the state for texunits 2,3: + */ + unsigned int TexState2[I830_TEX_SETUP_SIZE]; + unsigned int TexBlendState2[I830_TEXBLEND_SIZE]; + unsigned int TexBlendStateWordsUsed2; + + unsigned int TexState3[I830_TEX_SETUP_SIZE]; + unsigned int TexBlendState3[I830_TEXBLEND_SIZE]; + unsigned int TexBlendStateWordsUsed3; + + unsigned int StippleState[I830_STP_SETUP_SIZE]; } drm_i830_sarea_t; +/* Flags for perf_boxes + */ +#define I830_BOX_RING_EMPTY 0x1 /* populated by kernel */ +#define I830_BOX_FLIP 0x2 /* populated by kernel */ +#define I830_BOX_WAIT 0x4 /* populated by kernel & client */ +#define I830_BOX_TEXTURE_LOAD 0x8 /* populated by kernel */ +#define I830_BOX_LOST_CONTEXT 0x10 /* populated by client */ + + /* I830 specific ioctls * The device specific ioctl range is 0x40 to 0x79. */ @@ -213,6 +260,11 @@ #define DRM_IOCTL_I830_SWAP DRM_IO ( 0x46) #define DRM_IOCTL_I830_COPY DRM_IOW( 0x47, drm_i830_copy_t) #define DRM_IOCTL_I830_DOCOPY DRM_IO ( 0x48) +#define DRM_IOCTL_I830_FLIP DRM_IO ( 0x49) +#define DRM_IOCTL_I830_IRQ_EMIT DRM_IOWR(0x4a, drm_i830_irq_emit_t) +#define DRM_IOCTL_I830_IRQ_WAIT DRM_IOW( 0x4b, drm_i830_irq_wait_t) +#define DRM_IOCTL_I830_GETPARAM DRM_IOWR(0x4c, drm_i830_getparam_t) +#define DRM_IOCTL_I830_SETPARAM DRM_IOWR(0x4d, drm_i830_setparam_t) typedef struct _drm_i830_clear { int clear_color; @@ -247,5 +299,37 @@ int request_size; int granted; } drm_i830_dma_t; + + +/* 1.3: Userspace can request & wait on irq's: + */ +typedef struct drm_i830_irq_emit { + int *irq_seq; +} drm_i830_irq_emit_t; + +typedef struct drm_i830_irq_wait { + int irq_seq; +} drm_i830_irq_wait_t; + + +/* 1.3: New ioctl to query kernel params: + */ +#define I830_PARAM_IRQ_ACTIVE 1 + +typedef struct drm_i830_getparam { + int param; + int *value; +} drm_i830_getparam_t; + + +/* 1.3: New ioctl to set kernel params: + */ +#define I830_SETPARAM_USE_MI_BATCHBUFFER_START 1 + +typedef struct drm_i830_setparam { + int param; + int value; +} drm_i830_setparam_t; + #endif /* _I830_DRM_H_ */ diff -Nru a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h --- a/drivers/char/drm/i830_drv.h Sat Nov 16 17:33:53 2002 +++ b/drivers/char/drm/i830_drv.h Sat Mar 29 22:34:33 2003 @@ -78,6 +78,19 @@ int back_pitch; int depth_pitch; unsigned int cpp; + + int do_boxes; + int dma_used; + + int current_page; + int page_flipping; + + wait_queue_head_t irq_queue; + atomic_t irq_received; + atomic_t irq_emitted; + + int use_mi_batchbuffer_start; + } drm_i830_private_t; /* i830_dma.c */ @@ -88,7 +101,7 @@ unsigned int cmd, unsigned long arg); extern int i830_flush_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern void i830_reclaim_buffers(drm_device_t *dev, pid_t pid); +extern void i830_reclaim_buffers(struct file *filp); extern int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma); @@ -108,6 +121,23 @@ extern int i830_clear_bufs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern int i830_flip_bufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + +extern int i830_getparam( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); + +extern int i830_setparam( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); + +/* i830_irq.c */ +extern int i830_irq_emit( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); +extern int i830_irq_wait( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); +extern int i830_wait_irq(drm_device_t *dev, int irq_nr); +extern int i830_emit_irq(drm_device_t *dev); + #define I830_BASE(reg) ((unsigned long) \ dev_priv->mmio_map->handle) @@ -119,12 +149,53 @@ #define I830_READ16(reg) I830_DEREF16(reg) #define I830_WRITE16(reg,val) do { I830_DEREF16(reg) = val; } while (0) + + +#define I830_VERBOSE 0 + +#define RING_LOCALS unsigned int outring, ringmask, outcount; \ + volatile char *virt; + +#define BEGIN_LP_RING(n) do { \ + if (I830_VERBOSE) \ + printk("BEGIN_LP_RING(%d) in %s\n", \ + n, __FUNCTION__); \ + if (dev_priv->ring.space < n*4) \ + i830_wait_ring(dev, n*4, __FUNCTION__); \ + outcount = 0; \ + outring = dev_priv->ring.tail; \ + ringmask = dev_priv->ring.tail_mask; \ + virt = dev_priv->ring.virtual_start; \ +} while (0) + + +#define OUT_RING(n) do { \ + if (I830_VERBOSE) printk(" OUT_RING %x\n", (int)(n)); \ + *(volatile unsigned int *)(virt + outring) = n; \ + outcount++; \ + outring += 4; \ + outring &= ringmask; \ +} while (0) + +#define ADVANCE_LP_RING() do { \ + if (I830_VERBOSE) printk("ADVANCE_LP_RING %x\n", outring); \ + dev_priv->ring.tail = outring; \ + dev_priv->ring.space -= outcount * 4; \ + I830_WRITE(LP_RING + RING_TAIL, outring); \ +} while(0) + +extern int i830_wait_ring(drm_device_t *dev, int n, const char *caller); + + #define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23)) #define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23)) #define CMD_REPORT_HEAD (7<<23) #define CMD_STORE_DWORD_IDX ((0x21<<23) | 0x1) #define CMD_OP_BATCH_BUFFER ((0x0<<29)|(0x30<<23)|0x1) +#define STATE3D_LOAD_STATE_IMMEDIATE_2 ((0x3<<29)|(0x1d<<24)|(0x03<<16)) +#define LOAD_TEXTURE_MAP0 (1<<11) + #define INST_PARSER_CLIENT 0x00000000 #define INST_OP_FLUSH 0x02000000 #define INST_FLUSH_MAP_CACHE 0x00000001 @@ -140,6 +211,9 @@ #define I830REG_INT_MASK_R 0x020a8 #define I830REG_INT_ENABLE_R 0x020a0 +#define I830_IRQ_RESERVED ((1<<13)|(3<<2)) + + #define LP_RING 0x2030 #define HP_RING 0x2040 #define RING_TAIL 0x00 @@ -182,6 +256,9 @@ #define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1) +#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2) +#define ASYNC_FLIP (1<<22) + #define CMD_3D (0x3<<29) #define STATE3D_CONST_BLEND_COLOR_CMD (CMD_3D|(0x1d<<24)|(0x88<<16)) #define STATE3D_MAP_COORD_SETBIND_CMD (CMD_3D|(0x1d<<24)|(0x02<<16)) @@ -213,6 +290,11 @@ #define MI_BATCH_BUFFER_END (0xA<<23) #define MI_BATCH_NON_SECURE (1) +#define MI_WAIT_FOR_EVENT ((0x3<<23)) +#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) +#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1) + +#define MI_LOAD_SCAN_LINES_INCL ((0x12<<23)) #endif diff -Nru a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/drm/i830_irq.c Sat Mar 29 22:34:33 2003 @@ -0,0 +1,177 @@ +/* i830_dma.c -- DMA support for the I830 -*- linux-c -*- + * + * Copyright 2002 Tungsten Graphics, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Keith Whitwell + * + */ + +#include "i830.h" +#include "drmP.h" +#include "drm.h" +#include "i830_drm.h" +#include "i830_drv.h" +#include /* For task queue support */ +#include + + +void DRM(dma_service)(int irq, void *device, struct pt_regs *regs) +{ + drm_device_t *dev = (drm_device_t *)device; + drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; + u16 temp; + + temp = I830_READ16(I830REG_INT_IDENTITY_R); + printk("%s: %x\n", __FUNCTION__, temp); + + if(temp == 0) + return; + + I830_WRITE16(I830REG_INT_IDENTITY_R, temp); + + if (temp & 2) { + atomic_inc(&dev_priv->irq_received); + wake_up_interruptible(&dev_priv->irq_queue); + } +} + + +int i830_emit_irq(drm_device_t *dev) +{ + drm_i830_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + DRM_DEBUG("%s\n", __FUNCTION__); + + atomic_inc(&dev_priv->irq_emitted); + + BEGIN_LP_RING(2); + OUT_RING( 0 ); + OUT_RING( GFX_OP_USER_INTERRUPT ); + ADVANCE_LP_RING(); + + return atomic_read(&dev_priv->irq_emitted); +} + + +int i830_wait_irq(drm_device_t *dev, int irq_nr) +{ + drm_i830_private_t *dev_priv = + (drm_i830_private_t *)dev->dev_private; + DECLARE_WAITQUEUE(entry, current); + unsigned long end = jiffies + HZ*3; + int ret = 0; + + DRM_DEBUG("%s\n", __FUNCTION__); + + if (atomic_read(&dev_priv->irq_received) >= irq_nr) + return 0; + + dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT; + + add_wait_queue(&dev_priv->irq_queue, &entry); + + for (;;) { + current->state = TASK_INTERRUPTIBLE; + if (atomic_read(&dev_priv->irq_received) >= irq_nr) + break; + if((signed)(end - jiffies) <= 0) { + DRM_ERROR("timeout iir %x imr %x ier %x hwstam %x\n", + I830_READ16( I830REG_INT_IDENTITY_R ), + I830_READ16( I830REG_INT_MASK_R ), + I830_READ16( I830REG_INT_ENABLE_R ), + I830_READ16( I830REG_HWSTAM )); + + ret = -EBUSY; /* Lockup? Missed irq? */ + break; + } + schedule_timeout(HZ*3); + if (signal_pending(current)) { + ret = -EINTR; + break; + } + } + + current->state = TASK_RUNNING; + remove_wait_queue(&dev_priv->irq_queue, &entry); + return ret; +} + + +/* Needs the lock as it touches the ring. + */ +int i830_irq_emit( struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i830_private_t *dev_priv = dev->dev_private; + drm_i830_irq_emit_t emit; + int result; + + if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { + DRM_ERROR("i830_irq_emit called without lock held\n"); + return -EINVAL; + } + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + if (copy_from_user( &emit, (drm_i830_irq_emit_t *)arg, sizeof(emit) )) + return -EFAULT; + + result = i830_emit_irq( dev ); + + if ( copy_to_user( emit.irq_seq, &result, sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return -EFAULT; + } + + return 0; +} + + +/* Doesn't need the hardware lock. + */ +int i830_irq_wait( struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_i830_private_t *dev_priv = dev->dev_private; + drm_i830_irq_wait_t irqwait; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + if (copy_from_user( &irqwait, (drm_i830_irq_wait_t *)arg, + sizeof(irqwait) )) + return -EFAULT; + + return i830_wait_irq( dev, irqwait.irq_seq ); +} + diff -Nru a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c --- a/drivers/char/drm/mga_dma.c Sat Nov 16 17:33:53 2002 +++ b/drivers/char/drm/mga_dma.c Sat Mar 29 22:34:33 2003 @@ -686,7 +686,7 @@ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; drm_lock_t lock; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( lock, (drm_lock_t *)data, sizeof(lock) ); @@ -720,7 +720,7 @@ DRM_DEVICE; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); return mga_do_dma_reset( dev_priv ); } @@ -730,7 +730,8 @@ * DMA buffer management */ -static int mga_dma_get_buffers( drm_device_t *dev, drm_dma_t *d ) +static int mga_dma_get_buffers( DRMFILE filp, + drm_device_t *dev, drm_dma_t *d ) { drm_buf_t *buf; int i; @@ -739,7 +740,7 @@ buf = mga_freelist_get( dev ); if ( !buf ) return DRM_ERR(EAGAIN); - buf->pid = DRM_CURRENTPID; + buf->filp = filp; if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx, sizeof(buf->idx) ) ) @@ -761,7 +762,7 @@ drm_dma_t d; int ret = 0; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( d, (drm_dma_t *)data, sizeof(d) ); @@ -786,7 +787,7 @@ d.granted_count = 0; if ( d.request_count ) { - ret = mga_dma_get_buffers( dev, &d ); + ret = mga_dma_get_buffers( filp, dev, &d ); } DRM_COPY_TO_USER_IOCTL( (drm_dma_t *)data, d, sizeof(d) ); diff -Nru a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h --- a/drivers/char/drm/mga_drv.h Sat Nov 16 17:33:53 2002 +++ b/drivers/char/drm/mga_drv.h Sat Mar 29 22:34:33 2003 @@ -90,14 +90,14 @@ unsigned int texture_offset; unsigned int texture_size; - drm_map_t *sarea; - drm_map_t *fb; - drm_map_t *mmio; - drm_map_t *status; - drm_map_t *warp; - drm_map_t *primary; - drm_map_t *buffers; - drm_map_t *agp_textures; + drm_local_map_t *sarea; + drm_local_map_t *fb; + drm_local_map_t *mmio; + drm_local_map_t *status; + drm_local_map_t *warp; + drm_local_map_t *primary; + drm_local_map_t *buffers; + drm_local_map_t *agp_textures; } drm_mga_private_t; /* mga_dma.c */ @@ -131,32 +131,30 @@ extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv ); extern int mga_warp_init( drm_mga_private_t *dev_priv ); -#define mga_flush_write_combine() DRM_WRITEMEMORYBARRIER() - +#define mga_flush_write_combine() DRM_WRITEMEMORYBARRIER(dev_priv->primary) +#if defined(__linux__) && defined(__alpha__) #define MGA_BASE( reg ) ((unsigned long)(dev_priv->mmio->handle)) #define MGA_ADDR( reg ) (MGA_BASE(reg) + reg) #define MGA_DEREF( reg ) *(volatile u32 *)MGA_ADDR( reg ) #define MGA_DEREF8( reg ) *(volatile u8 *)MGA_ADDR( reg ) -#ifdef __alpha__ #define MGA_READ( reg ) (_MGA_READ((u32 *)MGA_ADDR(reg))) #define MGA_READ8( reg ) (_MGA_READ((u8 *)MGA_ADDR(reg))) -#define MGA_WRITE( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF( reg ) = val; } while (0) -#define MGA_WRITE8( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8( reg ) = val; } while (0) +#define MGA_WRITE( reg, val ) do { DRM_WRITEMEMORYBARRIER(dev_priv->mmio); MGA_DEREF( reg ) = val; } while (0) +#define MGA_WRITE8( reg, val ) do { DRM_WRITEMEMORYBARRIER(dev_priv->mmio); MGA_DEREF8( reg ) = val; } while (0) static inline u32 _MGA_READ(u32 *addr) { - DRM_READMEMORYBARRIER(); + DRM_READMEMORYBARRIER(dev_priv->mmio); return *(volatile u32 *)addr; } - #else -#define MGA_READ( reg ) MGA_DEREF( reg ) -#define MGA_READ8( reg ) MGA_DEREF8( reg ) -#define MGA_WRITE( reg, val ) do { MGA_DEREF( reg ) = val; } while (0) -#define MGA_WRITE8( reg, val ) do { MGA_DEREF8( reg ) = val; } while (0) +#define MGA_READ8( reg ) DRM_READ8(dev_priv->mmio, (reg)) +#define MGA_READ( reg ) DRM_READ32(dev_priv->mmio, (reg)) +#define MGA_WRITE8( reg, val ) DRM_WRITE8(dev_priv->mmio, (reg), (val)) +#define MGA_WRITE( reg, val ) DRM_WRITE32(dev_priv->mmio, (reg), (val)) #endif #define DWGREG0 0x1c00 @@ -183,16 +181,6 @@ } else { \ mga_g200_emit_state( dev_priv ); \ } \ - } \ -} while (0) - -#define LOCK_TEST_WITH_RETURN( dev ) \ -do { \ - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \ - dev->lock.pid != DRM_CURRENTPID ) { \ - DRM_ERROR( "%s called without lock held\n", \ - __FUNCTION__ ); \ - return DRM_ERR(EINVAL); \ } \ } while (0) diff -Nru a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c --- a/drivers/char/drm/mga_state.c Sat Nov 16 17:33:54 2002 +++ b/drivers/char/drm/mga_state.c Sat Mar 29 22:34:33 2003 @@ -887,7 +887,7 @@ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_clear_t clear; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( clear, (drm_mga_clear_t *)data, sizeof(clear) ); @@ -911,7 +911,7 @@ drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS ) sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; @@ -936,7 +936,7 @@ drm_mga_buf_priv_t *buf_priv; drm_mga_vertex_t vertex; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( vertex, (drm_mga_vertex_t *)data, @@ -975,7 +975,7 @@ drm_mga_buf_priv_t *buf_priv; drm_mga_indices_t indices; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( indices, (drm_mga_indices_t *)data, @@ -1015,7 +1015,7 @@ drm_mga_iload_t iload; DRM_DEBUG( "\n" ); - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( iload, (drm_mga_iload_t *)data, sizeof(iload) ); @@ -1055,7 +1055,7 @@ drm_mga_blit_t blit; DRM_DEBUG( "\n" ); - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( blit, (drm_mga_blit_t *)data, sizeof(blit) ); diff -Nru a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c --- a/drivers/char/drm/r128_cce.c Tue Oct 29 14:29:21 2002 +++ b/drivers/char/drm/r128_cce.c Sat Mar 29 22:34:33 2003 @@ -579,6 +579,7 @@ (dev_priv->ring.size / sizeof(u32)) - 1; dev_priv->ring.high_mark = 128; + dev_priv->ring.ring_rptr = dev_priv->ring_rptr; dev_priv->sarea_priv->last_frame = 0; R128_WRITE( R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame ); @@ -663,7 +664,7 @@ drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "\n" ); - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); if ( dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4 ) { DRM_DEBUG( "%s while CCE running\n", __FUNCTION__ ); @@ -686,7 +687,7 @@ int ret; DRM_DEBUG( "\n" ); - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL(stop, (drm_r128_cce_stop_t *)data, sizeof(stop) ); @@ -725,7 +726,7 @@ drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "\n" ); - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); if ( !dev_priv ) { DRM_DEBUG( "%s called before init done\n", __FUNCTION__ ); @@ -746,7 +747,7 @@ drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "\n" ); - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); if ( dev_priv->cce_running ) { r128_do_cce_flush( dev_priv ); @@ -760,7 +761,7 @@ DRM_DEVICE; DRM_DEBUG( "\n" ); - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); return r128_do_engine_reset( dev ); } @@ -807,7 +808,7 @@ DRM_DEVICE; drm_r128_fullscreen_t fs; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( fs, (drm_r128_fullscreen_t *)data, sizeof(fs) ); @@ -889,7 +890,7 @@ for ( i = 0 ; i < dma->buf_count ; i++ ) { buf = dma->buflist[i]; buf_priv = buf->dev_private; - if ( buf->pid == 0 ) + if ( buf->filp == 0 ) return buf; } @@ -948,7 +949,7 @@ return DRM_ERR(EBUSY); } -static int r128_cce_get_buffers( drm_device_t *dev, drm_dma_t *d ) +static int r128_cce_get_buffers( DRMFILE filp, drm_device_t *dev, drm_dma_t *d ) { int i; drm_buf_t *buf; @@ -957,7 +958,7 @@ buf = r128_freelist_get( dev ); if ( !buf ) return DRM_ERR(EAGAIN); - buf->pid = DRM_CURRENTPID; + buf->filp = filp; if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx, sizeof(buf->idx) ) ) @@ -978,7 +979,7 @@ int ret = 0; drm_dma_t d; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( d, (drm_dma_t *) data, sizeof(d) ); @@ -1001,7 +1002,7 @@ d.granted_count = 0; if ( d.request_count ) { - ret = r128_cce_get_buffers( dev, &d ); + ret = r128_cce_get_buffers( filp, dev, &d ); } DRM_COPY_TO_USER_IOCTL((drm_dma_t *) data, d, sizeof(d) ); diff -Nru a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h --- a/drivers/char/drm/r128_drv.h Sat Nov 16 17:33:55 2002 +++ b/drivers/char/drm/r128_drv.h Sat Mar 29 22:34:33 2003 @@ -34,8 +34,8 @@ #ifndef __R128_DRV_H__ #define __R128_DRV_H__ -#define GET_RING_HEAD(ring) DRM_READ32( (volatile u32 *) (ring)->head ) -#define SET_RING_HEAD(ring,val) DRM_WRITE32( (volatile u32 *) (ring)->head, (val) ) +#define GET_RING_HEAD(ring) DRM_READ32( (ring)->ring_rptr, 0 ) /* (ring)->head */ +#define SET_RING_HEAD(ring,val) DRM_WRITE32( (ring)->ring_rptr, 0, (val) ) /* (ring)->head */ typedef struct drm_r128_freelist { unsigned int age; @@ -56,6 +56,7 @@ int space; int high_mark; + drm_local_map_t *ring_rptr; } drm_r128_ring_buffer_t; typedef struct drm_r128_private { @@ -98,13 +99,13 @@ u32 depth_pitch_offset_c; u32 span_pitch_offset_c; - drm_map_t *sarea; - drm_map_t *fb; - drm_map_t *mmio; - drm_map_t *cce_ring; - drm_map_t *ring_rptr; - drm_map_t *buffers; - drm_map_t *agp_textures; + drm_local_map_t *sarea; + drm_local_map_t *fb; + drm_local_map_t *mmio; + drm_local_map_t *cce_ring; + drm_local_map_t *ring_rptr; + drm_local_map_t *buffers; + drm_local_map_t *agp_textures; } drm_r128_private_t; typedef struct drm_r128_buf_priv { @@ -370,15 +371,10 @@ #define R128_PERFORMANCE_BOXES 0 - -#define R128_BASE(reg) ((unsigned long)(dev_priv->mmio->handle)) -#define R128_ADDR(reg) (R128_BASE( reg ) + reg) - -#define R128_READ(reg) DRM_READ32( (volatile u32 *) R128_ADDR(reg) ) -#define R128_WRITE(reg,val) DRM_WRITE32( (volatile u32 *) R128_ADDR(reg), (val) ) - -#define R128_READ8(reg) DRM_READ8( (volatile u8 *) R128_ADDR(reg) ) -#define R128_WRITE8(reg,val) DRM_WRITE8( (volatile u8 *) R128_ADDR(reg), (val) ) +#define R128_READ(reg) DRM_READ32( dev_priv->mmio, (reg) ) +#define R128_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) ) +#define R128_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) ) +#define R128_WRITE8(reg,val) DRM_WRITE8( dev_priv->mmio, (reg), (val) ) #define R128_WRITE_PLL(addr,val) \ do { \ @@ -403,15 +399,6 @@ * Misc helper macros */ -#define LOCK_TEST_WITH_RETURN( dev ) \ -do { \ - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \ - dev->lock.pid != DRM_CURRENTPID ) { \ - DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); \ - return DRM_ERR(EINVAL); \ - } \ -} while (0) - #define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \ do { \ drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i; \ @@ -453,7 +440,7 @@ #if defined(__powerpc__) #define r128_flush_write_combine() (void) GET_RING_HEAD( &dev_priv->ring ) #else -#define r128_flush_write_combine() DRM_WRITEMEMORYBARRIER() +#define r128_flush_write_combine() DRM_WRITEMEMORYBARRIER(dev_priv->ring_rptr) #endif diff -Nru a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c --- a/drivers/char/drm/r128_state.c Sat Nov 16 17:33:55 2002 +++ b/drivers/char/drm/r128_state.c Sat Mar 29 22:34:33 2003 @@ -778,7 +778,8 @@ sarea_priv->nbox = 0; } -static int r128_cce_dispatch_blit( drm_device_t *dev, +static int r128_cce_dispatch_blit( DRMFILE filp, + drm_device_t *dev, drm_r128_blit_t *blit ) { drm_r128_private_t *dev_priv = dev->dev_private; @@ -829,9 +830,9 @@ buf = dma->buflist[blit->idx]; buf_priv = buf->dev_private; - if ( buf->pid != DRM_CURRENTPID ) { - DRM_ERROR( "process %d using buffer owned by %d\n", - DRM_CURRENTPID, buf->pid ); + if ( buf->filp != filp ) { + DRM_ERROR( "process %d using buffer owned by %p\n", + DRM_CURRENTPID, buf->filp ); return DRM_ERR(EINVAL); } if ( buf->pending ) { @@ -896,7 +897,7 @@ int count, x, y; u32 *buffer; u8 *mask; - int i; + int i, buffer_size, mask_size; RING_LOCALS; DRM_DEBUG( "\n" ); @@ -908,25 +909,25 @@ return DRM_ERR(EFAULT); } - buffer = DRM_MALLOC( depth->n * sizeof(u32) ); + buffer_size = depth->n * sizeof(u32); + buffer = DRM_MALLOC( buffer_size ); if ( buffer == NULL ) return DRM_ERR(ENOMEM); - if ( DRM_COPY_FROM_USER( buffer, depth->buffer, - depth->n * sizeof(u32) ) ) { - DRM_FREE( buffer ); + if ( DRM_COPY_FROM_USER( buffer, depth->buffer, buffer_size ) ) { + DRM_FREE( buffer, buffer_size); return DRM_ERR(EFAULT); } + mask_size = depth->n * sizeof(u8); if ( depth->mask ) { - mask = DRM_MALLOC( depth->n * sizeof(u8) ); + mask = DRM_MALLOC( mask_size ); if ( mask == NULL ) { - DRM_FREE( buffer ); + DRM_FREE( buffer, buffer_size ); return DRM_ERR(ENOMEM); } - if ( DRM_COPY_FROM_USER( mask, depth->mask, - depth->n * sizeof(u8) ) ) { - DRM_FREE( buffer ); - DRM_FREE( mask ); + if ( DRM_COPY_FROM_USER( mask, depth->mask, mask_size ) ) { + DRM_FREE( buffer, buffer_size ); + DRM_FREE( mask, mask_size ); return DRM_ERR(EFAULT); } @@ -953,7 +954,7 @@ } } - DRM_FREE( mask ); + DRM_FREE( mask, mask_size ); } else { for ( i = 0 ; i < count ; i++, x++ ) { BEGIN_RING( 6 ); @@ -977,7 +978,7 @@ } } - DRM_FREE( buffer ); + DRM_FREE( buffer, buffer_size ); return 0; } @@ -989,60 +990,62 @@ int count, *x, *y; u32 *buffer; u8 *mask; - int i; + int i, xbuf_size, ybuf_size, buffer_size, mask_size; RING_LOCALS; DRM_DEBUG( "\n" ); count = depth->n; - x = DRM_MALLOC( count * sizeof(*x) ); + xbuf_size = count * sizeof(*x); + ybuf_size = count * sizeof(*y); + x = DRM_MALLOC( xbuf_size ); if ( x == NULL ) { return DRM_ERR(ENOMEM); } - y = DRM_MALLOC( count * sizeof(*y) ); + y = DRM_MALLOC( ybuf_size ); if ( y == NULL ) { - DRM_FREE( x ); + DRM_FREE( x, xbuf_size ); return DRM_ERR(ENOMEM); } - if ( DRM_COPY_FROM_USER( x, depth->x, count * sizeof(int) ) ) { - DRM_FREE( x ); - DRM_FREE( y ); + if ( DRM_COPY_FROM_USER( x, depth->x, xbuf_size ) ) { + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); return DRM_ERR(EFAULT); } - if ( DRM_COPY_FROM_USER( y, depth->y, count * sizeof(int) ) ) { - DRM_FREE( x ); - DRM_FREE( y ); + if ( DRM_COPY_FROM_USER( y, depth->y, xbuf_size ) ) { + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); return DRM_ERR(EFAULT); } - buffer = DRM_MALLOC( depth->n * sizeof(u32) ); + buffer_size = depth->n * sizeof(u32); + buffer = DRM_MALLOC( buffer_size ); if ( buffer == NULL ) { - DRM_FREE( x ); - DRM_FREE( y ); + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); return DRM_ERR(ENOMEM); } - if ( DRM_COPY_FROM_USER( buffer, depth->buffer, - depth->n * sizeof(u32) ) ) { - DRM_FREE( x ); - DRM_FREE( y ); - DRM_FREE( buffer ); + if ( DRM_COPY_FROM_USER( buffer, depth->buffer, buffer_size ) ) { + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); + DRM_FREE( buffer, buffer_size ); return DRM_ERR(EFAULT); } if ( depth->mask ) { - mask = DRM_MALLOC( depth->n * sizeof(u8) ); + mask_size = depth->n * sizeof(u8); + mask = DRM_MALLOC( mask_size ); if ( mask == NULL ) { - DRM_FREE( x ); - DRM_FREE( y ); - DRM_FREE( buffer ); + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); + DRM_FREE( buffer, buffer_size ); return DRM_ERR(ENOMEM); } - if ( DRM_COPY_FROM_USER( mask, depth->mask, - depth->n * sizeof(u8) ) ) { - DRM_FREE( x ); - DRM_FREE( y ); - DRM_FREE( buffer ); - DRM_FREE( mask ); + if ( DRM_COPY_FROM_USER( mask, depth->mask, mask_size ) ) { + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); + DRM_FREE( buffer, buffer_size ); + DRM_FREE( mask, mask_size ); return DRM_ERR(EFAULT); } @@ -1069,7 +1072,7 @@ } } - DRM_FREE( mask ); + DRM_FREE( mask, mask_size ); } else { for ( i = 0 ; i < count ; i++ ) { BEGIN_RING( 6 ); @@ -1093,9 +1096,9 @@ } } - DRM_FREE( x ); - DRM_FREE( y ); - DRM_FREE( buffer ); + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); + DRM_FREE( buffer, buffer_size ); return 0; } @@ -1146,7 +1149,7 @@ { drm_r128_private_t *dev_priv = dev->dev_private; int count, *x, *y; - int i; + int i, xbuf_size, ybuf_size; RING_LOCALS; DRM_DEBUG( "%s\n", __FUNCTION__ ); @@ -1155,23 +1158,25 @@ count = dev_priv->depth_pitch; } - x = DRM_MALLOC( count * sizeof(*x) ); + xbuf_size = count * sizeof(*x); + ybuf_size = count * sizeof(*y); + x = DRM_MALLOC( xbuf_size ); if ( x == NULL ) { return DRM_ERR(ENOMEM); } - y = DRM_MALLOC( count * sizeof(*y) ); + y = DRM_MALLOC( ybuf_size ); if ( y == NULL ) { - DRM_FREE( x ); + DRM_FREE( x, xbuf_size ); return DRM_ERR(ENOMEM); } - if ( DRM_COPY_FROM_USER( x, depth->x, count * sizeof(int) ) ) { - DRM_FREE( x ); - DRM_FREE( y ); + if ( DRM_COPY_FROM_USER( x, depth->x, xbuf_size ) ) { + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); return DRM_ERR(EFAULT); } - if ( DRM_COPY_FROM_USER( y, depth->y, count * sizeof(int) ) ) { - DRM_FREE( x ); - DRM_FREE( y ); + if ( DRM_COPY_FROM_USER( y, depth->y, ybuf_size ) ) { + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); return DRM_ERR(EFAULT); } @@ -1199,8 +1204,8 @@ ADVANCE_RING(); } - DRM_FREE( x ); - DRM_FREE( y ); + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); return 0; } @@ -1240,7 +1245,7 @@ drm_r128_clear_t clear; DRM_DEBUG( "\n" ); - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( clear, (drm_r128_clear_t *) data, sizeof(clear) ); @@ -1266,7 +1271,7 @@ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; DRM_DEBUG( "%s\n", __FUNCTION__ ); - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); RING_SPACE_TEST_WITH_RETURN( dev_priv ); @@ -1293,7 +1298,7 @@ drm_r128_buf_priv_t *buf_priv; drm_r128_vertex_t vertex; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); @@ -1324,9 +1329,9 @@ buf = dma->buflist[vertex.idx]; buf_priv = buf->dev_private; - if ( buf->pid != DRM_CURRENTPID ) { - DRM_ERROR( "process %d using buffer owned by %d\n", - DRM_CURRENTPID, buf->pid ); + if ( buf->filp != filp ) { + DRM_ERROR( "process %d using buffer owned by %p\n", + DRM_CURRENTPID, buf->filp ); return DRM_ERR(EINVAL); } if ( buf->pending ) { @@ -1353,7 +1358,7 @@ drm_r128_indices_t elts; int count; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); @@ -1383,9 +1388,9 @@ buf = dma->buflist[elts.idx]; buf_priv = buf->dev_private; - if ( buf->pid != DRM_CURRENTPID ) { - DRM_ERROR( "process %d using buffer owned by %d\n", - DRM_CURRENTPID, buf->pid ); + if ( buf->filp != filp ) { + DRM_ERROR( "process %d using buffer owned by %p\n", + DRM_CURRENTPID, buf->filp ); return DRM_ERR(EINVAL); } if ( buf->pending ) { @@ -1421,7 +1426,7 @@ drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_blit_t blit; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( blit, (drm_r128_blit_t *) data, sizeof(blit) ); @@ -1437,7 +1442,7 @@ RING_SPACE_TEST_WITH_RETURN( dev_priv ); VB_AGE_TEST_WITH_RETURN( dev_priv ); - return r128_cce_dispatch_blit( dev, &blit ); + return r128_cce_dispatch_blit( filp, dev, &blit ); } int r128_cce_depth( DRM_IOCTL_ARGS ) @@ -1446,7 +1451,7 @@ drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_depth_t depth; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( depth, (drm_r128_depth_t *) data, sizeof(depth) ); @@ -1474,7 +1479,7 @@ drm_r128_stipple_t stipple; u32 mask[32]; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( stipple, (drm_r128_stipple_t *) data, sizeof(stipple) ); @@ -1502,7 +1507,7 @@ RING_LOCALS; #endif - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); @@ -1525,9 +1530,9 @@ buf = dma->buflist[indirect.idx]; buf_priv = buf->dev_private; - if ( buf->pid != DRM_CURRENTPID ) { - DRM_ERROR( "process %d using buffer owned by %d\n", - DRM_CURRENTPID, buf->pid ); + if ( buf->filp != filp ) { + DRM_ERROR( "process %d using buffer owned by %p\n", + DRM_CURRENTPID, buf->filp ); return DRM_ERR(EINVAL); } if ( buf->pending ) { diff -Nru a/drivers/char/drm/radeon.h b/drivers/char/drm/radeon.h --- a/drivers/char/drm/radeon.h Sat Nov 16 17:33:55 2002 +++ b/drivers/char/drm/radeon.h Sat Mar 29 22:34:33 2003 @@ -51,7 +51,7 @@ #define DRIVER_DATE "20020828" #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 7 +#define DRIVER_MINOR 8 #define DRIVER_PATCHLEVEL 0 /* Interface history: @@ -77,6 +77,7 @@ * and R200_PP_CUBIC_OFFSET_F1_[0..5]. * Added packets R200_EMIT_PP_CUBIC_FACES_[0..5] and * R200_EMIT_PP_CUBIC_OFFSETS_[0..5]. (brian) + * 1.8 - Remove need to call cleanup ioctls on last client exit (keith) */ #define DRIVER_IOCTLS \ [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \ @@ -105,11 +106,6 @@ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)] = { radeon_irq_wait, 1, 0 }, -#define USE_IRQS 1 -#if USE_IRQS -#define __HAVE_DMA_IRQ 1 -#define __HAVE_VBL_IRQ 1 -#define __HAVE_SHARED_IRQ 1 /* When a client dies: * - Check for and clean up flipped page state @@ -117,35 +113,34 @@ * * DRM infrastructure takes care of reclaiming dma buffers. */ -#define DRIVER_PRERELEASE() do { \ +#define DRIVER_PRERELEASE() \ +do { \ if ( dev->dev_private ) { \ drm_radeon_private_t *dev_priv = dev->dev_private; \ if ( dev_priv->page_flipping ) { \ radeon_do_cleanup_pageflip( dev ); \ } \ - radeon_mem_release( dev_priv->agp_heap ); \ + radeon_mem_release( filp, dev_priv->agp_heap ); \ + radeon_mem_release( filp, dev_priv->fb_heap ); \ } \ } while (0) -/* On unloading the module: - * - Free memory heap structure - * - Remove mappings made at startup and free dev_private. +/* When the last client dies, shut down the CP and free dev->dev_priv. */ -#define DRIVER_PRETAKEDOWN() do { \ - if ( dev->dev_private ) { \ - drm_radeon_private_t *dev_priv = dev->dev_private; \ - radeon_mem_takedown( &(dev_priv->agp_heap) ); \ - radeon_do_cleanup_cp( dev ); \ - } \ +/* #define __HAVE_RELEASE 1 */ +#define DRIVER_PRETAKEDOWN() \ +do { \ + radeon_do_release( dev ); \ } while (0) -#else -#define __HAVE_DMA_IRQ 0 -#endif + /* DMA customization: */ #define __HAVE_DMA 1 +#define __HAVE_DMA_IRQ 1 +#define __HAVE_VBL_IRQ 1 +#define __HAVE_SHARED_IRQ 1 /* Buffer customization: diff -Nru a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c --- a/drivers/char/drm/radeon_cp.c Wed Dec 18 09:56:28 2002 +++ b/drivers/char/drm/radeon_cp.c Sat Mar 29 22:34:33 2003 @@ -926,11 +926,11 @@ RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 ); /* Writeback doesn't seem to work everywhere, test it first */ - DRM_WRITE32( &dev_priv->scratch[1], 0 ); + DRM_WRITE32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0 ); RADEON_WRITE( RADEON_SCRATCH_REG1, 0xdeadbeef ); for ( tmp = 0 ; tmp < dev_priv->usec_timeout ; tmp++ ) { - if ( DRM_READ32( &dev_priv->scratch[1] ) == 0xdeadbeef ) + if ( DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(1) ) == 0xdeadbeef ) break; DRM_UDELAY( 1 ); } @@ -1217,6 +1217,7 @@ (dev_priv->ring.size / sizeof(u32)) - 1; dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; + dev_priv->ring.ring_rptr = dev_priv->ring_rptr; #if __REALLY_HAVE_SG if ( dev_priv->is_pci ) { @@ -1322,7 +1323,7 @@ drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "\n" ); - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); if ( dev_priv->cp_running ) { DRM_DEBUG( "%s while CP running\n", __FUNCTION__ ); @@ -1350,10 +1351,13 @@ int ret; DRM_DEBUG( "\n" ); - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( stop, (drm_radeon_cp_stop_t *)data, sizeof(stop) ); + if (!dev_priv->cp_running) + return 0; + /* Flush any pending CP commands. This ensures any outstanding * commands are exectuted by the engine before we turn it off. */ @@ -1381,6 +1385,39 @@ return 0; } + +void radeon_do_release( drm_device_t *dev ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + int ret; + + if (dev_priv) { + if (dev_priv->cp_running) { + /* Stop the cp */ + while ((ret = radeon_do_cp_idle( dev_priv )) != 0) { + DRM_DEBUG("radeon_do_cp_idle %d\n", ret); +#ifdef __linux__ + schedule(); +#else + tsleep(&ret, PZERO, "rdnrel", 1); +#endif + } + radeon_do_cp_stop( dev_priv ); + radeon_do_engine_reset( dev ); + } + + /* Disable *all* interrupts */ + RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); + + /* Free memory heap structures */ + radeon_mem_takedown( &(dev_priv->agp_heap) ); + radeon_mem_takedown( &(dev_priv->fb_heap) ); + + /* deallocate kernel resources */ + radeon_do_cleanup_cp( dev ); + } +} + /* Just reset the CP ring. Called as part of an X Server engine reset. */ int radeon_cp_reset( DRM_IOCTL_ARGS ) @@ -1389,7 +1426,7 @@ drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "\n" ); - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); if ( !dev_priv ) { DRM_DEBUG( "%s called before init done\n", __FUNCTION__ ); @@ -1410,10 +1447,7 @@ drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "\n" ); - LOCK_TEST_WITH_RETURN( dev ); - -/* if (dev->irq) */ -/* radeon_emit_and_wait_irq( dev ); */ + LOCK_TEST_WITH_RETURN( dev, filp ); return radeon_do_cp_idle( dev_priv ); } @@ -1423,7 +1457,7 @@ DRM_DEVICE; DRM_DEBUG( "\n" ); - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); return radeon_do_engine_reset( dev ); } @@ -1482,7 +1516,7 @@ for ( i = start ; i < dma->buf_count ; i++ ) { buf = dma->buflist[i]; buf_priv = buf->dev_private; - if ( buf->pid == 0 || (buf->pending && + if ( buf->filp == 0 || (buf->pending && buf_priv->age <= done_age) ) { dev_priv->stats.requested_bufs++; buf->pending = 0; @@ -1509,7 +1543,7 @@ drm_buf_t *buf; int i, t; int start; - u32 done_age = DRM_READ32(&dev_priv->scratch[1]); + u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)); if ( ++dev_priv->last_buf >= dma->buf_count ) dev_priv->last_buf = 0; @@ -1521,7 +1555,7 @@ for ( i = start ; i < dma->buf_count ; i++ ) { buf = dma->buflist[i]; buf_priv = buf->dev_private; - if ( buf->pid == 0 || (buf->pending && + if ( buf->filp == 0 || (buf->pending && buf_priv->age <= done_age) ) { dev_priv->stats.requested_bufs++; buf->pending = 0; @@ -1586,7 +1620,7 @@ return DRM_ERR(EBUSY); } -static int radeon_cp_get_buffers( drm_device_t *dev, drm_dma_t *d ) +static int radeon_cp_get_buffers( DRMFILE filp, drm_device_t *dev, drm_dma_t *d ) { int i; drm_buf_t *buf; @@ -1595,7 +1629,7 @@ buf = radeon_freelist_get( dev ); if ( !buf ) return DRM_ERR(EBUSY); /* NOTE: broken client */ - buf->pid = DRM_CURRENTPID; + buf->filp = filp; if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx, sizeof(buf->idx) ) ) @@ -1616,7 +1650,7 @@ int ret = 0; drm_dma_t d; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( d, (drm_dma_t *)data, sizeof(d) ); @@ -1639,7 +1673,7 @@ d.granted_count = 0; if ( d.request_count ) { - ret = radeon_cp_get_buffers( dev, &d ); + ret = radeon_cp_get_buffers( filp, dev, &d ); } DRM_COPY_TO_USER_IOCTL( (drm_dma_t *)data, d, sizeof(d) ); diff -Nru a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h --- a/drivers/char/drm/radeon_drm.h Sat Nov 16 17:33:55 2002 +++ b/drivers/char/drm/radeon_drm.h Sat Mar 29 22:34:33 2003 @@ -382,7 +382,7 @@ #define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( 0x4c, drm_radeon_stipple_t) #define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t) #define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4e, drm_radeon_texture_t) -#define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( 0x4f, drm_radeon_vertex_t) +#define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( 0x4f, drm_radeon_vertex2_t) #define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( 0x50, drm_radeon_cmd_buffer_t) #define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(0x51, drm_radeon_getparam_t) #define DRM_IOCTL_RADEON_FLIP DRM_IO( 0x52) @@ -396,7 +396,7 @@ enum { RADEON_INIT_CP = 0x01, RADEON_CLEANUP_CP = 0x02, - RADEON_INIT_R200_CP = 0x03, + RADEON_INIT_R200_CP = 0x03 } func; unsigned long sarea_priv_offset; int is_pci; diff -Nru a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h --- a/drivers/char/drm/radeon_drv.h Sat Nov 16 17:33:55 2002 +++ b/drivers/char/drm/radeon_drv.h Sat Mar 29 22:34:33 2003 @@ -31,8 +31,8 @@ #ifndef __RADEON_DRV_H__ #define __RADEON_DRV_H__ -#define GET_RING_HEAD(ring) DRM_READ32( (volatile u32 *) (ring)->head ) -#define SET_RING_HEAD(ring,val) DRM_WRITE32( (volatile u32 *) (ring)->head , (val)) +#define GET_RING_HEAD(ring) DRM_READ32( (ring)->ring_rptr, 0 ) /* (ring)->head */ +#define SET_RING_HEAD(ring,val) DRM_WRITE32( (ring)->ring_rptr, 0, (val) ) /* (ring)->head */ typedef struct drm_radeon_freelist { unsigned int age; @@ -53,6 +53,7 @@ int space; int high_mark; + drm_local_map_t *ring_rptr; } drm_radeon_ring_buffer_t; typedef struct drm_radeon_depth_clear_t { @@ -67,7 +68,7 @@ struct mem_block *prev; int start; int size; - int pid; /* 0: free, -1: heap, other: real pids */ + DRMFILE filp; /* 0: free, -1: heap, other: real files */ }; typedef struct drm_radeon_private { @@ -126,13 +127,13 @@ drm_radeon_depth_clear_t depth_clear; - drm_map_t *sarea; - drm_map_t *fb; - drm_map_t *mmio; - drm_map_t *cp_ring; - drm_map_t *ring_rptr; - drm_map_t *buffers; - drm_map_t *agp_textures; + drm_local_map_t *sarea; + drm_local_map_t *fb; + drm_local_map_t *mmio; + drm_local_map_t *cp_ring; + drm_local_map_t *ring_rptr; + drm_local_map_t *buffers; + drm_local_map_t *agp_textures; struct mem_block *agp_heap; struct mem_block *fb_heap; @@ -183,7 +184,7 @@ extern int radeon_mem_free( DRM_IOCTL_ARGS ); extern int radeon_mem_init_heap( DRM_IOCTL_ARGS ); extern void radeon_mem_takedown( struct mem_block **heap ); -extern void radeon_mem_release( struct mem_block *heap ); +extern void radeon_mem_release( DRMFILE filp, struct mem_block *heap ); /* radeon_irq.c */ extern int radeon_irq_emit( DRM_IOCTL_ARGS ); @@ -193,6 +194,7 @@ extern int radeon_wait_irq(drm_device_t *dev, int swi_nr); extern int radeon_emit_irq(drm_device_t *dev); +extern void radeon_do_release(drm_device_t *dev); /* Flags for stats.boxes */ @@ -266,8 +268,10 @@ #define RADEON_SCRATCH_UMSK 0x0770 #define RADEON_SCRATCH_ADDR 0x0774 +#define RADEON_SCRATCHOFF( x ) (RADEON_SCRATCH_REG_OFFSET + 4*(x)) + #define GET_SCRATCH( x ) (dev_priv->writeback_works \ - ? DRM_READ32( &dev_priv->scratch[(x)] ) \ + ? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \ : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) ) @@ -686,15 +690,10 @@ #define RADEON_RING_HIGH_MARK 128 - -#define RADEON_BASE(reg) ((unsigned long)(dev_priv->mmio->handle)) -#define RADEON_ADDR(reg) (RADEON_BASE( reg ) + reg) - -#define RADEON_READ(reg) DRM_READ32( (volatile u32 *) RADEON_ADDR(reg) ) -#define RADEON_WRITE(reg,val) DRM_WRITE32( (volatile u32 *) RADEON_ADDR(reg), (val) ) - -#define RADEON_READ8(reg) DRM_READ8( (volatile u8 *) RADEON_ADDR(reg) ) -#define RADEON_WRITE8(reg,val) DRM_WRITE8( (volatile u8 *) RADEON_ADDR(reg), (val) ) +#define RADEON_READ(reg) DRM_READ32( dev_priv->mmio, (reg) ) +#define RADEON_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) ) +#define RADEON_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) ) +#define RADEON_WRITE8(reg,val) DRM_WRITE8( dev_priv->mmio, (reg), (val) ) #define RADEON_WRITE_PLL( addr, val ) \ do { \ @@ -771,16 +770,6 @@ * Misc helper macros */ -#define LOCK_TEST_WITH_RETURN( dev ) \ -do { \ - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \ - dev->lock.pid != DRM_CURRENTPID ) { \ - DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); \ - return DRM_ERR(EINVAL); \ - } \ -} while (0) - - /* Perfbox functionality only. */ #define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \ @@ -823,13 +812,6 @@ * Ring control */ -#if defined(__powerpc__) -#define radeon_flush_write_combine() (void) GET_RING_HEAD( &dev_priv->ring ) -#else -#define radeon_flush_write_combine() DRM_WRITEMEMORYBARRIER() -#endif - - #define RADEON_VERBOSE 0 #define RING_LOCALS int write, _nr; unsigned int mask; u32 *ring; @@ -863,8 +845,13 @@ dev_priv->ring.tail = write; \ } while (0) -#define COMMIT_RING() do { \ - RADEON_WRITE( RADEON_CP_RB_WPTR, dev_priv->ring.tail ); \ +#define COMMIT_RING() do { \ + /* Flush writes to ring */ \ + DRM_READMEMORYBARRIER(dev_priv->mmio); \ + GET_RING_HEAD( &dev_priv->ring ); \ + RADEON_WRITE( RADEON_CP_RB_WPTR, dev_priv->ring.tail ); \ + /* read from PCI bus to ensure correct posting */ \ + RADEON_READ( RADEON_CP_RB_RPTR ); \ } while (0) #define OUT_RING( x ) do { \ diff -Nru a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c --- a/drivers/char/drm/radeon_irq.c Wed Dec 18 09:56:28 2002 +++ b/drivers/char/drm/radeon_irq.c Sat Mar 29 22:34:33 2003 @@ -61,7 +61,11 @@ (drm_radeon_private_t *)dev->dev_private; u32 stat; - stat = RADEON_READ(RADEON_GEN_INT_STATUS); + /* Only consider the bits we're interested in - others could be used + * outside the DRM + */ + stat = RADEON_READ(RADEON_GEN_INT_STATUS) + & (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT); if (!stat) return; @@ -77,15 +81,14 @@ DRM(vbl_send_signals)( dev ); } - /* Acknowledge all the bits in GEN_INT_STATUS -- seem to get - * more than we asked for... - */ + /* Acknowledge interrupts we handle */ RADEON_WRITE(RADEON_GEN_INT_STATUS, stat); } static __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv) { - u32 tmp = RADEON_READ( RADEON_GEN_INT_STATUS ); + u32 tmp = RADEON_READ( RADEON_GEN_INT_STATUS ) + & (RADEON_SW_INT_TEST_ACK | RADEON_CRTC_VBLANK_STAT); if (tmp) RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp ); } @@ -176,7 +179,7 @@ drm_radeon_irq_emit_t emit; int result; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); diff -Nru a/drivers/char/drm/radeon_mem.c b/drivers/char/drm/radeon_mem.c --- a/drivers/char/drm/radeon_mem.c Sun Jan 5 19:08:26 2003 +++ b/drivers/char/drm/radeon_mem.c Sat Mar 29 22:34:33 2003 @@ -40,7 +40,7 @@ */ static struct mem_block *split_block(struct mem_block *p, int start, int size, - int pid ) + DRMFILE filp ) { /* Maybe cut off the start of an existing block */ if (start > p->start) { @@ -49,7 +49,7 @@ goto out; newblock->start = start; newblock->size = p->size - (start - p->start); - newblock->pid = 0; + newblock->filp = 0; newblock->next = p->next; newblock->prev = p; p->next->prev = newblock; @@ -65,7 +65,7 @@ goto out; newblock->start = start + size; newblock->size = p->size - size; - newblock->pid = 0; + newblock->filp = 0; newblock->next = p->next; newblock->prev = p; p->next->prev = newblock; @@ -75,20 +75,20 @@ out: /* Our block is in the middle */ - p->pid = pid; + p->filp = filp; return p; } static struct mem_block *alloc_block( struct mem_block *heap, int size, - int align2, int pid ) + int align2, DRMFILE filp ) { struct mem_block *p; int mask = (1 << align2)-1; for (p = heap->next ; p != heap ; p = p->next) { int start = (p->start + mask) & ~mask; - if (p->pid == 0 && start + size <= p->start + p->size) - return split_block( p, start, size, pid ); + if (p->filp == 0 && start + size <= p->start + p->size) + return split_block( p, start, size, filp ); } return NULL; @@ -108,25 +108,25 @@ static void free_block( struct mem_block *p ) { - p->pid = 0; + p->filp = 0; - /* Assumes a single contiguous range. Needs a special pid in + /* Assumes a single contiguous range. Needs a special filp in * 'heap' to stop it being subsumed. */ - if (p->next->pid == 0) { + if (p->next->filp == 0) { struct mem_block *q = p->next; p->size += q->size; p->next = q->next; p->next->prev = p; - DRM_FREE(q); + DRM_FREE(q, sizeof(*q)); } - if (p->prev->pid == 0) { + if (p->prev->filp == 0) { struct mem_block *q = p->prev; q->size += p->size; q->next = p->next; q->next->prev = q; - DRM_FREE(p); + DRM_FREE(p, sizeof(*q)); } } @@ -141,47 +141,46 @@ *heap = DRM_MALLOC(sizeof(**heap)); if (!*heap) { - DRM_FREE( blocks ); + DRM_FREE( blocks, sizeof(*blocks) ); return -ENOMEM; } blocks->start = start; blocks->size = size; - blocks->pid = 0; + blocks->filp = 0; blocks->next = blocks->prev = *heap; memset( *heap, 0, sizeof(**heap) ); - (*heap)->pid = -1; + (*heap)->filp = (DRMFILE) -1; (*heap)->next = (*heap)->prev = blocks; return 0; } -/* Free all blocks associated with the releasing pid. +/* Free all blocks associated with the releasing file. */ -void radeon_mem_release( struct mem_block *heap ) +void radeon_mem_release( DRMFILE filp, struct mem_block *heap ) { - int pid = DRM_CURRENTPID; struct mem_block *p; if (!heap || !heap->next) return; for (p = heap->next ; p != heap ; p = p->next) { - if (p->pid == pid) - p->pid = 0; + if (p->filp == filp) + p->filp = 0; } - /* Assumes a single contiguous range. Needs a special pid in + /* Assumes a single contiguous range. Needs a special filp in * 'heap' to stop it being subsumed. */ for (p = heap->next ; p != heap ; p = p->next) { - while (p->pid == 0 && p->next->pid == 0) { + while (p->filp == 0 && p->next->filp == 0) { struct mem_block *q = p->next; p->size += q->size; p->next = q->next; p->next->prev = p; - DRM_FREE(q); + DRM_FREE(q, sizeof(*q)); } } } @@ -198,10 +197,10 @@ for (p = (*heap)->next ; p != *heap ; ) { struct mem_block *q = p; p = p->next; - DRM_FREE(q); + DRM_FREE(q, sizeof(*q)); } - DRM_FREE( *heap ); + DRM_FREE( *heap, sizeof(**heap) ); *heap = 0; } @@ -248,7 +247,7 @@ alloc.alignment = 12; block = alloc_block( *heap, alloc.size, alloc.alignment, - DRM_CURRENTPID ); + filp ); if (!block) return DRM_ERR(ENOMEM); @@ -287,7 +286,7 @@ if (!block) return DRM_ERR(EFAULT); - if (block->pid != DRM_CURRENTPID) + if (block->filp != filp) return DRM_ERR(EPERM); free_block( block ); diff -Nru a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c --- a/drivers/char/drm/radeon_state.c Wed Dec 18 09:56:28 2002 +++ b/drivers/char/drm/radeon_state.c Sat Mar 29 22:34:33 2003 @@ -1063,7 +1063,8 @@ #define RADEON_MAX_TEXTURE_SIZE (RADEON_BUFFER_SIZE - 8 * sizeof(u32)) -static int radeon_cp_dispatch_texture( drm_device_t *dev, +static int radeon_cp_dispatch_texture( DRMFILE filp, + drm_device_t *dev, drm_radeon_texture_t *tex, drm_radeon_tex_image_t *image ) { @@ -1073,7 +1074,7 @@ u32 *buffer; const u8 *data; int size, dwords, tex_width, blit_width; - u32 y, height; + u32 height; int i; RING_LOCALS; @@ -1138,10 +1139,9 @@ tex->offset >> 10, tex->pitch, tex->format, image->x, image->y, image->width, image->height ); - /* Make a copy of the parameters in case we have to + /* Make a copy of some parameters in case we have to * update them for a multi-pass texture blit. */ - y = image->y; height = image->height; data = (const u8 *)image->data; @@ -1156,11 +1156,6 @@ return 0; } - /* Update the input parameters for next time */ - image->y += height; - image->height -= height; - image->data += size; - buf = radeon_freelist_get( dev ); if ( 0 && !buf ) { radeon_do_cp_idle( dev_priv ); @@ -1190,7 +1185,7 @@ buffer[2] = (tex->pitch << 22) | (tex->offset >> 10); buffer[3] = 0xffffffff; buffer[4] = 0xffffffff; - buffer[5] = (y << 16) | image->x; + buffer[5] = (image->y << 16) | image->x; buffer[6] = (height << 16) | image->width; buffer[7] = dwords; buffer += 8; @@ -1222,11 +1217,15 @@ } } - buf->pid = DRM_CURRENTPID; + buf->filp = filp; buf->used = (dwords + 8) * sizeof(u32); radeon_cp_dispatch_indirect( dev, buf, 0, buf->used ); radeon_cp_discard_buffer( dev, buf ); + /* Update the input parameters for next time */ + image->y += height; + image->height -= height; + (const u8 *)image->data += size; } while (image->height > 0); /* Flush the pixel cache after the blit completes. This ensures @@ -1275,7 +1274,7 @@ drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS]; DRM_DEBUG( "\n" ); - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( clear, (drm_radeon_clear_t *)data, sizeof(clear) ); @@ -1344,7 +1343,7 @@ drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "\n" ); - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); RING_SPACE_TEST_WITH_RETURN( dev_priv ); @@ -1364,7 +1363,7 @@ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; DRM_DEBUG( "\n" ); - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); RING_SPACE_TEST_WITH_RETURN( dev_priv ); @@ -1388,7 +1387,7 @@ drm_radeon_vertex_t vertex; drm_radeon_tcl_prim_t prim; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); @@ -1418,9 +1417,9 @@ buf = dma->buflist[vertex.idx]; - if ( buf->pid != DRM_CURRENTPID ) { - DRM_ERROR( "process %d using buffer owned by %d\n", - DRM_CURRENTPID, buf->pid ); + if ( buf->filp != filp ) { + DRM_ERROR( "process %d using buffer owned by %p\n", + DRM_CURRENTPID, buf->filp ); return DRM_ERR(EINVAL); } if ( buf->pending ) { @@ -1475,7 +1474,7 @@ drm_radeon_tcl_prim_t prim; int count; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); @@ -1505,9 +1504,9 @@ buf = dma->buflist[elts.idx]; - if ( buf->pid != DRM_CURRENTPID ) { - DRM_ERROR( "process %d using buffer owned by %d\n", - DRM_CURRENTPID, buf->pid ); + if ( buf->filp != filp ) { + DRM_ERROR( "process %d using buffer owned by %p\n", + DRM_CURRENTPID, buf->filp ); return DRM_ERR(EINVAL); } if ( buf->pending ) { @@ -1570,7 +1569,7 @@ drm_radeon_tex_image_t image; int ret; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( tex, (drm_radeon_texture_t *)data, sizeof(tex) ); @@ -1587,7 +1586,7 @@ RING_SPACE_TEST_WITH_RETURN( dev_priv ); VB_AGE_TEST_WITH_RETURN( dev_priv ); - ret = radeon_cp_dispatch_texture( dev, &tex, &image ); + ret = radeon_cp_dispatch_texture( filp, dev, &tex, &image ); COMMIT_RING(); return ret; @@ -1600,7 +1599,7 @@ drm_radeon_stipple_t stipple; u32 mask[32]; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); DRM_COPY_FROM_USER_IOCTL( stipple, (drm_radeon_stipple_t *)data, sizeof(stipple) ); @@ -1625,7 +1624,7 @@ drm_radeon_indirect_t indirect; RING_LOCALS; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); @@ -1647,9 +1646,9 @@ buf = dma->buflist[indirect.idx]; - if ( buf->pid != DRM_CURRENTPID ) { - DRM_ERROR( "process %d using buffer owned by %d\n", - DRM_CURRENTPID, buf->pid ); + if ( buf->filp != filp ) { + DRM_ERROR( "process %d using buffer owned by %p\n", + DRM_CURRENTPID, buf->filp ); return DRM_ERR(EINVAL); } if ( buf->pending ) { @@ -1702,7 +1701,7 @@ int i; unsigned char laststate; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); @@ -1727,9 +1726,9 @@ buf = dma->buflist[vertex.idx]; - if ( buf->pid != DRM_CURRENTPID ) { - DRM_ERROR( "process %d using buffer owned by %d\n", - DRM_CURRENTPID, buf->pid ); + if ( buf->filp != filp ) { + DRM_ERROR( "process %d using buffer owned by %p\n", + DRM_CURRENTPID, buf->filp ); return DRM_ERR(EINVAL); } @@ -2029,7 +2028,7 @@ drm_radeon_cmd_header_t header; int orig_nbox; - LOCK_TEST_WITH_RETURN( dev ); + LOCK_TEST_WITH_RETURN( dev, filp ); if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); @@ -2098,8 +2097,9 @@ } buf = dma->buflist[idx]; - if ( buf->pid != DRM_CURRENTPID || buf->pending ) { - DRM_ERROR( "bad buffer\n" ); + if ( buf->filp != filp || buf->pending ) { + DRM_ERROR( "bad buffer %p %p %d\n", + buf->filp, filp, buf->pending); return DRM_ERR(EINVAL); } diff -Nru a/drivers/char/drm/sis.h b/drivers/char/drm/sis.h --- a/drivers/char/drm/sis.h Tue Oct 29 14:29:24 2002 +++ b/drivers/char/drm/sis.h Sat Mar 29 22:34:33 2003 @@ -24,7 +24,7 @@ * DEALINGS IN THE SOFTWARE. * */ -/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/sis.h,v 1.2 2001/12/19 21:25:59 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/sis.h,v 1.3 2002/10/30 12:52:38 alanh Exp $ */ #ifndef __SIS_H__ #define __SIS_H__ diff -Nru a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c --- a/drivers/char/drm/sis_mm.c Thu Mar 13 16:52:15 2003 +++ b/drivers/char/drm/sis_mm.c Sat Mar 29 22:34:33 2003 @@ -182,10 +182,10 @@ if(block){ /* TODO */ agp.offset = block->ofs; - agp.free = (unsigned int)block; + agp.free = (unsigned long)block; if(!add_alloc_set(agp.context, AGP_TYPE, agp.free)){ DRM_DEBUG("adding to allocation set fails\n"); - mmFreeMem((PMemBlock)agp.free); + mmFreeMem((PMemBlock)(unsigned long)agp.free); retval = -1; } } @@ -218,7 +218,7 @@ return -1; } - mmFreeMem((PMemBlock)agp.free); + mmFreeMem((PMemBlock)(unsigned long)agp.free); if(!del_alloc_set(agp.context, AGP_TYPE, agp.free)) retval = -1; @@ -288,7 +288,7 @@ retval = setFirst(set, &item); while(retval){ DRM_DEBUG("free agp memory 0x%x\n", item); - mmFreeMem((PMemBlock)item); + mmFreeMem((PMemBlock)(unsigned long)item); retval = setNext(set, &item); } setDestroy(set); diff -Nru a/drivers/char/hw_random.c b/drivers/char/hw_random.c --- a/drivers/char/hw_random.c Thu Mar 13 15:51:14 2003 +++ b/drivers/char/hw_random.c Sat Mar 29 08:26:19 2003 @@ -151,6 +151,7 @@ */ static struct pci_device_id rng_pci_tbl[] __initdata = { { 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_amd }, + { 0x1022, 0x746b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_amd }, { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, diff -Nru a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig --- a/drivers/char/ipmi/Kconfig Mon Jan 13 06:53:01 2003 +++ b/drivers/char/ipmi/Kconfig Wed Mar 26 00:05:10 2003 @@ -7,8 +7,14 @@ tristate 'IPMI top-level message handler' help This enables the central IPMI message handler, required for IPMI - to work. Note that you must have this enabled to do any other IPMI - things. See IPMI.txt for more details. + to work. + + IPMI is a standard for managing sensors (temperature, + voltage, etc.) in a system. + + See Documentation/IPMI.txt for more details on the driver. + + If unsure, say N. config IPMI_PANIC_EVENT bool 'Generate a panic event to all BMCs on a panic' diff -Nru a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c --- a/drivers/char/ipmi/ipmi_devintf.c Sat Mar 22 09:04:18 2003 +++ b/drivers/char/ipmi/ipmi_devintf.c Wed Mar 26 00:13:31 2003 @@ -449,7 +449,7 @@ if (if_num > MAX_DEVICES) return; - snprinf(name, sizeof(name), "ipmidev/%d", if_num); + snprintf(name, sizeof(name), "ipmidev/%d", if_num); handles[if_num] = devfs_register(NULL, name, DEVFS_FL_NONE, ipmi_major, if_num, diff -Nru a/drivers/char/ipmi/ipmi_kcs_intf.c b/drivers/char/ipmi/ipmi_kcs_intf.c --- a/drivers/char/ipmi/ipmi_kcs_intf.c Fri Feb 21 11:45:45 2003 +++ b/drivers/char/ipmi/ipmi_kcs_intf.c Wed Mar 26 00:14:11 2003 @@ -826,7 +826,7 @@ if (kcs_port && kcs_physaddr) return -EINVAL; - new_kcs = kmalloc(kcs_size(), GFP_KERNEL); + new_kcs = kmalloc(sizeof(*new_kcs), GFP_KERNEL); if (!new_kcs) { printk(KERN_ERR "ipmi_kcs: out of memory\n"); return -ENOMEM; diff -Nru a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c --- a/drivers/char/ipmi/ipmi_kcs_sm.c Fri Jan 10 13:00:07 2003 +++ b/drivers/char/ipmi/ipmi_kcs_sm.c Thu Mar 27 08:46:03 2003 @@ -468,7 +468,7 @@ break; case KCS_HOSED: - return KCS_SM_HOSED; + break; } if (kcs->state == KCS_HOSED) { diff -Nru a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c --- a/drivers/char/pcmcia/synclink_cs.c Tue Feb 25 02:17:46 2003 +++ b/drivers/char/pcmcia/synclink_cs.c Mon Mar 17 07:43:03 2003 @@ -76,7 +76,6 @@ #include #include #include -#include #ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE #define CONFIG_SYNCLINK_SYNCPPP 1 @@ -241,7 +240,6 @@ dev_link_t link; dev_node_t node; int stop; - struct bus_operations *bus; /* SPPP/Cisco HDLC device parts */ int netcount; @@ -826,7 +824,6 @@ break; case CS_EVENT_CARD_INSERTION: link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - info->bus = args->bus; mgslpc_config(link); break; case CS_EVENT_PM_SUSPEND: diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c --- a/drivers/char/tty_io.c Sat Mar 22 22:14:19 2003 +++ b/drivers/char/tty_io.c Thu Mar 27 21:15:44 2003 @@ -2143,31 +2143,16 @@ */ int tty_unregister_driver(struct tty_driver *driver) { - int retval; - struct tty_driver *p; - int i, found = 0; + int retval, i; struct termios *tp; - const char *othername = NULL; - + if (*driver->refcount) return -EBUSY; - list_for_each_entry(p, &tty_drivers, tty_drivers) { - if (p == driver) - found++; - else if (p->major == driver->major) - othername = p->name; - } - - if (!found) - return -ENOENT; - - if (othername == NULL) { - retval = unregister_chrdev(driver->major, driver->name); - if (retval) - return retval; - } else - register_chrdev(driver->major, othername, &tty_fops); + retval = unregister_chrdev_region(driver->major, driver->minor_start, + driver->num, driver->name); + if (retval) + return retval; list_del(&driver->tty_drivers); diff -Nru a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c --- a/drivers/i2c/busses/i2c-ali15x3.c Thu Mar 20 03:14:08 2003 +++ b/drivers/i2c/busses/i2c-ali15x3.c Fri Mar 21 12:45:15 2003 @@ -474,9 +474,11 @@ static struct i2c_adapter ali15x3_adapter = { .owner = THIS_MODULE, - .name = "unset", .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3, .algo = &smbus_algorithm, + .dev = { + .name = "unset", + }, }; static struct pci_device_id ali15x3_ids[] __devinitdata = { @@ -500,8 +502,8 @@ /* set up the driverfs linkage to our parent device */ ali15x3_adapter.dev.parent = &dev->dev; - sprintf(ali15x3_adapter.name, "SMBus ALI15X3 adapter at %04x", - ali15x3_smba); + snprintf(ali15x3_adapter.dev.name, DEVICE_NAME_SIZE, + "SMBus ALI15X3 adapter at %04x", ali15x3_smba); return i2c_add_adapter(&ali15x3_adapter); } diff -Nru a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c --- a/drivers/i2c/busses/i2c-amd756.c Thu Mar 20 03:14:12 2003 +++ b/drivers/i2c/busses/i2c-amd756.c Fri Mar 21 12:45:15 2003 @@ -312,9 +312,11 @@ static struct i2c_adapter amd756_adapter = { .owner = THIS_MODULE, - .name = "unset", .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD756, .algo = &smbus_algorithm, + .dev = { + .name = "unset", + }, }; enum chiptype { AMD756, AMD766, AMD768, NFORCE }; @@ -376,7 +378,7 @@ /* set up the driverfs linkage to our parent device */ amd756_adapter.dev.parent = &pdev->dev; - sprintf(amd756_adapter.name, + snprintf(amd756_adapter.dev.name, DEVICE_NAME_SIZE, "SMBus AMD75x adapter at %04x", amd756_ioport); error = i2c_add_adapter(&amd756_adapter); diff -Nru a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c --- a/drivers/i2c/busses/i2c-amd8111.c Thu Mar 20 11:28:04 2003 +++ b/drivers/i2c/busses/i2c-amd8111.c Fri Mar 21 12:45:15 2003 @@ -357,8 +357,8 @@ goto out_kfree; smbus->adapter.owner = THIS_MODULE; - sprintf(smbus->adapter.name, - "SMBus2 AMD8111 adapter at %04x", smbus->base); + snprintf(smbus->adapter.dev.name, DEVICE_NAME_SIZE, + "SMBus2 AMD8111 adapter at %04x", smbus->base); smbus->adapter.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD8111; smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo_data = smbus; diff -Nru a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c --- a/drivers/i2c/busses/i2c-i801.c Tue Mar 18 06:36:23 2003 +++ b/drivers/i2c/busses/i2c-i801.c Fri Mar 21 12:45:15 2003 @@ -546,9 +546,11 @@ static struct i2c_adapter i801_adapter = { .owner = THIS_MODULE, - .name = "unset", .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801, .algo = &smbus_algorithm, + .dev = { + .name = "unset", + }, }; static struct pci_device_id i801_ids[] __devinitdata = { @@ -597,8 +599,8 @@ /* set up the driverfs linkage to our parent device */ i801_adapter.dev.parent = &dev->dev; - sprintf(i801_adapter.name, "SMBus I801 adapter at %04x", - i801_smba); + snprintf(i801_adapter.dev.name, DEVICE_NAME_SIZE, + "SMBus I801 adapter at %04x", i801_smba); return i2c_add_adapter(&i801_adapter); } diff -Nru a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c --- a/drivers/i2c/busses/i2c-isa.c Thu Mar 20 11:47:34 2003 +++ b/drivers/i2c/busses/i2c-isa.c Fri Mar 21 12:45:15 2003 @@ -39,9 +39,11 @@ /* There can only be one... */ static struct i2c_adapter isa_adapter = { .owner = THIS_MODULE, - .name = "ISA main adapter", .id = I2C_ALGO_ISA | I2C_HW_ISA, .algo = &isa_algorithm, + .dev = { + .name = "ISA main adapter", + }, }; static int __init i2c_isa_init(void) diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c --- a/drivers/i2c/busses/i2c-piix4.c Tue Mar 18 09:10:21 2003 +++ b/drivers/i2c/busses/i2c-piix4.c Fri Mar 21 12:45:15 2003 @@ -394,9 +394,11 @@ static struct i2c_adapter piix4_adapter = { .owner = THIS_MODULE, - .name = "unset", .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_PIIX4, .algo = &smbus_algorithm, + .dev = { + .name = "unset", + }, }; static struct pci_device_id piix4_ids[] __devinitdata = { @@ -449,8 +451,8 @@ /* set up the driverfs linkage to our parent device */ piix4_adapter.dev.parent = &dev->dev; - sprintf(piix4_adapter.name, "SMBus PIIX4 adapter at %04x", - piix4_smba); + snprintf(piix4_adapter.dev.name, DEVICE_NAME_SIZE, + "SMBus PIIX4 adapter at %04x", piix4_smba); retval = i2c_add_adapter(&piix4_adapter); diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c --- a/drivers/i2c/chips/adm1021.c Thu Mar 13 13:49:39 2003 +++ b/drivers/i2c/chips/adm1021.c Fri Mar 21 08:38:29 2003 @@ -144,7 +144,7 @@ /* This is the driver that will be inserted */ static struct i2c_driver adm1021_driver = { .owner = THIS_MODULE, - .name = "ADM1021, MAX1617 sensor driver", + .name = "ADM1021-MAX1617", .id = I2C_DRIVERID_ADM1021, .flags = I2C_DF_NOTIFY, .attach_adapter = adm1021_attach_adapter, @@ -221,10 +221,12 @@ err = -ENOMEM; goto error0; } + memset(new_client, 0x00, sizeof(struct i2c_client) + + sizeof(struct adm1021_data)); data = (struct adm1021_data *) (new_client + 1); + i2c_set_clientdata(new_client, data); new_client->addr = address; - new_client->data = data; new_client->adapter = adapter; new_client->driver = &adm1021_driver; new_client->flags = 0; @@ -299,7 +301,7 @@ } /* Fill in the remaining client fields and put it into the global list */ - strcpy(new_client->name, client_name); + strncpy(new_client->dev.name, client_name, DEVICE_NAME_SIZE); data->type = kind; new_client->id = adm1021_id++; @@ -354,8 +356,7 @@ int err; - i2c_deregister_entry(((struct adm1021_data *) (client->data))-> - sysctl_id); + i2c_deregister_entry(((struct adm1021_data *) (i2c_get_clientdata(client)))->sysctl_id); if ((err = i2c_detach_client(client))) { printk @@ -384,7 +385,7 @@ static void adm1021_update_client(struct i2c_client *client) { - struct adm1021_data *data = client->data; + struct adm1021_data *data = i2c_get_clientdata(client); down(&data->update_lock); @@ -435,7 +436,7 @@ static void adm1021_temp(struct i2c_client *client, int operation, int ctl_name, int *nrels_mag, long *results) { - struct adm1021_data *data = client->data; + struct adm1021_data *data = i2c_get_clientdata(client); if (operation == SENSORS_PROC_REAL_INFO) *nrels_mag = 0; @@ -462,7 +463,7 @@ static void adm1021_remote_temp(struct i2c_client *client, int operation, int ctl_name, int *nrels_mag, long *results) { - struct adm1021_data *data = client->data; + struct adm1021_data *data = i2c_get_clientdata(client); int prec = 0; if (operation == SENSORS_PROC_REAL_INFO) @@ -535,7 +536,7 @@ static void adm1021_die_code(struct i2c_client *client, int operation, int ctl_name, int *nrels_mag, long *results) { - struct adm1021_data *data = client->data; + struct adm1021_data *data = i2c_get_clientdata(client); if (operation == SENSORS_PROC_REAL_INFO) *nrels_mag = 0; @@ -551,7 +552,7 @@ static void adm1021_alarms(struct i2c_client *client, int operation, int ctl_name, int *nrels_mag, long *results) { - struct adm1021_data *data = client->data; + struct adm1021_data *data = i2c_get_clientdata(client); if (operation == SENSORS_PROC_REAL_INFO) *nrels_mag = 0; else if (operation == SENSORS_PROC_REAL_READ) { diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c --- a/drivers/i2c/chips/lm75.c Thu Mar 13 13:38:56 2003 +++ b/drivers/i2c/chips/lm75.c Fri Mar 21 08:38:29 2003 @@ -82,7 +82,7 @@ /* This is the driver that will be inserted */ static struct i2c_driver lm75_driver = { .owner = THIS_MODULE, - .name = "LM75 sensor chip driver", + .name = "LM75 sensor", .id = I2C_DRIVERID_LM75, .flags = I2C_DF_NOTIFY, .attach_adapter = lm75_attach_adapter, @@ -140,10 +140,12 @@ err = -ENOMEM; goto error0; } + memset(new_client, 0x00, sizeof(struct i2c_client) + + sizeof(struct lm75_data)); data = (struct lm75_data *) (new_client + 1); + i2c_set_clientdata(new_client, data); new_client->addr = address; - new_client->data = data; new_client->adapter = adapter; new_client->driver = &lm75_driver; new_client->flags = 0; @@ -180,7 +182,7 @@ } /* Fill in the remaining client fields and put it into the global list */ - strcpy(new_client->name, client_name); + strncpy(new_client->dev.name, client_name, DEVICE_NAME_SIZE); new_client->id = lm75_id++; data->valid = 0; @@ -215,7 +217,7 @@ static int lm75_detach_client(struct i2c_client *client) { - struct lm75_data *data = client->data; + struct lm75_data *data = i2c_get_clientdata(client); i2c_deregister_entry(data->sysctl_id); i2c_detach_client(client); @@ -263,7 +265,7 @@ static void lm75_update_client(struct i2c_client *client) { - struct lm75_data *data = client->data; + struct lm75_data *data = i2c_get_clientdata(client); down(&data->update_lock); @@ -286,7 +288,7 @@ static void lm75_temp(struct i2c_client *client, int operation, int ctl_name, int *nrels_mag, long *results) { - struct lm75_data *data = client->data; + struct lm75_data *data = i2c_get_clientdata(client); if (operation == SENSORS_PROC_REAL_INFO) *nrels_mag = 1; else if (operation == SENSORS_PROC_REAL_READ) { diff -Nru a/drivers/i2c/i2c-algo-bit.c b/drivers/i2c/i2c-algo-bit.c --- a/drivers/i2c/i2c-algo-bit.c Tue Mar 11 12:21:11 2003 +++ b/drivers/i2c/i2c-algo-bit.c Fri Mar 21 12:45:15 2003 @@ -23,6 +23,8 @@ /* $Id: i2c-algo-bit.c,v 1.44 2003/01/21 08:08:16 kmalkki Exp $ */ +/* #define DEBUG 1 */ + #include #include #include @@ -338,16 +340,14 @@ while (count > 0) { c = *temp; - DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: %s sendbytes: writing %2.2X\n", - i2c_adap->name, c&0xff)); + DEB2(dev_dbg(&i2c_adap->dev, "sendbytes: writing %2.2X\n", c&0xff)); retval = i2c_outb(i2c_adap,c); if ((retval>0) || (nak_ok && (retval==0))) { /* ok or ignored NAK */ count--; temp++; wrcount++; } else { /* arbitration or no acknowledge */ - printk(KERN_ERR "i2c-algo-bit.o: %s sendbytes: error - bailout.\n", - i2c_adap->name); + dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n"); i2c_stop(adap); return (retval<0)? retval : -EFAULT; /* got a better one ?? */ @@ -527,13 +527,12 @@ struct i2c_algo_bit_data *bit_adap = adap->algo_data; if (bit_test) { - int ret = test_bus(bit_adap, adap->name); + int ret = test_bus(bit_adap, adap->dev.name); if (ret<0) return -ENODEV; } - DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: hw routines for %s registered.\n", - adap->name)); + DEB2(dev_dbg(&adap->dev, "hw routines registered.\n")); /* register new adapter to i2c module... */ diff -Nru a/drivers/i2c/i2c-algo-pcf.c b/drivers/i2c/i2c-algo-pcf.c --- a/drivers/i2c/i2c-algo-pcf.c Thu Mar 13 13:49:39 2003 +++ b/drivers/i2c/i2c-algo-pcf.c Fri Mar 21 12:45:15 2003 @@ -27,6 +27,8 @@ messages, proper stop/repstart signaling during receive, added detect code */ +/* #define DEBUG 1 */ /* to pick up dev_dbg calls */ + #include #include #include @@ -222,21 +224,19 @@ int wrcount, status, timeout; for (wrcount=0; wrcountname, buf[wrcount]&0xff)); + DEB2(dev_dbg(&i2c_adap->dev, "i2c_write: writing %2.2X\n", + buf[wrcount]&0xff)); i2c_outb(adap, buf[wrcount]); timeout = wait_for_pin(adap, &status); if (timeout) { i2c_stop(adap); - printk(KERN_ERR "i2c-algo-pcf.o: %s i2c_write: " - "error - timeout.\n", i2c_adap->name); + dev_err(&i2c_adap->dev, "i2c_write: error - timeout.\n"); return -EREMOTEIO; /* got a better one ?? */ } #ifndef STUB_I2C if (status & I2C_PCF_LRB) { i2c_stop(adap); - printk(KERN_ERR "i2c-algo-pcf.o: %s i2c_write: " - "error - no ack.\n", i2c_adap->name); + dev_err(&i2c_adap->dev, "i2c_write: error - no ack.\n"); return -EREMOTEIO; /* got a better one ?? */ } #endif @@ -263,14 +263,14 @@ if (wait_for_pin(adap, &status)) { i2c_stop(adap); - printk(KERN_ERR "i2c-algo-pcf.o: pcf_readbytes timed out.\n"); + dev_err(&i2c_adap->dev, "pcf_readbytes timed out.\n"); return (-1); } #ifndef STUB_I2C if ((status & I2C_PCF_LRB) && (i != count)) { i2c_stop(adap); - printk(KERN_ERR "i2c-algo-pcf.o: i2c_read: i2c_inb, No ack.\n"); + dev_err(&i2c_adap->dev, "i2c_read: i2c_inb, No ack.\n"); return (-1); } #endif @@ -445,8 +445,7 @@ struct i2c_algo_pcf_data *pcf_adap = adap->algo_data; int rval; - DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: hw routines for %s registered.\n", - adap->name)); + DEB2(dev_dbg(&adap->dev, "hw routines registered.\n")); /* register new adapter to i2c module... */ diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c --- a/drivers/i2c/i2c-core.c Thu Mar 20 12:07:43 2003 +++ b/drivers/i2c/i2c-core.c Mon Mar 24 07:13:56 2003 @@ -23,6 +23,8 @@ /* $Id: i2c-core.c,v 1.95 2003/01/22 05:25:08 kmalkki Exp $ */ +/* #define DEBUG 1 */ /* needed to pick up the dev_dbg() calls */ + #include #include #include @@ -63,6 +65,14 @@ return 0; } +static struct device_driver i2c_generic_driver = { + .name = "i2c", + .bus = &i2c_bus_type, + .probe = i2c_device_probe, + .remove = i2c_device_remove, +}; + + /* --------------------------------------------------- * registering functions * --------------------------------------------------- @@ -82,9 +92,8 @@ if (NULL == adapters[i]) break; if (I2C_ADAP_MAX == i) { - printk(KERN_WARNING - " i2c-core.o: register_adapter(%s) - enlarge I2C_ADAP_MAX.\n", - adap->name); + dev_warn(&adap->dev, + "register_adapter - enlarge I2C_ADAP_MAX.\n"); res = -ENOMEM; goto out_unlock; } @@ -105,7 +114,7 @@ if (adap->dev.parent == NULL) adap->dev.parent = &legacy_bus; sprintf(adap->dev.bus_id, "i2c-%d", i); - strcpy(adap->dev.name, "i2c controller"); + adap->dev.driver = &i2c_generic_driver; device_register(&adap->dev); /* inform drivers of new adapters */ @@ -116,8 +125,7 @@ drivers[j]->attach_adapter(adap); up(&core_lists); - DEB(printk(KERN_DEBUG "i2c-core.o: adapter %s registered as adapter %d.\n", - adap->name,i)); + DEB(dev_dbg(&adap->dev, "registered as adapter %d.\n", i)); out_unlock: up(&core_lists); @@ -134,8 +142,7 @@ if (adap == adapters[i]) break; if (I2C_ADAP_MAX == i) { - printk( KERN_WARNING "i2c-core.o: unregister_adapter adap [%s] not found.\n", - adap->name); + dev_warn(&adap->dev, "unregister_adapter adap not found.\n"); res = -ENODEV; goto out_unlock; } @@ -148,9 +155,9 @@ for (j = 0; j < I2C_DRIVER_MAX; j++) if (drivers[j] && (drivers[j]->flags & I2C_DF_DUMMY)) if ((res = drivers[j]->attach_adapter(adap))) { - printk(KERN_WARNING "i2c-core.o: can't detach adapter %s " + dev_warn(&adap->dev, "can't detach adapter" "while detaching driver %s: driver not " - "detached!",adap->name,drivers[j]->name); + "detached!", drivers[j]->name); goto out_unlock; } @@ -164,10 +171,10 @@ * must be deleted, as this would cause invalid states. */ if ((res=client->driver->detach_client(client))) { - printk(KERN_ERR "i2c-core.o: adapter %s not " + dev_err(&adap->dev, "adapter not " "unregistered, because client at " "address %02x can't be detached. ", - adap->name, client->addr); + client->addr); goto out_unlock; } } @@ -180,7 +187,7 @@ adapters[i] = NULL; - DEB(printk(KERN_DEBUG "i2c-core.o: adapter unregistered: %s\n",adap->name)); + DEB(dev_dbg(&adap->dev, "adapter unregistered\n")); out_unlock: up(&core_lists); @@ -272,8 +279,7 @@ struct i2c_adapter *adap = adapters[k]; if (adap == NULL) /* skip empty entries. */ continue; - DEB2(printk(KERN_DEBUG "i2c-core.o: examining adapter %s:\n", - adap->name)); + DEB2(dev_dbg(&adap->dev, "examining adapter\n")); if (driver->flags & I2C_DF_DUMMY) { /* DUMMY drivers do not register their clients, so we have to * use a trick here: we call driver->attach_adapter to @@ -281,11 +287,10 @@ * this or hell will break loose... */ if ((res = driver->attach_adapter(adap))) { - printk(KERN_WARNING "i2c-core.o: while unregistering " - "dummy driver %s, adapter %s could " + dev_warn(&adap->dev, "while unregistering " + "dummy driver %s, adapter could " "not be detached properly; driver " - "not unloaded!",driver->name, - adap->name); + "not unloaded!",driver->name); goto out_unlock; } } else { @@ -295,20 +300,17 @@ client->driver == driver) { DEB2(printk(KERN_DEBUG "i2c-core.o: " "detaching client %s:\n", - client->name)); - if ((res = driver-> - detach_client(client))) - { - printk(KERN_ERR "i2c-core.o: while " + client->dev.name)); + if ((res = driver->detach_client(client))) { + dev_err(&adap->dev, "while " "unregistering driver " "`%s', the client at " "address %02x of " - "adapter `%s' could not " + "adapter could not " "be detached; driver " "not unloaded!", driver->name, - client->addr, - adap->name); + client->addr); goto out_unlock; } } @@ -362,7 +364,7 @@ printk(KERN_WARNING " i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n", - client->name); + client->dev.name); out_unlock_list: up(&adapter->list); @@ -374,19 +376,26 @@ if (adapter->client_register) { if (adapter->client_register(client)) { - printk(KERN_DEBUG - "i2c-core.o: warning: client_register seems " - "to have failed for client %02x at adapter %s\n", - client->addr, adapter->name); + dev_warn(&adapter->dev, "warning: client_register " + "seems to have failed for client %02x\n", + client->addr); } } - DEB(printk(KERN_DEBUG - "i2c-core.o: client [%s] registered to adapter [%s] " - "(pos. %d).\n", client->name, adapter->name, i)); + DEB(dev_dbg(&adapter->dev, "client [%s] registered to adapter " + "(pos. %d).\n", client->dev.name, i)); if (client->flags & I2C_CLIENT_ALLOW_USE) client->usage_count = 0; + + client->dev.parent = &client->adapter->dev; + client->dev.driver = &client->driver->driver; + client->dev.bus = &i2c_bus_type; + + snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id), "i2c_dev_%d", i); + printk("registering %s\n", client->dev.bus_id); + device_register(&client->dev); + return 0; } @@ -404,7 +413,7 @@ if (res) { printk(KERN_ERR "i2c-core.o: client_unregister [%s] failed, " - "client not detached", client->name); + "client not detached", client->dev.name); goto out; } } @@ -419,10 +428,11 @@ printk(KERN_WARNING " i2c-core.o: unregister_client [%s] not found\n", - client->name); + client->dev.name); res = -ENODEV; out_unlock: + device_unregister(&client->dev); up(&adapter->list); out: return res; @@ -531,7 +541,7 @@ client = adapters[i]->clients[order[j]]; len += sprintf(kbuf+len,"%02x\t%-32s\t%-32s\n", client->addr, - client->name, + client->dev.name, client->driver->name); } len = len - file->f_pos; @@ -579,7 +589,7 @@ seq_printf(s, "dummy "); seq_printf(s, "\t%-32s\t%-32s\n", - adapter->name, adapter->algo->name); + adapter->dev.name, adapter->algo->name); } up(&core_lists); @@ -675,7 +685,7 @@ bus_unregister(&i2c_bus_type); } -module_init(i2c_init); +subsys_initcall(i2c_init); module_exit(i2c_exit); /* ---------------------------------------------------- @@ -688,8 +698,7 @@ int ret; if (adap->algo->master_xfer) { - DEB2(printk(KERN_DEBUG "i2c-core.o: master_xfer: %s with %d msgs.\n", - adap->name,num)); + DEB2(dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n", num)); down(&adap->bus); ret = adap->algo->master_xfer(adap,msgs,num); @@ -697,8 +706,7 @@ return ret; } else { - printk(KERN_ERR "i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n", - adap->id); + dev_err(&adap->dev, "I2C level transfers not supported\n"); return -ENOSYS; } } @@ -715,8 +723,8 @@ msg.len = count; (const char *)msg.buf = buf; - DEB2(printk(KERN_DEBUG "i2c-core.o: master_send: writing %d bytes on %s.\n", - count,client->adapter->name)); + DEB2(dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n", + count)); down(&adap->bus); ret = adap->algo->master_xfer(adap,&msg,1); @@ -745,8 +753,8 @@ msg.len = count; msg.buf = buf; - DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: reading %d bytes on %s.\n", - count,client->adapter->name)); + DEB2(dev_dbg(&client->adapter->dev, "master_recv: reading %d bytes.\n", + count)); down(&adap->bus); ret = adap->algo->master_xfer(adap,&msg,1); diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c --- a/drivers/i2c/i2c-dev.c Sat Mar 22 07:38:05 2003 +++ b/drivers/i2c/i2c-dev.c Mon Mar 24 15:29:37 2003 @@ -30,6 +30,9 @@ /* $Id: i2c-dev.c,v 1.53 2003/01/21 08:08:16 kmalkki Exp $ */ +/* If you want debugging uncomment: */ +/* #define DEBUG 1 */ + #include #include #include @@ -41,10 +44,6 @@ #include #include -/* If you want debugging uncomment: */ -/* #define DEBUG */ - - /* struct file_operations changed too often in the 2.1 series for nice code */ static ssize_t i2cdev_read (struct file *file, char *buf, size_t count, @@ -87,7 +86,9 @@ }; static struct i2c_client i2cdev_client_template = { - .name = "I2C /dev entry", + .dev = { + .name = "I2C /dev entry", + }, .id = 1, .addr = -1, .driver = &i2cdev_driver, @@ -386,11 +387,11 @@ char name[12]; if ((i = i2c_adapter_id(adap)) < 0) { - printk(KERN_DEBUG "i2c-dev.o: Unknown adapter ?!?\n"); + dev_dbg(&adap->dev, "Unknown adapter ?!?\n"); return -ENODEV; } if (i >= I2CDEV_ADAPS_MAX) { - printk(KERN_DEBUG "i2c-dev.o: Adapter number too large?!? (%d)\n",i); + dev_dbg(&adap->dev, "Adapter number too large?!? (%d)\n",i); return -ENODEV; } @@ -401,14 +402,12 @@ DEVFS_FL_DEFAULT, I2C_MAJOR, i, S_IFCHR | S_IRUSR | S_IWUSR, &i2cdev_fops, NULL); - printk(KERN_DEBUG "i2c-dev.o: Registered '%s' as minor %d\n",adap->name,i); + dev_dbg(&adap->dev, "Registered as minor %d\n", i); } else { /* This is actually a detach_adapter call! */ devfs_remove("i2c/%d", i); i2cdev_adaps[i] = NULL; -#ifdef DEBUG - printk(KERN_DEBUG "i2c-dev.o: Adapter unregistered: %s\n",adap->name); -#endif + dev_dbg(&adap->dev, "Adapter unregistered\n"); } return 0; diff -Nru a/drivers/i2c/i2c-elektor.c b/drivers/i2c/i2c-elektor.c --- a/drivers/i2c/i2c-elektor.c Mon Dec 30 10:05:13 2002 +++ b/drivers/i2c/i2c-elektor.c Fri Mar 21 12:45:15 2003 @@ -174,10 +174,12 @@ }; static struct i2c_adapter pcf_isa_ops = { - .owner = THIS_MODULE, - .name = "PCF8584 ISA adapter", - .id = I2C_HW_P_ELEK, - .algo_data = &pcf_isa_data, + .owner = THIS_MODULE, + .id = I2C_HW_P_ELEK, + .algo_data = &pcf_isa_data, + .dev = { + .name = "PCF8584 ISA adapter", + }, }; static int __init i2c_pcfisa_init(void) diff -Nru a/drivers/i2c/i2c-elv.c b/drivers/i2c/i2c-elv.c --- a/drivers/i2c/i2c-elv.c Tue Feb 4 12:58:09 2003 +++ b/drivers/i2c/i2c-elv.c Fri Mar 21 06:37:14 2003 @@ -129,9 +129,11 @@ static struct i2c_adapter bit_elv_ops = { .owner = THIS_MODULE, - .name = "ELV Parallel port adaptor", .id = I2C_HW_B_ELV, .algo_data = &bit_elv_data, + .dev = { + .name = "ELV Parallel port adaptor", + }, }; static int __init i2c_bitelv_init(void) @@ -148,7 +150,7 @@ return -ENODEV; } } else { - bit_elv_ops.data=(void*)base; + i2c_set_adapdata(&bit_elv_ops, (void *)base); if (bit_elv_init()==0) { if(i2c_bit_add_bus(&bit_elv_ops) < 0) return -ENODEV; diff -Nru a/drivers/i2c/i2c-philips-par.c b/drivers/i2c/i2c-philips-par.c --- a/drivers/i2c/i2c-philips-par.c Tue Feb 4 12:58:09 2003 +++ b/drivers/i2c/i2c-philips-par.c Fri Mar 21 12:45:15 2003 @@ -151,8 +151,10 @@ static struct i2c_adapter bit_lp_ops = { .owner = THIS_MODULE, - .name = "Philips Parallel port adapter", .id = I2C_HW_B_LP, + .dev = { + .name = "Philips Parallel port adapter", + }, }; static void i2c_parport_attach (struct parport *port) diff -Nru a/drivers/i2c/i2c-proc.c b/drivers/i2c/i2c-proc.c --- a/drivers/i2c/i2c-proc.c Thu Mar 13 13:38:57 2003 +++ b/drivers/i2c/i2c-proc.c Fri Mar 21 16:45:50 2003 @@ -23,6 +23,8 @@ This driver puts entries in /proc/sys/dev/sensors for each I2C device */ +/* #define DEBUG 1 */ + #include #include #include @@ -581,9 +583,9 @@ is_isa ? SENSORS_ISA_BUS : i2c_adapter_id(adapter); /* Forget it if we can't probe using SMBUS_QUICK */ - if ((!is_isa) - && !i2c_check_functionality(adapter, - I2C_FUNC_SMBUS_QUICK)) return -1; + if ((!is_isa) && + !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) + return -1; for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) { /* XXX: WTF is going on here??? */ @@ -594,31 +596,14 @@ /* If it is in one of the force entries, we don't do any detection at all */ found = 0; - for (i = 0; - !found - && (this_force = - address_data->forces + i, this_force->force); i++) { - for (j = 0; - !found - && (this_force->force[j] != SENSORS_I2C_END); - j += 2) { - if ( - ((adapter_id == this_force->force[j]) - || - ((this_force-> - force[j] == SENSORS_ANY_I2C_BUS) - && !is_isa)) - && (addr == this_force->force[j + 1])) { -#ifdef DEBUG - printk - (KERN_DEBUG "i2c-proc.o: found force parameter for adapter %d, addr %04x\n", - adapter_id, addr); -#endif - if ( - (err = - found_proc(adapter, addr, 0, - this_force-> - kind))) return err; + for (i = 0; !found && (this_force = address_data->forces + i, this_force->force); i++) { + for (j = 0; !found && (this_force->force[j] != SENSORS_I2C_END); j += 2) { + if ( ((adapter_id == this_force->force[j]) || + ((this_force->force[j] == SENSORS_ANY_I2C_BUS) && !is_isa)) && + (addr == this_force->force[j + 1]) ) { + dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n", adapter_id, addr); + if ((err = found_proc(adapter, addr, 0, this_force->kind))) + return err; found = 1; } } @@ -628,42 +613,22 @@ /* If this address is in one of the ignores, we can forget about it right now */ - for (i = 0; - !found - && (address_data->ignore[i] != SENSORS_I2C_END); - i += 2) { - if ( - ((adapter_id == address_data->ignore[i]) - || - ((address_data-> - ignore[i] == SENSORS_ANY_I2C_BUS) - && !is_isa)) - && (addr == address_data->ignore[i + 1])) { -#ifdef DEBUG - printk - (KERN_DEBUG "i2c-proc.o: found ignore parameter for adapter %d, " - "addr %04x\n", adapter_id, addr); -#endif + for (i = 0; !found && (address_data->ignore[i] != SENSORS_I2C_END); i += 2) { + if ( ((adapter_id == address_data->ignore[i]) || + ((address_data->ignore[i] == SENSORS_ANY_I2C_BUS) && + !is_isa)) && + (addr == address_data->ignore[i + 1])) { + dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, addr %04x\n", adapter_id, addr); found = 1; } } - for (i = 0; - !found - && (address_data->ignore_range[i] != SENSORS_I2C_END); - i += 3) { - if ( - ((adapter_id == address_data->ignore_range[i]) - || - ((address_data-> - ignore_range[i] == - SENSORS_ANY_I2C_BUS) & !is_isa)) - && (addr >= address_data->ignore_range[i + 1]) - && (addr <= address_data->ignore_range[i + 2])) { -#ifdef DEBUG - printk - (KERN_DEBUG "i2c-proc.o: found ignore_range parameter for adapter %d, " - "addr %04x\n", adapter_id, addr); -#endif + for (i = 0; !found && (address_data->ignore_range[i] != SENSORS_I2C_END); i += 3) { + if ( ((adapter_id == address_data->ignore_range[i]) || + ((address_data-> ignore_range[i] == SENSORS_ANY_I2C_BUS) & + !is_isa)) && + (addr >= address_data->ignore_range[i + 1]) && + (addr <= address_data->ignore_range[i + 2])) { + dev_dbg(&adapter->dev, "found ignore_range parameter for adapter %d, addr %04x\n", adapter_id, addr); found = 1; } } @@ -673,68 +638,31 @@ /* Now, we will do a detection, but only if it is in the normal or probe entries */ if (is_isa) { - for (i = 0; - !found - && (address_data->normal_isa[i] != - SENSORS_ISA_END); i += 1) { + for (i = 0; !found && (address_data->normal_isa[i] != SENSORS_ISA_END); i += 1) { if (addr == address_data->normal_isa[i]) { -#ifdef DEBUG - printk - (KERN_DEBUG "i2c-proc.o: found normal isa entry for adapter %d, " - "addr %04x\n", adapter_id, - addr); -#endif + dev_dbg(&adapter->dev, "found normal isa entry for adapter %d, addr %04x\n", adapter_id, addr); found = 1; } } - for (i = 0; - !found - && (address_data->normal_isa_range[i] != - SENSORS_ISA_END); i += 3) { - if ((addr >= - address_data->normal_isa_range[i]) - && (addr <= - address_data->normal_isa_range[i + 1]) - && - ((addr - - address_data->normal_isa_range[i]) % - address_data->normal_isa_range[i + 2] == - 0)) { -#ifdef DEBUG - printk - (KERN_DEBUG "i2c-proc.o: found normal isa_range entry for adapter %d, " - "addr %04x", adapter_id, addr); -#endif + for (i = 0; !found && (address_data->normal_isa_range[i] != SENSORS_ISA_END); i += 3) { + if ((addr >= address_data->normal_isa_range[i]) && + (addr <= address_data->normal_isa_range[i + 1]) && + ((addr - address_data->normal_isa_range[i]) % address_data->normal_isa_range[i + 2] == 0)) { + dev_dbg(&adapter->dev, "found normal isa_range entry for adapter %d, addr %04x", adapter_id, addr); found = 1; } } } else { - for (i = 0; - !found && (address_data->normal_i2c[i] != - SENSORS_I2C_END); i += 1) { + for (i = 0; !found && (address_data->normal_i2c[i] != SENSORS_I2C_END); i += 1) { if (addr == address_data->normal_i2c[i]) { found = 1; -#ifdef DEBUG - printk - (KERN_DEBUG "i2c-proc.o: found normal i2c entry for adapter %d, " - "addr %02x", adapter_id, addr); -#endif + dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, addr %02x", adapter_id, addr); } } - for (i = 0; - !found - && (address_data->normal_i2c_range[i] != - SENSORS_I2C_END); i += 2) { - if ((addr >= - address_data->normal_i2c_range[i]) - && (addr <= - address_data->normal_i2c_range[i + 1])) - { -#ifdef DEBUG - printk - (KERN_DEBUG "i2c-proc.o: found normal i2c_range entry for adapter %d, " - "addr %04x\n", adapter_id, addr); -#endif + for (i = 0; !found && (address_data->normal_i2c_range[i] != SENSORS_I2C_END); i += 2) { + if ((addr >= address_data->normal_i2c_range[i]) && + (addr <= address_data->normal_i2c_range[i + 1])) { + dev_dbg(&adapter->dev, "found normal i2c_range entry for adapter %d, addr %04x\n", adapter_id, addr); found = 1; } } @@ -747,30 +675,17 @@ ((address_data-> probe[i] == SENSORS_ANY_I2C_BUS) & !is_isa)) && (addr == address_data->probe[i + 1])) { -#ifdef DEBUG - printk - (KERN_DEBUG "i2c-proc.o: found probe parameter for adapter %d, " - "addr %04x\n", adapter_id, addr); -#endif + dev_dbg(&adapter->dev, "found probe parameter for adapter %d, addr %04x\n", adapter_id, addr); found = 1; } } - for (i = 0; !found && - (address_data->probe_range[i] != SENSORS_I2C_END); - i += 3) { - if ( - ((adapter_id == address_data->probe_range[i]) - || - ((address_data->probe_range[i] == - SENSORS_ANY_I2C_BUS) & !is_isa)) - && (addr >= address_data->probe_range[i + 1]) - && (addr <= address_data->probe_range[i + 2])) { + for (i = 0; !found && (address_data->probe_range[i] != SENSORS_I2C_END); i += 3) { + if ( ((adapter_id == address_data->probe_range[i]) || + ((address_data->probe_range[i] == SENSORS_ANY_I2C_BUS) & !is_isa)) && + (addr >= address_data->probe_range[i + 1]) && + (addr <= address_data->probe_range[i + 2])) { found = 1; -#ifdef DEBUG - printk - (KERN_DEBUG "i2c-proc.o: found probe_range parameter for adapter %d, " - "addr %04x\n", adapter_id, addr); -#endif + dev_dbg(&adapter->dev, "found probe_range parameter for adapter %d, addr %04x\n", adapter_id, addr); } } if (!found) @@ -779,8 +694,7 @@ /* OK, so we really should examine this address. First check whether there is some client here at all! */ if (is_isa || - (i2c_smbus_xfer - (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0)) + (i2c_smbus_xfer (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0)) if ((err = found_proc(adapter, addr, 0, -1))) return err; } diff -Nru a/drivers/i2c/i2c-velleman.c b/drivers/i2c/i2c-velleman.c --- a/drivers/i2c/i2c-velleman.c Tue Feb 4 12:58:09 2003 +++ b/drivers/i2c/i2c-velleman.c Fri Mar 21 12:45:15 2003 @@ -114,9 +114,11 @@ static struct i2c_adapter bit_velle_ops = { .owner = THIS_MODULE, - .name = "Velleman K8000", .id = I2C_HW_B_VELLE, .algo_data = &bit_velle_data, + .dev = { + .name = "Velleman K8000", + }, }; static int __init i2c_bitvelle_init(void) diff -Nru a/drivers/i2c/scx200_acb.c b/drivers/i2c/scx200_acb.c --- a/drivers/i2c/scx200_acb.c Mon Dec 30 03:32:34 2002 +++ b/drivers/i2c/scx200_acb.c Mon Mar 24 04:58:11 2003 @@ -140,8 +140,7 @@ switch (iface->state) { case state_idle: - printk(KERN_WARNING NAME ": %s, interrupt in idle state\n", - iface->adapter.name); + dev_warn(&iface->adapter.dev, "interrupt in idle state\n"); break; case state_address: @@ -226,8 +225,8 @@ return; error: - printk(KERN_ERR NAME ": %s, %s in state %s\n", iface->adapter.name, - errmsg, scx200_acb_state_name[iface->state]); + dev_err(&iface->adapter.dev, "%s in state %s\n", errmsg, + scx200_acb_state_name[iface->state]); iface->state = state_idle; iface->result = -EIO; @@ -236,8 +235,8 @@ static void scx200_acb_timeout(struct scx200_acb_iface *iface) { - printk(KERN_ERR NAME ": %s, timeout in state %s\n", - iface->adapter.name, scx200_acb_state_name[iface->state]); + dev_err(&iface->adapter.dev, "timeout in state %s\n", + scx200_acb_state_name[iface->state]); iface->state = state_idle; iface->result = -EIO; @@ -290,7 +289,7 @@ char rw, u8 command, int size, union i2c_smbus_data *data) { - struct scx200_acb_iface *iface = adapter->data; + struct scx200_acb_iface *iface = i2c_get_adapdata(adapter); int len; u8 *buffer; u16 cur_word; @@ -331,13 +330,12 @@ size, address, command, len, rw == I2C_SMBUS_READ); if (!len && rw == I2C_SMBUS_READ) { - printk(KERN_WARNING NAME ": %s, zero length read\n", - adapter->name); + dev_warn(&adapter->dev, "zero length read\n"); return -EINVAL; } if (len && !buffer) { - printk(KERN_WARNING NAME ": %s, nonzero length but no buffer\n", adapter->name); + dev_warn(&adapter->dev, "nonzero length but no buffer\n"); return -EFAULT; } @@ -457,18 +455,18 @@ memset(iface, 0, sizeof(*iface)); adapter = &iface->adapter; - adapter->data = iface; - sprintf(adapter->name, "SCx200 ACB%d", index); + i2c_set_adapdata(adapter, iface); + snprintf(adapter->dev.name, DEVICE_NAME_SIZE, "SCx200 ACB%d", index); adapter->owner = THIS_MODULE; adapter->id = I2C_ALGO_SMBUS; adapter->algo = &scx200_acb_algorithm; init_MUTEX(&iface->sem); - sprintf(description, "NatSemi SCx200 ACCESS.bus [%s]", adapter->name); + snprintf(description, sizeof(description), "NatSemi SCx200 ACCESS.bus [%s]", adapter->dev.name); if (request_region(base, 8, description) == 0) { - printk(KERN_ERR NAME ": %s, can't allocate io 0x%x-0x%x\n", - adapter->name, base, base + 8-1); + dev_err(&adapter->dev, "can't allocate io 0x%x-0x%x\n", + base, base + 8-1); rc = -EBUSY; goto errout; } @@ -476,14 +474,14 @@ rc = scx200_acb_probe(iface); if (rc) { - printk(KERN_WARNING NAME ": %s, probe failed\n", adapter->name); + dev_warn(&adapter->dev, "probe failed\n"); goto errout; } scx200_acb_reset(iface); if (i2c_add_adapter(adapter) < 0) { - printk(KERN_ERR NAME ": %s, failed to register\n", adapter->name); + dev_err(&adapter->dev, "failed to register\n"); rc = -ENODEV; goto errout; } diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c --- a/drivers/ide/ide-disk.c Sat Mar 22 12:32:12 2003 +++ b/drivers/ide/ide-disk.c Wed Mar 26 12:23:01 2003 @@ -1098,6 +1098,7 @@ * in above order (i.e., if value of higher priority is available, * reset will be ignored). */ +#define IDE_STROKE_LIMIT (32000*1024*2) static void init_idedisk_capacity (ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -1118,7 +1119,7 @@ drive->cyl = (unsigned int) capacity_2 / (drive->head * drive->sect); drive->select.b.lba = 1; set_max_ext = idedisk_read_native_max_address_ext(drive); - if (set_max_ext > capacity_2) { + if (set_max_ext > capacity_2 && capacity_2 > IDE_STROKE_LIMIT) { #ifdef CONFIG_IDEDISK_STROKE set_max_ext = idedisk_read_native_max_address_ext(drive); set_max_ext = idedisk_set_max_address_ext(drive, set_max_ext); @@ -1145,7 +1146,7 @@ drive->select.b.lba = 1; } - if (set_max > capacity) { + if (set_max > capacity && capacity > IDE_STROKE_LIMIT) { #ifdef CONFIG_IDEDISK_STROKE set_max = idedisk_read_native_max_address(drive); set_max = idedisk_set_max_address(drive, set_max); diff -Nru a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c --- a/drivers/ide/ide-iops.c Sat Mar 22 19:26:14 2003 +++ b/drivers/ide/ide-iops.c Wed Mar 26 12:05:24 2003 @@ -903,6 +903,14 @@ * Select the drive, and issue the SETFEATURES command */ disable_irq_nosync(hwif->irq); + + /* + * FIXME: we race against the running IRQ here if + * this is called from non IRQ context. If we use + * disable_irq() we hang on the error path. Work + * is needed. + */ + udelay(1); SELECT_DRIVE(drive); SELECT_MASK(drive, 0); diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c --- a/drivers/ide/ide-taskfile.c Thu Mar 20 10:23:19 2003 +++ b/drivers/ide/ide-taskfile.c Wed Mar 26 12:22:22 2003 @@ -1670,7 +1670,7 @@ #else - int err = 0; + int err = -EIO; u8 args[4], *argbuf = args; u8 xfer_rate = 0; int argsize = 0; diff -Nru a/drivers/ide/ide-timing.h b/drivers/ide/ide-timing.h --- a/drivers/ide/ide-timing.h Fri Dec 27 01:45:49 2002 +++ b/drivers/ide/ide-timing.h Fri Mar 7 09:35:09 2003 @@ -245,14 +245,6 @@ } /* - * If the drive is an ATAPI device it may need slower address setup timing, - * so we stay on the safe side. - */ - - if (drive->media != ide_disk) - p.setup = 120; - -/* * Convert the timing to bus clock counts. */ diff -Nru a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c --- a/drivers/ieee1394/pcilynx.c Fri Feb 21 11:45:45 2003 +++ b/drivers/ieee1394/pcilynx.c Sat Mar 22 23:29:17 2003 @@ -138,10 +138,12 @@ }; static struct i2c_adapter bit_ops = { - .name = "PCILynx I2C adapter", .id = 0xAA, //FIXME: probably we should get an id in i2c-id.h .client_register = bit_reg, .client_unregister = bit_unreg, + .dev = { + .name = "PCILynx I2C", + }, }; diff -Nru a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c --- a/drivers/isdn/hisax/elsa_cs.c Mon Feb 4 23:49:25 2002 +++ b/drivers/isdn/hisax/elsa_cs.c Mon Mar 17 07:43:03 2003 @@ -53,7 +53,6 @@ #include #include #include -#include MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Elsa PCM cards"); MODULE_AUTHOR("Klaus Lichtenwalder"); @@ -163,17 +162,12 @@ "stopped" due to a power management event, or card ejection. The device IO routines can use a flag like this to throttle IO to a card that is not ready to accept it. - - The bus_operations pointer is used on platforms for which we need - to use special socket-specific versions of normal IO primitives - (inb, outb, readb, writeb, etc) for card IO. */ typedef struct local_info_t { dev_link_t link; dev_node_t node; int busy; - struct bus_operations *bus; } local_info_t; /*====================================================================*/ @@ -522,7 +516,6 @@ break; case CS_EVENT_CARD_INSERTION: link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - dev->bus = args->bus; elsa_cs_config(link); break; case CS_EVENT_PM_SUSPEND: diff -Nru a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c --- a/drivers/isdn/hisax/sedlbauer_cs.c Sat Jan 4 07:35:39 2003 +++ b/drivers/isdn/hisax/sedlbauer_cs.c Mon Mar 17 07:43:03 2003 @@ -53,7 +53,6 @@ #include #include #include -#include MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Sedlbauer cards"); MODULE_AUTHOR("Marcus Niemann"); @@ -171,17 +170,12 @@ "stopped" due to a power management event, or card ejection. The device IO routines can use a flag like this to throttle IO to a card that is not ready to accept it. - - The bus_operations pointer is used on platforms for which we need - to use special socket-specific versions of normal IO primitives - (inb, outb, readb, writeb, etc) for card IO. */ typedef struct local_info_t { dev_link_t link; dev_node_t node; int stop; - struct bus_operations *bus; } local_info_t; /*====================================================================*/ @@ -620,7 +614,6 @@ break; case CS_EVENT_CARD_INSERTION: link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - dev->bus = args->bus; sedlbauer_config(link); break; case CS_EVENT_PM_SUSPEND: diff -Nru a/drivers/md/linear.c b/drivers/md/linear.c --- a/drivers/md/linear.c Sat Mar 22 22:14:13 2003 +++ b/drivers/md/linear.c Tue Mar 25 15:37:28 2003 @@ -37,7 +37,11 @@ linear_conf_t *conf = mddev_to_conf(mddev); sector_t block = sector >> 1; - hash = conf->hash_table + sector_div(block, conf->smallest->size); + /* + * sector_div(a,b) returns the remainer and sets a to a/b + */ + (void)sector_div(block, conf->smallest->size); + hash = conf->hash_table + block; if ((sector>>1) >= (hash->dev0->size + hash->dev0->offset)) return hash->dev1; @@ -75,8 +79,6 @@ unsigned int curr_offset; struct list_head *tmp; - MOD_INC_USE_COUNT; - conf = kmalloc (sizeof (*conf), GFP_KERNEL); if (!conf) goto out; @@ -163,7 +165,6 @@ out: if (conf) kfree(conf); - MOD_DEC_USE_COUNT; return 1; } @@ -174,8 +175,6 @@ kfree(conf->hash_table); kfree(conf); - MOD_DEC_USE_COUNT; - return 0; } @@ -189,7 +188,7 @@ block = bio->bi_sector >> 1; if (unlikely(!tmp_dev)) { - printk ("linear_make_request : hash->dev1==NULL for block %llu\n", + printk("linear_make_request: hash->dev1==NULL for block %llu\n", (unsigned long long)block); bio_io_error(bio, bio->bi_size); return 0; @@ -199,7 +198,7 @@ || block < tmp_dev->offset)) { char b[BDEVNAME_SIZE]; - printk ("linear_make_request: Block %llu out of bounds on " + printk("linear_make_request: Block %llu out of bounds on " "dev %s size %ld offset %ld\n", (unsigned long long)block, bdevname(tmp_dev->rdev->bdev, b), @@ -242,6 +241,7 @@ static mdk_personality_t linear_personality= { .name = "linear", + .owner = THIS_MODULE, .make_request = linear_make_request, .run = linear_run, .stop = linear_stop, diff -Nru a/drivers/md/md.c b/drivers/md/md.c --- a/drivers/md/md.c Sat Mar 22 07:38:04 2003 +++ b/drivers/md/md.c Tue Mar 25 15:56:07 2003 @@ -64,6 +64,7 @@ #endif static mdk_personality_t *pers[MAX_PERSONALITY]; +static spinlock_t pers_lock = SPIN_LOCK_UNLOCKED; /* * Current RAID-1,4,5 parallel reconstruction 'guaranteed speed limit' @@ -302,22 +303,6 @@ return 0; } - -#define BAD_MAGIC KERN_ERR \ -"md: invalid raid superblock magic on %s\n" - -#define BAD_MINOR KERN_ERR \ -"md: %s: invalid raid minor (%x)\n" - -#define OUT_OF_MEM KERN_ALERT \ -"md: out of memory.\n" - -#define NO_SB KERN_ERR \ -"md: disabled device %s, could not read superblock.\n" - -#define BAD_CSUM KERN_WARNING \ -"md: invalid superblock checksum on %s\n" - static int alloc_disk_sb(mdk_rdev_t * rdev) { if (rdev->sb_page) @@ -325,7 +310,7 @@ rdev->sb_page = alloc_page(GFP_KERNEL); if (!rdev->sb_page) { - printk(OUT_OF_MEM); + printk(KERN_ALERT "md: out of memory.\n"); return -EINVAL; } @@ -397,7 +382,8 @@ return 0; fail: - printk(NO_SB,bdev_partition_name(rdev->bdev)); + printk(KERN_ERR "md: disabled device %s, could not read superblock.\n", + bdev_partition_name(rdev->bdev)); return -EINVAL; } @@ -526,27 +512,30 @@ sb = (mdp_super_t*)page_address(rdev->sb_page); if (sb->md_magic != MD_SB_MAGIC) { - printk(BAD_MAGIC, bdev_partition_name(rdev->bdev)); + printk(KERN_ERR "md: invalid raid superblock magic on %s\n", + bdev_partition_name(rdev->bdev)); goto abort; } if (sb->major_version != 0 || sb->minor_version != 90) { printk(KERN_WARNING "Bad version number %d.%d on %s\n", - sb->major_version, sb->minor_version, - bdev_partition_name(rdev->bdev)); + sb->major_version, sb->minor_version, + bdev_partition_name(rdev->bdev)); goto abort; } if (sb->md_minor >= MAX_MD_DEVS) { - printk(BAD_MINOR, bdev_partition_name(rdev->bdev), sb->md_minor); + printk(KERN_ERR "md: %s: invalid raid minor (%x)\n", + bdev_partition_name(rdev->bdev), sb->md_minor); goto abort; } if (sb->raid_disks <= 0) goto abort; if (calc_sb_csum(sb) != sb->sb_csum) { - printk(BAD_CSUM, bdev_partition_name(rdev->bdev)); + printk(KERN_WARNING "md: invalid superblock checksum on %s\n", + bdev_partition_name(rdev->bdev)); goto abort; } @@ -565,14 +554,15 @@ mdp_super_t *refsb = (mdp_super_t*)page_address(refdev->sb_page); if (!uuid_equal(refsb, sb)) { printk(KERN_WARNING "md: %s has different UUID to %s\n", - bdev_partition_name(rdev->bdev), - bdev_partition_name(refdev->bdev)); + bdev_partition_name(rdev->bdev), + bdev_partition_name(refdev->bdev)); goto abort; } if (!sb_equal(refsb, sb)) { - printk(KERN_WARNING "md: %s has same UUID but different superblock to %s\n", - bdev_partition_name(rdev->bdev), - bdev_partition_name(refdev->bdev)); + printk(KERN_WARNING "md: %s has same UUID" + " but different superblock to %s\n", + bdev_partition_name(rdev->bdev), + bdev_partition_name(refdev->bdev)); goto abort; } ev1 = md_event(sb); @@ -826,7 +816,8 @@ return -EINVAL; if (calc_sb_1_csum(sb) != sb->sb_csum) { - printk(BAD_CSUM, bdev_partition_name(rdev->bdev)); + printk("md: invalid superblock checksum on %s\n", + bdev_partition_name(rdev->bdev)); return -EINVAL; } rdev->preferred_minor = 0xffff; @@ -843,9 +834,10 @@ sb->level != refsb->level || sb->layout != refsb->layout || sb->chunksize != refsb->chunksize) { - printk(KERN_WARNING "md: %s has strangely different superblock to %s\n", - bdev_partition_name(rdev->bdev), - bdev_partition_name(refdev->bdev)); + printk(KERN_WARNING "md: %s has strangely different" + " superblock to %s\n", + bdev_partition_name(rdev->bdev), + bdev_partition_name(refdev->bdev)); return -EINVAL; } ev1 = le64_to_cpu(sb->events); @@ -1020,11 +1012,12 @@ } same_pdev = match_dev_unit(mddev, rdev); if (same_pdev) - printk( KERN_WARNING -"md%d: WARNING: %s appears to be on the same physical disk as %s. True\n" -" protection against single-disk failure might be compromised.\n", + printk(KERN_WARNING + "md%d: WARNING: %s appears to be on the same physical" + " disk as %s. True\n protection against single-disk" + " failure might be compromised.\n", mdidx(mddev), bdev_partition_name(rdev->bdev), - bdev_partition_name(same_pdev->bdev)); + bdev_partition_name(same_pdev->bdev)); /* Verify rdev->desc_nr is unique. * If it is -1, assign a free number, else @@ -1099,7 +1092,8 @@ static void export_rdev(mdk_rdev_t * rdev) { - printk(KERN_INFO "md: export_rdev(%s)\n",bdev_partition_name(rdev->bdev)); + printk(KERN_INFO "md: export_rdev(%s)\n", + bdev_partition_name(rdev->bdev)); if (rdev->mddev) MD_BUG(); free_disk_sb(rdev); @@ -1135,11 +1129,6 @@ mddev->major_version = 0; } -#undef BAD_CSUM -#undef BAD_MAGIC -#undef OUT_OF_MEM -#undef NO_SB - static void print_desc(mdp_disk_t *desc) { printk(" DISK\n", desc->number, @@ -1151,14 +1140,16 @@ { int i; - printk(KERN_INFO "md: SB: (V:%d.%d.%d) ID:<%08x.%08x.%08x.%08x> CT:%08x\n", + printk(KERN_INFO + "md: SB: (V:%d.%d.%d) ID:<%08x.%08x.%08x.%08x> CT:%08x\n", sb->major_version, sb->minor_version, sb->patch_version, sb->set_uuid0, sb->set_uuid1, sb->set_uuid2, sb->set_uuid3, sb->ctime); - printk(KERN_INFO "md: L%d S%08d ND:%d RD:%d md%d LO:%d CS:%d\n", sb->level, - sb->size, sb->nr_disks, sb->raid_disks, sb->md_minor, - sb->layout, sb->chunk_size); - printk(KERN_INFO "md: UT:%08x ST:%d AD:%d WD:%d FD:%d SD:%d CSUM:%08x E:%08lx\n", + printk(KERN_INFO "md: L%d S%08d ND:%d RD:%d md%d LO:%d CS:%d\n", + sb->level, sb->size, sb->nr_disks, sb->raid_disks, + sb->md_minor, sb->layout, sb->chunk_size); + printk(KERN_INFO "md: UT:%08x ST:%d AD:%d WD:%d" + " FD:%d SD:%d CSUM:%08x E:%08lx\n", sb->utime, sb->state, sb->active_disks, sb->working_disks, sb->failed_disks, sb->spare_disks, sb->sb_csum, (unsigned long)sb->events_lo); @@ -1182,8 +1173,8 @@ static void print_rdev(mdk_rdev_t *rdev) { printk(KERN_INFO "md: rdev %s, SZ:%08llu F:%d S:%d DN:%d ", - bdev_partition_name(rdev->bdev), - (unsigned long long)rdev->size, rdev->faulty, rdev->in_sync, rdev->desc_nr); + bdev_partition_name(rdev->bdev), (unsigned long long)rdev->size, + rdev->faulty, rdev->in_sync, rdev->desc_nr); if (rdev->sb_loaded) { printk(KERN_INFO "md: rdev superblock:\n"); print_sb((mdp_super_t*)page_address(rdev->sb_page)); @@ -1227,13 +1218,15 @@ return 1; } - dprintk(KERN_INFO "(write) %s's sb offset: %llu\n", bdev_partition_name(rdev->bdev), + dprintk(KERN_INFO "(write) %s's sb offset: %llu\n", + bdev_partition_name(rdev->bdev), (unsigned long long)rdev->sb_offset); if (sync_page_io(rdev->bdev, rdev->sb_offset<<1, MD_SB_BYTES, rdev->sb_page, WRITE)) return 0; - printk("md: write_disk_sb failed for device %s\n", bdev_partition_name(rdev->bdev)); + printk("md: write_disk_sb failed for device %s\n", + bdev_partition_name(rdev->bdev)); return 1; } @@ -1278,8 +1271,9 @@ if (!mddev->persistent) return; - dprintk(KERN_INFO "md: updating md%d RAID superblock on device (in sync %d)\n", - mdidx(mddev),mddev->in_sync); + dprintk(KERN_INFO + "md: updating md%d RAID superblock on device (in sync %d)\n", + mdidx(mddev),mddev->in_sync); err = 0; ITERATE_RDEV(mddev,rdev,tmp) { @@ -1298,10 +1292,12 @@ } if (err) { if (--count) { - printk(KERN_ERR "md: errors occurred during superblock update, repeating\n"); + printk(KERN_ERR "md: errors occurred during superblock" + " update, repeating\n"); goto repeat; } - printk(KERN_ERR "md: excessive errors occurred during superblock update, exiting\n"); + printk(KERN_ERR \ + "md: excessive errors occurred during superblock update, exiting\n"); } } @@ -1323,7 +1319,8 @@ rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL); if (!rdev) { - printk(KERN_ERR "md: could not alloc mem for %s!\n", partition_name(newdev)); + printk(KERN_ERR "md: could not alloc mem for %s!\n", + partition_name(newdev)); return ERR_PTR(-ENOMEM); } memset(rdev, 0, sizeof(*rdev)); @@ -1345,9 +1342,9 @@ size = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; if (!size) { - printk(KERN_WARNING - "md: %s has zero or unknown size, marking faulty!\n", - bdev_partition_name(rdev->bdev)); + printk(KERN_WARNING + "md: %s has zero or unknown size, marking faulty!\n", + bdev_partition_name(rdev->bdev)); err = -EINVAL; goto abort_free; } @@ -1356,13 +1353,15 @@ err = super_types[super_format]. load_super(rdev, NULL, super_minor); if (err == -EINVAL) { - printk(KERN_WARNING "md: %s has invalid sb, not importing!\n", - bdev_partition_name(rdev->bdev)); + printk(KERN_WARNING + "md: %s has invalid sb, not importing!\n", + bdev_partition_name(rdev->bdev)); goto abort_free; } if (err < 0) { - printk(KERN_WARNING "md: could not read %s's sb, not importing!\n", - bdev_partition_name(rdev->bdev)); + printk(KERN_WARNING + "md: could not read %s's sb, not importing!\n", + bdev_partition_name(rdev->bdev)); goto abort_free; } } @@ -1384,20 +1383,6 @@ * Check a full RAID array for plausibility */ -#define INCONSISTENT KERN_ERR \ -"md: fatal superblock inconsistency in %s -- removing from array\n" - -#define OUT_OF_DATE KERN_ERR \ -"md: superblock update time inconsistency -- using the most recent one\n" - -#define OLD_VERSION KERN_ALERT \ -"md: md%d: unsupported raid array version %d.%d.%d\n" - -#define NOT_CLEAN_IGNORE KERN_ERR \ -"md: md%d: raid array is not clean -- starting background reconstruction\n" - -#define UNKNOWN_LEVEL KERN_ERR \ -"md: md%d: unsupported raid level %d\n" static int analyze_sbs(mddev_t * mddev) { @@ -1415,7 +1400,10 @@ case 0: break; default: - printk(INCONSISTENT, bdev_partition_name(rdev->bdev)); + printk( KERN_ERR \ + "md: fatal superblock inconsistency in %s" + " -- removing from array\n", + bdev_partition_name(rdev->bdev)); kick_rdev_from_array(rdev); } @@ -1428,8 +1416,9 @@ if (rdev != freshest) if (super_types[mddev->major_version]. validate_super(mddev, rdev)) { - printk(KERN_WARNING "md: kicking non-fresh %s from array!\n", - bdev_partition_name(rdev->bdev)); + printk(KERN_WARNING "md: kicking non-fresh %s" + " from array!\n", + bdev_partition_name(rdev->bdev)); kick_rdev_from_array(rdev); continue; } @@ -1446,26 +1435,24 @@ */ if (mddev->major_version != MD_MAJOR_VERSION || mddev->minor_version > MD_MINOR_VERSION) { - - printk(OLD_VERSION, mdidx(mddev), mddev->major_version, - mddev->minor_version, mddev->patch_version); + printk(KERN_ALERT + "md: md%d: unsupported raid array version %d.%d.%d\n", + mdidx(mddev), mddev->major_version, + mddev->minor_version, mddev->patch_version); goto abort; } if ((mddev->recovery_cp != MaxSector) && ((mddev->level == 1) || (mddev->level == 4) || (mddev->level == 5))) - printk(NOT_CLEAN_IGNORE, mdidx(mddev)); + printk(KERN_ERR "md: md%d: raid array is not clean" + " -- starting background reconstruction\n", + mdidx(mddev)); return 0; abort: return 1; } -#undef INCONSISTENT -#undef OUT_OF_DATE -#undef OLD_VERSION -#undef OLD_LEVEL - static int device_size_calculation(mddev_t * mddev) { int data_disks = 0; @@ -1484,9 +1471,11 @@ continue; if (rdev->size < mddev->chunk_size / 1024) { printk(KERN_WARNING - "md: Dev %s smaller than chunk_size: %lluk < %dk\n", + "md: Dev %s smaller than chunk_size:" + " %lluk < %dk\n", bdev_partition_name(rdev->bdev), - (unsigned long long)rdev->size, mddev->chunk_size / 1024); + (unsigned long long)rdev->size, + mddev->chunk_size / 1024); return -EINVAL; } } @@ -1517,7 +1506,8 @@ data_disks = mddev->raid_disks-1; break; default: - printk(UNKNOWN_LEVEL, mdidx(mddev), mddev->level); + printk(KERN_ERR "md: md%d: unsupported raid level %d\n", + mdidx(mddev), mddev->level); goto abort; } if (!md_size[mdidx(mddev)]) @@ -1539,7 +1529,7 @@ printk(KERN_INFO "md%d: %d data-disks, max readahead per data-disk: %ldk\n", - mdidx(mddev), data_disks, readahead/data_disks*(PAGE_SIZE/1024)); + mdidx(mddev), data_disks, readahead/data_disks*(PAGE_SIZE/1024)); return 0; abort: return 1; @@ -1589,14 +1579,6 @@ md_wakeup_thread(mddev->thread); } -#define TOO_BIG_CHUNKSIZE KERN_ERR \ -"too big chunk_size: %d > %d\n" - -#define TOO_SMALL_CHUNKSIZE KERN_ERR \ -"too small chunk_size: %d < %ld\n" - -#define BAD_CHUNKSIZE KERN_ERR \ -"no chunksize specified, see 'man raidtab'\n" static int do_md_run(mddev_t * mddev) { @@ -1639,11 +1621,13 @@ * we abort here to be on the safe side. We don't * want to continue the bad practice. */ - printk(BAD_CHUNKSIZE); + printk(KERN_ERR + "no chunksize specified, see 'man raidtab'\n"); return -EINVAL; } if (chunk_size > MAX_CHUNK_SIZE) { - printk(TOO_BIG_CHUNKSIZE, chunk_size, MAX_CHUNK_SIZE); + printk(KERN_ERR "too big chunk_size: %d > %d\n", + chunk_size, MAX_CHUNK_SIZE); return -EINVAL; } /* @@ -1654,7 +1638,8 @@ return -EINVAL; } if (chunk_size < PAGE_SIZE) { - printk(TOO_SMALL_CHUNKSIZE, chunk_size, PAGE_SIZE); + printk(KERN_ERR "too small chunk_size: %d < %ld\n", + chunk_size, PAGE_SIZE); return -EINVAL; } } @@ -1664,20 +1649,14 @@ return -EINVAL; } +#ifdef CONFIG_KMOD if (!pers[pnum]) { -#ifdef CONFIG_KMOD char module_name[80]; sprintf (module_name, "md-personality-%d", pnum); request_module (module_name); - if (!pers[pnum]) -#endif - { - printk(KERN_ERR "md: personality %d is not loaded!\n", - pnum); - return -EINVAL; - } } +#endif if (device_size_calculation(mddev)) return -EINVAL; @@ -1711,13 +1690,23 @@ disk = disks[mdidx(mddev)]; if (!disk) return -ENOMEM; + + spin_lock(&pers_lock); + if (!pers[pnum] || !try_module_get(pers[pnum]->owner)) { + spin_unlock(&pers_lock); + printk(KERN_ERR "md: personality %d is not loaded!\n", + pnum); + return -EINVAL; + } + mddev->pers = pers[pnum]; + spin_unlock(&pers_lock); blk_queue_make_request(&mddev->queue, mddev->pers->make_request); printk("%s: setting max_sectors to %d, segment boundary to %d\n", - disk->disk_name, - chunk_size >> 9, - (chunk_size>>1)-1); + disk->disk_name, + chunk_size >> 9, + (chunk_size>>1)-1); blk_queue_max_sectors(&mddev->queue, chunk_size >> 9); blk_queue_segment_boundary(&mddev->queue, (chunk_size>>1) - 1); mddev->queue.queuedata = mddev; @@ -1726,6 +1715,7 @@ if (err) { printk(KERN_ERR "md: pers->run() failed ...\n"); mddev->pers = NULL; + module_put(mddev->pers->owner); return -EINVAL; } atomic_set(&mddev->writes_pending,0); @@ -1741,9 +1731,6 @@ return (0); } -#undef TOO_BIG_CHUNKSIZE -#undef BAD_CHUNKSIZE - static int restart_array(mddev_t *mddev) { struct gendisk *disk = disks[mdidx(mddev)]; @@ -1765,8 +1752,8 @@ mddev->ro = 0; set_disk_ro(disk, 0); - printk(KERN_INFO - "md: md%d switched to read-write mode.\n", mdidx(mddev)); + printk(KERN_INFO "md: md%d switched to read-write mode.\n", + mdidx(mddev)); /* * Kick recovery or resync if necessary */ @@ -1783,18 +1770,13 @@ return err; } -#define STILL_MOUNTED KERN_WARNING \ -"md: md%d still mounted.\n" -#define STILL_IN_USE \ -"md: md%d still in use.\n" - static int do_md_stop(mddev_t * mddev, int ro) { int err = 0; struct gendisk *disk = disks[mdidx(mddev)]; if (atomic_read(&mddev->active)>2) { - printk(STILL_IN_USE, mdidx(mddev)); + printk("md: md%d still in use.\n",mdidx(mddev)); err = -EBUSY; goto out; } @@ -1824,6 +1806,7 @@ set_disk_ro(disk, 1); goto out; } + module_put(mddev->pers->owner); mddev->pers = NULL; if (mddev->ro) mddev->ro = 0; @@ -1850,7 +1833,8 @@ if (disk) set_capacity(disk, 0); } else - printk(KERN_INFO "md: md%d switched to read-only mode.\n", mdidx(mddev)); + printk(KERN_INFO "md: md%d switched to read-only mode.\n", + mdidx(mddev)); err = 0; out: return err; @@ -1905,11 +1889,13 @@ rdev0 = list_entry(pending_raid_disks.next, mdk_rdev_t, same_set); - printk(KERN_INFO "md: considering %s ...\n", bdev_partition_name(rdev0->bdev)); + printk(KERN_INFO "md: considering %s ...\n", + bdev_partition_name(rdev0->bdev)); INIT_LIST_HEAD(&candidates); ITERATE_RDEV_PENDING(rdev,tmp) if (super_90_load(rdev, rdev0, 0) >= 0) { - printk(KERN_INFO "md: adding %s ...\n", bdev_partition_name(rdev->bdev)); + printk(KERN_INFO "md: adding %s ...\n", + bdev_partition_name(rdev->bdev)); list_move(&rdev->same_set, &candidates); } /* @@ -1920,7 +1906,8 @@ mddev = mddev_find(rdev0->preferred_minor); if (!mddev) { - printk(KERN_ERR "md: cannot allocate memory for md drive.\n"); + printk(KERN_ERR + "md: cannot allocate memory for md drive.\n"); break; } if (mddev_lock(mddev)) @@ -1928,8 +1915,9 @@ mdidx(mddev)); else if (mddev->raid_disks || mddev->major_version || !list_empty(&mddev->disks)) { - printk(KERN_WARNING "md: md%d already running, cannot run %s\n", - mdidx(mddev), bdev_partition_name(rdev0->bdev)); + printk(KERN_WARNING + "md: md%d already running, cannot run %s\n", + mdidx(mddev), bdev_partition_name(rdev0->bdev)); mddev_unlock(mddev); } else { printk(KERN_INFO "md: created md%d\n", mdidx(mddev)); @@ -1956,33 +1944,6 @@ * if possible, the array gets run as well. */ -#define BAD_VERSION KERN_ERR \ -"md: %s has RAID superblock version 0.%d, autodetect needs v0.90 or higher\n" - -#define OUT_OF_MEM KERN_ALERT \ -"md: out of memory.\n" - -#define NO_DEVICE KERN_ERR \ -"md: disabled device %s\n" - -#define AUTOADD_FAILED KERN_ERR \ -"md: auto-adding devices to md%d FAILED (error %d).\n" - -#define AUTOADD_FAILED_USED KERN_ERR \ -"md: cannot auto-add device %s to md%d, already used.\n" - -#define AUTORUN_FAILED KERN_ERR \ -"md: auto-running md%d FAILED (error %d).\n" - -#define MDDEV_BUSY KERN_ERR \ -"md: cannot auto-add to md%d, already running.\n" - -#define AUTOADDING KERN_INFO \ -"md: auto-adding devices to md%d, based on %s's superblock.\n" - -#define AUTORUNNING KERN_INFO \ -"md: auto-running md%d.\n" - static int autostart_array(dev_t startdev) { int err = -EINVAL, i; @@ -1991,7 +1952,8 @@ start_rdev = md_import_device(startdev, 0, 0); if (IS_ERR(start_rdev)) { - printk(KERN_WARNING "md: could not import %s!\n", partition_name(startdev)); + printk(KERN_WARNING "md: could not import %s!\n", + partition_name(startdev)); return err; } @@ -2005,8 +1967,9 @@ } if (start_rdev->faulty) { - printk(KERN_WARNING "md: can not autostart based on faulty %s!\n", - bdev_partition_name(start_rdev->bdev)); + printk(KERN_WARNING + "md: can not autostart based on faulty %s!\n", + bdev_partition_name(start_rdev->bdev)); export_rdev(start_rdev); return err; } @@ -2025,8 +1988,9 @@ continue; rdev = md_import_device(dev, 0, 0); if (IS_ERR(rdev)) { - printk(KERN_WARNING "md: could not import %s, trying to run array nevertheless.\n", - partition_name(dev)); + printk(KERN_WARNING "md: could not import %s," + " trying to run array nevertheless.\n", + partition_name(dev)); continue; } list_add(&rdev->same_set, &pending_raid_disks); @@ -2040,15 +2004,6 @@ } -#undef BAD_VERSION -#undef OUT_OF_MEM -#undef NO_DEVICE -#undef AUTOADD_FAILED_USED -#undef AUTOADD_FAILED -#undef AUTORUN_FAILED -#undef AUTOADDING -#undef AUTORUNNING - static int get_version(void * arg) { @@ -2113,8 +2068,6 @@ return 0; } -#undef SET_FROM_SB - static int get_disk_info(mddev_t * mddev, void * arg) { @@ -2161,7 +2114,9 @@ /* expecting a device which has a superblock */ rdev = md_import_device(dev, mddev->major_version, mddev->minor_version); if (IS_ERR(rdev)) { - printk(KERN_WARNING "md: md_import_device returned %ld\n", PTR_ERR(rdev)); + printk(KERN_WARNING + "md: md_import_device returned %ld\n", + PTR_ERR(rdev)); return PTR_ERR(rdev); } if (!list_empty(&mddev->disks)) { @@ -2170,8 +2125,10 @@ int err = super_types[mddev->major_version] .load_super(rdev, rdev0, mddev->minor_version); if (err < 0) { - printk(KERN_WARNING "md: %s has different UUID to %s\n", - bdev_partition_name(rdev->bdev), bdev_partition_name(rdev0->bdev)); + printk(KERN_WARNING + "md: %s has different UUID to %s\n", + bdev_partition_name(rdev->bdev), + bdev_partition_name(rdev0->bdev)); export_rdev(rdev); return -EINVAL; } @@ -2190,14 +2147,17 @@ if (mddev->pers) { int err; if (!mddev->pers->hot_add_disk) { - printk(KERN_WARNING "md%d: personality does not support diskops!\n", + printk(KERN_WARNING + "md%d: personality does not support diskops!\n", mdidx(mddev)); return -EINVAL; } rdev = md_import_device(dev, mddev->major_version, mddev->minor_version); if (IS_ERR(rdev)) { - printk(KERN_WARNING "md: md_import_device returned %ld\n", PTR_ERR(rdev)); + printk(KERN_WARNING + "md: md_import_device returned %ld\n", + PTR_ERR(rdev)); return PTR_ERR(rdev); } rdev->in_sync = 0; /* just to be sure */ @@ -2223,7 +2183,9 @@ int err; rdev = md_import_device (dev, -1, 0); if (IS_ERR(rdev)) { - printk(KERN_WARNING "md: error, md_import_device() returned %ld\n", PTR_ERR(rdev)); + printk(KERN_WARNING + "md: error, md_import_device() returned %ld\n", + PTR_ERR(rdev)); return PTR_ERR(rdev); } rdev->desc_nr = info->number; @@ -2333,19 +2295,23 @@ partition_name(dev), mdidx(mddev)); if (mddev->major_version != 0) { - printk(KERN_WARNING "md%d: HOT_ADD may only be used with version-0 superblocks.\n", - mdidx(mddev)); + printk(KERN_WARNING "md%d: HOT_ADD may only be used with" + " version-0 superblocks.\n", + mdidx(mddev)); return -EINVAL; } if (!mddev->pers->hot_add_disk) { - printk(KERN_WARNING "md%d: personality does not support diskops!\n", - mdidx(mddev)); + printk(KERN_WARNING + "md%d: personality does not support diskops!\n", + mdidx(mddev)); return -EINVAL; } rdev = md_import_device (dev, -1, 0); if (IS_ERR(rdev)) { - printk(KERN_WARNING "md: error, md_import_device() returned %ld\n", PTR_ERR(rdev)); + printk(KERN_WARNING + "md: error, md_import_device() returned %ld\n", + PTR_ERR(rdev)); return -EINVAL; } @@ -2354,16 +2320,18 @@ rdev->size = size; if (size < mddev->size) { - printk(KERN_WARNING "md%d: disk size %llu blocks < array size %llu\n", - mdidx(mddev), (unsigned long long)size, - (unsigned long long)mddev->size); + printk(KERN_WARNING + "md%d: disk size %llu blocks < array size %llu\n", + mdidx(mddev), (unsigned long long)size, + (unsigned long long)mddev->size); err = -ENOSPC; goto abort_export; } if (rdev->faulty) { - printk(KERN_WARNING "md: can not hot-add faulty %s disk to md%d!\n", - bdev_partition_name(rdev->bdev), mdidx(mddev)); + printk(KERN_WARNING + "md: can not hot-add faulty %s disk to md%d!\n", + bdev_partition_name(rdev->bdev), mdidx(mddev)); err = -EINVAL; goto abort_export; } @@ -2378,7 +2346,7 @@ if (rdev->desc_nr == mddev->max_disks) { printk(KERN_WARNING "md%d: can not hot-add to full array!\n", - mdidx(mddev)); + mdidx(mddev)); err = -EBUSY; goto abort_unbind_export; } @@ -2426,8 +2394,9 @@ info->major_version >= sizeof(super_types)/sizeof(super_types[0]) || super_types[info->major_version].name == NULL) { /* maybe try to auto-load a module? */ - printk(KERN_INFO "md: superblock version %d not known\n", - info->major_version); + printk(KERN_INFO + "md: superblock version %d not known\n", + info->major_version); return -EINVAL; } mddev->major_version = info->major_version; @@ -2540,7 +2509,7 @@ err = autostart_array(arg); if (err) { printk(KERN_WARNING "md: autostart %s failed!\n", - partition_name(arg)); + partition_name(arg)); goto abort; } goto done; @@ -2548,8 +2517,9 @@ err = mddev_lock(mddev); if (err) { - printk(KERN_INFO "md: ioctl lock interrupted, reason %d, cmd %d\n", - err, cmd); + printk(KERN_INFO + "md: ioctl lock interrupted, reason %d, cmd %d\n", + err, cmd); goto abort; } @@ -2558,13 +2528,15 @@ case SET_ARRAY_INFO: if (!list_empty(&mddev->disks)) { - printk(KERN_WARNING "md: array md%d already has disks!\n", + printk(KERN_WARNING + "md: array md%d already has disks!\n", mdidx(mddev)); err = -EBUSY; goto abort_unlock; } if (mddev->raid_disks) { - printk(KERN_WARNING "md: array md%d already initialised!\n", + printk(KERN_WARNING + "md: array md%d already initialised!\n", mdidx(mddev)); err = -EBUSY; goto abort_unlock; @@ -2579,7 +2551,8 @@ } err = set_array_info(mddev, &info); if (err) { - printk(KERN_WARNING "md: couldn't set array info. %d\n", err); + printk(KERN_WARNING "md: couldn't set" + " array info. %d\n", err); goto abort_unlock; } } @@ -2701,9 +2674,10 @@ default: if (_IOC_TYPE(cmd) == MD_MAJOR) - printk(KERN_WARNING "md: %s(pid %d) used obsolete MD ioctl, " - "upgrade your software to use new ictls.\n", - current->comm, current->pid); + printk(KERN_WARNING "md: %s(pid %d) used" + " obsolete MD ioctl, upgrade your" + " software to use new ictls.\n", + current->comm, current->pid); err = -EINVAL; goto abort_unlock; } @@ -2879,7 +2853,8 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev) { dprintk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n", - MD_MAJOR,mdidx(mddev),MAJOR(rdev->bdev->bd_dev),MINOR(rdev->bdev->bd_dev), + MD_MAJOR,mdidx(mddev), + MAJOR(rdev->bdev->bd_dev), MINOR(rdev->bdev->bd_dev), __builtin_return_address(0),__builtin_return_address(1), __builtin_return_address(2),__builtin_return_address(3)); @@ -3038,10 +3013,12 @@ if (v == (void*)1) { seq_printf(seq, "Personalities : "); + spin_lock(&pers_lock); for (i = 0; i < MAX_PERSONALITY; i++) if (pers[i]) seq_printf(seq, "[%s] ", pers[i]->name); + spin_unlock(&pers_lock); seq_printf(seq, "\n"); return 0; } @@ -3125,13 +3102,16 @@ return -EINVAL; } + spin_lock(&pers_lock); if (pers[pnum]) { + spin_unlock(&pers_lock); MD_BUG(); return -EBUSY; } pers[pnum] = p; printk(KERN_INFO "md: %s personality registered as nr %d\n", p->name, pnum); + spin_unlock(&pers_lock); return 0; } @@ -3143,7 +3123,9 @@ } printk(KERN_INFO "md: %s personality unregistered\n", pers[pnum]->name); + spin_lock(&pers_lock); pers[pnum] = NULL; + spin_unlock(&pers_lock); return 0; } @@ -3228,7 +3210,8 @@ void md_handle_safemode(mddev_t *mddev) { if (signal_pending(current)) { - printk(KERN_INFO "md: md%d in immediate safe mode\n",mdidx(mddev)); + printk(KERN_INFO "md: md%d in immediate safe mode\n", + mdidx(mddev)); mddev->safemode = 2; flush_signals(current); } @@ -3271,8 +3254,9 @@ continue; if (mddev2->curr_resync && match_mddev_units(mddev,mddev2)) { - printk(KERN_INFO "md: delaying resync of md%d until md%d " - "has finished resync (they share one or more physical units)\n", + printk(KERN_INFO "md: delaying resync of md%d" + " until md%d has finished resync (they" + " share one or more physical units)\n", mdidx(mddev), mdidx(mddev2)); if (mddev < mddev2) {/* arbitrarily yield */ mddev->curr_resync = 1; @@ -3295,7 +3279,8 @@ max_sectors = mddev->size << 1; printk(KERN_INFO "md: syncing RAID array md%d\n", mdidx(mddev)); - printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed: %d KB/sec/disc.\n", sysctl_speed_limit_min); + printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed:" + " %d KB/sec/disc.\n", sysctl_speed_limit_min); printk(KERN_INFO "md: using maximum available idle IO bandwith " "(but not more than %d KB/sec) for reconstruction.\n", sysctl_speed_limit_max); @@ -3318,14 +3303,16 @@ */ window = 32*(PAGE_SIZE/512); printk(KERN_INFO "md: using %dk window, over a total of %d blocks.\n", - window/2,max_sectors/2); + window/2,max_sectors/2); atomic_set(&mddev->recovery_active, 0); init_waitqueue_head(&mddev->recovery_wait); last_check = 0; if (j) - printk(KERN_INFO "md: resuming recovery of md%d from checkpoint.\n", mdidx(mddev)); + printk(KERN_INFO + "md: resuming recovery of md%d from checkpoint.\n", + mdidx(mddev)); while (j < max_sectors) { int sectors; @@ -3367,7 +3354,8 @@ /* * got a signal, exit. */ - printk(KERN_INFO "md: md_do_sync() got signal ... exiting\n"); + printk(KERN_INFO + "md: md_do_sync() got signal ... exiting\n"); flush_signals(current); set_bit(MD_RECOVERY_INTR, &mddev->recovery); goto out; @@ -3408,7 +3396,9 @@ mddev->curr_resync > 2 && mddev->curr_resync > mddev->recovery_cp) { if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { - printk(KERN_INFO "md: checkpointing recovery of md%d.\n", mdidx(mddev)); + printk(KERN_INFO + "md: checkpointing recovery of md%d.\n", + mdidx(mddev)); mddev->recovery_cp = mddev->curr_resync; } else mddev->recovery_cp = MaxSector; @@ -3526,7 +3516,9 @@ mddev, "md%d_resync"); if (!mddev->sync_thread) { - printk(KERN_ERR "md%d: could not start resync thread...\n", mdidx(mddev)); + printk(KERN_ERR "md%d: could not start resync" + " thread...\n", + mdidx(mddev)); /* leave the spares where they are, it shouldn't hurt */ mddev->recovery = 0; } else { @@ -3590,7 +3582,8 @@ { int minor; - printk(KERN_INFO "md: md driver %d.%d.%d MAX_MD_DEVS=%d, MD_SB_DISKS=%d\n", + printk(KERN_INFO "md: md driver %d.%d.%d MAX_MD_DEVS=%d," + " MD_SB_DISKS=%d\n", MD_MAJOR_VERSION, MD_MINOR_VERSION, MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS); diff -Nru a/drivers/md/multipath.c b/drivers/md/multipath.c --- a/drivers/md/multipath.c Tue Mar 11 18:15:04 2003 +++ b/drivers/md/multipath.c Tue Mar 25 15:37:52 2003 @@ -78,7 +78,7 @@ } spin_unlock_irq(&conf->device_lock); - printk (KERN_ERR "multipath_map(): no more operational IO paths?\n"); + printk(KERN_ERR "multipath_map(): no more operational IO paths?\n"); return (-1); } @@ -130,7 +130,8 @@ */ md_error (mp_bh->mddev, rdev); printk(KERN_ERR "multipath: %s: rescheduling sector %llu\n", - bdev_partition_name(rdev->bdev), (unsigned long long)bio->bi_sector); + bdev_partition_name(rdev->bdev), + (unsigned long long)bio->bi_sector); multipath_reschedule_retry(mp_bh); } atomic_dec(&rdev->nr_pending); @@ -198,16 +199,6 @@ seq_printf (seq, "]"); } -#define LAST_DISK KERN_ALERT \ -"multipath: only one IO path left and IO error.\n" - -#define NO_SPARE_DISK KERN_ALERT \ -"multipath: no spare IO path left!\n" - -#define DISK_FAILED KERN_ALERT \ -"multipath: IO failure on %s, disabling IO path. \n" \ -" Operation continuing on %d IO paths.\n" - /* * Careful, this can execute in IRQ contexts as well! @@ -222,7 +213,8 @@ * first check if this is a queued request for a device * which has just failed. */ - printk (LAST_DISK); + printk(KERN_ALERT + "multipath: only one IO path left and IO error.\n"); /* leave it active... it's all we have */ } else { /* @@ -233,17 +225,15 @@ rdev->faulty = 1; mddev->sb_dirty = 1; conf->working_disks--; - printk (DISK_FAILED, bdev_partition_name (rdev->bdev), + printk(KERN_ALERT "multipath: IO failure on %s," + " disabling IO path. \n Operation continuing" + " on %d IO paths.\n", + bdev_partition_name (rdev->bdev), conf->working_disks); } } } -#undef LAST_DISK -#undef NO_SPARE_DISK -#undef DISK_FAILED - - static void print_multipath_conf (multipath_conf_t *conf) { int i; @@ -302,7 +292,7 @@ if (p->rdev) { if (p->rdev->in_sync || atomic_read(&p->rdev->nr_pending)) { - printk(KERN_ERR "hot-remove-disk, slot %d is identified but is still operational!\n", number); + printk(KERN_ERR "hot-remove-disk, slot %d is identified" " but is still operational!\n", number); err = -EBUSY; goto abort; } @@ -318,11 +308,7 @@ return err; } -#define IO_ERROR KERN_ALERT \ -"multipath: %s: unrecoverable IO read error for block %llu\n" -#define REDIRECT_SECTOR KERN_ERR \ -"multipath: %s: redirecting sector %llu to another IO path\n" /* * This is a kernel thread which: @@ -354,59 +340,22 @@ rdev = NULL; if (multipath_map (mddev, &rdev)<0) { - printk(IO_ERROR, - bdev_partition_name(bio->bi_bdev), (unsigned long long)bio->bi_sector); + printk(KERN_ALERT "multipath: %s: unrecoverable IO read" + " error for block %llu\n", + bdev_partition_name(bio->bi_bdev), + (unsigned long long)bio->bi_sector); multipath_end_bh_io(mp_bh, 0); } else { - printk(REDIRECT_SECTOR, - bdev_partition_name(bio->bi_bdev), (unsigned long long)bio->bi_sector); + printk(KERN_ERR "multipath: %s: redirecting sector %llu" + " to another IO path\n", + bdev_partition_name(bio->bi_bdev), + (unsigned long long)bio->bi_sector); bio->bi_bdev = rdev->bdev; generic_make_request(bio); } } spin_unlock_irqrestore(&retry_list_lock, flags); } -#undef IO_ERROR -#undef REDIRECT_SECTOR - -#define INVALID_LEVEL KERN_WARNING \ -"multipath: md%d: raid level not set to multipath IO (%d)\n" - -#define NO_SB KERN_ERR \ -"multipath: disabled IO path %s (couldn't access raid superblock)\n" - -#define ERRORS KERN_ERR \ -"multipath: disabled IO path %s (errors detected)\n" - -#define NOT_IN_SYNC KERN_ERR \ -"multipath: making IO path %s a spare path (not in sync)\n" - -#define INCONSISTENT KERN_ERR \ -"multipath: disabled IO path %s (inconsistent descriptor)\n" - -#define ALREADY_RUNNING KERN_ERR \ -"multipath: disabled IO path %s (multipath %d already operational)\n" - -#define OPERATIONAL KERN_INFO \ -"multipath: device %s operational as IO path %d\n" - -#define MEM_ERROR KERN_ERR \ -"multipath: couldn't allocate memory for md%d\n" - -#define SPARE KERN_INFO \ -"multipath: spare IO path %s\n" - -#define NONE_OPERATIONAL KERN_ERR \ -"multipath: no operational IO paths for md%d\n" - -#define SB_DIFFERENCES KERN_ERR \ -"multipath: detected IO path differences!\n" - -#define ARRAY_IS_ACTIVE KERN_INFO \ -"multipath: array md%d active with %d out of %d IO paths\n" - -#define THREAD_ERROR KERN_ERR \ -"multipath: couldn't allocate thread for md%d\n" static int multipath_run (mddev_t *mddev) { @@ -416,10 +365,9 @@ mdk_rdev_t *rdev; struct list_head *tmp; - MOD_INC_USE_COUNT; - if (mddev->level != LEVEL_MULTIPATH) { - printk(INVALID_LEVEL, mdidx(mddev), mddev->level); + printk("multipath: md%d: raid level not set to multipath IO (%d)\n", + mdidx(mddev), mddev->level); goto out; } /* @@ -431,7 +379,9 @@ conf = kmalloc(sizeof(multipath_conf_t), GFP_KERNEL); mddev->private = conf; if (!conf) { - printk(MEM_ERROR, mdidx(mddev)); + printk(KERN_ERR + "multipath: couldn't allocate memory for md%d\n", + mdidx(mddev)); goto out; } memset(conf, 0, sizeof(*conf)); @@ -455,7 +405,8 @@ conf->device_lock = SPIN_LOCK_UNLOCKED; if (!conf->working_disks) { - printk(NONE_OPERATIONAL, mdidx(mddev)); + printk(KERN_ERR "multipath: no operational IO paths for md%d\n", + mdidx(mddev)); goto out_free_conf; } mddev->degraded = conf->raid_disks = conf->working_disks; @@ -464,7 +415,9 @@ mp_pool_alloc, mp_pool_free, NULL); if (conf->pool == NULL) { - printk(MEM_ERROR, mdidx(mddev)); + printk(KERN_ERR + "multipath: couldn't allocate memory for md%d\n", + mdidx(mddev)); goto out_free_conf; } @@ -473,13 +426,15 @@ mddev->thread = md_register_thread(multipathd, mddev, name); if (!mddev->thread) { - printk(THREAD_ERROR, mdidx(mddev)); + printk(KERN_ERR "multipath: couldn't allocate thread" + " for md%d\n", mdidx(mddev)); goto out_free_conf; } } - printk(ARRAY_IS_ACTIVE, mdidx(mddev), conf->working_disks, - mddev->raid_disks); + printk(KERN_INFO + "multipath: array md%d active with %d out of %d IO paths\n", + mdidx(mddev), conf->working_disks, mddev->raid_disks); /* * Ok, everything is just fine now */ @@ -491,21 +446,9 @@ kfree(conf); mddev->private = NULL; out: - MOD_DEC_USE_COUNT; return -EIO; } -#undef INVALID_LEVEL -#undef NO_SB -#undef ERRORS -#undef NOT_IN_SYNC -#undef INCONSISTENT -#undef ALREADY_RUNNING -#undef OPERATIONAL -#undef SPARE -#undef NONE_OPERATIONAL -#undef SB_DIFFERENCES -#undef ARRAY_IS_ACTIVE static int multipath_stop (mddev_t *mddev) { @@ -515,13 +458,13 @@ mempool_destroy(conf->pool); kfree(conf); mddev->private = NULL; - MOD_DEC_USE_COUNT; return 0; } static mdk_personality_t multipath_personality= { .name = "multipath", + .owner = THIS_MODULE, .make_request = multipath_make_request, .run = multipath_run, .stop = multipath_stop, diff -Nru a/drivers/md/raid0.c b/drivers/md/raid0.c --- a/drivers/md/raid0.c Tue Mar 11 18:46:36 2003 +++ b/drivers/md/raid0.c Tue Mar 25 15:37:28 2003 @@ -43,12 +43,15 @@ conf->nr_strip_zones = 0; ITERATE_RDEV(mddev,rdev1,tmp1) { - printk("raid0: looking at %s\n", bdev_partition_name(rdev1->bdev)); + printk("raid0: looking at %s\n", + bdev_partition_name(rdev1->bdev)); c = 0; ITERATE_RDEV(mddev,rdev2,tmp2) { printk("raid0: comparing %s(%llu) with %s(%llu)\n", - bdev_partition_name(rdev1->bdev), (unsigned long long)rdev1->size, - bdev_partition_name(rdev2->bdev), (unsigned long long)rdev2->size); + bdev_partition_name(rdev1->bdev), + (unsigned long long)rdev1->size, + bdev_partition_name(rdev2->bdev), + (unsigned long long)rdev2->size); if (rdev2 == rdev1) { printk("raid0: END\n"); break; @@ -94,7 +97,8 @@ goto abort; } if (zone->dev[j]) { - printk("raid0: multiple devices for %d - aborting!\n", j); + printk("raid0: multiple devices for %d - aborting!\n", + j); goto abort; } zone->dev[j] = rdev1; @@ -103,8 +107,8 @@ cnt++; } if (cnt != mddev->raid_disks) { - printk("raid0: too few disks (%d of %d) - aborting!\n", cnt, - mddev->raid_disks); + printk("raid0: too few disks (%d of %d) - aborting!\n", + cnt, mddev->raid_disks); goto abort; } zone->nb_dev = cnt; @@ -136,7 +140,7 @@ if (!smallest || (rdev->size size)) { smallest = rdev; printk(" (%llu) is smallest!.\n", - (unsigned long long)rdev->size); + (unsigned long long)rdev->size); } } else printk(" nope.\n"); @@ -144,7 +148,8 @@ zone->nb_dev = c; zone->size = (smallest->size - current_offset) * c; - printk("raid0: zone->nb_dev: %d, size: %llu\n",zone->nb_dev, (unsigned long long)zone->size); + printk("raid0: zone->nb_dev: %d, size: %llu\n", + zone->nb_dev, (unsigned long long)zone->size); if (!conf->smallest || (zone->size < conf->smallest->size)) conf->smallest = zone; @@ -153,7 +158,8 @@ curr_zone_offset += zone->size; current_offset = smallest->size; - printk("raid0: current zone offset: %llu\n", (unsigned long long)current_offset); + printk("raid0: current zone offset: %llu\n", + (unsigned long long)current_offset); } printk("raid0: done.\n"); return 0; @@ -191,8 +197,6 @@ s64 size; raid0_conf_t *conf; - MOD_INC_USE_COUNT; - conf = vmalloc(sizeof (raid0_conf_t)); if (!conf) goto out; @@ -201,8 +205,10 @@ if (create_strip_zones (mddev)) goto out_free_conf; - printk("raid0 : md_size is %llu blocks.\n", (unsigned long long)md_size[mdidx(mddev)]); - printk("raid0 : conf->smallest->size is %llu blocks.\n", (unsigned long long)conf->smallest->size); + printk("raid0 : md_size is %llu blocks.\n", + (unsigned long long)md_size[mdidx(mddev)]); + printk("raid0 : conf->smallest->size is %llu blocks.\n", + (unsigned long long)conf->smallest->size); { #if __GNUC__ < 3 volatile @@ -267,7 +273,6 @@ vfree(conf); mddev->private = NULL; out: - MOD_DEC_USE_COUNT; return 1; } @@ -282,7 +287,6 @@ vfree (conf); mddev->private = NULL; - MOD_DEC_USE_COUNT; return 0; } @@ -357,16 +361,21 @@ return 1; bad_map: - printk ("raid0_make_request bug: can't convert block across chunks or bigger than %dk %llu %d\n", chunk_size, (unsigned long long)bio->bi_sector, bio->bi_size >> 10); + printk("raid0_make_request bug: can't convert block across chunks" + " or bigger than %dk %llu %d\n", chunk_size, + (unsigned long long)bio->bi_sector, bio->bi_size >> 10); goto outerr; bad_hash: - printk("raid0_make_request bug: hash==NULL for block %llu\n", (unsigned long long)block); + printk("raid0_make_request bug: hash==NULL for block %llu\n", + (unsigned long long)block); goto outerr; bad_zone0: - printk ("raid0_make_request bug: hash->zone0==NULL for block %llu\n", (unsigned long long)block); + printk("raid0_make_request bug: hash->zone0==NULL for block %llu\n", + (unsigned long long)block); goto outerr; bad_zone1: - printk ("raid0_make_request bug: hash->zone1==NULL for block %llu\n", (unsigned long long)block); + printk("raid0_make_request bug: hash->zone1==NULL for block %llu\n", + (unsigned long long)block); outerr: bio_io_error(bio, bio->bi_size); return 0; @@ -411,6 +420,7 @@ static mdk_personality_t raid0_personality= { .name = "raid0", + .owner = THIS_MODULE, .make_request = raid0_make_request, .run = raid0_run, .stop = raid0_stop, diff -Nru a/drivers/md/raid1.c b/drivers/md/raid1.c --- a/drivers/md/raid1.c Wed Mar 19 15:43:16 2003 +++ b/drivers/md/raid1.c Tue Mar 25 15:37:59 2003 @@ -217,7 +217,7 @@ } spin_unlock_irq(&conf->device_lock); - printk (KERN_ERR "raid1_map(): huh, no more operational devices?\n"); + printk(KERN_ERR "raid1_map(): huh, no more operational devices?\n"); return -1; } @@ -305,7 +305,7 @@ * oops, read error: */ printk(KERN_ERR "raid1: %s: rescheduling sector %llu\n", - bdev_partition_name(conf->mirrors[mirror].rdev->bdev), (unsigned long long)r1_bio->sector); + bdev_partition_name(conf->mirrors[mirror].rdev->bdev), (unsigned long long)r1_bio->sector); reschedule_retry(r1_bio); } } else { @@ -584,22 +584,6 @@ seq_printf(seq, "]"); } -#define LAST_DISK KERN_ALERT \ -"raid1: only one disk left and IO error.\n" - -#define NO_SPARE_DISK KERN_ALERT \ -"raid1: no spare disk left, degrading mirror level by one.\n" - -#define DISK_FAILED KERN_ALERT \ -"raid1: Disk failure on %s, disabling device. \n" \ -" Operation continuing on %d devices\n" - -#define START_SYNCING KERN_ALERT \ -"raid1: start syncing spare disk.\n" - -#define ALREADY_SYNCING KERN_INFO \ -"raid1: syncing already in progress.\n" - static void error(mddev_t *mddev, mdk_rdev_t *rdev) { @@ -629,7 +613,9 @@ rdev->in_sync = 0; rdev->faulty = 1; mddev->sb_dirty = 1; - printk(DISK_FAILED, bdev_partition_name(rdev->bdev), conf->working_disks); + printk(KERN_ALERT "raid1: Disk failure on %s, disabling device. \n" + " Operation continuing on %d devices\n", + bdev_partition_name(rdev->bdev), conf->working_disks); } static void print_conf(conf_t *conf) @@ -643,14 +629,14 @@ return; } printk(" --- wd:%d rd:%d\n", conf->working_disks, - conf->raid_disks); + conf->raid_disks); for (i = 0; i < conf->raid_disks; i++) { tmp = conf->mirrors + i; if (tmp->rdev) printk(" disk %d, wo:%d, o:%d, dev:%s\n", - i, !tmp->rdev->in_sync, !tmp->rdev->faulty, - bdev_partition_name(tmp->rdev->bdev)); + i, !tmp->rdev->in_sync, !tmp->rdev->faulty, + bdev_partition_name(tmp->rdev->bdev)); } } @@ -743,11 +729,6 @@ return err; } -#define IO_ERROR KERN_ALERT \ -"raid1: %s: unrecoverable I/O read error for block %llu\n" - -#define REDIRECT_SECTOR KERN_ERR \ -"raid1: %s: redirecting sector %llu to another mirror\n" static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) { @@ -823,7 +804,10 @@ * There is no point trying a read-for-reconstruct as * reconstruct is about to be aborted */ - printk(IO_ERROR, bdev_partition_name(bio->bi_bdev), (unsigned long long)r1_bio->sector); + printk(KERN_ALERT "raid1: %s: unrecoverable I/O read error" + " for block %llu\n", + bdev_partition_name(bio->bi_bdev), + (unsigned long long)r1_bio->sector); md_done_sync(mddev, r1_bio->master_bio->bi_size >> 9, 0); put_buf(r1_bio); return; @@ -874,7 +858,8 @@ * Nowhere to write this to... I guess we * must be done */ - printk(KERN_ALERT "raid1: sync aborting as there is nowhere to write sector %llu\n", + printk(KERN_ALERT "raid1: sync aborting as there is nowhere" + " to write sector %llu\n", (unsigned long long)r1_bio->sector); md_done_sync(mddev, r1_bio->master_bio->bi_size >> 9, 0); put_buf(r1_bio); @@ -928,12 +913,17 @@ case READ: case READA: if (map(mddev, &rdev) == -1) { - printk(IO_ERROR, bdev_partition_name(bio->bi_bdev), (unsigned long long)r1_bio->sector); + printk(KERN_ALERT "raid1: %s: unrecoverable I/O" + " read error for block %llu\n", + bdev_partition_name(bio->bi_bdev), + (unsigned long long)r1_bio->sector); raid_end_bio_io(r1_bio, 0); break; } - printk(REDIRECT_SECTOR, - bdev_partition_name(rdev->bdev), (unsigned long long)r1_bio->sector); + printk(KERN_ERR "raid1: %s: redirecting sector %llu to" + " another mirror\n", + bdev_partition_name(rdev->bdev), + (unsigned long long)r1_bio->sector); bio->bi_bdev = rdev->bdev; bio->bi_sector = r1_bio->sector + rdev->data_offset; bio->bi_rw = r1_bio->cmd; @@ -1063,45 +1053,6 @@ return nr_sectors; } -#define INVALID_LEVEL KERN_WARNING \ -"raid1: md%d: raid level not set to mirroring (%d)\n" - -#define NO_SB KERN_ERR \ -"raid1: disabled mirror %s (couldn't access raid superblock)\n" - -#define ERRORS KERN_ERR \ -"raid1: disabled mirror %s (errors detected)\n" - -#define NOT_IN_SYNC KERN_ERR \ -"raid1: disabled mirror %s (not in sync)\n" - -#define INCONSISTENT KERN_ERR \ -"raid1: disabled mirror %s (inconsistent descriptor)\n" - -#define ALREADY_RUNNING KERN_ERR \ -"raid1: disabled mirror %s (mirror %d already operational)\n" - -#define OPERATIONAL KERN_INFO \ -"raid1: device %s operational as mirror %d\n" - -#define MEM_ERROR KERN_ERR \ -"raid1: couldn't allocate memory for md%d\n" - -#define SPARE KERN_INFO \ -"raid1: spare disk %s\n" - -#define NONE_OPERATIONAL KERN_ERR \ -"raid1: no operational mirrors for md%d\n" - -#define ARRAY_IS_ACTIVE KERN_INFO \ -"raid1: raid set md%d active with %d out of %d mirrors\n" - -#define THREAD_ERROR KERN_ERR \ -"raid1: couldn't allocate thread for md%d\n" - -#define START_RESYNC KERN_WARNING \ -"raid1: raid set md%d not clean; reconstructing mirrors\n" - static int run(mddev_t *mddev) { conf_t *conf; @@ -1110,10 +1061,9 @@ mdk_rdev_t *rdev; struct list_head *tmp; - MOD_INC_USE_COUNT; - if (mddev->level != 1) { - printk(INVALID_LEVEL, mdidx(mddev), mddev->level); + printk("raid1: md%d: raid level not set to mirroring (%d)\n", + mdidx(mddev), mddev->level); goto out; } /* @@ -1124,7 +1074,8 @@ conf = kmalloc(sizeof(conf_t), GFP_KERNEL); mddev->private = conf; if (!conf) { - printk(MEM_ERROR, mdidx(mddev)); + printk(KERN_ERR "raid1: couldn't allocate memory for md%d\n", + mdidx(mddev)); goto out; } memset(conf, 0, sizeof(*conf)); @@ -1132,7 +1083,8 @@ conf->r1bio_pool = mempool_create(NR_RAID1_BIOS, r1bio_pool_alloc, r1bio_pool_free, NULL); if (!conf->r1bio_pool) { - printk(MEM_ERROR, mdidx(mddev)); + printk(KERN_ERR "raid1: couldn't allocate memory for md%d\n", + mdidx(mddev)); goto out; } @@ -1160,7 +1112,8 @@ init_waitqueue_head(&conf->wait_resume); if (!conf->working_disks) { - printk(NONE_OPERATIONAL, mdidx(mddev)); + printk(KERN_ERR "raid1: no operational mirrors for md%d\n", + mdidx(mddev)); goto out_free_conf; } @@ -1190,12 +1143,16 @@ { mddev->thread = md_register_thread(raid1d, mddev, "md%d_raid1"); if (!mddev->thread) { - printk(THREAD_ERROR, mdidx(mddev)); + printk(KERN_ERR + "raid1: couldn't allocate thread for md%d\n", + mdidx(mddev)); goto out_free_conf; } } - - printk(ARRAY_IS_ACTIVE, mdidx(mddev), mddev->raid_disks - mddev->degraded, mddev->raid_disks); + printk(KERN_INFO + "raid1: raid set md%d active with %d out of %d mirrors\n", + mdidx(mddev), mddev->raid_disks - mddev->degraded, + mddev->raid_disks); /* * Ok, everything is just fine now */ @@ -1207,7 +1164,6 @@ kfree(conf); mddev->private = NULL; out: - MOD_DEC_USE_COUNT; return -EIO; } @@ -1221,13 +1177,13 @@ mempool_destroy(conf->r1bio_pool); kfree(conf); mddev->private = NULL; - MOD_DEC_USE_COUNT; return 0; } static mdk_personality_t raid1_personality = { .name = "raid1", + .owner = THIS_MODULE, .make_request = make_request, .run = run, .stop = stop, diff -Nru a/drivers/md/raid5.c b/drivers/md/raid5.c --- a/drivers/md/raid5.c Tue Mar 11 18:46:36 2003 +++ b/drivers/md/raid5.c Tue Mar 25 15:37:28 2003 @@ -182,7 +182,8 @@ BUG(); CHECK_DEVLOCK(); - PRINTK("init_stripe called, stripe %llu\n", (unsigned long long)sh->sector); + PRINTK("init_stripe called, stripe %llu\n", + (unsigned long long)sh->sector); remove_hash(sh); @@ -338,7 +339,9 @@ if (bi == &sh->dev[i].req) break; - PRINTK("end_read_request %llu/%d, count: %d, uptodate %d.\n", (unsigned long long)sh->sector, i, atomic_read(&sh->count), uptodate); + PRINTK("end_read_request %llu/%d, count: %d, uptodate %d.\n", + (unsigned long long)sh->sector, i, atomic_read(&sh->count), + uptodate); if (i == disks) { BUG(); return 0; @@ -409,7 +412,9 @@ if (bi == &sh->dev[i].req) break; - PRINTK("end_write_request %llu/%d, count %d, uptodate: %d.\n", (unsigned long long)sh->sector, i, atomic_read(&sh->count), uptodate); + PRINTK("end_write_request %llu/%d, count %d, uptodate: %d.\n", + (unsigned long long)sh->sector, i, atomic_read(&sh->count), + uptodate); if (i == disks) { BUG(); return 0; @@ -533,7 +538,8 @@ *dd_idx = (*pd_idx + 1 + *dd_idx) % raid_disks; break; default: - printk ("raid5: unsupported algorithm %d\n", conf->algorithm); + printk("raid5: unsupported algorithm %d\n", + conf->algorithm); } /* @@ -573,7 +579,8 @@ i -= (sh->pd_idx + 1); break; default: - printk ("raid5: unsupported algorithm %d\n", conf->algorithm); + printk("raid5: unsupported algorithm %d\n", + conf->algorithm); } chunk_number = stripe * data_disks + i; @@ -655,7 +662,8 @@ int i, count, disks = conf->raid_disks; void *ptr[MAX_XOR_BLOCKS], *p; - PRINTK("compute_block, stripe %llu, idx %d\n", (unsigned long long)sh->sector, dd_idx); + PRINTK("compute_block, stripe %llu, idx %d\n", + (unsigned long long)sh->sector, dd_idx); ptr[0] = page_address(sh->dev[dd_idx].page); memset(ptr[0], 0, STRIPE_SIZE); @@ -667,7 +675,9 @@ if (test_bit(R5_UPTODATE, &sh->dev[i].flags)) ptr[count++] = p; else - printk("compute_block() %d, stripe %llu, %d not present\n", dd_idx, (unsigned long long)sh->sector, i); + printk("compute_block() %d, stripe %llu, %d" + " not present\n", dd_idx, + (unsigned long long)sh->sector, i); check_xor(); } @@ -683,7 +693,8 @@ void *ptr[MAX_XOR_BLOCKS]; struct bio *chosen; - PRINTK("compute_parity, stripe %llu, method %d\n", (unsigned long long)sh->sector, method); + PRINTK("compute_parity, stripe %llu, method %d\n", + (unsigned long long)sh->sector, method); count = 1; ptr[0] = page_address(sh->dev[pd_idx].page); @@ -768,7 +779,9 @@ struct bio **bip; raid5_conf_t *conf = sh->raid_conf; - PRINTK("adding bh b#%llu to stripe s#%llu\n", (unsigned long long)bi->bi_sector, (unsigned long long)sh->sector); + PRINTK("adding bh b#%llu to stripe s#%llu\n", + (unsigned long long)bi->bi_sector, + (unsigned long long)sh->sector); spin_lock(&sh->lock); @@ -789,7 +802,9 @@ spin_unlock_irq(&conf->device_lock); spin_unlock(&sh->lock); - PRINTK("added bi b#%llu to stripe s#%llu, disk %d.\n", (unsigned long long)bi->bi_sector, (unsigned long long)sh->sector, dd_idx); + PRINTK("added bi b#%llu to stripe s#%llu, disk %d.\n", + (unsigned long long)bi->bi_sector, + (unsigned long long)sh->sector, dd_idx); if (forwrite) { /* check if page is coverred */ @@ -838,7 +853,9 @@ int failed_num=0; struct r5dev *dev; - PRINTK("handling stripe %llu, cnt=%d, pd_idx=%d\n", (unsigned long long)sh->sector, atomic_read(&sh->count), sh->pd_idx); + PRINTK("handling stripe %llu, cnt=%d, pd_idx=%d\n", + (unsigned long long)sh->sector, atomic_read(&sh->count), + sh->pd_idx); spin_lock(&sh->lock); clear_bit(STRIPE_HANDLE, &sh->state); @@ -853,8 +870,8 @@ clear_bit(R5_Insync, &dev->flags); clear_bit(R5_Syncio, &dev->flags); - PRINTK("check %d: state 0x%lx read %p write %p written %p\n", i, - dev->flags, dev->toread, dev->towrite, dev->written); + PRINTK("check %d: state 0x%lx read %p write %p written %p\n", + i, dev->flags, dev->toread, dev->towrite, dev->written); /* maybe we can reply to a read */ if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) { struct bio *rbi, *rbi2; @@ -895,8 +912,9 @@ } else set_bit(R5_Insync, &dev->flags); } - PRINTK("locked=%d uptodate=%d to_read=%d to_write=%d failed=%d failed_num=%d\n", - locked, uptodate, to_read, to_write, failed, failed_num); + PRINTK("locked=%d uptodate=%d to_read=%d" + " to_write=%d failed=%d failed_num=%d\n", + locked, uptodate, to_read, to_write, failed, failed_num); /* check if the array has lost two devices and, if so, some requests might * need to be failed */ @@ -1015,7 +1033,8 @@ } #endif locked++; - PRINTK("Reading block %d (sync=%d)\n", i, syncing); + PRINTK("Reading block %d (sync=%d)\n", + i, syncing); if (syncing) md_sync_acct(conf->disks[i].rdev, STRIPE_SECTORS); } @@ -1055,7 +1074,8 @@ else rcw += 2*disks; } } - PRINTK("for sector %llu, rmw=%d rcw=%d\n", (unsigned long long)sh->sector, rmw, rcw); + PRINTK("for sector %llu, rmw=%d rcw=%d\n", + (unsigned long long)sh->sector, rmw, rcw); set_bit(STRIPE_HANDLE, &sh->state); if (rmw < rcw && rmw > 0) /* prefer read-modify-write, but need to get some data */ @@ -1204,7 +1224,8 @@ md_sync_acct(rdev, STRIPE_SECTORS); bi->bi_bdev = rdev->bdev; - PRINTK("for %llu schedule op %ld on disc %d\n", (unsigned long long)sh->sector, bi->bi_rw, i); + PRINTK("for %llu schedule op %ld on disc %d\n", + (unsigned long long)sh->sector, bi->bi_rw, i); atomic_inc(&sh->count); bi->bi_sector = sh->sector + rdev->data_offset; bi->bi_flags = 1 << BIO_UPTODATE; @@ -1217,7 +1238,8 @@ bi->bi_next = NULL; generic_make_request(bi); } else { - PRINTK("skip op %ld on disc %d for sector %llu\n", bi->bi_rw, i, (unsigned long long)sh->sector); + PRINTK("skip op %ld on disc %d for sector %llu\n", + bi->bi_rw, i, (unsigned long long)sh->sector); clear_bit(R5_LOCKED, &sh->dev[i].flags); set_bit(STRIPE_HANDLE, &sh->state); } @@ -1285,8 +1307,9 @@ new_sector = raid5_compute_sector(logical_sector, raid_disks, data_disks, &dd_idx, &pd_idx, conf); - PRINTK("raid5: make_request, sector %Lu logical %Lu\n", - (unsigned long long)new_sector, (unsigned long long)logical_sector); + PRINTK("raid5: make_request, sector %Lu logical %Lu\n", + (unsigned long long)new_sector, + (unsigned long long)logical_sector); sh = get_active_stripe(conf, new_sector, pd_idx, (bi->bi_rw&RWA_MASK)); if (sh) { @@ -1410,11 +1433,8 @@ struct disk_info *disk; struct list_head *tmp; - MOD_INC_USE_COUNT; - if (mddev->level != 5 && mddev->level != 4) { printk("raid5: md%d: raid level not set to 4/5 (%d)\n", mdidx(mddev), mddev->level); - MOD_DEC_USE_COUNT; return -EIO; } @@ -1450,7 +1470,9 @@ disk->rdev = rdev; if (rdev->in_sync) { - printk(KERN_INFO "raid5: device %s operational as raid disk %d\n", bdev_partition_name(rdev->bdev), raid_disk); + printk(KERN_INFO "raid5: device %s operational as raid" + " disk %d\n", bdev_partition_name(rdev->bdev), + raid_disk); conf->working_disks++; } } @@ -1467,48 +1489,62 @@ conf->max_nr_stripes = NR_STRIPES; if (!conf->chunk_size || conf->chunk_size % 4) { - printk(KERN_ERR "raid5: invalid chunk size %d for md%d\n", conf->chunk_size, mdidx(mddev)); + printk(KERN_ERR "raid5: invalid chunk size %d for md%d\n", + conf->chunk_size, mdidx(mddev)); goto abort; } if (conf->algorithm > ALGORITHM_RIGHT_SYMMETRIC) { - printk(KERN_ERR "raid5: unsupported parity algorithm %d for md%d\n", conf->algorithm, mdidx(mddev)); + printk(KERN_ERR + "raid5: unsupported parity algorithm %d for md%d\n", + conf->algorithm, mdidx(mddev)); goto abort; } if (mddev->degraded > 1) { - printk(KERN_ERR "raid5: not enough operational devices for md%d (%d/%d failed)\n", mdidx(mddev), conf->failed_disks, conf->raid_disks); + printk(KERN_ERR "raid5: not enough operational devices for md%d" + " (%d/%d failed)\n", + mdidx(mddev), conf->failed_disks, conf->raid_disks); goto abort; } if (mddev->degraded == 1 && mddev->recovery_cp != MaxSector) { - printk(KERN_ERR "raid5: cannot start dirty degraded array for md%d\n", mdidx(mddev)); + printk(KERN_ERR + "raid5: cannot start dirty degraded array for md%d\n", + mdidx(mddev)); goto abort; } { mddev->thread = md_register_thread(raid5d, mddev, "md%d_raid5"); if (!mddev->thread) { - printk(KERN_ERR "raid5: couldn't allocate thread for md%d\n", mdidx(mddev)); + printk(KERN_ERR + "raid5: couldn't allocate thread for md%d\n", + mdidx(mddev)); goto abort; } } - - memory = conf->max_nr_stripes * (sizeof(struct stripe_head) + +memory = conf->max_nr_stripes * (sizeof(struct stripe_head) + conf->raid_disks * ((sizeof(struct bio) + PAGE_SIZE))) / 1024; if (grow_stripes(conf, conf->max_nr_stripes)) { - printk(KERN_ERR "raid5: couldn't allocate %dkB for buffers\n", memory); + printk(KERN_ERR + "raid5: couldn't allocate %dkB for buffers\n", memory); shrink_stripes(conf); md_unregister_thread(mddev->thread); goto abort; } else - printk(KERN_INFO "raid5: allocated %dkB for md%d\n", memory, mdidx(mddev)); + printk(KERN_INFO "raid5: allocated %dkB for md%d\n", + memory, mdidx(mddev)); if (mddev->degraded == 0) - printk("raid5: raid level %d set md%d active with %d out of %d devices, algorithm %d\n", conf->level, mdidx(mddev), - mddev->raid_disks-mddev->degraded, mddev->raid_disks, conf->algorithm); + printk("raid5: raid level %d set md%d active with %d out of %d" + " devices, algorithm %d\n", conf->level, mdidx(mddev), + mddev->raid_disks-mddev->degraded, mddev->raid_disks, + conf->algorithm); else - printk(KERN_ALERT "raid5: raid level %d set md%d active with %d out of %d devices, algorithm %d\n", conf->level, mdidx(mddev), - mddev->raid_disks - mddev->degraded, mddev->raid_disks, conf->algorithm); + printk(KERN_ALERT "raid5: raid level %d set md%d active with %d" + " out of %d devices, algorithm %d\n", conf->level, + mdidx(mddev), mddev->raid_disks - mddev->degraded, + mddev->raid_disks, conf->algorithm); print_raid5_conf(conf); @@ -1524,7 +1560,6 @@ } mddev->private = NULL; printk(KERN_ALERT "raid5: failed to run raid set md%d\n", mdidx(mddev)); - MOD_DEC_USE_COUNT; return -EIO; } @@ -1540,7 +1575,6 @@ free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); kfree(conf); mddev->private = NULL; - MOD_DEC_USE_COUNT; return 0; } @@ -1549,11 +1583,14 @@ { int i; - printk("sh %llu, pd_idx %d, state %ld.\n", (unsigned long long)sh->sector, sh->pd_idx, sh->state); - printk("sh %llu, count %d.\n", (unsigned long long)sh->sector, atomic_read(&sh->count)); + printk("sh %llu, pd_idx %d, state %ld.\n", + (unsigned long long)sh->sector, sh->pd_idx, sh->state); + printk("sh %llu, count %d.\n", + (unsigned long long)sh->sector, atomic_read(&sh->count)); printk("sh %llu, ", (unsigned long long)sh->sector); for (i = 0; i < sh->raid_conf->raid_disks; i++) { - printk("(cache%d: %p %ld) ", i, sh->dev[i].page, sh->dev[i].flags); + printk("(cache%d: %p %ld) ", + i, sh->dev[i].page, sh->dev[i].flags); } printk("\n"); } @@ -1693,6 +1730,7 @@ static mdk_personality_t raid5_personality= { .name = "raid5", + .owner = THIS_MODULE, .make_request = make_request, .run = run, .stop = stop, diff -Nru a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c --- a/drivers/media/radio/radio-cadet.c Wed Feb 19 09:41:03 2003 +++ b/drivers/media/radio/radio-cadet.c Sun Mar 23 15:41:29 2003 @@ -23,7 +23,9 @@ * 2002-01-17 Adam Belay * Updated to latest pnp code * -*/ + * 2003-01-31 Alan Cox + * Cleaned up locking, delay code, general odds and ends + */ #include /* Modules */ #include /* Initdata */ @@ -43,11 +45,11 @@ static int curtuner=0; static int tunestat=0; static int sigstrength=0; -static wait_queue_head_t tunerq,rdsq,readq; +static wait_queue_head_t readq; struct timer_list tunertimer,rdstimer,readtimer; static __u8 rdsin=0,rdsout=0,rdsstat=0; static unsigned char rdsbuf[RDS_BUFFER]; -static int cadet_lock=0; +static spinlock_t cadet_io_lock; static int cadet_probe(void); @@ -58,37 +60,19 @@ */ static __u16 sigtable[2][4]={{5,10,30,150},{28,40,63,1000}}; -static void cadet_wake(unsigned long qnum) -{ - switch(qnum) { - case 0: /* cadet_setfreq */ - wake_up(&tunerq); - break; - case 1: /* cadet_getrds */ - wake_up(&rdsq); - break; - } -} - - - static int cadet_getrds(void) { int rdsstat=0; - cadet_lock++; + spin_lock(&cadet_io_lock); outb(3,io); /* Select Decoder Control/Status */ outb(inb(io+1)&0x7f,io+1); /* Reset RDS detection */ - cadet_lock--; - init_timer(&rdstimer); - rdstimer.function=cadet_wake; - rdstimer.data=(unsigned long)1; - rdstimer.expires=jiffies+(HZ/10); - init_waitqueue_head(&rdsq); - add_timer(&rdstimer); - sleep_on(&rdsq); + spin_unlock(&cadet_io_lock); - cadet_lock++; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/10); + + spin_lock(&cadet_io_lock); outb(3,io); /* Select Decoder Control/Status */ if((inb(io+1)&0x80)!=0) { rdsstat|=VIDEO_TUNER_RDS_ON; @@ -96,32 +80,24 @@ if((inb(io+1)&0x10)!=0) { rdsstat|=VIDEO_TUNER_MBS_ON; } - cadet_lock--; + spin_unlock(&cadet_io_lock); return rdsstat; } - - - static int cadet_getstereo(void) { - if(curtuner!=0) { /* Only FM has stereo capability! */ + int ret = 0; + if(curtuner != 0) /* Only FM has stereo capability! */ return 0; - } - cadet_lock++; + + spin_lock(&cadet_io_lock); outb(7,io); /* Select tuner control */ - if((inb(io+1)&0x40)==0) { - cadet_lock--; - return 1; /* Stereo pilot detected */ - } - else { - cadet_lock--; - return 0; /* Mono */ - } + if( (inb(io+1) & 0x40) == 0) + ret = 1; + spin_unlock(&cadet_io_lock); + return ret; } - - static unsigned cadet_gettune(void) { int curvol,i; @@ -130,7 +106,9 @@ /* * Prepare for read */ - cadet_lock++; + + spin_lock(&cadet_io_lock); + outb(7,io); /* Select tuner control */ curvol=inb(io+1); /* Save current volume/mute setting */ outb(0x00,io+1); /* Ensure WRITE-ENABLE is LOW */ @@ -152,13 +130,11 @@ * Restore volume/mute setting */ outb(curvol,io+1); - cadet_lock--; + spin_unlock(&cadet_io_lock); return fifo; } - - static unsigned cadet_getfreq(void) { int i; @@ -191,14 +167,13 @@ return freq; } - - static void cadet_settune(unsigned fifo) { int i; unsigned test; - cadet_lock++; + spin_lock(&cadet_io_lock); + outb(7,io); /* Select tuner control */ /* * Write the shift register @@ -217,11 +192,9 @@ test=0x1c|((fifo>>23)&0x02); outb(test,io+1); } - cadet_lock--; + spin_unlock(&cadet_io_lock); } - - static void cadet_setfreq(unsigned freq) { unsigned fifo; @@ -253,92 +226,90 @@ /* * Save current volume/mute setting */ - cadet_lock++; + + spin_lock(&cadet_io_lock); outb(7,io); /* Select tuner control */ curvol=inb(io+1); + spin_unlock(&cadet_io_lock); /* * Tune the card */ for(j=3;j>-1;j--) { cadet_settune(fifo|(j<<16)); + + spin_lock(&cadet_io_lock); outb(7,io); /* Select tuner control */ outb(curvol,io+1); - cadet_lock--; - init_timer(&tunertimer); - tunertimer.function=cadet_wake; - tunertimer.data=(unsigned long)0; - tunertimer.expires=jiffies+(HZ/10); - init_waitqueue_head(&tunerq); - add_timer(&tunertimer); - sleep_on(&tunerq); + spin_unlock(&cadet_io_lock); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/10); + cadet_gettune(); - if((tunestat&0x40)==0) { /* Tuned */ + if((tunestat & 0x40) == 0) { /* Tuned */ sigstrength=sigtable[curtuner][j]; return; } - cadet_lock++; } - cadet_lock--; sigstrength=0; } static int cadet_getvol(void) { - cadet_lock++; + int ret = 0; + + spin_lock(&cadet_io_lock); + outb(7,io); /* Select tuner control */ - if((inb(io+1)&0x20)!=0) { - cadet_lock--; - return 0xffff; - } - else { - cadet_lock--; - return 0; - } + if((inb(io + 1) & 0x20) != 0) + ret = 0xffff; + + spin_unlock(&cadet_io_lock); + return ret; } static void cadet_setvol(int vol) { - cadet_lock++; + spin_lock(&cadet_io_lock); outb(7,io); /* Select tuner control */ - if(vol>0) { + if(vol>0) outb(0x20,io+1); - } - else { + else outb(0x00,io+1); - } - cadet_lock--; + spin_unlock(&cadet_io_lock); } - - void cadet_handler(unsigned long data) { /* * Service the RDS fifo */ - if(cadet_lock==0) { + + if(spin_trylock(&cadet_io_lock)) + { outb(0x3,io); /* Select RDS Decoder Control */ if((inb(io+1)&0x20)!=0) { printk(KERN_CRIT "cadet: RDS fifo overflow\n"); } outb(0x80,io); /* Select RDS fifo */ while((inb(io)&0x80)!=0) { - rdsbuf[rdsin++]=inb(io+1); - if(rdsin==rdsout) { - printk(KERN_CRIT "cadet: RDS buffer overflow\n"); - } + rdsbuf[rdsin]=inb(io+1); + if(rdsin==rdsout) + printk(KERN_WARNING "cadet: RDS buffer overflow\n"); + else + rdsin++; } + spin_unlock(&cadet_io_lock); } /* * Service pending read */ - if( rdsin!=rdsout) { + if( rdsin!=rdsout) wake_up_interruptible(&readq); - } /* * Clean up and exit @@ -359,10 +330,10 @@ unsigned char readbuf[RDS_BUFFER]; if(rdsstat==0) { - cadet_lock++; + spin_lock(&cadet_io_lock); rdsstat=1; outb(0x80,io); /* Select RDS fifo */ - cadet_lock--; + spin_unlock(&cadet_io_lock); init_timer(&readtimer); readtimer.function=cadet_handler; readtimer.data=(unsigned long)0; @@ -370,14 +341,13 @@ add_timer(&readtimer); } if(rdsin==rdsout) { - if (file->f_flags & O_NONBLOCK) { + if (file->f_flags & O_NONBLOCK) return -EWOULDBLOCK; - } interruptible_sleep_on(&readq); } - while((iname, dname); + strncpy(client->dev.name, dname, DEVICE_NAME_SIZE); init_MUTEX(&encoder->lock); encoder->client = client; + i2c_set_clientdata(client, encoder); encoder->addr = addr; encoder->norm = VIDEO_MODE_PAL; encoder->input = 0; @@ -201,7 +203,7 @@ for (i=1; iname, rv); + printk(KERN_ERR "%s_attach: init error %d\n", client->dev.name, rv); break; } } @@ -211,7 +213,7 @@ i2c_smbus_write_byte_data(client,0x07, TR0MODE); i2c_smbus_read_byte_data(client,0x12); printk(KERN_INFO "%s_attach: %s rev. %d at 0x%02x\n", - client->name, dname, rv & 1, client->addr); + client->dev.name, dname, rv & 1, client->addr); } i2c_attach_client(client); @@ -229,7 +231,7 @@ static int adv717x_detach(struct i2c_client *client) { i2c_detach_client(client); - kfree(client->data); + i2c_get_clientdata(client); kfree(client); return 0; } @@ -237,7 +239,7 @@ static int adv717x_command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct adv7175 *encoder = client->data; + struct adv7175 *encoder = i2c_get_clientdata(client); int i, x_ntsc=13, x_pal=13; /* x_ntsc is number of entries in init_ntsc -1 */ /* x_pal is number of entries in init_pal -1 */ @@ -297,7 +299,7 @@ default: printk(KERN_ERR "%s: illegal norm: %d\n", - client->name, iarg); + client->dev.name, iarg); return -EINVAL; } @@ -353,7 +355,7 @@ default: printk(KERN_ERR "%s: illegal input: %d\n", - client->name, iarg); + client->dev.name, iarg); return -EINVAL; } @@ -419,8 +421,10 @@ }; static struct i2c_client client_template = { - .name = "adv7175_client", - .driver = &i2c_driver_adv7175 + .driver = &i2c_driver_adv7175, + .dev = { + .name = "adv7175_client", + }, }; static int adv717x_init(void) diff -Nru a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c --- a/drivers/media/video/bt819.c Tue Feb 4 15:36:05 2003 +++ b/drivers/media/video/bt819.c Sat Mar 22 23:17:51 2003 @@ -128,7 +128,7 @@ struct timing *timing; - decoder = client->data; + decoder = i2c_get_clientdata(client); timing = &timing_data[decoder->norm]; init[3 * 2 - 1] = (((timing->vdelay >> 8) & 0x03) << 6) | @@ -159,6 +159,7 @@ client = kmalloc(sizeof(*client), GFP_KERNEL); if(client == NULL) return -ENOMEM; + memset(client, 0, sizeof(*client)); client_template.adapter = adap; client_template.addr = addr; memcpy(client, &client_template, sizeof(*client)); @@ -170,8 +171,8 @@ } memset(decoder, 0, sizeof(struct bt819)); - strcpy(client->name, "bt819"); - client->data = decoder; + strncpy(client->dev.name, "bt819", DEVICE_NAME_SIZE); + i2c_set_clientdata(client, decoder); decoder->client = client; decoder->addr = addr; decoder->norm = VIDEO_MODE_NTSC; @@ -186,10 +187,10 @@ i = bt819_init(client); if (i < 0) { printk(KERN_ERR "%s: bt819_attach: init status %d\n", - decoder->client->name, i); + decoder->client->dev.name, i); } else { printk(KERN_INFO "%s: bt819_attach: chip version %x\n", - decoder->client->name, i2c_smbus_read_byte_data(client, + decoder->client->dev.name, i2c_smbus_read_byte_data(client, 0x17) & 0x0f); } init_MUTEX(&decoder->lock); @@ -205,7 +206,7 @@ static int bt819_detach(struct i2c_client *client) { i2c_detach_client(client); - kfree(client->data); + i2c_get_clientdata(client); kfree(client); MOD_DEC_USE_COUNT; return 0; @@ -215,7 +216,7 @@ { int temp; - struct bt819 *decoder = client->data; + struct bt819 *decoder = i2c_get_clientdata(client); //return 0; if (!decoder->initialized) { // First call to bt819_init could be @@ -268,7 +269,7 @@ *iarg = res; DEBUG(printk(KERN_INFO "%s-bt819: get status %x\n", - decoder->client->name, *iarg)); + decoder->client->dev.name, *iarg)); } break; @@ -278,7 +279,7 @@ struct timing *timing; DEBUG(printk(KERN_INFO "%s-bt819: set norm %x\n", - decoder->client->name, *iarg)); + decoder->client->dev.name, *iarg)); if (*iarg == VIDEO_MODE_NTSC) { bt819_setbit(decoder, 0x01, 0, 1); @@ -319,7 +320,7 @@ int *iarg = arg; DEBUG(printk(KERN_INFO "%s-bt819: set input %x\n", - decoder->client->name, *iarg)); + decoder->client->dev.name, *iarg)); if (*iarg < 0 || *iarg > 7) { return -EINVAL; @@ -344,7 +345,7 @@ int *iarg = arg; DEBUG(printk(KERN_INFO "%s-bt819: set output %x\n", - decoder->client->name, *iarg)); + decoder->client->dev.name, *iarg)); /* not much choice of outputs */ if (*iarg != 0) { @@ -360,7 +361,7 @@ DEBUG(printk (KERN_INFO "%s-bt819: enable output %x\n", - decoder->client->name, *iarg)); + decoder->client->dev.name, *iarg)); if (decoder->enable != enable) { decoder->enable = enable; @@ -381,7 +382,7 @@ DEBUG(printk (KERN_INFO "%s-bt819: set picture brightness %d contrast %d colour %d\n", - decoder->client->name, pic->brightness, + decoder->client->dev.name, pic->brightness, pic->contrast, pic->colour)); @@ -448,9 +449,11 @@ }; static struct i2c_client client_template = { - .name = "bt819_client", .id = -1, - .driver = &i2c_driver_bt819 + .driver = &i2c_driver_bt819, + .dev = { + .name = "bt819_client", + }, }; static int bt819_setup(void) diff -Nru a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c --- a/drivers/media/video/bt856.c Tue Feb 4 21:00:54 2003 +++ b/drivers/media/video/bt856.c Sat Mar 22 23:17:51 2003 @@ -106,6 +106,7 @@ client = kmalloc(sizeof(*client), GFP_KERNEL); if(client == NULL) return -ENOMEM; + memset(client, 0, sizeof(*client)); client_template.adapter = adap; client_template.addr = addr; memcpy(client, &client_template, sizeof(*client)); @@ -123,14 +124,14 @@ memset(encoder, 0, sizeof(struct bt856)); - strcpy(client->name, "bt856"); + strncpy(client->dev.name, "bt856", DEVICE_NAME_SIZE); encoder->client = client; - client->data = encoder; + i2c_set_clientdata(client, encoder); encoder->addr = client->addr; encoder->norm = VIDEO_MODE_NTSC; encoder->enable = 1; - DEBUG(printk(KERN_INFO "%s-bt856: attach\n", encoder->client->name)); + DEBUG(printk(KERN_INFO "%s-bt856: attach\n", encoder->client->dev.name)); i2c_smbus_write_byte_data(client, 0xdc, 0x18); encoder->reg[0xdc] = 0x18; @@ -171,7 +172,7 @@ static int bt856_detach(struct i2c_client *client) { i2c_detach_client(client); - kfree(client->data); + i2c_get_clientdata(client); kfree(client); MOD_DEC_USE_COUNT; return 0; @@ -180,7 +181,7 @@ static int bt856_command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct bt856 *encoder = client->data; + struct bt856 *encoder = i2c_get_clientdata(client); switch (cmd) { @@ -190,7 +191,7 @@ DEBUG(printk (KERN_INFO "%s-bt856: get capabilities\n", - encoder->client->name)); + encoder->client->dev.name)); cap->flags = VIDEO_ENCODER_PAL @@ -205,7 +206,7 @@ int *iarg = arg; DEBUG(printk(KERN_INFO "%s-bt856: set norm %d\n", - encoder->client->name, *iarg)); + encoder->client->dev.name, *iarg)); switch (*iarg) { @@ -232,7 +233,7 @@ int *iarg = arg; DEBUG(printk(KERN_INFO "%s-bt856: set input %d\n", - encoder->client->name, *iarg)); + encoder->client->dev.name, *iarg)); /* We only have video bus. *iarg = 0: input is from bt819 @@ -268,7 +269,7 @@ int *iarg = arg; DEBUG(printk(KERN_INFO "%s-bt856: set output %d\n", - encoder->client->name, *iarg)); + encoder->client->dev.name, *iarg)); /* not much choice of outputs */ if (*iarg != 0) { @@ -285,7 +286,7 @@ DEBUG(printk (KERN_INFO "%s-bt856: enable output %d\n", - encoder->client->name, encoder->enable)); + encoder->client->dev.name, encoder->enable)); } break; @@ -309,9 +310,11 @@ }; static struct i2c_client client_template = { - .name = "bt856_client", .id = -1, - .driver = &i2c_driver_bt856 + .driver = &i2c_driver_bt856, + .dev = { + .name = "bt856_client", + }, }; static int bt856_init(void) diff -Nru a/drivers/media/video/bttv-if.c b/drivers/media/video/bttv-if.c --- a/drivers/media/video/bttv-if.c Tue Mar 18 09:00:00 2003 +++ b/drivers/media/video/bttv-if.c Sat Mar 22 23:17:51 2003 @@ -194,7 +194,7 @@ static int attach_inform(struct i2c_client *client) { - struct bttv *btv = (struct bttv*)client->adapter->data; + struct bttv *btv = i2c_get_adapdata(client->adapter); int i; for (i = 0; i < I2C_CLIENTS_MAX; i++) { @@ -207,13 +207,13 @@ bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type); if (bttv_verbose) printk("bttv%d: i2c attach [client=%s,%s]\n",btv->nr, - client->name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed"); + client->dev.name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed"); return 0; } static int detach_inform(struct i2c_client *client) { - struct bttv *btv = (struct bttv*)client->adapter->data; + struct bttv *btv = i2c_get_adapdata(client->adapter); int i; for (i = 0; i < I2C_CLIENTS_MAX; i++) { @@ -224,7 +224,7 @@ } if (bttv_verbose) printk("bttv%d: i2c detach [client=%s,%s]\n",btv->nr, - client->name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed"); + client->dev.name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed"); return 0; } @@ -261,15 +261,19 @@ static struct i2c_adapter bttv_i2c_adap_template = { .owner = THIS_MODULE, - .name = "bt848", .id = I2C_HW_B_BT848, .client_register = attach_inform, .client_unregister = detach_inform, + .dev = { + .name = "bt848", + }, }; static struct i2c_client bttv_i2c_client_template = { - .name = "bttv internal use only", - .id = -1, + .id = -1, + .dev = { + .name = "bttv internal", + }, }; @@ -343,10 +347,10 @@ memcpy(&btv->i2c_client, &bttv_i2c_client_template, sizeof(struct i2c_client)); - sprintf(btv->i2c_adap.name+strlen(btv->i2c_adap.name), + sprintf(btv->i2c_adap.dev.name+strlen(btv->i2c_adap.dev.name), " #%d", btv->nr); btv->i2c_algo.data = btv; - btv->i2c_adap.data = btv; + i2c_set_adapdata(&btv->i2c_adap, btv); btv->i2c_adap.algo_data = &btv->i2c_algo; btv->i2c_client.adapter = &btv->i2c_adap; diff -Nru a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c --- a/drivers/media/video/msp3400.c Wed Mar 12 06:07:06 2003 +++ b/drivers/media/video/msp3400.c Sat Mar 22 23:17:51 2003 @@ -349,7 +349,7 @@ static void msp3400c_set_scart(struct i2c_client *client, int in, int out) { - struct msp3400c *msp = client->data; + struct msp3400c *msp = i2c_get_clientdata(client); if (-1 == scarts[out][in]) return; @@ -411,7 +411,7 @@ static void msp3400c_setmode(struct i2c_client *client, int type) { - struct msp3400c *msp = client->data; + struct msp3400c *msp = i2c_get_clientdata(client); int i; dprintk("msp3400: setmode: %d\n",type); @@ -471,7 +471,7 @@ { static char *strmode[] = { "0", "mono", "stereo", "3", "lang1", "5", "6", "7", "lang2" }; - struct msp3400c *msp = client->data; + struct msp3400c *msp = i2c_get_clientdata(client); int nicam=0; /* channel source: FM/AM or nicam */ int src=0; @@ -599,7 +599,7 @@ static void msp3400c_restore_dfp(struct i2c_client *client) { - struct msp3400c *msp = client->data; + struct msp3400c *msp = i2c_get_clientdata(client); int i; for (i = 0; i < DFP_COUNT; i++) { @@ -627,7 +627,7 @@ static int autodetect_stereo(struct i2c_client *client) { - struct msp3400c *msp = client->data; + struct msp3400c *msp = i2c_get_clientdata(client); int val; int newstereo = msp->stereo; int newnicam = msp->nicam_on; @@ -727,7 +727,7 @@ /* stereo/multilang monitoring */ static void watch_stereo(struct i2c_client *client) { - struct msp3400c *msp = client->data; + struct msp3400c *msp = i2c_get_clientdata(client); if (autodetect_stereo(client)) { if (msp->stereo & VIDEO_SOUND_STEREO) @@ -746,7 +746,7 @@ static int msp3400c_thread(void *data) { struct i2c_client *client = data; - struct msp3400c *msp = client->data; + struct msp3400c *msp = i2c_get_clientdata(client); struct CARRIER_DETECT *cd; int count, max1,max2,val1,val2, val,this; @@ -1002,7 +1002,7 @@ static int msp3410d_thread(void *data) { struct i2c_client *client = data; - struct msp3400c *msp = client->data; + struct msp3400c *msp = i2c_get_clientdata(client); int mode,val,i,std; #ifdef CONFIG_SMP @@ -1226,9 +1226,11 @@ static struct i2c_client client_template = { - .name = "(unset)", .flags = I2C_CLIENT_ALLOW_USE, .driver = &driver, + .dev = { + .name = "(unset)", + }, }; static int msp_attach(struct i2c_adapter *adap, int addr, @@ -1265,7 +1267,7 @@ for (i = 0; i < DFP_COUNT; i++) msp->dfp_regs[i] = -1; - c->data = msp; + i2c_set_clientdata(c, msp); init_waitqueue_head(&msp->wq); if (-1 == msp3400c_reset(c)) { @@ -1291,7 +1293,7 @@ #endif msp3400c_setvolume(c,msp->muted,msp->left,msp->right); - sprintf(c->name,"MSP34%02d%c-%c%d", + snprintf(c->dev.name, DEVICE_NAME_SIZE, "MSP34%02d%c-%c%d", (rev2>>8)&0xff, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f); msp->nicam = (((rev2>>8)&0xff) != 00) ? 1 : 0; @@ -1310,7 +1312,7 @@ msp->wake_stereo.data = (unsigned long)msp; /* hello world :-) */ - printk(KERN_INFO "msp34xx: init: chip=%s",c->name); + printk(KERN_INFO "msp34xx: init: chip=%s",c->dev.name); if (msp->nicam) printk(", has NICAM support"); printk("\n"); @@ -1340,7 +1342,7 @@ static int msp_detach(struct i2c_client *client) { DECLARE_MUTEX_LOCKED(sem); - struct msp3400c *msp = (struct msp3400c*)client->data; + struct msp3400c *msp = i2c_get_clientdata(client); int i; /* shutdown control thread */ @@ -1379,7 +1381,7 @@ static void msp_wake_thread(struct i2c_client *client) { - struct msp3400c *msp = (struct msp3400c*)client->data; + struct msp3400c *msp = i2c_get_clientdata(client); msp3400c_setvolume(client,msp->muted,0,0); msp->watch_stereo=0; @@ -1391,7 +1393,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct msp3400c *msp = (struct msp3400c*)client->data; + struct msp3400c *msp = i2c_get_clientdata(client); __u16 *sarg = arg; #if 0 int *iarg = (int*)arg; diff -Nru a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c --- a/drivers/media/video/saa5249.c Tue Feb 11 07:41:01 2003 +++ b/drivers/media/video/saa5249.c Sat Mar 22 23:17:51 2003 @@ -171,20 +171,21 @@ return -ENOMEM; } memset(t, 0, sizeof(*t)); - strcpy(client->name, IF_NAME); + strncpy(client->dev.name, IF_NAME, DEVICE_NAME_SIZE); init_MUTEX(&t->lock); /* * Now create a video4linux device */ - client->data = vd=(struct video_device *)kmalloc(sizeof(struct video_device), GFP_KERNEL); + vd = (struct video_device *)kmalloc(sizeof(struct video_device), GFP_KERNEL); if(vd==NULL) { kfree(t); kfree(client); return -ENOMEM; } + i2c_set_clientdata(client, vd); memcpy(vd, &saa_template, sizeof(*vd)); for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) @@ -234,7 +235,7 @@ static int saa5249_detach(struct i2c_client *client) { - struct video_device *vd=client->data; + struct video_device *vd = i2c_get_clientdata(client); i2c_detach_client(client); video_unregister_device(vd); kfree(vd->priv); @@ -264,9 +265,11 @@ }; static struct i2c_client client_template = { - .name = "(unset)", .id = -1, - .driver = &i2c_driver_videotext + .driver = &i2c_driver_videotext, + .dev = { + .name = "(unset)", + }, }; /* diff -Nru a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c --- a/drivers/media/video/saa7110.c Tue Feb 25 11:05:23 2003 +++ b/drivers/media/video/saa7110.c Sat Mar 22 23:17:51 2003 @@ -163,6 +163,7 @@ client=kmalloc(sizeof(*client), GFP_KERNEL); if(client == NULL) return -ENOMEM; + memset(client, 0, sizeof(*client)); client_template.adapter = adap; client_template.addr = addr; memcpy(client, &client_template, sizeof(*client)); @@ -175,9 +176,9 @@ /* clear our private data */ memset(decoder, 0, sizeof(*decoder)); - strcpy(client->name, IF_NAME); + strncpy(client->dev.name, IF_NAME, DEVICE_NAME_SIZE); decoder->client = client; - client->data = decoder; + i2c_set_clientdata(client, decoder); decoder->addr = addr; decoder->norm = VIDEO_MODE_PAL; decoder->input = 0; @@ -189,7 +190,7 @@ rv = i2c_master_send(client, initseq, sizeof(initseq)); if (rv < 0) - printk(KERN_ERR "%s_attach: init status %d\n", client->name, rv); + printk(KERN_ERR "%s_attach: init status %d\n", client->dev.name, rv); else { i2c_smbus_write_byte_data(client,0x21,0x16); i2c_smbus_write_byte_data(client,0x0D,0x04); @@ -213,7 +214,7 @@ static int saa7110_detach(struct i2c_client *client) { - struct saa7110* decoder = client->data; + struct saa7110* decoder = i2c_get_clientdata(client); i2c_detach_client(client); @@ -232,7 +233,7 @@ static int saa7110_command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct saa7110* decoder = client->data; + struct saa7110* decoder = i2c_get_clientdata(client); int v; switch (cmd) { @@ -251,7 +252,7 @@ case DECODER_GET_STATUS: { - struct saa7110* decoder = client->data; + struct saa7110* decoder = i2c_get_clientdata(client); int status; int res = 0; @@ -390,9 +391,11 @@ .command = saa7110_command }; static struct i2c_client client_template = { - .name = "saa7110_client", .id = -1, - .driver = &i2c_driver_saa7110 + .driver = &i2c_driver_saa7110, + .dev = { + .name = "saa7110_client", + }, }; static int saa7110_init(void) diff -Nru a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c --- a/drivers/media/video/saa7111.c Thu Nov 21 13:56:20 2002 +++ b/drivers/media/video/saa7111.c Sat Mar 22 23:17:51 2003 @@ -120,6 +120,7 @@ client = kmalloc(sizeof(*client), GFP_KERNEL); if(client == NULL) return -ENOMEM; + memset(client, 0, sizeof(*client)); client_template.adapter = adap; client_template.addr = addr; memcpy(client, &client_template, sizeof(*client)); @@ -132,9 +133,9 @@ } memset(decoder, 0, sizeof(*decoder)); - strcpy(client->name, "saa7111"); + strncpy(client->dev.name, "saa7111", DEVICE_NAME_SIZE); decoder->client = client; - client->data = decoder; + i2c_set_clientdata(client, decoder); decoder->addr = addr; decoder->norm = VIDEO_MODE_NTSC; decoder->input = 0; @@ -147,10 +148,10 @@ i = i2c_master_send(client, init, sizeof(init)); if (i < 0) { printk(KERN_ERR "%s_attach: init status %d\n", - client->name, i); + client->dev.name, i); } else { printk(KERN_INFO "%s_attach: chip version %x\n", - client->name, i2c_smbus_read_byte_data(client, 0x00) >> 4); + client->dev.name, i2c_smbus_read_byte_data(client, 0x00) >> 4); } init_MUTEX(&decoder->lock); i2c_attach_client(client); @@ -164,7 +165,7 @@ static int saa7111_detach(struct i2c_client *client) { - struct saa7111 *decoder = client->data; + struct saa7111 *decoder = i2c_get_clientdata(client); i2c_detach_client(client); kfree(decoder); kfree(client); @@ -175,7 +176,7 @@ static int saa7111_command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct saa7111 *decoder = client->data; + struct saa7111 *decoder = i2c_get_clientdata(client); switch (cmd) { @@ -187,7 +188,7 @@ for (i = 0; i < 32; i += 16) { int j; - printk("KERN_DEBUG %s: %03x", client->name, + printk("KERN_DEBUG %s: %03x", client->dev.name, i); for (j = 0; j < 16; ++j) { printk(" %02x", @@ -407,9 +408,11 @@ }; static struct i2c_client client_template = { - .name = "saa7111_client", .id = -1, - .driver = &i2c_driver_saa7111 + .driver = &i2c_driver_saa7111, + .dev = { + .name = "saa7111_client", + }, }; static int saa7111_init(void) diff -Nru a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c --- a/drivers/media/video/saa7134/saa7134-i2c.c Tue Mar 18 09:00:14 2003 +++ b/drivers/media/video/saa7134/saa7134-i2c.c Sat Mar 22 23:17:51 2003 @@ -334,15 +334,19 @@ static struct i2c_adapter saa7134_adap_template = { .owner = THIS_MODULE, - .name = "saa7134", .id = I2C_ALGO_SAA7134, .algo = &saa7134_algo, .client_register = attach_inform, + .dev = { + .name = "saa7134", + }, }; static struct i2c_client saa7134_client_template = { - .name = "saa7134 internal", .id = -1, + .dev = { + .name = "saa7134 internal", + }, }; /* ----------------------------------------------------------- */ @@ -410,7 +414,7 @@ int saa7134_i2c_register(struct saa7134_dev *dev) { dev->i2c_adap = saa7134_adap_template; - strcpy(dev->i2c_adap.name,dev->name); + strncpy(dev->i2c_adap.dev.name, dev->name, DEVICE_NAME_SIZE); dev->i2c_adap.algo_data = dev; i2c_add_adapter(&dev->i2c_adap); diff -Nru a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c --- a/drivers/media/video/saa7185.c Tue Feb 4 22:24:22 2003 +++ b/drivers/media/video/saa7185.c Sat Mar 22 23:17:51 2003 @@ -191,6 +191,7 @@ client = kmalloc(sizeof(*client), GFP_KERNEL); if (client == NULL) return -ENOMEM; + memset(client, 0, sizeof(*client)); client_template.adapter = adap; client_template.addr = addr; memcpy(client, &client_template, sizeof(*client)); @@ -202,9 +203,9 @@ memset(encoder, 0, sizeof(*encoder)); - strcpy(client->name, "saa7185"); + strncpy(client->dev.name, "saa7185", DEVICE_NAME_SIZE); encoder->client = client; - client->data = encoder; + i2c_set_clientdata(client, encoder); encoder->addr = addr; encoder->norm = VIDEO_MODE_NTSC; encoder->enable = 1; @@ -215,11 +216,11 @@ sizeof(init_ntsc)); } if (i < 0) { - printk(KERN_ERR "%s_attach: init error %d\n", client->name, + printk(KERN_ERR "%s_attach: init error %d\n", client->dev.name, i); } else { printk(KERN_INFO "%s_attach: chip version %d\n", - client->name, i2c_smbus_read_byte(client) >> 5); + client->dev.name, i2c_smbus_read_byte(client) >> 5); } init_MUTEX(&encoder->lock); i2c_attach_client(client); @@ -233,7 +234,7 @@ static int saa7185_detach(struct i2c_client *client) { - struct saa7185 *encoder = client->data; + struct saa7185 *encoder = i2c_get_clientdata(client); i2c_detach_client(client); i2c_smbus_write_byte_data(client, 0x61, (encoder->reg[0x61]) | 0x40); /* SW: output off is active */ //i2c_smbus_write_byte_data(client, 0x3a, (encoder->reg[0x3a]) | 0x80); /* SW: color bar */ @@ -246,7 +247,7 @@ static int saa7185_command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct saa7185 *encoder = client->data; + struct saa7185 *encoder = i2c_get_clientdata(client); switch (cmd) { @@ -365,9 +366,11 @@ }; static struct i2c_client client_template = { - .name = "saa7185_client", .id = -1, - .driver = &i2c_driver_saa7185 + .driver = &i2c_driver_saa7185, + .dev = { + .name = "saa7185_client", + }, }; static int saa7185_init(void) diff -Nru a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c --- a/drivers/media/video/tda7432.c Wed Mar 12 06:07:06 2003 +++ b/drivers/media/video/tda7432.c Sat Mar 22 23:17:51 2003 @@ -260,7 +260,7 @@ static int tda7432_set(struct i2c_client *client) { - struct tda7432 *t = client->data; + struct tda7432 *t = i2c_get_clientdata(client); unsigned char buf[16]; d2printk("tda7432: In tda7432_set\n"); @@ -287,7 +287,7 @@ static void do_tda7432_init(struct i2c_client *client) { - struct tda7432 *t = client->data; + struct tda7432 *t = i2c_get_clientdata(client); d2printk("tda7432: In tda7432_init\n"); t->input = TDA7432_STEREO_IN | /* Main (stereo) input */ @@ -328,11 +328,11 @@ memcpy(client,&client_template,sizeof(struct i2c_client)); client->adapter = adap; client->addr = addr; - client->data = t; + i2c_set_clientdata(client, t); do_tda7432_init(client); MOD_INC_USE_COUNT; - strcpy(client->name,"TDA7432"); + strncpy(client->dev.name, "TDA7432", DEVICE_NAME_SIZE); printk(KERN_INFO "tda7432: init\n"); i2c_attach_client(client); @@ -348,7 +348,7 @@ static int tda7432_detach(struct i2c_client *client) { - struct tda7432 *t = client->data; + struct tda7432 *t = i2c_get_clientdata(client); do_tda7432_init(client); i2c_detach_client(client); @@ -361,7 +361,7 @@ static int tda7432_command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct tda7432 *t = client->data; + struct tda7432 *t = i2c_get_clientdata(client); d2printk("tda7432: In tda7432_command\n"); switch (cmd) { @@ -526,9 +526,11 @@ static struct i2c_client client_template = { - .name = "tda7432", .id = -1, .driver = &driver, + .dev = { + .name = "tda7432", + }, }; static int tda7432_init(void) diff -Nru a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c --- a/drivers/media/video/tda9875.c Wed Mar 12 06:07:06 2003 +++ b/drivers/media/video/tda9875.c Sat Mar 22 23:17:51 2003 @@ -158,7 +158,7 @@ static void tda9875_set(struct i2c_client *client) { - struct tda9875 *tda = client->data; + struct tda9875 *tda = i2c_get_clientdata(client); unsigned char a; dprintk(KERN_DEBUG "tda9875_set(%04x,%04x,%04x,%04x)\n",tda->lvol,tda->rvol,tda->bass,tda->treble); @@ -176,7 +176,7 @@ static void do_tda9875_init(struct i2c_client *client) { - struct tda9875 *t = client->data; + struct tda9875 *t = i2c_get_clientdata(client); dprintk("In tda9875_init\n"); tda9875_write(client, TDA9875_CFG, 0xd0 ); /*reg de config 0 (reset)*/ tda9875_write(client, TDA9875_MSR, 0x03 ); /* Monitor 0b00000XXX*/ @@ -256,7 +256,7 @@ memcpy(client,&client_template,sizeof(struct i2c_client)); client->adapter = adap; client->addr = addr; - client->data = t; + i2c_set_clientdata(client, t); if(!tda9875_checkit(adap,addr)) { kfree(t); @@ -265,7 +265,7 @@ do_tda9875_init(client); MOD_INC_USE_COUNT; - strcpy(client->name,"TDA9875"); + strncpy(client->dev.name, "TDA9875", DEVICE_NAME_SIZE); printk(KERN_INFO "tda9875: init\n"); i2c_attach_client(client); @@ -281,7 +281,7 @@ static int tda9875_detach(struct i2c_client *client) { - struct tda9875 *t = client->data; + struct tda9875 *t = i2c_get_clientdata(client); do_tda9875_init(client); i2c_detach_client(client); @@ -294,7 +294,7 @@ static int tda9875_command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct tda9875 *t = client->data; + struct tda9875 *t = i2c_get_clientdata(client); dprintk("In tda9875_command...\n"); @@ -396,9 +396,11 @@ static struct i2c_client client_template = { - .name = "tda9875", .id = -1, .driver = &driver, + .dev = { + .name = "tda9875", + }, }; static int tda9875_init(void) diff -Nru a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c --- a/drivers/media/video/tda9887.c Wed Mar 12 06:07:06 2003 +++ b/drivers/media/video/tda9887.c Sat Mar 22 23:17:51 2003 @@ -359,7 +359,7 @@ return -ENOMEM; memset(t,0,sizeof(*t)); t->client = client_template; - t->client.data = t; + i2c_set_clientdata(&t->client, t); t->pinnacle_id = -1; i2c_attach_client(&t->client); @@ -376,12 +376,12 @@ case I2C_ALGO_BIT | I2C_HW_B_RIVA: case I2C_ALGO_SAA7134: printk("tda9887: probing %s i2c adapter [id=0x%x]\n", - adap->name,adap->id); + adap->dev.name,adap->id); rc = i2c_probe(adap, &addr_data, tda9887_attach); break; default: printk("tda9887: ignoring %s i2c adapter [id=0x%x]\n", - adap->name,adap->id); + adap->dev.name,adap->id); rc = 0; /* nothing */ } @@ -390,7 +390,7 @@ static int tda9887_detach(struct i2c_client *client) { - struct tda9887 *t = (struct tda9887*)client->data; + struct tda9887 *t = i2c_get_clientdata(client); i2c_detach_client(client); kfree(t); @@ -401,7 +401,7 @@ static int tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct tda9887 *t = (struct tda9887*)client->data; + struct tda9887 *t = i2c_get_clientdata(client); switch (cmd) { @@ -456,9 +456,11 @@ }; static struct i2c_client client_template = { - .name = "tda9887", .flags = I2C_CLIENT_ALLOW_USE, .driver = &driver, + .dev = { + .name = "tda9887", + }, }; static int tda9887_init_module(void) diff -Nru a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c --- a/drivers/media/video/tuner-3036.c Wed Mar 12 06:07:06 2003 +++ b/drivers/media/video/tuner-3036.c Sat Mar 22 23:17:51 2003 @@ -196,9 +196,11 @@ static struct i2c_client client_template = { - .name = "SAB3036", .id = -1, - .driver = &i2c_driver_tuner + .driver = &i2c_driver_tuner, + .dev = { + .name = "SAB3036", + }, }; int __init diff -Nru a/drivers/media/video/tuner.c b/drivers/media/video/tuner.c --- a/drivers/media/video/tuner.c Wed Mar 12 06:07:06 2003 +++ b/drivers/media/video/tuner.c Sat Mar 22 23:17:51 2003 @@ -226,7 +226,7 @@ { unsigned char byte; - struct tuner *t = (struct tuner*)c->data; + struct tuner *t = i2c_get_clientdata(c); if (t->type == TUNER_MT2032) return 0; @@ -276,7 +276,7 @@ { unsigned char buf[21]; int ret,xogc,xok=0; - struct tuner *t = (struct tuner*)c->data; + struct tuner *t = i2c_get_clientdata(c); buf[0]=0; ret=i2c_master_send(c,buf,1); @@ -517,7 +517,7 @@ { unsigned char buf[21]; int lint_try,ret,sel,lock=0; - struct tuner *t = (struct tuner*)c->data; + struct tuner *t = i2c_get_clientdata(c); dprintk("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n",rfin,if1,if2,from,to); @@ -594,7 +594,7 @@ u8 config; u16 div; struct tunertype *tun; - struct tuner *t = c->data; + struct tuner *t = i2c_get_clientdata(c); unsigned char buffer[4]; int rc; @@ -733,7 +733,7 @@ static void set_radio_freq(struct i2c_client *c, int freq) { struct tunertype *tun; - struct tuner *t = (struct tuner*)c->data; + struct tuner *t = i2c_get_clientdata(c); unsigned char buffer[4]; int rc,div; @@ -794,16 +794,17 @@ if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) return -ENOMEM; memcpy(client,&client_template,sizeof(struct i2c_client)); - client->data = t = kmalloc(sizeof(struct tuner),GFP_KERNEL); + t = kmalloc(sizeof(struct tuner),GFP_KERNEL); if (NULL == t) { kfree(client); return -ENOMEM; } + i2c_set_clientdata(client, t); memset(t,0,sizeof(struct tuner)); if (type >= 0 && type < TUNERS) { t->type = type; printk("tuner(bttv): type forced to %d (%s) [insmod]\n",t->type,tuners[t->type].name); - strncpy(client->name, tuners[t->type].name, sizeof(client->name)); + strncpy(client->dev.name, tuners[t->type].name, DEVICE_NAME_SIZE); } else { t->type = -1; } @@ -830,12 +831,12 @@ case I2C_ALGO_SAA7134: case I2C_ALGO_SAA7146: printk("tuner: probing %s i2c adapter [id=0x%x]\n", - adap->name,adap->id); + adap->dev.name,adap->id); rc = i2c_probe(adap, &addr_data, tuner_attach); break; default: printk("tuner: ignoring %s i2c adapter [id=0x%x]\n", - adap->name,adap->id); + adap->dev.name,adap->id); rc = 0; /* nothing */ } @@ -844,7 +845,7 @@ static int tuner_detach(struct i2c_client *client) { - struct tuner *t = (struct tuner*)client->data; + struct tuner *t = i2c_get_clientdata(client); i2c_detach_client(client); kfree(t); @@ -856,7 +857,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct tuner *t = (struct tuner*)client->data; + struct tuner *t = i2c_get_clientdata(client); int *iarg = (int*)arg; #if 0 __u16 *sarg = (__u16*)arg; @@ -875,7 +876,7 @@ t->type = *iarg; printk("tuner: type set to %d (%s)\n", t->type,tuners[t->type].name); - strncpy(client->name, tuners[t->type].name, sizeof(client->name)); + strncpy(client->dev.name, tuners[t->type].name, DEVICE_NAME_SIZE); if (t->type == TUNER_MT2032) mt2032_init(client); break; @@ -977,9 +978,11 @@ }; static struct i2c_client client_template = { - .name = "(tuner unset)", .flags = I2C_CLIENT_ALLOW_USE, .driver = &driver, + .dev = { + .name = "(tuner unset)", + }, }; static int tuner_init_module(void) diff -Nru a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c --- a/drivers/media/video/tvaudio.c Wed Mar 12 06:07:06 2003 +++ b/drivers/media/video/tvaudio.c Sat Mar 22 23:17:51 2003 @@ -161,22 +161,22 @@ unsigned char buffer[2]; if (-1 == subaddr) { - dprintk("%s: chip_write: 0x%x\n", chip->c.name, val); + dprintk("%s: chip_write: 0x%x\n", chip->c.dev.name, val); chip->shadow.bytes[1] = val; buffer[0] = val; if (1 != i2c_master_send(&chip->c,buffer,1)) { printk(KERN_WARNING "%s: I/O error (write 0x%x)\n", - chip->c.name, val); + chip->c.dev.name, val); return -1; } } else { - dprintk("%s: chip_write: reg%d=0x%x\n", chip->c.name, subaddr, val); + dprintk("%s: chip_write: reg%d=0x%x\n", chip->c.dev.name, subaddr, val); chip->shadow.bytes[subaddr+1] = val; buffer[0] = subaddr; buffer[1] = val; if (2 != i2c_master_send(&chip->c,buffer,2)) { printk(KERN_WARNING "%s: I/O error (write reg%d=0x%x)\n", - chip->c.name, subaddr, val); + chip->c.dev.name, subaddr, val); return -1; } } @@ -201,10 +201,10 @@ if (1 != i2c_master_recv(&chip->c,&buffer,1)) { printk(KERN_WARNING "%s: I/O error (read)\n", - chip->c.name); + chip->c.dev.name); return -1; } - dprintk("%s: chip_read: 0x%x\n",chip->c.name,buffer); + dprintk("%s: chip_read: 0x%x\n",chip->c.dev.name,buffer); return buffer; } @@ -220,11 +220,11 @@ if (2 != i2c_transfer(chip->c.adapter,msgs,2)) { printk(KERN_WARNING "%s: I/O error (read2)\n", - chip->c.name); + chip->c.dev.name); return -1; } dprintk("%s: chip_read2: reg%d=0x%x\n", - chip->c.name,subaddr,read[0]); + chip->c.dev.name,subaddr,read[0]); return read[0]; } @@ -237,7 +237,7 @@ /* update our shadow register set; print bytes if (debug > 0) */ dprintk("%s: chip_cmd(%s): reg=%d, data:", - chip->c.name,name,cmd->bytes[0]); + chip->c.dev.name,name,cmd->bytes[0]); for (i = 1; i < cmd->count; i++) { dprintk(" 0x%x",cmd->bytes[i]); chip->shadow.bytes[i+cmd->bytes[0]] = cmd->bytes[i]; @@ -246,7 +246,7 @@ /* send data to the chip */ if (cmd->count != i2c_master_send(&chip->c,cmd->bytes,cmd->count)) { - printk(KERN_WARNING "%s: I/O error (%s)\n", chip->c.name, name); + printk(KERN_WARNING "%s: I/O error (%s)\n", chip->c.dev.name, name); return -1; } return 0; @@ -273,19 +273,19 @@ #ifdef CONFIG_SMP lock_kernel(); #endif - daemonize("%s", chip->c.name); + daemonize("%s", chip->c.dev.name); chip->thread = current; #ifdef CONFIG_SMP unlock_kernel(); #endif - dprintk("%s: thread started\n", chip->c.name); + dprintk("%s: thread started\n", chip->c.dev.name); if(chip->notify != NULL) up(chip->notify); for (;;) { interruptible_sleep_on(&chip->wq); - dprintk("%s: thread wakeup\n", chip->c.name); + dprintk("%s: thread wakeup\n", chip->c.dev.name); if (chip->done || signal_pending(current)) break; @@ -301,7 +301,7 @@ } chip->thread = NULL; - dprintk("%s: thread exiting\n", chip->c.name); + dprintk("%s: thread exiting\n", chip->c.dev.name); if(chip->notify != NULL) up(chip->notify); @@ -316,7 +316,7 @@ if (mode == chip->prevmode) return; - dprintk("%s: thread checkmode\n", chip->c.name); + dprintk("%s: thread checkmode\n", chip->c.dev.name); chip->prevmode = mode; if (mode & VIDEO_SOUND_STEREO) @@ -1339,7 +1339,7 @@ memcpy(&chip->c,&client_template,sizeof(struct i2c_client)); chip->c.adapter = adap; chip->c.addr = addr; - chip->c.data = chip; + i2c_set_clientdata(&chip->c, chip); /* find description for the chip */ dprintk("tvaudio: chip found @ i2c-addr=0x%x\n", addr<<1); @@ -1364,7 +1364,7 @@ (desc->flags & CHIP_HAS_INPUTSEL) ? " audiomux" : ""); /* fill required data structures */ - strcpy(chip->c.name,desc->name); + strncpy(chip->c.dev.name, desc->name, DEVICE_NAME_SIZE); chip->type = desc-chiplist; chip->shadow.count = desc->registers+1; chip->prevmode = -1; @@ -1421,7 +1421,7 @@ static int chip_detach(struct i2c_client *client) { - struct CHIPSTATE *chip = client->data; + struct CHIPSTATE *chip = i2c_get_clientdata(client); del_timer(&chip->wt); if (NULL != chip->thread) { @@ -1447,10 +1447,10 @@ unsigned int cmd, void *arg) { __u16 *sarg = arg; - struct CHIPSTATE *chip = client->data; + struct CHIPSTATE *chip = i2c_get_clientdata(client); struct CHIPDESC *desc = chiplist + chip->type; - dprintk("%s: chip_command 0x%x\n",chip->c.name,cmd); + dprintk("%s: chip_command 0x%x\n",chip->c.dev.name,cmd); switch (cmd) { case AUDC_SET_INPUT: @@ -1558,9 +1558,11 @@ static struct i2c_client client_template = { - .name = "(unset)", .flags = I2C_CLIENT_ALLOW_USE, .driver = &driver, + .dev = { + .name = "(unset)", + }, }; static int audiochip_init_module(void) diff -Nru a/drivers/mtd/maps/epxa10db-flash.c b/drivers/mtd/maps/epxa10db-flash.c --- a/drivers/mtd/maps/epxa10db-flash.c Wed Feb 26 04:10:09 2003 +++ b/drivers/mtd/maps/epxa10db-flash.c Wed Mar 26 07:19:43 2003 @@ -199,12 +199,12 @@ printk("Using default partitions for %s\n",BOARD_NAME); npartitions=1; - parts = kmalloc(npartitions*sizeof(*parts)+strlen(name), GFP_KERNEL); - memzero(parts,npartitions*sizeof(*parts)+strlen(name)); + parts = kmalloc(npartitions*sizeof(*parts)+strlen(name)+1, GFP_KERNEL); if (!parts) { ret = -ENOMEM; goto out; } + memzero(parts,npartitions*sizeof(*parts)+strlen(name)); i=0; names = (char *)&parts[npartitions]; parts[i].name = names; @@ -218,10 +218,11 @@ parts[i].size = FLASH_SIZE-0x00180000; parts[i].offset = 0x00180000; #endif + ret = npartitions; out: *pparts = parts; - return npartitions; + return ret; } diff -Nru a/drivers/net/3c509.c b/drivers/net/3c509.c --- a/drivers/net/3c509.c Tue Mar 4 18:45:08 2003 +++ b/drivers/net/3c509.c Wed Mar 19 15:35:44 2003 @@ -208,7 +208,9 @@ static int el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data); #endif /* generic device remove for all device types */ +#if defined(CONFIG_EISA) || defined(CONFIG_MCA) static int el3_device_remove (struct device *device); +#endif #ifdef CONFIG_EISA struct eisa_device_id el3_eisa_ids[] = { diff -Nru a/drivers/net/bonding.c b/drivers/net/bonding.c --- a/drivers/net/bonding.c Sat Mar 8 14:50:38 2003 +++ b/drivers/net/bonding.c Fri Mar 28 21:14:07 2003 @@ -258,10 +258,47 @@ * - correct ifr_data reference. Update ifr_data reference * to mii_ioctl_data struct values to avoid confusion. * - * * 2002/11/22 - Bert Barbe * - Add support for multiple arp_ip_target * + * 2002/12/13 - Jay Vosburgh + * - Changed to allow text strings for mode and multicast, e.g., + * insmod bonding mode=active-backup. The numbers still work. + * One change: an invalid choice will cause module load failure, + * rather than the previous behavior of just picking one. + * - Minor cleanups; got rid of dup ctype stuff, atoi function + * + * 2003/02/07 - Jay Vosburgh + * - Added use_carrier module parameter that causes miimon to + * use netif_carrier_ok() test instead of MII/ETHTOOL ioctls. + * - Minor cleanups; consolidated ioctl calls to one function. + * + * 2003/02/07 - Tony Cureington + * - Fix bond_mii_monitor() logic error that could result in + * bonding round-robin mode ignoring links after failover/recovery + * + * 2003/03/17 - Jay Vosburgh + * - kmalloc fix (GFP_KERNEL to GFP_ATOMIC) reported by + * Shmulik dot Hen at intel.com. + * - Based on discussion on mailing list, changed use of + * update_slave_cnt(), created wrapper functions for adding/removing + * slaves, changed bond_xmit_xor() to check slave_cnt instead of + * checking slave and slave->dev (which only worked by accident). + * - Misc code cleanup: get arp_send() prototype from header file, + * add max_bonds to bonding.txt. + * + * 2003/03/18 - Tsippy Mendelson and + * Shmulik Hen + * - Make sure only bond_attach_slave() and bond_detach_slave() can + * manipulate the slave list, including slave_cnt, even when in + * bond_release_all(). + * - Fixed hang in bond_release() while traffic is running. + * netdev_set_master() must not be called from within the bond lock. + * + * 2003/03/18 - Tsippy Mendelson and + * Shmulik Hen + * - Fixed hang in bond_enslave(): netdev_set_master() must not be + * called from within the bond lock while traffic is running. */ #include @@ -278,6 +315,7 @@ #include #include #include +#include #include #include #include @@ -288,7 +326,7 @@ #include #include #include -#include +#include #include #include @@ -298,8 +336,8 @@ #include #include -#define DRV_VERSION "2.4.20-20021210" -#define DRV_RELDATE "December 10, 2002" +#define DRV_VERSION "2.5.65-20030320" +#define DRV_RELDATE "March 20, 2003" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" @@ -330,14 +368,30 @@ static int max_bonds = BOND_DEFAULT_MAX_BONDS; static int miimon = BOND_LINK_MON_INTERV; -static int mode = BOND_MODE_ROUNDROBIN; +static int use_carrier = 1; +static int bond_mode = BOND_MODE_ROUNDROBIN; static int updelay = 0; static int downdelay = 0; -#define BOND_MULTICAST_DISABLED 0 -#define BOND_MULTICAST_ACTIVE 1 -#define BOND_MULTICAST_ALL 2 -static int multicast = BOND_MULTICAST_ALL; +static char *mode = NULL; + +static struct bond_parm_tbl bond_mode_tbl[] = { +{ "balance-rr", BOND_MODE_ROUNDROBIN}, +{ "active-backup", BOND_MODE_ACTIVEBACKUP}, +{ "balance-xor", BOND_MODE_XOR}, +{ "broadcast", BOND_MODE_BROADCAST}, +{ NULL, -1}, +}; + +static int multicast_mode = BOND_MULTICAST_ALL; +static char *multicast = NULL; + +static struct bond_parm_tbl bond_mc_tbl[] = { +{ "disabled", BOND_MULTICAST_DISABLED}, +{ "active", BOND_MULTICAST_ACTIVE}, +{ "all", BOND_MULTICAST_ALL}, +{ NULL, -1}, +}; static int first_pass = 1; static struct bonding *these_bonds = NULL; @@ -347,25 +401,23 @@ MODULE_PARM_DESC(max_bonds, "Max number of bonded devices"); MODULE_PARM(miimon, "i"); MODULE_PARM_DESC(miimon, "Link check interval in milliseconds"); -MODULE_PARM(mode, "i"); +MODULE_PARM(use_carrier, "i"); +MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; 09 for off, 1 for on (default)"); +MODULE_PARM(mode, "s"); +MODULE_PARM_DESC(mode, "Mode of operation : 0 for round robin, 1 for active-backup, 2 for xor"); MODULE_PARM(arp_interval, "i"); MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds"); MODULE_PARM(arp_ip_target, "1-" __MODULE_STRING(MAX_ARP_IP_TARGETS) "s"); MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form"); -MODULE_PARM_DESC(mode, "Mode of operation : 0 for round robin, 1 for active-backup, 2 for xor"); MODULE_PARM(updelay, "i"); MODULE_PARM_DESC(updelay, "Delay before considering link up, in milliseconds"); MODULE_PARM(downdelay, "i"); MODULE_PARM_DESC(downdelay, "Delay before considering link down, in milliseconds"); MODULE_PARM(primary, "s"); MODULE_PARM_DESC(primary, "Primary network device to use"); -MODULE_PARM(multicast, "i"); +MODULE_PARM(multicast, "s"); MODULE_PARM_DESC(multicast, "Mode for multicast support : 0 for none, 1 for active slave, 2 for all slaves (default)"); -extern void arp_send( int type, int ptype, u32 dest_ip, struct net_device *dev, - u32 src_ip, unsigned char *dest_hw, unsigned char *src_hw, - unsigned char *target_hw); - static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *dev); static int bond_xmit_xor(struct sk_buff *skb, struct net_device *dev); static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *dev); @@ -408,18 +460,20 @@ static void arp_send_all(slave_t *slave) { - int i; - for ( i=0; (idev, - my_ip, arp_target_hw_addr, slave->dev->dev_addr, - arp_target_hw_addr); - } + int i; + + for (i = 0; (idev, + my_ip, arp_target_hw_addr, slave->dev->dev_addr, + arp_target_hw_addr); + } } -static const char *bond_mode(void) +static const char * +bond_mode_name(void) { - switch (mode) { + switch (bond_mode) { case BOND_MODE_ROUNDROBIN : return "load balancing (round-robin)"; case BOND_MODE_ACTIVEBACKUP : @@ -433,9 +487,10 @@ } } -static const char *multicast_mode(void) +static const char * +multicast_mode_name(void) { - switch(multicast) { + switch(multicast_mode) { case BOND_MULTICAST_DISABLED : return "disabled"; case BOND_MULTICAST_ACTIVE : @@ -464,6 +519,29 @@ slave->dev->flags &= ~IFF_NOARP; } +/* + * This function counts and verifies the the number of attached + * slaves, checking the count against the expected value (given that incr + * is either 1 or -1, for add or removal of a slave). Only + * bond_xmit_xor() uses the slave_cnt value, but this is still a good + * consistency check. + */ +static inline void +update_slave_cnt(bonding_t *bond, int incr) +{ + slave_t *slave = NULL; + int expect = bond->slave_cnt + incr; + + bond->slave_cnt = 0; + for (slave = bond->prev; slave != (slave_t*)bond; + slave = slave->prev) { + bond->slave_cnt++; + } + + if (expect != bond->slave_cnt) + BUG(); +} + /* * This function detaches the slave from the list . * WARNING: no check is made to verify if the slave effectively @@ -471,8 +549,11 @@ * Nothing is freed on return, structures are just unchained. * If the bond->current_slave pointer was pointing to , * it's replaced with slave->next, or if not applicable. + * + * bond->lock held by caller. */ -static slave_t *bond_detach_slave(bonding_t *bond, slave_t *slave) +static slave_t * +bond_detach_slave(bonding_t *bond, slave_t *slave) { if ((bond == NULL) || (slave == NULL) || ((void *)bond == (void *)slave)) { @@ -499,8 +580,7 @@ } write_unlock(&bond->ptrlock); } - } - else { + } else { slave->prev->next = slave->next; if (bond->prev == slave) { /* is this slave the last one ? */ bond->prev = slave->prev; @@ -515,9 +595,44 @@ write_unlock(&bond->ptrlock); } + update_slave_cnt(bond, -1); + return slave; } +static void +bond_attach_slave(struct bonding *bond, struct slave *new_slave) +{ + /* + * queue to the end of the slaves list, make the first element its + * successor, the last one its predecessor, and make it the bond's + * predecessor. + * + * Just to clarify, so future bonding driver hackers don't go through + * the same confusion stage I did trying to figure this out, the + * slaves are stored in a double linked circular list, sortof. + * In the ->next direction, the last slave points to the first slave, + * bypassing bond; only the slaves are in the ->next direction. + * In the ->prev direction, however, the first slave points to bond + * and bond points to the last slave. + * + * It looks like a circle with a little bubble hanging off one side + * in the ->prev direction only. + * + * When going through the list once, its best to start at bond->prev + * and go in the ->prev direction, testing for bond. Doing this + * in the ->next direction doesn't work. Trust me, I know this now. + * :) -mts 2002.03.14 + */ + new_slave->prev = bond->prev; + new_slave->prev->next = new_slave; + bond->prev = new_slave; + new_slave->next = bond->next; + + update_slave_cnt(bond, 1); +} + + /* * Less bad way to call ioctl from within the kernel; this needs to be * done some other way to get the call out of interrupt context. @@ -534,17 +649,31 @@ /* * if supports MII link status reporting, check its link status. * + * We either do MII/ETHTOOL ioctls, or check netif_carrier_ok(), + * depening upon the setting of the use_carrier parameter. + * * Return either BMSR_LSTATUS, meaning that the link is up (or we * can't tell and just pretend it is), or 0, meaning that the link is * down. + * + * If reporting is non-zero, instead of faking link up, return -1 if + * both ETHTOOL and MII ioctls fail (meaning the device does not + * support them). If use_carrier is set, return whatever it says. + * It'd be nice if there was a good way to tell if a driver supports + * netif_carrier, but there really isn't. */ -static u16 bond_check_dev_link(struct net_device *dev) +static int +bond_check_dev_link(struct net_device *dev, int reporting) { static int (* ioctl)(struct net_device *, struct ifreq *, int); struct ifreq ifr; struct mii_ioctl_data *mii; struct ethtool_value etool; + if (use_carrier) { + return netif_carrier_ok(dev) ? BMSR_LSTATUS : 0; + } + ioctl = dev->do_ioctl; if (ioctl) { /* TODO: set pointer to correct ioctl on a per team member */ @@ -576,18 +705,24 @@ if (IOCTL(dev, &ifr, SIOCETHTOOL) == 0) { if (etool.data == 1) { return BMSR_LSTATUS; - } - else { + } else { #ifdef BONDING_DEBUG printk(KERN_INFO - ":: SIOCETHTOOL shows failure \n"); + ":: SIOCETHTOOL shows link down \n"); #endif - return(0); + return 0; } } } - return BMSR_LSTATUS; /* spoof link up ( we can't check it) */ + + /* + * If reporting, report that either there's no dev->do_ioctl, + * or both SIOCGMIIREG and SIOCETHTOOL failed (meaning that we + * cannot report link status). If not reporting, pretend + * we're ok. + */ + return reporting ? -1 : BMSR_LSTATUS; } static u16 bond_check_mii_link(bonding_t *bond) @@ -622,7 +757,7 @@ init_timer(arp_timer); arp_timer->expires = jiffies + (arp_interval * HZ / 1000); arp_timer->data = (unsigned long)dev; - if (mode == BOND_MODE_ACTIVEBACKUP) { + if (bond_mode == BOND_MODE_ACTIVEBACKUP) { arp_timer->function = (void *)&activebackup_arp_monitor; } else { arp_timer->function = (void *)&loadbalance_arp_monitor; @@ -692,7 +827,7 @@ static void bond_mc_add(bonding_t *bond, void *addr, int alen) { slave_t *slave; - switch (multicast) { + switch (multicast_mode) { case BOND_MULTICAST_ACTIVE : /* write lock already acquired */ if (bond->current_slave != NULL) @@ -713,7 +848,7 @@ static void bond_mc_delete(bonding_t *bond, void *addr, int alen) { slave_t *slave; - switch (multicast) { + switch (multicast_mode) { case BOND_MULTICAST_ACTIVE : /* write lock already acquired */ if (bond->current_slave != NULL) @@ -769,7 +904,7 @@ static void bond_set_promiscuity(bonding_t *bond, int inc) { slave_t *slave; - switch (multicast) { + switch (multicast_mode) { case BOND_MULTICAST_ACTIVE : /* write lock already acquired */ if (bond->current_slave != NULL) @@ -790,7 +925,7 @@ static void bond_set_allmulti(bonding_t *bond, int inc) { slave_t *slave; - switch (multicast) { + switch (multicast_mode) { case BOND_MULTICAST_ACTIVE : /* write lock already acquired */ if (bond->current_slave != NULL) @@ -827,7 +962,7 @@ struct dev_mc_list *dmi; unsigned long flags = 0; - if (multicast == BOND_MULTICAST_DISABLED) + if (multicast_mode == BOND_MULTICAST_DISABLED) return; /* * Lock the private data for the master @@ -865,7 +1000,7 @@ /* save master's multicast list */ bond_mc_list_destroy (bond); - bond_mc_list_copy (master->mc_list, bond, GFP_KERNEL); + bond_mc_list_copy (master->mc_list, bond, GFP_ATOMIC); write_unlock_irqrestore(&bond->lock, flags); } @@ -878,7 +1013,7 @@ { struct dev_mc_list *dmi; - switch(multicast) { + switch(multicast_mode) { case BOND_MULTICAST_ACTIVE : if (bond->device->flags & IFF_PROMISC) { if (old != NULL && new != old) @@ -907,20 +1042,6 @@ } } -/* - * This function counts the number of attached - * slaves for use by bond_xmit_xor. - */ -static void update_slave_cnt(bonding_t *bond) -{ - slave_t *slave = NULL; - - bond->slave_cnt = 0; - for (slave = bond->prev; slave != (slave_t*)bond; slave = slave->prev) { - bond->slave_cnt++; - } -} - /* enslave device to bond device */ static int bond_enslave(struct net_device *master_dev, struct net_device *slave_dev) @@ -934,10 +1055,7 @@ struct dev_mc_list *dmi; struct in_ifaddr **ifap; struct in_ifaddr *ifa; - static int (* ioctl)(struct net_device *, struct ifreq *, int); - struct ifreq ifr; - struct ethtool_value etool; - int link_reporting = 0; + int link_reporting; if (master_dev == NULL || slave_dev == NULL) { return -ENODEV; @@ -949,14 +1067,12 @@ "Warning : no link monitoring support for %s\n", slave_dev->name); } - write_lock_irqsave(&bond->lock, flags); /* not running. */ if ((slave_dev->flags & IFF_UP) != IFF_UP) { #ifdef BONDING_DEBUG printk(KERN_CRIT "Error, slave_dev is not running\n"); #endif - write_unlock_irqrestore(&bond->lock, flags); return -EINVAL; } @@ -965,12 +1081,10 @@ #ifdef BONDING_DEBUG printk(KERN_CRIT "Error, Device was already enslaved\n"); #endif - write_unlock_irqrestore(&bond->lock, flags); return -EBUSY; } - if ((new_slave = kmalloc(sizeof(slave_t), GFP_KERNEL)) == NULL) { - write_unlock_irqrestore(&bond->lock, flags); + if ((new_slave = kmalloc(sizeof(slave_t), GFP_ATOMIC)) == NULL) { return -ENOMEM; } memset(new_slave, 0, sizeof(slave_t)); @@ -983,14 +1097,12 @@ #ifdef BONDING_DEBUG printk(KERN_CRIT "Error %d calling netdev_set_master\n", err); #endif - kfree(new_slave); - write_unlock_irqrestore(&bond->lock, flags); - return err; + goto err_free; } new_slave->dev = slave_dev; - if (multicast == BOND_MULTICAST_ALL) { + if (multicast_mode == BOND_MULTICAST_ALL) { /* set promiscuity level to new slave */ if (master_dev->flags & IFF_PROMISC) dev_set_promiscuity(slave_dev, 1); @@ -1004,64 +1116,24 @@ dev_mc_add (slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); } - /* - * queue to the end of the slaves list, make the first element its - * successor, the last one its predecessor, and make it the bond's - * predecessor. - * - * Just to clarify, so future bonding driver hackers don't go through - * the same confusion stage I did trying to figure this out, the - * slaves are stored in a double linked circular list, sortof. - * In the ->next direction, the last slave points to the first slave, - * bypassing bond; only the slaves are in the ->next direction. - * In the ->prev direction, however, the first slave points to bond - * and bond points to the last slave. - * - * It looks like a circle with a little bubble hanging off one side - * in the ->prev direction only. - * - * When going through the list once, its best to start at bond->prev - * and go in the ->prev direction, testing for bond. Doing this - * in the ->next direction doesn't work. Trust me, I know this now. - * :) -mts 2002.03.14 - */ - new_slave->prev = bond->prev; - new_slave->prev->next = new_slave; - bond->prev = new_slave; - new_slave->next = bond->next; - + write_lock_irqsave(&bond->lock, flags); + + bond_attach_slave(bond, new_slave); new_slave->delay = 0; new_slave->link_failure_count = 0; - if (miimon > 0) { - /* if the network driver for the slave does not support - * ETHTOOL/MII link status reporting, warn the user of this - */ - if ((ioctl = slave_dev->do_ioctl) != NULL) { - etool.cmd = ETHTOOL_GLINK; - ifr.ifr_data = (char*)&etool; - if (IOCTL(slave_dev, &ifr, SIOCETHTOOL) == 0) { - link_reporting = 1; - } - else { - if (IOCTL(slave_dev, &ifr, SIOCGMIIPHY) == 0) { - /* Yes, the mii is overlaid on the - * ifreq.ifr_ifru - */ - ((struct mii_ioctl_data*) - (&ifr.ifr_data))->reg_num = 1; - if (IOCTL(slave_dev, &ifr, SIOCGMIIREG) - == 0) { - link_reporting = 1; - } - } - } - } + if (miimon > 0 && !use_carrier) { + link_reporting = bond_check_dev_link(slave_dev, 1); - if ((link_reporting == 0) && (arp_interval == 0)) { - /* miimon is set but a bonded network driver does - * not support ETHTOOL/MII and arp_interval is - * not set + if ((link_reporting == -1) && (arp_interval == 0)) { + /* + * miimon is set but a bonded network driver + * does not support ETHTOOL/MII and + * arp_interval is not set. Note: if + * use_carrier is enabled, we will never go + * here (because netif_carrier is always + * supported); thus, we don't need to change + * the messages for netif_carrier. */ printk(KERN_ERR "bond_enslave(): MII and ETHTOOL support not " @@ -1070,8 +1142,7 @@ "not specified, thus bonding will not detect " "link failures! see bonding.txt for details.\n", slave_dev->name); - } - else if (link_reporting == 0) { + } else if (link_reporting == -1) { /* unable get link status using mii/ethtool */ printk(KERN_WARNING "bond_enslave: can't get link status from " @@ -1085,7 +1156,7 @@ /* check for initial state */ if ((miimon <= 0) || - (bond_check_dev_link(slave_dev) == BMSR_LSTATUS)) { + (bond_check_dev_link(slave_dev, 0) == BMSR_LSTATUS)) { #ifdef BONDING_DEBUG printk(KERN_CRIT "Initial state of slave_dev is BOND_LINK_UP\n"); #endif @@ -1106,7 +1177,7 @@ * since we guarantee that current_slave always point to the last * usable interface, we just have to verify this interface's flag. */ - if (mode == BOND_MODE_ACTIVEBACKUP) { + if (bond_mode == BOND_MODE_ACTIVEBACKUP) { if (((bond->current_slave == NULL) || (bond->current_slave->dev->flags & IFF_NOARP)) && (new_slave->link == BOND_LINK_UP)) { @@ -1145,8 +1216,6 @@ bond->current_slave = new_slave; } - update_slave_cnt(bond); - write_unlock_irqrestore(&bond->lock, flags); /* @@ -1187,7 +1256,11 @@ new_slave->state == BOND_STATE_ACTIVE ? "n active" : " backup", new_slave->link == BOND_LINK_UP ? "n up" : " down"); + /* enslave is successful */ return 0; +err_free: + kfree(new_slave); + return err; } /* @@ -1276,13 +1349,13 @@ } else { printk (" but could not find any %s interface.\n", - (mode == BOND_MODE_ACTIVEBACKUP) ? "backup":"other"); + (bond_mode == BOND_MODE_ACTIVEBACKUP) ? "backup":"other"); write_lock(&bond->ptrlock); bond->current_slave = (slave_t *)NULL; write_unlock(&bond->ptrlock); return NULL; /* still no slave, return NULL */ } - } else if (mode == BOND_MODE_ACTIVEBACKUP) { + } else if (bond_mode == BOND_MODE_ACTIVEBACKUP) { /* make sure oldslave doesn't send arps - this could * cause a ping-pong effect between interfaces since they * would be able to tx arps - in active backup only one @@ -1311,7 +1384,7 @@ if (IS_UP(newslave->dev)) { if (newslave->link == BOND_LINK_UP) { /* this one is immediately usable */ - if (mode == BOND_MODE_ACTIVEBACKUP) { + if (bond_mode == BOND_MODE_ACTIVEBACKUP) { bond_set_slave_active_flags(newslave); bond_mc_update(bond, newslave, oldslave); printk (" and making interface %s the active one.\n", @@ -1358,8 +1431,8 @@ return bestslave; } - if ((mode == BOND_MODE_ACTIVEBACKUP) && - (multicast == BOND_MULTICAST_ACTIVE) && + if ((bond_mode == BOND_MODE_ACTIVEBACKUP) && + (multicast_mode == BOND_MULTICAST_ACTIVE) && (oldslave != NULL)) { /* flush bonds (master's) mc_list from oldslave since it wasn't * updated (and deleted) above @@ -1374,7 +1447,7 @@ } printk (" but could not find any %s interface.\n", - (mode == BOND_MODE_ACTIVEBACKUP) ? "backup":"other"); + (bond_mode == BOND_MODE_ACTIVEBACKUP) ? "backup":"other"); /* absolutely nothing found. let's return NULL */ write_lock(&bond->ptrlock); @@ -1406,16 +1479,14 @@ bond = (struct bonding *) master->priv; - write_lock_irqsave(&bond->lock, flags); - /* master already enslaved, or slave not enslaved, or no slave for this master */ if ((master->flags & IFF_SLAVE) || !(slave->flags & IFF_SLAVE)) { printk (KERN_DEBUG "%s: cannot release %s.\n", master->name, slave->name); - write_unlock_irqrestore(&bond->lock, flags); return -EINVAL; } + write_lock_irqsave(&bond->lock, flags); bond->current_arp_slave = NULL; our_slave = (slave_t *)bond; old_current = bond->current_slave; @@ -1434,60 +1505,62 @@ } else { printk(".\n"); } - - /* release the slave from its bond */ - - if (multicast == BOND_MULTICAST_ALL) { - /* flush master's mc_list from slave */ - bond_mc_list_flush (slave, master); - - /* unset promiscuity level from slave */ - if (master->flags & IFF_PROMISC) - dev_set_promiscuity(slave, -1); - - /* unset allmulti level from slave */ - if (master->flags & IFF_ALLMULTI) - dev_set_allmulti(slave, -1); - } - - netdev_set_master(slave, NULL); - - /* only restore its RUNNING flag if monitoring set it down */ - if (slave->flags & IFF_UP) { - slave->flags |= IFF_RUNNING; - } - - if (slave->flags & IFF_NOARP || - bond->current_slave != NULL) { - dev_close(slave); - our_slave->original_flags &= ~IFF_UP; - } - - bond_restore_slave_flags(our_slave); - kfree(our_slave); - + if (bond->current_slave == NULL) { printk(KERN_INFO "%s: now running without any active interface !\n", master->name); } - update_slave_cnt(bond); - if (bond->primary_slave == our_slave) { bond->primary_slave = NULL; } - write_unlock_irqrestore(&bond->lock, flags); - return 0; /* deletion OK */ + break; } - } - /* if we get here, it's because the device was not found */ + } write_unlock_irqrestore(&bond->lock, flags); + + if (our_slave == (slave_t *)bond) { + /* if we get here, it's because the device was not found */ + printk (KERN_INFO "%s: %s not enslaved\n", master->name, slave->name); + return -EINVAL; + } - printk (KERN_INFO "%s: %s not enslaved\n", master->name, slave->name); - return -EINVAL; + /* undo settings and restore original values */ + + if (multicast_mode == BOND_MULTICAST_ALL) { + /* flush master's mc_list from slave */ + bond_mc_list_flush (slave, master); + + /* unset promiscuity level from slave */ + if (master->flags & IFF_PROMISC) + dev_set_promiscuity(slave, -1); + + /* unset allmulti level from slave */ + if (master->flags & IFF_ALLMULTI) + dev_set_allmulti(slave, -1); + } + + netdev_set_master(slave, NULL); + + /* only restore its RUNNING flag if monitoring set it down */ + if (slave->flags & IFF_UP) { + slave->flags |= IFF_RUNNING; + } + + if (slave->flags & IFF_NOARP || + bond->current_slave != NULL) { + dev_close(slave); + our_slave->original_flags &= ~IFF_UP; + } + + bond_restore_slave_flags(our_slave); + + kfree(our_slave); + + return 0; /* deletion OK */ } /* @@ -1510,13 +1583,15 @@ bond = (struct bonding *) master->priv; bond->current_arp_slave = NULL; + bond->current_slave = NULL; + bond->primary_slave = NULL; while ((our_slave = bond->prev) != (slave_t *)bond) { slave_dev = our_slave->dev; - bond->prev = our_slave->prev; + bond_detach_slave(bond, our_slave); - if (multicast == BOND_MULTICAST_ALL - || (multicast == BOND_MULTICAST_ACTIVE + if (multicast_mode == BOND_MULTICAST_ALL + || (multicast_mode == BOND_MULTICAST_ACTIVE && bond->current_slave == our_slave)) { /* flush master's mc_list from slave */ @@ -1533,6 +1608,10 @@ kfree(our_slave); + /* + * Can be safely called from inside the bond lock + * since traffic and timers have already stopped + */ netdev_set_master(slave_dev, NULL); /* only restore its RUNNING flag if monitoring set it down */ @@ -1543,10 +1622,6 @@ dev_close(slave_dev); } - bond->current_slave = NULL; - bond->next = (slave_t *)bond; - bond->slave_cnt = 0; - bond->primary_slave = NULL; printk (KERN_INFO "%s: released all slaves\n", master->name); return 0; @@ -1579,9 +1654,9 @@ /* use updelay+1 to match an UP slave even when updelay is 0 */ int mindelay = updelay + 1; struct net_device *dev = slave->dev; - u16 link_state; + int link_state; - link_state = bond_check_dev_link(dev); + link_state = bond_check_dev_link(dev, 0); switch (slave->link) { case BOND_LINK_UP: /* the link was up */ @@ -1608,7 +1683,7 @@ "%s, disabling it in %d ms.\n", master->name, IS_UP(dev) - ? ((mode == BOND_MODE_ACTIVEBACKUP) + ? ((bond_mode == BOND_MODE_ACTIVEBACKUP) ? ((slave == oldcurrent) ? "active " : "backup ") : "") @@ -1628,7 +1703,7 @@ slave->link = BOND_LINK_DOWN; /* in active/backup mode, we must completely disable this interface */ - if (mode == BOND_MODE_ACTIVEBACKUP) { + if (bond_mode == BOND_MODE_ACTIVEBACKUP) { bond_set_slave_inactive_flags(slave); } printk(KERN_INFO @@ -1708,14 +1783,12 @@ slave->link = BOND_LINK_UP; slave->jiffies = jiffies; - if ( (mode == BOND_MODE_ACTIVEBACKUP) - || (slave != bond->primary_slave) ) { - /* prevent it from being the active one */ - slave->state = BOND_STATE_BACKUP; - } - else { + if (bond_mode != BOND_MODE_ACTIVEBACKUP) { /* make it immediately active */ slave->state = BOND_STATE_ACTIVE; + } else if (slave != bond->primary_slave) { + /* prevent it from being the active one */ + slave->state = BOND_STATE_BACKUP; } printk(KERN_INFO @@ -1775,7 +1848,7 @@ bestslave->jiffies = jiffies; } - if (mode == BOND_MODE_ACTIVEBACKUP) { + if (bond_mode == BOND_MODE_ACTIVEBACKUP) { bond_set_slave_active_flags(bestslave); bond_mc_update(bond, bestslave, NULL); } else { @@ -2171,19 +2244,6 @@ read_unlock_irqrestore(&bond->lock, flags); } - -#define isdigit(c) (c >= '0' && c <= '9') -__inline static int atoi( char **s) -{ -int i = 0; -while (isdigit(**s)) - i = i*20 + *((*s)++) - '0'; -return i; -} - -#define isascii(c) (((unsigned char)(c))<=0x7f) -#define LF 0xA -#define isspace(c) (c==' ' || c==' '|| c==LF) typedef uint32_t in_addr_t; int @@ -2279,7 +2339,7 @@ slave_t *slave; unsigned long flags; - info->bond_mode = mode; + info->bond_mode = bond_mode; info->num_slaves = 0; info->miimon = miimon; @@ -2416,7 +2476,7 @@ break; case BOND_CHANGE_ACTIVE_OLD: case SIOCBONDCHANGEACTIVE: - if (mode == BOND_MODE_ACTIVEBACKUP) { + if (bond_mode == BOND_MODE_ACTIVEBACKUP) { ret = bond_change_active(master_dev, slave_dev); } else { @@ -2567,20 +2627,13 @@ slave = bond->prev; /* we're at the root, get the first slave */ - if ((slave == NULL) || (slave->dev == NULL)) { + if (bond->slave_cnt == 0) { /* no suitable interface, frame not sent */ dev_kfree_skb(skb); read_unlock_irqrestore(&bond->lock, flags); return 0; } - if (bond->slave_cnt == 0) { - /* no slaves in the bond, frame not sent */ - dev_kfree_skb(skb); - read_unlock_irqrestore(&bond->lock, flags); - return 0; - } - slave_no = (data->h_dest[5]^slave->dev->dev_addr[5]) % bond->slave_cnt; while ( (slave_no > 0) && (slave != (slave_t *)bond) ) { @@ -2642,7 +2695,7 @@ * receive packets to stay up, and the only ones they receive are * broadcasts. */ - if ( (mode != BOND_MODE_ACTIVEBACKUP) && + if ( (bond_mode != BOND_MODE_ACTIVEBACKUP) && (arp_ip_count == 1) && (arp_interval > 0) && (arp_target_hw_addr == NULL) && (skb->protocol == __constant_htons(ETH_P_IP) ) ) { @@ -2743,9 +2796,10 @@ */ link = bond_check_mii_link(bond); - len += sprintf(buf + len, "Bonding Mode: %s\n", bond_mode()); + len += sprintf(buf + len, "Bonding Mode: %s\n", + bond_mode_name()); - if (mode == BOND_MODE_ACTIVEBACKUP) { + if (bond_mode == BOND_MODE_ACTIVEBACKUP) { read_lock_irqsave(&bond->lock, flags); read_lock(&bond->ptrlock); if (bond->current_slave != NULL) { @@ -2766,7 +2820,8 @@ updelay * miimon); len += sprintf(buf + len, "Down Delay (ms): %d\n", downdelay * miimon); - len += sprintf(buf + len, "Multicast Mode: %s\n", multicast_mode()); + len += sprintf(buf + len, "Multicast Mode: %s\n", + multicast_mode_name()); read_lock_irqsave(&bond->lock, flags); for (slave = bond->prev; slave != (slave_t *)bond; @@ -2884,16 +2939,21 @@ dev->priv = bond; /* Initialize the device structure. */ - if (mode == BOND_MODE_ACTIVEBACKUP) { + switch (bond_mode) { + case BOND_MODE_ACTIVEBACKUP: dev->hard_start_xmit = bond_xmit_activebackup; - } else if (mode == BOND_MODE_ROUNDROBIN) { + break; + case BOND_MODE_ROUNDROBIN: dev->hard_start_xmit = bond_xmit_roundrobin; - } else if (mode == BOND_MODE_XOR) { + break; + case BOND_MODE_XOR: dev->hard_start_xmit = bond_xmit_xor; - } else if (mode == BOND_MODE_BROADCAST) { + break; + case BOND_MODE_BROADCAST: dev->hard_start_xmit = bond_xmit_broadcast; - } else { - printk(KERN_ERR "Unknown bonding mode %d\n", mode); + break; + default: + printk(KERN_ERR "Unknown bonding mode %d\n", bond_mode); kfree(bond->stats); kfree(bond); return -EINVAL; @@ -2926,7 +2986,7 @@ } else { printk("out MII link monitoring"); } - printk(", in %s mode.\n", bond_mode()); + printk(", in %s mode.\n", bond_mode_name()); printk(KERN_INFO "%s registered with", dev->name); if (arp_interval > 0) { @@ -2986,6 +3046,28 @@ } */ +/* + * Convert string input module parms. Accept either the + * number of the mode or its string name. + */ +static inline int +bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl) +{ + int i; + + for (i = 0; tbl[i].modename != NULL; i++) { + if ((isdigit(*mode_arg) && + tbl[i].mode == simple_strtol(mode_arg, NULL, 0)) || + (0 == strncmp(mode_arg, tbl[i].modename, + strlen(tbl[i].modename)))) { + return tbl[i].mode; + } + } + + return -1; +} + + static int __init bonding_init(void) { int no; @@ -2996,6 +3078,29 @@ printk(KERN_INFO "%s", version); + /* + * Convert string parameters. + */ + if (mode) { + bond_mode = bond_parse_parm(mode, bond_mode_tbl); + if (bond_mode == -1) { + printk(KERN_WARNING + "bonding_init(): Invalid bonding mode \"%s\"\n", + mode == NULL ? "NULL" : mode); + return -EINVAL; + } + } + + if (multicast) { + multicast_mode = bond_parse_parm(multicast, bond_mc_tbl); + if (multicast_mode == -1) { + printk(KERN_WARNING + "bonding_init(): Invalid multicast mode \"%s\"\n", + multicast == NULL ? "NULL" : multicast); + return -EINVAL; + } + } + if (max_bonds < 1 || max_bonds > INT_MAX) { printk(KERN_WARNING "bonding_init(): max_bonds (%d) not in range %d-%d, " @@ -3125,27 +3230,17 @@ "link failures! see bonding.txt for details.\n"); } - if ((primary != NULL) && (mode != BOND_MODE_ACTIVEBACKUP)){ + if ((primary != NULL) && (bond_mode != BOND_MODE_ACTIVEBACKUP)){ /* currently, using a primary only makes sence * in active backup mode */ printk(KERN_WARNING "bonding_init(): %s primary device specified but has " " no effect in %s mode\n", - primary, bond_mode()); + primary, bond_mode_name()); primary = NULL; } - - if (multicast != BOND_MULTICAST_DISABLED && - multicast != BOND_MULTICAST_ACTIVE && - multicast != BOND_MULTICAST_ALL) { - printk(KERN_WARNING - "bonding_init(): unknown multicast module " - "parameter (%d), multicast reset to %d\n", - multicast, BOND_MULTICAST_ALL); - multicast = BOND_MULTICAST_ALL; - } for (no = 0; no < max_bonds; no++) { dev_bond->init = bond_init; diff -Nru a/drivers/net/gt96100eth.c b/drivers/net/gt96100eth.c --- a/drivers/net/gt96100eth.c Thu Nov 21 14:06:11 2002 +++ b/drivers/net/gt96100eth.c Mon Jan 6 11:00:54 2003 @@ -758,19 +758,6 @@ goto free_region; } - /* Initialize our private structure. */ - if (dev->priv == NULL) { - - gp = (struct gt96100_private *)kmalloc(sizeof(*gp), - GFP_KERNEL); - if (gp == NULL) { - retval = -ENOMEM; - goto free_region; - } - - dev->priv = gp; - } - gp = dev->priv; memset(gp, 0, sizeof(*gp)); // clear it @@ -854,8 +841,6 @@ free_region: release_region(gtif->iobase, GT96100_ETH_IO_SIZE); unregister_netdev(dev); - if (dev->priv != NULL) - kfree (dev->priv); kfree (dev); err("%s failed. Returns %d\n", __FUNCTION__, retval); return retval; @@ -1601,8 +1586,6 @@ (struct gt96100_private *)gtif->dev->priv; release_region(gtif->iobase, gp->io_size); unregister_netdev(gtif->dev); - if (gtif->dev->priv != NULL) - kfree (gtif->dev->priv); kfree (gtif->dev); } } diff -Nru a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c --- a/drivers/net/irda/irda-usb.c Tue Feb 25 10:11:58 2003 +++ b/drivers/net/irda/irda-usb.c Thu Feb 20 07:22:52 2003 @@ -402,7 +402,7 @@ usb_fill_bulk_urb(urb, self->usbdev, usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), - skb->data, IRDA_USB_MAX_MTU, + skb->data, IRDA_SKB_MAX_MTU, write_bulk_callback, skb); urb->transfer_buffer_length = skb->len; /* Note : unlink *must* be Asynchronous because of the code in @@ -442,6 +442,9 @@ * would be lost in the noise - Jean II */ diff += IU_USB_MIN_RTT; #endif /* IU_USB_MIN_RTT */ + /* If the usec counter did wraparound, the diff will + * go negative (tv_usec is a long), so we need to + * correct it by one second. Jean II */ if (diff < 0) diff += 1000000; @@ -701,30 +704,11 @@ IRDA_DEBUG(2, "%s()\n", __FUNCTION__); - /* Check that we have an urb */ - if (!urb) { - WARNING("%s(), Bug : urb == NULL\n", __FUNCTION__); - return; - } - - /* Allocate new skb if it has not been recycled */ - if (!skb) { - skb = dev_alloc_skb(IRDA_USB_MAX_MTU + 1); - if (!skb) { - /* If this ever happen, we are in deep s***. - * Basically, the Rx path will stop... */ - WARNING("%s(), Failed to allocate Rx skb\n", __FUNCTION__); - return; - } - } else { - /* Reset recycled skb */ - skb->data = skb->tail = skb->head; - skb->len = 0; - } - /* Make sure IP header get aligned (IrDA header is 5 bytes ) */ - skb_reserve(skb, 1); + /* This should never happen */ + ASSERT(skb != NULL, return;); + ASSERT(urb != NULL, return;); - /* Save ourselves */ + /* Save ourselves in the skb */ cb = (struct irda_skb_cb *) skb->cb; cb->context = self; @@ -758,8 +742,10 @@ struct sk_buff *skb = (struct sk_buff *) urb->context; struct irda_usb_cb *self; struct irda_skb_cb *cb; - struct sk_buff *new; - + struct sk_buff *newskb; + struct sk_buff *dataskb; + int docopy; + IRDA_DEBUG(2, "%s(), len=%d\n", __FUNCTION__, urb->actual_length); /* Find ourselves */ @@ -808,39 +794,56 @@ */ do_gettimeofday(&self->stamp); - /* Fix skb, and remove USB-IrDA header */ - skb_put(skb, urb->actual_length); - skb_pull(skb, USB_IRDA_HEADER); - - /* Don't waste a lot of memory on small IrDA frames */ - if (skb->len < RX_COPY_THRESHOLD) { - new = dev_alloc_skb(skb->len+1); - if (!new) { - self->stats.rx_dropped++; - goto done; - } + /* Check if we need to copy the data to a new skb or not. + * For most frames, we use ZeroCopy and pass the already + * allocated skb up the stack. + * If the frame is small, it is more efficient to copy it + * to save memory (copy will be fast anyway - that's + * called Rx-copy-break). Jean II */ + docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD); + + /* Allocate a new skb */ + newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU); + if (!newskb) { + self->stats.rx_dropped++; + /* We could deliver the current skb, but this would stall + * the Rx path. Better drop the packet... Jean II */ + goto done; + } + + /* Make sure IP header get aligned (IrDA header is 5 bytes) */ + /* But IrDA-USB header is 1 byte. Jean II */ + //skb_reserve(newskb, USB_IRDA_HEADER - 1); - /* Make sure IP header get aligned (IrDA header is 5 bytes) */ - skb_reserve(new, 1); - + if(docopy) { /* Copy packet, so we can recycle the original */ - memcpy(skb_put(new, skb->len), skb->data, skb->len); - /* We will cleanup the skb in irda_usb_submit() */ + memcpy(newskb->data, skb->data, urb->actual_length); + /* Deliver this new skb */ + dataskb = newskb; + /* And hook the old skb to the URB + * Note : we don't need to "clean up" the old skb, + * as we never touched it. Jean II */ } else { - /* Deliver the original skb */ - new = skb; - skb = NULL; + /* We are using ZeroCopy. Deliver old skb */ + dataskb = skb; + /* And hook the new skb to the URB */ + skb = newskb; } - - self->stats.rx_bytes += new->len; - self->stats.rx_packets++; + + /* Set proper length on skb & remove USB-IrDA header */ + skb_put(dataskb, urb->actual_length); + skb_pull(dataskb, USB_IRDA_HEADER); /* Ask the networking layer to queue the packet for the IrDA stack */ - new->dev = self->netdev; - new->mac.raw = new->data; - new->protocol = htons(ETH_P_IRDA); - netif_rx(new); - self->netdev->last_rx = jiffies; + dataskb->dev = self->netdev; + dataskb->mac.raw = dataskb->data; + dataskb->protocol = htons(ETH_P_IRDA); + netif_rx(dataskb); + + /* Keep stats up to date */ + self->stats.rx_bytes += dataskb->len; + self->stats.rx_packets++; + self->netdev->last_rx = jiffies; done: /* Note : at this point, the URB we've just received (urb) @@ -973,8 +976,17 @@ /* Now that we can pass data to IrLAP, allow the USB layer * to send us some data... */ - for (i = 0; i < IU_MAX_ACTIVE_RX_URBS; i++) - irda_usb_submit(self, NULL, self->rx_urb[i]); + for (i = 0; i < IU_MAX_ACTIVE_RX_URBS; i++) { + struct sk_buff *skb = dev_alloc_skb(IRDA_SKB_MAX_MTU); + if (!skb) { + /* If this ever happen, we are in deep s***. + * Basically, we can't start the Rx path... */ + WARNING("%s(), Failed to allocate Rx skb\n", __FUNCTION__); + return -1; + } + //skb_reserve(newskb, USB_IRDA_HEADER - 1); + irda_usb_submit(self, skb, self->rx_urb[i]); + } /* Ready to play !!! */ return 0; @@ -1167,9 +1179,6 @@ spin_lock_init(&self->lock); irda_usb_init_qos(self); - - /* Initialise list of skb beeing curently transmitted */ - self->tx_list = hashbin_new(HB_NOLOCK); /* unused */ /* Allocate the buffer for speed changes */ /* Don't change this buffer size and allocation without doing @@ -1228,8 +1237,6 @@ self->netdev = NULL; rtnl_unlock(); } - /* Delete all pending skbs */ - hashbin_delete(self->tx_list, (FREE_FUNC) &dev_kfree_skb_any); /* Remove the speed buffer */ if (self->speed_buff != NULL) { kfree(self->speed_buff); @@ -1492,8 +1499,10 @@ case 0: break; case -EPIPE: /* -EPIPE = -32 */ - usb_clear_halt(dev, usb_sndctrlpipe(dev, 0)); - IRDA_DEBUG(0, "%s(), Clearing stall on control interface\n", __FUNCTION__); + /* Martin Diehl says if we get a -EPIPE we should + * be fine and we don't need to do a usb_clear_halt(). + * - Jean II */ + IRDA_DEBUG(0, "%s(), Received -EPIPE, ignoring...\n", __FUNCTION__); break; default: IRDA_DEBUG(0, "%s(), Unknown error %d\n", __FUNCTION__, ret); diff -Nru a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c --- a/drivers/net/irda/sir_dev.c Tue Feb 25 02:45:00 2003 +++ b/drivers/net/irda/sir_dev.c Thu Feb 20 03:11:44 2003 @@ -223,25 +223,24 @@ } /* Read the characters into the buffer */ - while (count--) { - if (likely(atomic_read(&dev->enable_rx))) { + if (likely(atomic_read(&dev->enable_rx))) { + while (count--) /* Unwrap and destuff one byte */ async_unwrap_char(dev->netdev, &dev->stats, - &dev->rx_buff, *cp++); - } - else { + &dev->rx_buff, *cp++); + } else { + while (count--) { /* rx not enabled: save the raw bytes and never * trigger any netif_rx. The received bytes are flushed * later when we re-enable rx but might be read meanwhile * by the dongle driver. */ dev->rx_buff.data[dev->rx_buff.len++] = *cp++; - } - /* What should we do when the buffer is full? */ - if (unlikely(dev->rx_buff.len == dev->rx_buff.truesize)) - dev->rx_buff.len = 0; - + /* What should we do when the buffer is full? */ + if (unlikely(dev->rx_buff.len == dev->rx_buff.truesize)) + dev->rx_buff.len = 0; + } } return 0; @@ -423,19 +422,24 @@ static int sirdev_alloc_buffers(struct sir_dev *dev) { - dev->rx_buff.truesize = SIRBUF_ALLOCSIZE; dev->tx_buff.truesize = SIRBUF_ALLOCSIZE; + dev->rx_buff.truesize = IRDA_SKB_MAX_MTU; - dev->rx_buff.head = kmalloc(dev->rx_buff.truesize, GFP_KERNEL); - if (dev->rx_buff.head == NULL) + /* Bootstrap ZeroCopy Rx */ + dev->rx_buff.skb = __dev_alloc_skb(dev->rx_buff.truesize, GFP_KERNEL); + if (dev->rx_buff.skb == NULL) return -ENOMEM; - memset(dev->rx_buff.head, 0, dev->rx_buff.truesize); + skb_reserve(dev->rx_buff.skb, 1); + dev->rx_buff.head = dev->rx_buff.skb->data; + /* No need to memset the buffer, unless you are really pedantic */ dev->tx_buff.head = kmalloc(dev->tx_buff.truesize, GFP_KERNEL); if (dev->tx_buff.head == NULL) { - kfree(dev->rx_buff.head); + kfree_skb(dev->rx_buff.skb); + dev->rx_buff.skb = NULL; dev->rx_buff.head = NULL; return -ENOMEM; + /* Hu ??? This should not be here, Martin ? */ memset(dev->tx_buff.head, 0, dev->tx_buff.truesize); } @@ -451,11 +455,12 @@ static void sirdev_free_buffers(struct sir_dev *dev) { - if (dev->rx_buff.head) - kfree(dev->rx_buff.head); + if (dev->rx_buff.skb) + kfree_skb(dev->rx_buff.skb); if (dev->tx_buff.head) kfree(dev->tx_buff.head); dev->rx_buff.head = dev->tx_buff.head = NULL; + dev->rx_buff.skb = NULL; } static int sirdev_open(struct net_device *ndev) diff -Nru a/drivers/net/mace.c b/drivers/net/mace.c --- a/drivers/net/mace.c Thu Nov 7 10:18:09 2002 +++ b/drivers/net/mace.c Wed Feb 12 14:07:11 2003 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -63,6 +64,7 @@ int chipid; struct device_node* of_node; struct net_device *next_mace; + spinlock_t lock; }; /* @@ -203,6 +205,7 @@ memset((char *) mp->tx_cmds, 0, (NCMDS_TX*N_TX_RING + N_RX_RING + 2) * sizeof(struct dbdma_cmd)); init_timer(&mp->tx_timeout); + spin_lock_init(&mp->lock); mp->timeout_active = 0; if (port_aaui >= 0) @@ -351,14 +354,14 @@ volatile struct mace *mb = mp->mace; unsigned long flags; - save_flags(flags); cli(); + spin_lock_irqsave(&mp->lock, flags); __mace_set_address(dev, addr); /* note: setting ADDRCHG clears ENRCV */ out_8(&mb->maccc, mp->maccc); - restore_flags(flags); + spin_unlock_irqrestore(&mp->lock, flags); return 0; } @@ -473,10 +476,7 @@ static inline void mace_set_timeout(struct net_device *dev) { struct mace_data *mp = (struct mace_data *) dev->priv; - unsigned long flags; - save_flags(flags); - cli(); if (mp->timeout_active) del_timer(&mp->tx_timeout); mp->tx_timeout.expires = jiffies + TX_TIMEOUT; @@ -484,7 +484,6 @@ mp->tx_timeout.data = (unsigned long) dev; add_timer(&mp->tx_timeout); mp->timeout_active = 1; - restore_flags(flags); } static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev) @@ -496,7 +495,7 @@ int fill, next, len; /* see if there's a free slot in the tx ring */ - save_flags(flags); cli(); + spin_lock_irqsave(&mp->lock, flags); fill = mp->tx_fill; next = fill + 1; if (next >= N_TX_RING) @@ -504,10 +503,10 @@ if (next == mp->tx_empty) { netif_stop_queue(dev); mp->tx_fullup = 1; - restore_flags(flags); + spin_unlock_irqrestore(&mp->lock, flags); return 1; /* can't take it at the moment */ } - restore_flags(flags); + spin_unlock_irqrestore(&mp->lock, flags); /* partially fill in the dma command block */ len = skb->len; @@ -524,8 +523,7 @@ out_le16(&np->command, DBDMA_STOP); /* poke the tx dma channel */ - save_flags(flags); - cli(); + spin_lock_irqsave(&mp->lock, flags); mp->tx_fill = next; if (!mp->tx_bad_runt && mp->tx_active < MAX_TX_ACTIVE) { out_le16(&cp->xfer_status, 0); @@ -538,7 +536,7 @@ next = 0; if (next == mp->tx_empty) netif_stop_queue(dev); - restore_flags(flags); + spin_unlock_irqrestore(&mp->lock, flags); return 0; } @@ -556,7 +554,9 @@ volatile struct mace *mb = mp->mace; int i, j; u32 crc; + unsigned long flags; + spin_lock_irqsave(&mp->lock, flags); mp->maccc &= ~PROM; if (dev->flags & IFF_PROMISC) { mp->maccc |= PROM; @@ -598,6 +598,7 @@ } /* reset maccc */ out_8(&mb->maccc, mp->maccc); + spin_unlock_irqrestore(&mp->lock, flags); } static void mace_handle_misc_intrs(struct mace_data *mp, int intr) @@ -630,8 +631,10 @@ volatile struct dbdma_cmd *cp; int intr, fs, i, stat, x; int xcount, dstat; + unsigned long flags; /* static int mace_last_fs, mace_last_xcount; */ + spin_lock_irqsave(&mp->lock, flags); intr = in_8(&mb->ir); /* read interrupt register */ in_8(&mb->xmtrc); /* get retries */ mace_handle_misc_intrs(mp, intr); @@ -761,6 +764,7 @@ out_le32(&td->control, ((RUN|WAKE) << 16) + (RUN|WAKE)); mace_set_timeout(dev); } + spin_unlock_irqrestore(&mp->lock, flags); } static void mace_tx_timeout(unsigned long data) @@ -774,8 +778,7 @@ unsigned long flags; int i; - save_flags(flags); - cli(); + spin_lock_irqsave(&mp->lock, flags); mp->timeout_active = 0; if (mp->tx_active == 0 && !mp->tx_bad_runt) goto out; @@ -827,7 +830,7 @@ out_8(&mb->maccc, mp->maccc); out: - restore_flags(flags); + spin_unlock_irqrestore(&mp->lock, flags); } static void mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs) @@ -845,7 +848,9 @@ unsigned frame_status; static int mace_lost_status; unsigned char *data; + unsigned long flags; + spin_lock_irqsave(&mp->lock, flags); for (i = mp->rx_empty; i != mp->rx_fill; ) { cp = mp->rx_cmds + i; stat = ld_le16(&cp->xfer_status); @@ -941,6 +946,7 @@ out_le32(&rd->control, ((RUN|WAKE) << 16) | (RUN|WAKE)); mp->rx_fill = i; } + spin_unlock_irqrestore(&mp->lock, flags); } MODULE_AUTHOR("Paul Mackerras"); diff -Nru a/drivers/net/r8169.c b/drivers/net/r8169.c --- a/drivers/net/r8169.c Fri Jan 10 12:05:31 2003 +++ b/drivers/net/r8169.c Thu Mar 27 13:19:18 2003 @@ -1110,7 +1110,7 @@ .name = MODULENAME, .id_table = rtl8169_pci_tbl, .probe = rtl8169_init_one, - .remove = rtl8169_remove_one, + .remove = __devexit_p(rtl8169_remove_one), .suspend = NULL, .resume = NULL, }; diff -Nru a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c --- a/drivers/net/tulip/de4x5.c Tue Feb 11 04:35:49 2003 +++ b/drivers/net/tulip/de4x5.c Fri Mar 28 20:39:53 2003 @@ -452,7 +452,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c --- a/drivers/net/tulip/dmfe.c Tue Feb 18 10:50:38 2003 +++ b/drivers/net/tulip/dmfe.c Fri Mar 28 21:04:10 2003 @@ -49,6 +49,10 @@ support. Updated PCI resource allocation. Do not forget to unmap PCI mapped skbs. + Alan Cox + Added new PCI identifiers provided by Clear Zhang at ALi + for their 1563 ethernet device. + TODO Implement pci_driver::suspend() and pci_driver::resume() @@ -75,7 +79,6 @@ #include #include #include -#include #include #include #include @@ -1975,6 +1978,7 @@ { 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9102_ID }, { 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9100_ID }, { 0x1282, 0x9009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9009_ID }, + { 0x10B9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9102_ID }, { 0, } }; MODULE_DEVICE_TABLE(pci, dmfe_pci_tbl); diff -Nru a/drivers/pci/Makefile b/drivers/pci/Makefile --- a/drivers/pci/Makefile Sat Mar 1 07:41:20 2003 +++ b/drivers/pci/Makefile Sun Mar 23 04:17:50 2003 @@ -29,6 +29,9 @@ obj-y += setup-bus.o endif +# Hotplug (eg, cardbus) now requires setup-bus +obj-$(CONFIG_HOTPLUG) += setup-bus.o + ifndef CONFIG_X86 obj-y += syscall.o endif diff -Nru a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig --- a/drivers/pcmcia/Kconfig Sun Feb 9 17:29:49 2003 +++ b/drivers/pcmcia/Kconfig Tue Mar 18 11:56:09 2003 @@ -87,5 +87,9 @@ tristate "SA1111 support" depends on PCMCIA_SA1100 && SA1111 +config PCMCIA_PROBE + bool + default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X + endmenu diff -Nru a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile --- a/drivers/pcmcia/Makefile Mon Feb 3 14:19:37 2003 +++ b/drivers/pcmcia/Makefile Mon Mar 24 01:13:57 2003 @@ -2,46 +2,43 @@ # Makefile for the kernel pcmcia subsystem (c/o David Hinds) # -obj-$(CONFIG_PCMCIA) += pcmcia_core.o ds.o +obj-$(CONFIG_PCMCIA) += pcmcia_core.o ds.o ifeq ($(CONFIG_CARDBUS),y) - obj-$(CONFIG_PCMCIA) += yenta_socket.o + obj-$(CONFIG_PCMCIA) += yenta_socket.o endif -obj-$(CONFIG_I82365) += i82365.o -obj-$(CONFIG_I82092) += i82092.o -obj-$(CONFIG_TCIC) += tcic.o -obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o -obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o -obj-$(CONFIG_PCMCIA_SA1111) += sa1111_cs.o +obj-$(CONFIG_I82365) += i82365.o +obj-$(CONFIG_I82092) += i82092.o +obj-$(CONFIG_TCIC) += tcic.o +obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o +obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o +obj-$(CONFIG_PCMCIA_SA1111) += sa1111_cs.o -yenta_socket-objs := pci_socket.o yenta.o +yenta_socket-y += pci_socket.o yenta.o -pcmcia_core-objs-y := cistpl.o rsrc_mgr.o bulkmem.o cs.o -pcmcia_core-objs-$(CONFIG_CARDBUS) += cardbus.o -pcmcia_core-objs := $(pcmcia_core-objs-y) +pcmcia_core-y += cistpl.o rsrc_mgr.o bulkmem.o cs.o +pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o -sa1111_cs-objs-y := sa1111_generic.o -sa1111_cs-objs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o -sa1111_cs-objs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o -sa1111_cs-objs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o -sa1111_cs-objs-$(CONFIG_SA1100_GRAPHICSMASTER) += sa1100_graphicsmaster.o -sa1111_cs-objs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o -sa1111_cs-objs-$(CONFIG_SA1100_PFS168) += sa1100_pfs168.o -sa1111_cs-objs-$(CONFIG_SA1100_PT_SYSTEM3) += sa1100_system3.o -sa1111_cs-objs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o -sa1111_cs-objs := $(sa1111_cs-objs-y) +sa1111_cs-y += sa1111_generic.o +sa1111_cs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o +sa1111_cs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o +sa1111_cs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o +sa1111_cs-$(CONFIG_SA1100_GRAPHICSMASTER) += sa1100_graphicsmaster.o +sa1111_cs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o +sa1111_cs-$(CONFIG_SA1100_PFS168) += sa1100_pfs168.o +sa1111_cs-$(CONFIG_SA1100_PT_SYSTEM3) += sa1100_system3.o +sa1111_cs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o -sa1100_cs-objs-y := sa1100_generic.o -sa1100_cs-objs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o -sa1100_cs-objs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o -sa1100_cs-objs-$(CONFIG_SA1100_FLEXANET) += sa1100_flexanet.o -sa1100_cs-objs-$(CONFIG_SA1100_FREEBIRD) += sa1100_freebird.o -sa1100_cs-objs-$(CONFIG_SA1100_GRAPHICSCLIENT) += sa1100_graphicsclient.o -sa1100_cs-objs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o -sa1100_cs-objs-$(CONFIG_SA1100_PANGOLIN) += sa1100_pangolin.o -sa1100_cs-objs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o -sa1100_cs-objs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o -sa1100_cs-objs-$(CONFIG_SA1100_STORK) += sa1100_stork.o -sa1100_cs-objs-$(CONFIG_SA1100_TRIZEPS) += sa1100_trizeps.o -sa1100_cs-objs-$(CONFIG_SA1100_YOPY) += sa1100_yopy.o -sa1100_cs-objs := $(sa1100_cs-objs-y) +sa1100_cs-y += sa1100_generic.o +sa1100_cs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o +sa1100_cs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o +sa1100_cs-$(CONFIG_SA1100_FLEXANET) += sa1100_flexanet.o +sa1100_cs-$(CONFIG_SA1100_FREEBIRD) += sa1100_freebird.o +sa1100_cs-$(CONFIG_SA1100_GRAPHICSCLIENT) += sa1100_graphicsclient.o +sa1100_cs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o +sa1100_cs-$(CONFIG_SA1100_PANGOLIN) += sa1100_pangolin.o +sa1100_cs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o +sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o +sa1100_cs-$(CONFIG_SA1100_STORK) += sa1100_stork.o +sa1100_cs-$(CONFIG_SA1100_TRIZEPS) += sa1100_trizeps.o +sa1100_cs-$(CONFIG_SA1100_YOPY) += sa1100_yopy.o diff -Nru a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c --- a/drivers/pcmcia/cardbus.c Thu Mar 13 16:52:15 2003 +++ b/drivers/pcmcia/cardbus.c Wed Mar 26 08:49:30 2003 @@ -87,10 +87,6 @@ #define PCDATA_CODE_TYPE 0x0014 #define PCDATA_INDICATOR 0x0015 -typedef struct cb_config_t { - struct pci_dev *dev[8]; -} cb_config_t; - /*===================================================================== Expansion ROM's have a special layout, and pointers specify an @@ -173,11 +169,10 @@ DEBUG(3, "cs: read_cb_mem(%d, %#x, %u)\n", space, addr, len); - if (!s->cb_config) + dev = pci_find_slot(s->cap.cb_dev->subordinate->number, 0); + if (!dev) goto fail; - dev = s->cb_config->dev[0]; - /* Config space? */ if (space == 0) { if (addr + len > 0x100) @@ -219,171 +214,61 @@ =====================================================================*/ -int cb_alloc(socket_info_t * s) +/* + * Since there is only one interrupt available to CardBus + * devices, all devices downstream of this device must + * be using this IRQ. + */ +static void cardbus_assign_irqs(struct pci_bus *bus, int irq) { - struct pci_bus *bus; - u_short vend, v, dev; - u_char i, hdr, fn; - cb_config_t *c; - int irq; - - bus = s->cap.cb_dev->subordinate; - - pci_bus_read_config_word(bus, 0, PCI_VENDOR_ID, &vend); - pci_bus_read_config_word(bus, 0, PCI_DEVICE_ID, &dev); - printk(KERN_INFO "cs: cb_alloc(bus %d): vendor 0x%04x, " - "device 0x%04x\n", bus->number, vend, dev); - - pci_bus_read_config_byte(bus, 0, PCI_HEADER_TYPE, &hdr); - fn = 1; - if (hdr & 0x80) { - do { - if (pci_bus_read_config_word(bus, fn, PCI_VENDOR_ID, &v) || - !v || v == 0xffff) - break; - fn++; - } while (fn < 8); - } - s->functions = fn; - - c = kmalloc(sizeof(struct cb_config_t), GFP_ATOMIC); - if (!c) - return CS_OUT_OF_RESOURCE; - memset(c, 0, sizeof(struct cb_config_t)); - - for (i = 0; i < fn; i++) { - c->dev[i] = kmalloc(sizeof(struct pci_dev), GFP_ATOMIC); - if (!c->dev[i]) { - for (; i--; ) - kfree(c->dev[i]); - kfree(c); - return CS_OUT_OF_RESOURCE; - } - memset(c->dev[i], 0, sizeof(struct pci_dev)); - } + struct pci_dev *dev; - irq = s->cap.pci_irq; - for (i = 0; i < fn; i++) { - struct pci_dev *dev = c->dev[i]; + list_for_each_entry(dev, &bus->devices, bus_list) { u8 irq_pin; - int r; - - dev->bus = bus; - dev->sysdata = bus->sysdata; - dev->dev.parent = bus->dev; - dev->dev.bus = &pci_bus_type; - dev->devfn = i; - - pci_read_config_word(dev, PCI_VENDOR_ID, &dev->vendor); - pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device); - dev->hdr_type = hdr & 0x7f; - dev->dma_mask = 0xffffffff; - dev->dev.dma_mask = &dev->dma_mask; - - pci_setup_device(dev); - - strcpy(dev->dev.bus_id, dev->slot_name); - - /* We need to assign resources for expansion ROM. */ - for (r = 0; r < 7; r++) { - struct resource *res = dev->resource + r; - if (res->flags) - pci_assign_resource(dev, r); - } - /* Does this function have an interrupt at all? */ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin); - if (irq_pin) + if (irq_pin) { dev->irq = irq; - - /* pci_enable_device needs to be called after pci_assign_resource */ - /* because it returns an error if (!res->start && res->end). */ - if (pci_enable_device(dev)) - continue; - - if (irq_pin) - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); - - device_register(&dev->dev); - pci_insert_device(dev, bus); - } - - s->cb_config = c; - s->irq.AssignedIRQ = irq; - return CS_SUCCESS; -} - -void cb_free(socket_info_t * s) -{ - cb_config_t *c = s->cb_config; - - if (c) { - s->cb_config = NULL; - pci_remove_behind_bridge(s->cap.cb_dev); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + } - kfree(c); - printk(KERN_INFO "cs: cb_free(bus %d)\n", s->cap.cb_dev->subordinate->number); + if (dev->subordinate) + cardbus_assign_irqs(dev->subordinate, irq); } } -/*===================================================================== - - cb_enable() has the job of configuring a socket for a Cardbus - card, and initializing the card's PCI configuration registers. - - It first sets up the Cardbus bridge windows, for IO and memory - accesses. Then, it initializes each card function's base address - registers, interrupt line register, and command register. - - It is called as part of the RequestConfiguration card service. - It should be called after a previous call to cb_config() (via the - RequestIO service). - -======================================================================*/ - -void cb_enable(socket_info_t * s) +int cb_alloc(socket_info_t * s) { + struct pci_bus *bus = s->cap.cb_dev->subordinate; struct pci_dev *dev; - u_char i; + unsigned int max, pass; - DEBUG(0, "cs: cb_enable(bus %d)\n", s->cap.cb_dev->subordinate->number); + s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0)); +// pcibios_fixup_bus(bus); - /* Configure bridge */ - cb_release_cis_mem(s); - - /* Set up PCI interrupt and command registers */ - for (i = 0; i < s->functions; i++) { - dev = s->cb_config->dev[i]; - pci_write_config_byte(dev, PCI_COMMAND, PCI_COMMAND_MASTER | - PCI_COMMAND_IO | PCI_COMMAND_MEMORY); - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, - L1_CACHE_BYTES / 4); - } + max = bus->secondary; + for (pass = 0; pass < 2; pass++) + list_for_each_entry(dev, &bus->devices, bus_list) + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || + dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) + max = pci_scan_bridge(bus, dev, max, pass); + + /* + * Size all resources below the CardBus controller. + */ + pci_bus_size_bridges(bus); + pci_bus_assign_resources(bus); + cardbus_assign_irqs(bus, s->cap.pci_irq); + pci_enable_bridges(bus); + pci_bus_add_devices(bus); - if (s->irq.AssignedIRQ) { - for (i = 0; i < s->functions; i++) { - dev = s->cb_config->dev[i]; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, - s->irq.AssignedIRQ); - } - s->socket.io_irq = s->irq.AssignedIRQ; - s->ss_entry->set_socket(s->sock, &s->socket); - } + s->irq.AssignedIRQ = s->cap.pci_irq; + return CS_SUCCESS; } -/*====================================================================== - - cb_disable() unconfigures a Cardbus card previously set up by - cb_enable(). - - It is called from the ReleaseConfiguration service. - -======================================================================*/ - -void cb_disable(socket_info_t * s) +void cb_free(socket_info_t * s) { - DEBUG(0, "cs: cb_disable(bus %d)\n", s->cap.cb_dev->subordinate->number); + struct pci_dev *bridge = s->cap.cb_dev; - /* Turn off bridge windows */ - cb_release_cis_mem(s); + pci_remove_behind_bridge(bridge); } diff -Nru a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c --- a/drivers/pcmcia/cistpl.c Thu Mar 13 16:52:15 2003 +++ b/drivers/pcmcia/cistpl.c Wed Mar 26 08:49:31 2003 @@ -47,7 +47,6 @@ #include #include -#include #include #include #include @@ -83,6 +82,52 @@ INT_MODULE_PARM(cis_width, 0); /* 16-bit CIS? */ +void release_cis_mem(socket_info_t *s) +{ + if (s->cis_mem.sys_start != 0) { + s->cis_mem.flags &= ~MAP_ACTIVE; + s->ss_entry->set_mem_map(s->sock, &s->cis_mem); + if (!(s->cap.features & SS_CAP_STATIC_MAP)) + release_mem_region(s->cis_mem.sys_start, s->cap.map_size); + iounmap(s->cis_virt); + s->cis_mem.sys_start = 0; + s->cis_virt = NULL; + } +} + +/* + * Map the card memory at "card_offset" into virtual space. + * If flags & MAP_ATTRIB, map the attribute space, otherwise + * map the memory space. + */ +static unsigned char * +set_cis_map(socket_info_t *s, unsigned int card_offset, unsigned int flags) +{ + pccard_mem_map *mem = &s->cis_mem; + if (!(s->cap.features & SS_CAP_STATIC_MAP) && + mem->sys_start == 0) { + int low = !(s->cap.features & SS_CAP_PAGE_REGS); + validate_mem(s); + mem->sys_start = 0; + if (find_mem_region(&mem->sys_start, s->cap.map_size, + s->cap.map_size, low, "card services", s)) { + printk(KERN_NOTICE "cs: unable to map card memory!\n"); + return NULL; + } + mem->sys_stop = mem->sys_start+s->cap.map_size-1; + s->cis_virt = ioremap(mem->sys_start, s->cap.map_size); + } + mem->card_start = card_offset; + mem->flags = flags; + s->ss_entry->set_mem_map(s->sock, mem); + if (s->cap.features & SS_CAP_STATIC_MAP) { + if (s->cis_virt) + iounmap(s->cis_virt); + s->cis_virt = ioremap(mem->sys_start, s->cap.map_size); + } + return s->cis_virt; +} + /*====================================================================== Low-level functions to read and write CIS memory. I think the @@ -94,60 +139,60 @@ #define IS_ATTR 1 #define IS_INDIRECT 8 -static int setup_cis_mem(socket_info_t *s); - -static void set_cis_map(socket_info_t *s, pccard_mem_map *mem) -{ - s->ss_entry->set_mem_map(s->sock, mem); - if (s->cap.features & SS_CAP_STATIC_MAP) { - if (s->cis_virt) - bus_iounmap(s->cap.bus, s->cis_virt); - s->cis_virt = bus_ioremap(s->cap.bus, mem->sys_start, - s->cap.map_size); - } -} - int read_cis_mem(socket_info_t *s, int attr, u_int addr, u_int len, void *ptr) { - pccard_mem_map *mem = &s->cis_mem; - u_char *sys, *buf = ptr; + u_char *sys, *end, *buf = ptr; DEBUG(3, "cs: read_cis_mem(%d, %#x, %u)\n", attr, addr, len); - if (setup_cis_mem(s) != 0) { - memset(ptr, 0xff, len); - return -1; - } - mem->flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0); if (attr & IS_INDIRECT) { /* Indirect accesses use a bunch of special registers at fixed locations in common memory */ u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN; - if (attr & IS_ATTR) { addr *= 2; flags = ICTRL0_AUTOINC; } - mem->card_start = 0; mem->flags = MAP_ACTIVE; - set_cis_map(s, mem); - sys = s->cis_virt; - bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0); - bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0); - bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1); - bus_writeb(s->cap.bus, (addr>>16) & 0xff, sys+CISREG_IADDR2); - bus_writeb(s->cap.bus, (addr>>24) & 0xff, sys+CISREG_IADDR3); + if (attr & IS_ATTR) { + addr *= 2; + flags = ICTRL0_AUTOINC; + } + + sys = set_cis_map(s, 0, MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0)); + if (!sys) { + memset(ptr, 0xff, len); + return -1; + } + + writeb(flags, sys+CISREG_ICTRL0); + writeb(addr & 0xff, sys+CISREG_IADDR0); + writeb((addr>>8) & 0xff, sys+CISREG_IADDR1); + writeb((addr>>16) & 0xff, sys+CISREG_IADDR2); + writeb((addr>>24) & 0xff, sys+CISREG_IADDR3); for ( ; len > 0; len--, buf++) - *buf = bus_readb(s->cap.bus, sys+CISREG_IDATA0); + *buf = readb(sys+CISREG_IDATA0); } else { - u_int inc = 1; - if (attr) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; } - sys += (addr & (s->cap.map_size-1)); - mem->card_start = addr & ~(s->cap.map_size-1); + u_int inc = 1, card_offset, flags; + + flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0); + if (attr) { + flags |= MAP_ATTRIB; + inc++; + addr *= 2; + } + + card_offset = addr & ~(s->cap.map_size-1); while (len) { - set_cis_map(s, mem); - sys = s->cis_virt + (addr & (s->cap.map_size-1)); + sys = set_cis_map(s, card_offset, flags); + if (!sys) { + memset(ptr, 0xff, len); + return -1; + } + end = sys + s->cap.map_size; + sys = sys + (addr & (s->cap.map_size-1)); for ( ; len > 0; len--, buf++, sys += inc) { - if (sys == s->cis_virt+s->cap.map_size) break; - *buf = bus_readb(s->cap.bus, sys); + if (sys == end) + break; + *buf = readb(sys); } - mem->card_start += s->cap.map_size; + card_offset += s->cap.map_size; addr = 0; } } @@ -160,40 +205,54 @@ void write_cis_mem(socket_info_t *s, int attr, u_int addr, u_int len, void *ptr) { - pccard_mem_map *mem = &s->cis_mem; - u_char *sys, *buf = ptr; + u_char *sys, *end, *buf = ptr; DEBUG(3, "cs: write_cis_mem(%d, %#x, %u)\n", attr, addr, len); - if (setup_cis_mem(s) != 0) return; - mem->flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0); if (attr & IS_INDIRECT) { /* Indirect accesses use a bunch of special registers at fixed locations in common memory */ u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN; - if (attr & IS_ATTR) { addr *= 2; flags = ICTRL0_AUTOINC; } - mem->card_start = 0; mem->flags = MAP_ACTIVE; - set_cis_map(s, mem); - sys = s->cis_virt; - bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0); - bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0); - bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1); - bus_writeb(s->cap.bus, (addr>>16) & 0xff, sys+CISREG_IADDR2); - bus_writeb(s->cap.bus, (addr>>24) & 0xff, sys+CISREG_IADDR3); + if (attr & IS_ATTR) { + addr *= 2; + flags = ICTRL0_AUTOINC; + } + + sys = set_cis_map(s, 0, MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0)); + if (!sys) + return; /* FIXME: Error */ + + writeb(flags, sys+CISREG_ICTRL0); + writeb(addr & 0xff, sys+CISREG_IADDR0); + writeb((addr>>8) & 0xff, sys+CISREG_IADDR1); + writeb((addr>>16) & 0xff, sys+CISREG_IADDR2); + writeb((addr>>24) & 0xff, sys+CISREG_IADDR3); for ( ; len > 0; len--, buf++) - bus_writeb(s->cap.bus, *buf, sys+CISREG_IDATA0); + writeb(*buf, sys+CISREG_IDATA0); } else { - int inc = 1; - if (attr & IS_ATTR) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; } - mem->card_start = addr & ~(s->cap.map_size-1); + u_int inc = 1, card_offset, flags; + + flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0); + if (attr & IS_ATTR) { + flags |= MAP_ATTRIB; + inc++; + addr *= 2; + } + + card_offset = addr & ~(s->cap.map_size-1); while (len) { - set_cis_map(s, mem); - sys = s->cis_virt + (addr & (s->cap.map_size-1)); + sys = set_cis_map(s, card_offset, flags); + if (!sys) + return; /* FIXME: error */ + + end = sys + s->cap.map_size; + sys = sys + (addr & (s->cap.map_size-1)); for ( ; len > 0; len--, buf++, sys += inc) { - if (sys == s->cis_virt+s->cap.map_size) break; - bus_writeb(s->cap.bus, *buf, sys); + if (sys == end) + break; + writeb(*buf, sys); } - mem->card_start += s->cap.map_size; + card_offset += s->cap.map_size; addr = 0; } } @@ -201,98 +260,6 @@ /*====================================================================== - This is tricky... when we set up CIS memory, we try to validate - the memory window space allocations. - -======================================================================*/ - -/* Scratch pointer to the socket we use for validation */ -static socket_info_t *vs = NULL; - -/* Validation function for cards with a valid CIS */ -static int cis_readable(u_long base) -{ - cisinfo_t info1, info2; - int ret; - vs->cis_mem.sys_start = base; - vs->cis_mem.sys_stop = base+vs->cap.map_size-1; - vs->cis_virt = bus_ioremap(vs->cap.bus, base, vs->cap.map_size); - ret = pcmcia_validate_cis(vs->clients, &info1); - /* invalidate mapping and CIS cache */ - bus_iounmap(vs->cap.bus, vs->cis_virt); vs->cis_used = 0; - if ((ret != 0) || (info1.Chains == 0)) - return 0; - vs->cis_mem.sys_start = base+vs->cap.map_size; - vs->cis_mem.sys_stop = base+2*vs->cap.map_size-1; - vs->cis_virt = bus_ioremap(vs->cap.bus, base+vs->cap.map_size, - vs->cap.map_size); - ret = pcmcia_validate_cis(vs->clients, &info2); - bus_iounmap(vs->cap.bus, vs->cis_virt); vs->cis_used = 0; - return ((ret == 0) && (info1.Chains == info2.Chains)); -} - -/* Validation function for simple memory cards */ -static int checksum(u_long base) -{ - int i, a, b, d; - vs->cis_mem.sys_start = base; - vs->cis_mem.sys_stop = base+vs->cap.map_size-1; - vs->cis_virt = bus_ioremap(vs->cap.bus, base, vs->cap.map_size); - vs->cis_mem.card_start = 0; - vs->cis_mem.flags = MAP_ACTIVE; - vs->ss_entry->set_mem_map(vs->sock, &vs->cis_mem); - /* Don't bother checking every word... */ - a = 0; b = -1; - for (i = 0; i < vs->cap.map_size; i += 44) { - d = bus_readl(vs->cap.bus, vs->cis_virt+i); - a += d; b &= d; - } - bus_iounmap(vs->cap.bus, vs->cis_virt); - return (b == -1) ? -1 : (a>>1); -} - -static int checksum_match(u_long base) -{ - int a = checksum(base), b = checksum(base+vs->cap.map_size); - return ((a == b) && (a >= 0)); -} - -static int setup_cis_mem(socket_info_t *s) -{ - if (!(s->cap.features & SS_CAP_STATIC_MAP) && - (s->cis_mem.sys_start == 0)) { - int low = !(s->cap.features & SS_CAP_PAGE_REGS); - vs = s; - validate_mem(cis_readable, checksum_match, low, s); - s->cis_mem.sys_start = 0; - vs = NULL; - if (find_mem_region(&s->cis_mem.sys_start, s->cap.map_size, - s->cap.map_size, low, "card services", s)) { - printk(KERN_NOTICE "cs: unable to map card memory!\n"); - return -1; - } - s->cis_mem.sys_stop = s->cis_mem.sys_start+s->cap.map_size-1; - s->cis_virt = bus_ioremap(s->cap.bus, s->cis_mem.sys_start, - s->cap.map_size); - } - return 0; -} - -void release_cis_mem(socket_info_t *s) -{ - if (s->cis_mem.sys_start != 0) { - s->cis_mem.flags &= ~MAP_ACTIVE; - s->ss_entry->set_mem_map(s->sock, &s->cis_mem); - if (!(s->cap.features & SS_CAP_STATIC_MAP)) - release_mem_region(s->cis_mem.sys_start, s->cap.map_size); - bus_iounmap(s->cap.bus, s->cis_virt); - s->cis_mem.sys_start = 0; - s->cis_virt = NULL; - } -} - -/*====================================================================== - This is a wrapper around read_cis_mem, with the same interface, but which caches information, for cards whose CIS may not be readable all the time. @@ -427,11 +394,9 @@ tuple->TupleLink = tuple->Flags = 0; #ifdef CONFIG_CARDBUS if (s->state & SOCKET_CARDBUS) { + struct pci_dev *dev = s->cap.cb_dev; u_int ptr; - struct pci_dev *dev = pci_find_slot (s->cap.cb_dev->subordinate->number, 0); - if (!dev) - return CS_BAD_HANDLE; - pci_read_config_dword(dev, 0x28, &ptr); + pci_bus_read_config_dword(dev->subordinate, 0, PCI_CARDBUS_CIS, &ptr); tuple->CISOffset = ptr & ~7; SPACE(tuple->Flags) = (ptr & 7); } else diff -Nru a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c --- a/drivers/pcmcia/cs.c Thu Mar 13 17:11:43 2003 +++ b/drivers/pcmcia/cs.c Wed Mar 26 08:49:32 2003 @@ -59,7 +59,6 @@ #include #include #include -#include #include "cs_internal.h" #ifdef CONFIG_PCI @@ -622,8 +621,10 @@ send_event(s, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW); } else if (s->state & SOCKET_SETUP_PENDING) { #ifdef CONFIG_CARDBUS - if (s->state & SOCKET_CARDBUS) + if (s->state & SOCKET_CARDBUS) { cb_alloc(s); + s->state |= SOCKET_CARDBUS_CONFIG; + } #endif send_event(s, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); s->state &= ~SOCKET_SETUP_PENDING; @@ -1077,7 +1078,7 @@ config->Vcc = s->socket.Vcc; config->Vpp1 = config->Vpp2 = s->socket.Vpp; config->Option = s->cap.cb_dev->subordinate->number; - if (s->cb_config) { + if (s->state & SOCKET_CARDBUS_CONFIG) { config->Attributes = CONF_VALID_CLIENT; config->IntType = INT_CARDBUS; config->AssignedIRQ = s->irq.AssignedIRQ; @@ -1473,7 +1474,6 @@ client->event_handler = req->event_handler; client->event_callback_args = req->event_callback_args; client->event_callback_args.client_handle = client; - client->event_callback_args.bus = s->cap.bus; if (s->state & SOCKET_CARDBUS) client->state |= CLIENT_CARDBUS; @@ -1522,11 +1522,8 @@ s = SOCKET(handle); #ifdef CONFIG_CARDBUS - if (handle->state & CLIENT_CARDBUS) { - cb_disable(s); - s->lock_count = 0; + if (handle->state & CLIENT_CARDBUS) return CS_SUCCESS; - } #endif if (!(handle->state & CLIENT_STALE)) { @@ -1573,9 +1570,8 @@ s = SOCKET(handle); #ifdef CONFIG_CARDBUS - if (handle->state & CLIENT_CARDBUS) { + if (handle->state & CLIENT_CARDBUS) return CS_SUCCESS; - } #endif if (!(handle->state & CLIENT_STALE)) { @@ -1622,10 +1618,10 @@ } if (req->Attributes & IRQ_HANDLE_PRESENT) { - bus_free_irq(s->cap.bus, req->AssignedIRQ, req->Instance); + free_irq(req->AssignedIRQ, req->Instance); } -#ifdef CONFIG_ISA +#ifdef CONFIG_PCMCIA_PROBE if (req->AssignedIRQ != s->cap.pci_irq) undo_irq(req->Attributes, req->AssignedIRQ); #endif @@ -1678,16 +1674,8 @@ return CS_NO_CARD; #ifdef CONFIG_CARDBUS - if (handle->state & CLIENT_CARDBUS) { - if (!(req->IntType & INT_CARDBUS)) - return CS_UNSUPPORTED_MODE; - if (s->lock_count != 0) - return CS_CONFIGURATION_LOCKED; - cb_enable(s); - handle->state |= CLIENT_CONFIG_LOCKED; - s->lock_count++; - return CS_SUCCESS; - } + if (handle->state & CLIENT_CARDBUS) + return CS_UNSUPPORTED_MODE; #endif if (req->IntType & INT_CARDBUS) @@ -1887,7 +1875,7 @@ if (!s->cap.irq_mask) { irq = s->cap.pci_irq; ret = (irq) ? 0 : CS_IN_USE; -#ifdef CONFIG_ISA +#ifdef CONFIG_PCMCIA_PROBE } else if (s->irq.AssignedIRQ != 0) { /* If the interrupt is already assigned, it must match */ irq = s->irq.AssignedIRQ; @@ -1917,7 +1905,7 @@ if (ret != 0) return ret; if (req->Attributes & IRQ_HANDLE_PRESENT) { - if (bus_request_irq(s->cap.bus, irq, req->Handler, + if (request_irq(irq, req->Handler, ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || (s->functions > 1) || (irq == s->cap.pci_irq)) ? SA_SHIRQ : 0, diff -Nru a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h --- a/drivers/pcmcia/cs_internal.h Sun Feb 23 03:39:32 2003 +++ b/drivers/pcmcia/cs_internal.h Sun Mar 23 04:17:51 2003 @@ -136,7 +136,6 @@ #ifdef CONFIG_CARDBUS struct resource * cb_cis_res; u_char *cb_cis_virt; - struct cb_config_t *cb_config; #endif struct { u_int AssignedIRQ; @@ -176,6 +175,7 @@ #define SOCKET_IO_REQ(i) (0x1000<<(i)) #define SOCKET_REGION_INFO 0x4000 #define SOCKET_CARDBUS 0x8000 +#define SOCKET_CARDBUS_CONFIG 0x10000 #define CHECK_HANDLE(h) \ (((h) == NULL) || ((h)->client_magic != CLIENT_MAGIC)) @@ -198,8 +198,6 @@ /* In cardbus.c */ int cb_alloc(socket_info_t *s); void cb_free(socket_info_t *s); -void cb_enable(socket_info_t *s); -void cb_disable(socket_info_t *s); int read_cb_mem(socket_info_t *s, int space, u_int addr, u_int len, void *ptr); void cb_release_cis_mem(socket_info_t *s); @@ -234,8 +232,7 @@ int copy_memory(memory_handle_t handle, copy_op_t *req); /* In rsrc_mgr */ -void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long), - int force_low, socket_info_t *s); +void validate_mem(socket_info_t *s); int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align, char *name, socket_info_t *s); int find_mem_region(u_long *base, u_long num, u_long align, diff -Nru a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c --- a/drivers/pcmcia/ds.c Sat Mar 22 07:54:06 2003 +++ b/drivers/pcmcia/ds.c Thu Mar 27 17:12:29 2003 @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -55,6 +56,7 @@ #include #include #include +#include /*====================================================================*/ @@ -69,8 +71,6 @@ #ifdef PCMCIA_DEBUG INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static const char *version = -"ds.c 1.112 2001/10/13 00:08:28 (David Hinds)"; #else #define DEBUG(n, args...) #endif @@ -97,15 +97,18 @@ } user_info_t; /* Socket state information */ -typedef struct socket_info_t { - client_handle_t handle; - int state; - user_info_t *user; - int req_pending, req_result; - wait_queue_head_t queue, request; - struct timer_list removal; - socket_bind_t *bind; -} socket_info_t; +struct pcmcia_bus_socket { + client_handle_t handle; + int state; + user_info_t *user; + int req_pending, req_result; + wait_queue_head_t queue, request; + struct timer_list removal; + socket_bind_t *bind; + struct device *socket_dev; + struct list_head socket_list; + unsigned int socket_no; /* deprecated */ +}; #define SOCKET_PRESENT 0x01 #define SOCKET_BUSY 0x02 @@ -116,13 +119,13 @@ /* Device driver ID passed to Card Services */ static dev_info_t dev_info = "Driver Services"; -static int sockets = 0, major_dev = -1; -static socket_info_t *socket_table = NULL; +static int major_dev = -1; -extern struct proc_dir_entry *proc_pccard; +/* list of all sockets registered with the pcmcia bus driver */ +static DECLARE_RWSEM(bus_socket_list_rwsem); +static LIST_HEAD(bus_socket_list); -/* We use this to distinguish in-kernel from modular drivers */ -static int init_status = 1; +extern struct proc_dir_entry *proc_pccard; /*====================================================================*/ @@ -135,6 +138,7 @@ /*======================================================================*/ static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info); +static struct pcmcia_bus_socket * get_socket_info_by_nr(unsigned int nr); /** * pcmcia_register_driver - register a PCMCIA driver with the bus core @@ -147,7 +151,6 @@ return -EINVAL; driver->use_count = 0; - driver->status = init_status; driver->drv.bus = &pcmcia_bus_type; return driver_register(&driver->drv); @@ -160,17 +163,19 @@ void pcmcia_unregister_driver(struct pcmcia_driver *driver) { socket_bind_t *b; - int i; + struct pcmcia_bus_socket *bus_sock; if (driver->use_count > 0) { /* Blank out any left-over device instances */ driver->attach = NULL; driver->detach = NULL; - for (i = 0; i < sockets; i++) - for (b = socket_table[i].bind; b; b = b->next) + down_read(&bus_socket_list_rwsem); + list_for_each_entry(bus_sock, &bus_socket_list, socket_list) { + for (b = bus_sock->bind; b; b = b->next) if (b->driver == driver) b->instance = NULL; - } - + } + up_read(&bus_socket_list_rwsem); + } driver_unregister(&driver->drv); } EXPORT_SYMBOL(pcmcia_unregister_driver); @@ -181,33 +186,21 @@ void (*detach)(dev_link_t *)) { struct pcmcia_driver *driver; - socket_bind_t *b; - int i; DEBUG(0, "ds: register_pccard_driver('%s')\n", (char *)dev_info); driver = get_pcmcia_driver(dev_info); - if (!driver) { - driver = kmalloc(sizeof(struct pcmcia_driver), GFP_KERNEL); - if (!driver) return -ENOMEM; - memset(driver, 0, sizeof(struct pcmcia_driver)); - driver->drv.name = (char *)dev_info; - pcmcia_register_driver(driver); - } + if (driver) + return -EBUSY; + + driver = kmalloc(sizeof(struct pcmcia_driver), GFP_KERNEL); + if (!driver) return -ENOMEM; + memset(driver, 0, sizeof(struct pcmcia_driver)); + driver->drv.name = (char *)dev_info; + pcmcia_register_driver(driver); driver->attach = attach; driver->detach = detach; - if (driver->use_count == 0) return 0; - - /* Instantiate any already-bound devices */ - for (i = 0; i < sockets; i++) - for (b = socket_table[i].bind; b; b = b->next) { - if (b->driver != driver) continue; - b->instance = driver->attach(); - if (b->instance == NULL) - printk(KERN_NOTICE "ds: unable to create instance " - "of '%s'!\n", driver->drv.name); - } - + return 0; } /* register_pccard_driver */ @@ -238,8 +231,7 @@ struct pcmcia_driver *p_dev = container_of(driver, struct pcmcia_driver, drv); - *p += sprintf(*p, "%-24.24s %d %d\n", driver->name, p_dev->status, - p_dev->use_count); + *p += sprintf(*p, "%-24.24s 1 %d\n", driver->name, p_dev->use_count); d = (void *) p; return 0; @@ -282,7 +274,7 @@ user->event[user->event_head] = event; } -static void handle_event(socket_info_t *s, event_t event) +static void handle_event(struct pcmcia_bus_socket *s, event_t event) { user_info_t *user; for (user = s->user; user; user = user->next) @@ -290,7 +282,7 @@ wake_up_interruptible(&s->queue); } -static int handle_request(socket_info_t *s, event_t event) +static int handle_request(struct pcmcia_bus_socket *s, event_t event) { if (s->req_pending != 0) return CS_IN_USE; @@ -309,7 +301,7 @@ static void handle_removal(u_long sn) { - socket_info_t *s = &socket_table[sn]; + struct pcmcia_bus_socket *s = get_socket_info_by_nr(sn); handle_event(s, CS_EVENT_CARD_REMOVAL); s->state &= ~SOCKET_REMOVAL_PENDING; } @@ -323,13 +315,11 @@ static int ds_event(event_t event, int priority, event_callback_args_t *args) { - socket_info_t *s; - int i; + struct pcmcia_bus_socket *s; DEBUG(1, "ds: ds_event(0x%06x, %d, 0x%p)\n", event, priority, args->client_handle); s = args->client_data; - i = s - socket_table; switch (event) { @@ -366,21 +356,21 @@ ======================================================================*/ -static int bind_mtd(int i, mtd_info_t *mtd_info) +static int bind_mtd(struct pcmcia_bus_socket *bus_sock, mtd_info_t *mtd_info) { mtd_bind_t bind_req; int ret; bind_req.dev_info = &mtd_info->dev_info; bind_req.Attributes = mtd_info->Attributes; - bind_req.Socket = i; + bind_req.Socket = bus_sock->socket_no; bind_req.CardOffset = mtd_info->CardOffset; ret = pcmcia_bind_mtd(&bind_req); if (ret != CS_SUCCESS) { cs_error(NULL, BindMTD, ret); printk(KERN_NOTICE "ds: unable to bind MTD '%s' to socket %d" " offset 0x%x\n", - (char *)bind_req.dev_info, i, bind_req.CardOffset); + (char *)bind_req.dev_info, bus_sock->socket_no, bind_req.CardOffset); return -ENODEV; } return 0; @@ -395,24 +385,21 @@ ======================================================================*/ -static int bind_request(int i, bind_info_t *bind_info) +static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) { struct pcmcia_driver *driver; socket_bind_t *b; bind_req_t bind_req; - socket_info_t *s = &socket_table[i]; int ret; - DEBUG(2, "bind_request(%d, '%s')\n", i, + if (!s) + return -EINVAL; + + DEBUG(2, "bind_request(%d, '%s')\n", s->socket_no, (char *)bind_info->dev_info); driver = get_pcmcia_driver(&bind_info->dev_info); - if (driver == NULL) { - driver = kmalloc(sizeof(struct pcmcia_driver), GFP_KERNEL); - if (!driver) return -ENOMEM; - memset(driver, 0, sizeof(struct pcmcia_driver)); - driver->drv.name = bind_info->dev_info; - pcmcia_register_driver(driver); - } + if (!driver) + return -EINVAL; for (b = s->bind; b; b = b->next) if ((driver == b->driver) && @@ -423,14 +410,14 @@ return -EBUSY; } - bind_req.Socket = i; + bind_req.Socket = s->socket_no; bind_req.Function = bind_info->function; bind_req.dev_info = (dev_info_t *) driver->drv.name; ret = pcmcia_bind_device(&bind_req); if (ret != CS_SUCCESS) { cs_error(NULL, BindDevice, ret); printk(KERN_NOTICE "ds: unable to bind '%s' to socket %d\n", - (char *)dev_info, i); + (char *)dev_info, s->socket_no); return -ENODEV; } @@ -462,9 +449,8 @@ /*====================================================================*/ -static int get_device_info(int i, bind_info_t *bind_info, int first) +static int get_device_info(struct pcmcia_bus_socket *s, bind_info_t *bind_info, int first) { - socket_info_t *s = &socket_table[i]; socket_bind_t *b; dev_node_t *node; @@ -532,12 +518,11 @@ /*====================================================================*/ -static int unbind_request(int i, bind_info_t *bind_info) +static int unbind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) { - socket_info_t *s = &socket_table[i]; socket_bind_t **b, *c; - DEBUG(2, "unbind_request(%d, '%s')\n", i, + DEBUG(2, "unbind_request(%d, '%s')\n", s->socket_no, (char *)bind_info->dev_info); for (b = &s->bind; *b; b = &(*b)->next) if ((strcmp((char *)(*b)->driver->drv.name, @@ -568,13 +553,15 @@ static int ds_open(struct inode *inode, struct file *file) { socket_t i = minor(inode->i_rdev); - socket_info_t *s; + struct pcmcia_bus_socket *s; user_info_t *user; DEBUG(0, "ds_open(socket %d)\n", i); - if ((i >= sockets) || (sockets == 0)) - return -ENODEV; - s = &socket_table[i]; + + s = get_socket_info_by_nr(i); + if (!s) + return -ENODEV; + if ((file->f_flags & O_ACCMODE) != O_RDONLY) { if (s->state & SOCKET_BUSY) return -EBUSY; @@ -600,13 +587,15 @@ static int ds_release(struct inode *inode, struct file *file) { socket_t i = minor(inode->i_rdev); - socket_info_t *s; + struct pcmcia_bus_socket *s; user_info_t *user, **link; DEBUG(0, "ds_release(socket %d)\n", i); - if ((i >= sockets) || (sockets == 0)) - return 0; - s = &socket_table[i]; + + s = get_socket_info_by_nr(i); + if (!s) + return 0; + user = file->private_data; if (CHECK_USER(user)) goto out; @@ -632,16 +621,18 @@ size_t count, loff_t *ppos) { socket_t i = minor(file->f_dentry->d_inode->i_rdev); - socket_info_t *s; + struct pcmcia_bus_socket *s; user_info_t *user; DEBUG(2, "ds_read(socket %d)\n", i); - if ((i >= sockets) || (sockets == 0)) - return -ENODEV; if (count < 4) return -EINVAL; - s = &socket_table[i]; + + s = get_socket_info_by_nr(i); + if (!s) + return -ENODEV; + user = file->private_data; if (CHECK_USER(user)) return -EIO; @@ -661,18 +652,20 @@ size_t count, loff_t *ppos) { socket_t i = minor(file->f_dentry->d_inode->i_rdev); - socket_info_t *s; + struct pcmcia_bus_socket *s; user_info_t *user; DEBUG(2, "ds_write(socket %d)\n", i); - if ((i >= sockets) || (sockets == 0)) - return -ENODEV; if (count != 4) return -EINVAL; if ((file->f_flags & O_ACCMODE) == O_RDONLY) return -EBADF; - s = &socket_table[i]; + + s = get_socket_info_by_nr(i); + if (!s) + return -ENODEV; + user = file->private_data; if (CHECK_USER(user)) return -EIO; @@ -694,14 +687,15 @@ static u_int ds_poll(struct file *file, poll_table *wait) { socket_t i = minor(file->f_dentry->d_inode->i_rdev); - socket_info_t *s; + struct pcmcia_bus_socket *s; user_info_t *user; DEBUG(2, "ds_poll(socket %d)\n", i); - if ((i >= sockets) || (sockets == 0)) - return POLLERR; - s = &socket_table[i]; + s = get_socket_info_by_nr(i); + if (!s) + return POLLERR; + user = file->private_data; if (CHECK_USER(user)) return POLLERR; @@ -717,16 +711,16 @@ u_int cmd, u_long arg) { socket_t i = minor(inode->i_rdev); - socket_info_t *s; + struct pcmcia_bus_socket *s; u_int size; int ret, err; ds_ioctl_arg_t buf; DEBUG(2, "ds_ioctl(socket %d, %#x, %#lx)\n", i, cmd, arg); - if ((i >= sockets) || (sockets == 0)) - return -ENODEV; - s = &socket_table[i]; + s = get_socket_info_by_nr(i); + if (!s) + return -ENODEV; size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL; @@ -827,20 +821,20 @@ break; case DS_BIND_REQUEST: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - err = bind_request(i, &buf.bind_info); + err = bind_request(s, &buf.bind_info); break; case DS_GET_DEVICE_INFO: - err = get_device_info(i, &buf.bind_info, 1); + err = get_device_info(s, &buf.bind_info, 1); break; case DS_GET_NEXT_DEVICE: - err = get_device_info(i, &buf.bind_info, 0); + err = get_device_info(s, &buf.bind_info, 0); break; case DS_UNBIND_REQUEST: - err = unbind_request(i, &buf.bind_info); + err = unbind_request(s, &buf.bind_info); break; case DS_BIND_MTD: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - err = bind_mtd(i, &buf.mtd_info); + err = bind_mtd(s, &buf.mtd_info); break; default: err = -EINVAL; @@ -889,140 +883,198 @@ /*====================================================================*/ -struct bus_type pcmcia_bus_type = { - .name = "pcmcia", -}; -EXPORT_SYMBOL(pcmcia_bus_type); - -static int __init init_pcmcia_bus(void) +static int __devinit pcmcia_bus_add_socket(struct device *dev, unsigned int socket_nr) { - bus_register(&pcmcia_bus_type); - return 0; -} + client_reg_t client_reg; + bind_req_t bind; + struct pcmcia_bus_socket *s, *tmp_s; + int ret; + int i; -static int __init init_pcmcia_ds(void) -{ - client_reg_t client_reg; - servinfo_t serv; - bind_req_t bind; - socket_info_t *s; - int i, ret; - - DEBUG(0, "%s\n", version); - - /* - * Ugly. But we want to wait for the socket threads to have started up. - * We really should let the drivers themselves drive some of this.. - */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/4); + s = kmalloc(sizeof(struct pcmcia_bus_socket), GFP_KERNEL); + if(!s) + return -ENOMEM; + memset(s, 0, sizeof(struct pcmcia_bus_socket)); + + /* + * Ugly. But we want to wait for the socket threads to have started up. + * We really should let the drivers themselves drive some of this.. + */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ/4); - pcmcia_get_card_services_info(&serv); - if (serv.Revision != CS_RELEASE_CODE) { - printk(KERN_NOTICE "ds: Card Services release does not match!\n"); - return -1; - } - if (serv.Count == 0) { - printk(KERN_NOTICE "ds: no socket drivers loaded!\n"); - return -1; - } - - sockets = serv.Count; - socket_table = kmalloc(sockets*sizeof(socket_info_t), GFP_KERNEL); - if (!socket_table) return -1; - for (i = 0, s = socket_table; i < sockets; i++, s++) { - s->state = 0; - s->user = NULL; - s->req_pending = 0; init_waitqueue_head(&s->queue); init_waitqueue_head(&s->request); - s->handle = NULL; - init_timer(&s->removal); - s->removal.data = i; + + /* find the lowest, unused socket no. Please note that this is a + * temporary workaround until "struct pcmcia_socket" is introduced + * into cs.c which will include this number, and which will be + * accessible to ds.c directly */ + i = 0; + next_try: + list_for_each_entry(tmp_s, &bus_socket_list, socket_list) { + if (tmp_s->socket_no == i) { + i++; + goto next_try; + } + } + s->socket_no = i; + + /* initialize data */ + s->socket_dev = dev; + s->removal.data = s->socket_no; s->removal.function = &handle_removal; - s->bind = NULL; - } + init_timer(&s->removal); - /* Set up hotline to Card Services */ - client_reg.dev_info = bind.dev_info = &dev_info; - client_reg.Attributes = INFO_MASTER_CLIENT; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_EJECTION_REQUEST | CS_EVENT_INSERTION_REQUEST | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &ds_event; - client_reg.Version = 0x0210; - for (i = 0; i < sockets; i++) { - bind.Socket = i; + /* Set up hotline to Card Services */ + client_reg.dev_info = bind.dev_info = &dev_info; + + bind.Socket = s->socket_no; bind.Function = BIND_FN_ALL; ret = pcmcia_bind_device(&bind); if (ret != CS_SUCCESS) { - cs_error(NULL, BindDevice, ret); - break; + cs_error(NULL, BindDevice, ret); + kfree(s); + return -EINVAL; } - client_reg.event_callback_args.client_data = &socket_table[i]; - ret = pcmcia_register_client(&socket_table[i].handle, - &client_reg); + + client_reg.Attributes = INFO_MASTER_CLIENT; + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_EJECTION_REQUEST | CS_EVENT_INSERTION_REQUEST | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &ds_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = s; + ret = pcmcia_register_client(&s->handle, &client_reg); if (ret != CS_SUCCESS) { - cs_error(NULL, RegisterClient, ret); - break; + cs_error(NULL, RegisterClient, ret); + kfree(s); + return -EINVAL; } - } - - /* Set up character device for user mode clients */ - i = register_chrdev(0, "pcmcia", &ds_fops); - if (i == -EBUSY) - printk(KERN_NOTICE "unable to find a free device # for " - "Driver Services\n"); - else - major_dev = i; -#ifdef CONFIG_PROC_FS - if (proc_pccard) - create_proc_read_entry("drivers",0,proc_pccard,proc_read_drivers,NULL); - init_status = 0; -#endif - return 0; + list_add(&s->socket_list, &bus_socket_list); + + return 0; } -static void __exit exit_pcmcia_ds(void) +static int __devinit pcmcia_bus_add_socket_dev(struct device *dev) { - int i; + struct pcmcia_socket_class_data *cls_d = dev->class_data; + unsigned int i; + unsigned int ret = 0; + + if (!cls_d) + return -ENODEV; + + down_write(&bus_socket_list_rwsem); + for (i = 0; i < cls_d->nsock; i++) + ret += pcmcia_bus_add_socket(dev, i); + up_write(&bus_socket_list_rwsem); + + return ret; +} + +static int __devexit pcmcia_bus_remove_socket_dev(struct device *dev) +{ + struct pcmcia_socket_class_data *cls_d = dev->class_data; + struct list_head *list_loop; + struct list_head *tmp_storage; + + if (!cls_d) + return -ENODEV; + + down_write(&bus_socket_list_rwsem); + list_for_each_safe(list_loop, tmp_storage, &bus_socket_list) { + struct pcmcia_bus_socket *bus_sock = container_of(list_loop, struct pcmcia_bus_socket, socket_list); + if (bus_sock->socket_dev == dev) { + pcmcia_deregister_client(bus_sock->handle); + list_del(&bus_sock->socket_list); + kfree(bus_sock); + } + } + up_write(&bus_socket_list_rwsem); + return 0; +} + + +/* the pcmcia_bus_interface is used to handle pcmcia socket devices */ +static struct device_interface pcmcia_bus_interface = { + .name = "pcmcia-bus", + .devclass = &pcmcia_socket_class, + .add_device = &pcmcia_bus_add_socket_dev, + .remove_device = __devexit_p(&pcmcia_bus_remove_socket_dev), + .kset = { .subsys = &pcmcia_socket_class.subsys, }, + .devnum = 0, +}; + + +struct bus_type pcmcia_bus_type = { + .name = "pcmcia", +}; +EXPORT_SYMBOL(pcmcia_bus_type); + + +static int __init init_pcmcia_bus(void) +{ + int i; + + bus_register(&pcmcia_bus_type); + interface_register(&pcmcia_bus_interface); + + /* Set up character device for user mode clients */ + i = register_chrdev(0, "pcmcia", &ds_fops); + if (i == -EBUSY) + printk(KERN_NOTICE "unable to find a free device # for " + "Driver Services\n"); + else + major_dev = i; + #ifdef CONFIG_PROC_FS - if (proc_pccard) - remove_proc_entry("drivers", proc_pccard); + if (proc_pccard) + create_proc_read_entry("drivers",0,proc_pccard,proc_read_drivers,NULL); #endif - if (major_dev != -1) - unregister_chrdev(major_dev, "pcmcia"); - for (i = 0; i < sockets; i++) - pcmcia_deregister_client(socket_table[i].handle); - sockets = 0; - kfree(socket_table); - bus_unregister(&pcmcia_bus_type); + + return 0; } +fs_initcall(init_pcmcia_bus); /* one level after subsys_initcall so that + * pcmcia_socket_class is already registered */ -#ifdef MODULE -/* init_pcmcia_bus must be done early, init_pcmcia_ds late. If we load this - * as a module, we can only specify one initcall, though... - */ -static int __init init_pcmcia_module(void) { - init_pcmcia_bus(); - return init_pcmcia_ds(); -} -module_init(init_pcmcia_module); - -#else /* !MODULE */ -subsys_initcall(init_pcmcia_bus); -late_initcall(init_pcmcia_ds); +static void __exit exit_pcmcia_bus(void) +{ + interface_unregister(&pcmcia_bus_interface); + +#ifdef CONFIG_PROC_FS + if (proc_pccard) + remove_proc_entry("drivers", proc_pccard); #endif + if (major_dev != -1) + unregister_chrdev(major_dev, "pcmcia"); + + bus_unregister(&pcmcia_bus_type); +} +module_exit(exit_pcmcia_bus); -module_exit(exit_pcmcia_ds); /* helpers for backwards-compatible functions */ + + +static struct pcmcia_bus_socket * get_socket_info_by_nr(unsigned int nr) +{ + struct pcmcia_bus_socket * s; + down_read(&bus_socket_list_rwsem); + list_for_each_entry(s, &bus_socket_list, socket_list) + if (s->socket_no == nr) { + up_read(&bus_socket_list_rwsem); + return s; + } + up_read(&bus_socket_list_rwsem); + return NULL; +} /* backwards-compatible accessing of driver --- by name! */ diff -Nru a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c --- a/drivers/pcmcia/hd64465_ss.c Tue Mar 4 22:35:34 2003 +++ b/drivers/pcmcia/hd64465_ss.c Mon Mar 17 07:38:31 2003 @@ -599,21 +599,6 @@ /*============================================================*/ -static int hs_get_io_map(unsigned int sock, struct pccard_io_map *io) -{ - hs_socket_t *sp = &hs_sockets[sock]; - int map = io->map; - - DPRINTK("hs_get_io_map(%d, %d)\n", sock, map); - if (map >= MAX_IO_WIN) - return -EINVAL; - - *io = sp->io_maps[map]; - return 0; -} - -/*============================================================*/ - static int hs_set_io_map(unsigned int sock, struct pccard_io_map *io) { hs_socket_t *sp = &hs_sockets[sock]; @@ -696,21 +681,6 @@ /*============================================================*/ -static int hs_get_mem_map(unsigned int sock, struct pccard_mem_map *mem) -{ - hs_socket_t *sp = &hs_sockets[sock]; - int map = mem->map; - - DPRINTK("hs_get_mem_map(%d, %d)\n", sock, map); - if (map >= MAX_WIN) - return -EINVAL; - - *mem = sp->mem_maps[map]; - return 0; -} - -/*============================================================*/ - static int hs_set_mem_map(unsigned int sock, struct pccard_mem_map *mem) { hs_socket_t *sp = &hs_sockets[sock]; @@ -894,9 +864,7 @@ .get_status = hs_get_status, .get_socket = hs_get_socket, .set_socket = hs_set_socket, - .get_io_map = hs_get_io_map, .set_io_map = hs_set_io_map, - .get_mem_map = hs_get_mem_map, .set_mem_map = hs_set_mem_map, .proc_setup = hs_proc_setup, }; diff -Nru a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c --- a/drivers/pcmcia/i82092.c Fri Feb 21 13:05:09 2003 +++ b/drivers/pcmcia/i82092.c Mon Mar 17 07:38:32 2003 @@ -63,9 +63,7 @@ .get_status = i82092aa_get_status, .get_socket = i82092aa_get_socket, .set_socket = i82092aa_set_socket, - .get_io_map = i82092aa_get_io_map, .set_io_map = i82092aa_set_io_map, - .get_mem_map = i82092aa_get_mem_map, .set_mem_map = i82092aa_set_mem_map, .proc_setup = i82092aa_proc_setup, }; @@ -688,34 +686,6 @@ return 0; } -static int i82092aa_get_io_map(unsigned int sock, struct pccard_io_map *io) -{ - unsigned char map, ioctl, addr; - - enter("i82092aa_get_io_map"); - map = io->map; - if (map > 1) { - leave("i82092aa_get_io_map with -EINVAL"); - return -EINVAL; - } - - /* FIXME: How does this fit in with the PCI resource (re)allocation */ - io->start = indirect_read16(sock, I365_IO(map)+I365_W_START); - io->stop = indirect_read16(sock, I365_IO(map)+I365_W_START); - - ioctl = indirect_read(sock,I365_IOCTL); /* IOCREG: I/O Control Register */ - addr = indirect_read(sock,I365_ADDRWIN); /* */ - - io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0; /* check this out later */ - io->flags = 0; - - if (addr & I365_IOCTL_16BIT(map)) - io->flags |= MAP_AUTOSZ; - - leave("i82092aa_get_io_map"); - return 0; -} - static int i82092aa_set_io_map(unsigned sock, struct pccard_io_map *io) { unsigned char map, ioctl; @@ -757,64 +727,6 @@ leave("i82092aa_set_io_map"); return 0; -} - -static int i82092aa_get_mem_map(unsigned sock, struct pccard_mem_map *mem) -{ - unsigned short base, i; - unsigned char map, addr; - - enter("i82092aa_get_mem_map"); - - mem->flags = 0; - mem->speed = 0; - map = mem->map; - if (map > 4) { - leave("i82092aa_get_mem_map: -EINVAL"); - return -EINVAL; - } - - addr = indirect_read(sock, I365_ADDRWIN); - - if (addr & I365_ENA_MEM(map)) - mem->flags |= MAP_ACTIVE; /* yes this mapping is active */ - - base = I365_MEM(map); - - /* Find the start address - this register also has mapping info */ - - i = indirect_read16(sock,base+I365_W_START); - if (i & I365_MEM_16BIT) - mem->flags |= MAP_16BIT; - if (i & I365_MEM_0WS) - mem->flags |= MAP_0WS; - - mem->sys_start = ((unsigned long)(i & 0x0fff) << 12); - - /* Find the end address - this register also has speed info */ - i = indirect_read16(sock,base+I365_W_STOP); - if (i & I365_MEM_WS0) - mem->speed = 1; - if (i & I365_MEM_WS1) - mem->speed += 2; - mem->speed = to_ns(mem->speed); - mem->sys_stop = ( (unsigned long)(i & 0x0fff) << 12) + 0x0fff; - - /* Find the card start address, also some more MAP attributes */ - - i = indirect_read16(sock, base+I365_W_OFF); - if (i & I365_MEM_WRPROT) - mem->flags |= MAP_WRPROT; - if (i & I365_MEM_REG) - mem->flags |= MAP_ATTRIB; - mem->card_start = ( (unsigned long)(i & 0x3fff)<12) + mem->sys_start; - mem->card_start &= 0x3ffffff; - - printk("Card %i is from %lx to %lx \n",sock,mem->sys_start,mem->sys_stop); - - leave("i82092aa_get_mem_map"); - return 0; - } static int i82092aa_set_mem_map(unsigned sock, struct pccard_mem_map *mem) diff -Nru a/drivers/pcmcia/i82092aa.h b/drivers/pcmcia/i82092aa.h --- a/drivers/pcmcia/i82092aa.h Mon Feb 4 23:54:45 2002 +++ b/drivers/pcmcia/i82092aa.h Mon Mar 17 07:38:32 2003 @@ -29,9 +29,7 @@ static int i82092aa_get_status(unsigned int sock, u_int *value); static int i82092aa_get_socket(unsigned int sock, socket_state_t *state); static int i82092aa_set_socket(unsigned int sock, socket_state_t *state); -static int i82092aa_get_io_map(unsigned int sock, struct pccard_io_map *io); static int i82092aa_set_io_map(unsigned int sock, struct pccard_io_map *io); -static int i82092aa_get_mem_map(unsigned int sock, struct pccard_mem_map *mem); static int i82092aa_set_mem_map(unsigned int sock, struct pccard_mem_map *mem); static int i82092aa_init(unsigned int s); static int i82092aa_suspend(unsigned int sock); diff -Nru a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c --- a/drivers/pcmcia/i82365.c Sat Mar 22 06:24:36 2003 +++ b/drivers/pcmcia/i82365.c Wed Mar 26 08:49:33 2003 @@ -1250,29 +1250,6 @@ /*====================================================================*/ -static int i365_get_io_map(u_short sock, struct pccard_io_map *io) -{ - u_char map, ioctl, addr; - - map = io->map; - if (map > 1) return -EINVAL; - io->start = i365_get_pair(sock, I365_IO(map)+I365_W_START); - io->stop = i365_get_pair(sock, I365_IO(map)+I365_W_STOP); - ioctl = i365_get(sock, I365_IOCTL); - addr = i365_get(sock, I365_ADDRWIN); - io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0; - io->flags = (addr & I365_ENA_IO(map)) ? MAP_ACTIVE : 0; - io->flags |= (ioctl & I365_IOCTL_0WS(map)) ? MAP_0WS : 0; - io->flags |= (ioctl & I365_IOCTL_16BIT(map)) ? MAP_16BIT : 0; - io->flags |= (ioctl & I365_IOCTL_IOCS16(map)) ? MAP_AUTOSZ : 0; - DEBUG(1, "i82365: GetIOMap(%d, %d) = %#2.2x, %d ns, " - "%#4.4x-%#4.4x\n", sock, map, io->flags, io->speed, - io->start, io->stop); - return 0; -} /* i365_get_io_map */ - -/*====================================================================*/ - static int i365_set_io_map(u_short sock, struct pccard_io_map *io) { u_char map, ioctl; @@ -1302,42 +1279,6 @@ /*====================================================================*/ -static int i365_get_mem_map(u_short sock, struct pccard_mem_map *mem) -{ - u_short base, i; - u_char map, addr; - - map = mem->map; - if (map > 4) return -EINVAL; - addr = i365_get(sock, I365_ADDRWIN); - mem->flags = (addr & I365_ENA_MEM(map)) ? MAP_ACTIVE : 0; - base = I365_MEM(map); - - i = i365_get_pair(sock, base+I365_W_START); - mem->flags |= (i & I365_MEM_16BIT) ? MAP_16BIT : 0; - mem->flags |= (i & I365_MEM_0WS) ? MAP_0WS : 0; - mem->sys_start = ((u_long)(i & 0x0fff) << 12); - - i = i365_get_pair(sock, base+I365_W_STOP); - mem->speed = (i & I365_MEM_WS0) ? 1 : 0; - mem->speed += (i & I365_MEM_WS1) ? 2 : 0; - mem->speed = to_ns(mem->speed); - mem->sys_stop = ((u_long)(i & 0x0fff) << 12) + 0x0fff; - - i = i365_get_pair(sock, base+I365_W_OFF); - mem->flags |= (i & I365_MEM_WRPROT) ? MAP_WRPROT : 0; - mem->flags |= (i & I365_MEM_REG) ? MAP_ATTRIB : 0; - mem->card_start = ((u_int)(i & 0x3fff) << 12) + mem->sys_start; - mem->card_start &= 0x3ffffff; - - DEBUG(1, "i82365: GetMemMap(%d, %d) = %#2.2x, %d ns, %#5.5lx-%#5." - "5lx, %#5.5x\n", sock, mem->map, mem->flags, mem->speed, - mem->sys_start, mem->sys_stop, mem->card_start); - return 0; -} /* i365_get_mem_map */ - -/*====================================================================*/ - static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem) { u_short base, i; @@ -1506,14 +1447,6 @@ LOCKED(i365_set_socket(sock, state)); } -static int pcic_get_io_map(unsigned int sock, struct pccard_io_map *io) -{ - if (socket[sock].flags & IS_ALIVE) - return -EINVAL; - - LOCKED(i365_get_io_map(sock, io)); -} - static int pcic_set_io_map(unsigned int sock, struct pccard_io_map *io) { if (socket[sock].flags & IS_ALIVE) @@ -1522,14 +1455,6 @@ LOCKED(i365_set_io_map(sock, io)); } -static int pcic_get_mem_map(unsigned int sock, struct pccard_mem_map *mem) -{ - if (socket[sock].flags & IS_ALIVE) - return -EINVAL; - - LOCKED(i365_get_mem_map(sock, mem)); -} - static int pcic_set_mem_map(unsigned int sock, struct pccard_mem_map *mem) { if (socket[sock].flags & IS_ALIVE) @@ -1571,9 +1496,7 @@ .get_status = pcic_get_status, .get_socket = pcic_get_socket, .set_socket = pcic_set_socket, - .get_io_map = pcic_get_io_map, .set_io_map = pcic_set_io_map, - .get_mem_map = pcic_get_mem_map, .set_mem_map = pcic_set_mem_map, .proc_setup = pcic_proc_setup, }; diff -Nru a/drivers/pcmcia/pci_socket.c b/drivers/pcmcia/pci_socket.c --- a/drivers/pcmcia/pci_socket.c Sun Feb 23 01:04:25 2003 +++ b/drivers/pcmcia/pci_socket.c Mon Mar 17 07:38:32 2003 @@ -105,15 +105,6 @@ return -EINVAL; } -static int pci_get_io_map(unsigned int sock, struct pccard_io_map *io) -{ - pci_socket_t *socket = pci_socket_array + sock; - - if (socket->op && socket->op->get_io_map) - return socket->op->get_io_map(socket, io); - return -EINVAL; -} - static int pci_set_io_map(unsigned int sock, struct pccard_io_map *io) { pci_socket_t *socket = pci_socket_array + sock; @@ -123,15 +114,6 @@ return -EINVAL; } -static int pci_get_mem_map(unsigned int sock, struct pccard_mem_map *mem) -{ - pci_socket_t *socket = pci_socket_array + sock; - - if (socket->op && socket->op->get_mem_map) - return socket->op->get_mem_map(socket, mem); - return -EINVAL; -} - static int pci_set_mem_map(unsigned int sock, struct pccard_mem_map *mem) { pci_socket_t *socket = pci_socket_array + sock; @@ -158,9 +140,7 @@ .get_status = pci_get_status, .get_socket = pci_get_socket, .set_socket = pci_set_socket, - .get_io_map = pci_get_io_map, .set_io_map = pci_set_io_map, - .get_mem_map = pci_get_mem_map, .set_mem_map = pci_set_mem_map, .proc_setup = pci_proc_setup, }; diff -Nru a/drivers/pcmcia/pci_socket.h b/drivers/pcmcia/pci_socket.h --- a/drivers/pcmcia/pci_socket.h Sun Feb 23 01:04:25 2003 +++ b/drivers/pcmcia/pci_socket.h Mon Mar 17 07:38:32 2003 @@ -37,9 +37,7 @@ int (*get_status)(struct pci_socket *, unsigned int *); int (*get_socket)(struct pci_socket *, socket_state_t *); int (*set_socket)(struct pci_socket *, socket_state_t *); - int (*get_io_map)(struct pci_socket *, struct pccard_io_map *); int (*set_io_map)(struct pci_socket *, struct pccard_io_map *); - int (*get_mem_map)(struct pci_socket *, struct pccard_mem_map *); int (*set_mem_map)(struct pci_socket *, struct pccard_mem_map *); void (*proc_setup)(struct pci_socket *, struct proc_dir_entry *base); }; diff -Nru a/drivers/pcmcia/ricoh.h b/drivers/pcmcia/ricoh.h --- a/drivers/pcmcia/ricoh.h Fri Oct 18 16:11:25 2002 +++ b/drivers/pcmcia/ricoh.h Mon Mar 17 07:38:32 2003 @@ -170,9 +170,7 @@ yenta_get_status, yenta_get_socket, yenta_set_socket, - yenta_get_io_map, yenta_set_io_map, - yenta_get_mem_map, yenta_set_mem_map, yenta_proc_setup }; diff -Nru a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c --- a/drivers/pcmcia/rsrc_mgr.c Thu Mar 13 16:52:15 2003 +++ b/drivers/pcmcia/rsrc_mgr.c Wed Mar 26 08:49:33 2003 @@ -60,7 +60,7 @@ #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i") INT_MODULE_PARM(probe_mem, 1); /* memory probe? */ -#ifdef CONFIG_ISA +#ifdef CONFIG_PCMCIA_PROBE INT_MODULE_PARM(probe_io, 1); /* IO port probe? */ INT_MODULE_PARM(mem_limit, 0x10000); #endif @@ -83,7 +83,9 @@ /* IO port resource database */ static resource_map_t io_db = { 0, 0, &io_db }; -#ifdef CONFIG_ISA +static DECLARE_MUTEX(rsrc_sem); + +#ifdef CONFIG_PCMCIA_PROBE typedef struct irq_info_t { u_int Attributes; @@ -269,7 +271,7 @@ ======================================================================*/ -#ifdef CONFIG_ISA +#ifdef CONFIG_PCMCIA_PROBE static void do_io_probe(ioaddr_t base, ioaddr_t num) { @@ -333,15 +335,69 @@ /*====================================================================== + This is tricky... when we set up CIS memory, we try to validate + the memory window space allocations. + +======================================================================*/ + +/* Validation function for cards with a valid CIS */ +static int cis_readable(socket_info_t *s, u_long base) +{ + cisinfo_t info1, info2; + int ret; + s->cis_mem.sys_start = base; + s->cis_mem.sys_stop = base+s->cap.map_size-1; + s->cis_virt = ioremap(base, s->cap.map_size); + ret = pcmcia_validate_cis(s->clients, &info1); + /* invalidate mapping and CIS cache */ + iounmap(s->cis_virt); + s->cis_used = 0; + if ((ret != 0) || (info1.Chains == 0)) + return 0; + s->cis_mem.sys_start = base+s->cap.map_size; + s->cis_mem.sys_stop = base+2*s->cap.map_size-1; + s->cis_virt = ioremap(base+s->cap.map_size, s->cap.map_size); + ret = pcmcia_validate_cis(s->clients, &info2); + iounmap(s->cis_virt); + s->cis_used = 0; + return ((ret == 0) && (info1.Chains == info2.Chains)); +} + +/* Validation function for simple memory cards */ +static int checksum(socket_info_t *s, u_long base) +{ + int i, a, b, d; + s->cis_mem.sys_start = base; + s->cis_mem.sys_stop = base+s->cap.map_size-1; + s->cis_virt = ioremap(base, s->cap.map_size); + s->cis_mem.card_start = 0; + s->cis_mem.flags = MAP_ACTIVE; + s->ss_entry->set_mem_map(s->sock, &s->cis_mem); + /* Don't bother checking every word... */ + a = 0; b = -1; + for (i = 0; i < s->cap.map_size; i += 44) { + d = readl(s->cis_virt+i); + a += d; b &= d; + } + iounmap(s->cis_virt); + return (b == -1) ? -1 : (a>>1); +} + +static int checksum_match(socket_info_t *s, u_long base) +{ + int a = checksum(s, base), b = checksum(s, base+s->cap.map_size); + return ((a == b) && (a >= 0)); +} + +/*====================================================================== + The memory probe. If the memory list includes a 64K-aligned block below 1MB, we probe in 64K chunks, and as soon as we accumulate at least mem_limit free space, we quit. ======================================================================*/ -static int do_mem_probe(u_long base, u_long num, - int (*is_valid)(u_long), int (*do_cksum)(u_long), - socket_info_t *s) +static int do_mem_probe(u_long base, u_long num, socket_info_t *s) { u_long i, j, bad, fail, step; @@ -349,18 +405,21 @@ base, base+num-1); bad = fail = 0; step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff); + /* cis_readable wants to map 2x map_size */ + if (step < 2 * s->cap.map_size) + step = 2 * s->cap.map_size; for (i = j = base; i < base+num; i = j + step) { if (!fail) { for (j = i; j < base+num; j += step) if ((check_mem_resource(j, step, s->cap.cb_dev) == 0) && - is_valid(j)) + cis_readable(s, j)) break; fail = ((i == base) && (j == base+num)); } if (fail) { for (j = i; j < base+num; j += 2*step) if ((check_mem_resource(j, 2*step, s->cap.cb_dev) == 0) && - do_cksum(j) && do_cksum(j+step)) + checksum_match(s, j) && checksum_match(s, j + step)) break; } if (i != j) { @@ -374,16 +433,14 @@ return (num - bad); } -#ifdef CONFIG_ISA +#ifdef CONFIG_PCMCIA_PROBE -static u_long inv_probe(int (*is_valid)(u_long), - int (*do_cksum)(u_long), - resource_map_t *m, socket_info_t *s) +static u_long inv_probe(resource_map_t *m, socket_info_t *s) { u_long ok; if (m == &mem_db) return 0; - ok = inv_probe(is_valid, do_cksum, m->next, s); + ok = inv_probe(m->next, s); if (ok) { if (m->base >= 0x100000) sub_interval(&mem_db, m->base, m->num); @@ -391,32 +448,36 @@ } if (m->base < 0x100000) return 0; - return do_mem_probe(m->base, m->num, is_valid, do_cksum, s); + return do_mem_probe(m->base, m->num, s); } -void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long), - int force_low, socket_info_t *s) +void validate_mem(socket_info_t *s) { resource_map_t *m, *n; static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 }; static int hi = 0, lo = 0; u_long b, i, ok = 0; - - if (!probe_mem) return; + int force_low = !(s->cap.features & SS_CAP_PAGE_REGS); + + if (!probe_mem) + return; + + down(&rsrc_sem); /* We do up to four passes through the list */ if (!force_low) { - if (hi++ || (inv_probe(is_valid, do_cksum, mem_db.next, s) > 0)) - return; + if (hi++ || (inv_probe(mem_db.next, s) > 0)) + goto out; printk(KERN_NOTICE "cs: warning: no high memory space " "available!\n"); } - if (lo++) return; + if (lo++) + goto out; for (m = mem_db.next; m != &mem_db; m = n) { n = m->next; /* Only probe < 1 MB */ if (m->base >= 0x100000) continue; if ((m->base | m->num) & 0xffff) { - ok += do_mem_probe(m->base, m->num, is_valid, do_cksum, s); + ok += do_mem_probe(m->base, m->num, s); continue; } /* Special probe for 64K-aligned block */ @@ -426,28 +487,31 @@ if (ok >= mem_limit) sub_interval(&mem_db, b, 0x10000); else - ok += do_mem_probe(b, 0x10000, is_valid, do_cksum, s); + ok += do_mem_probe(b, 0x10000, s); } } } + out: + up(&rsrc_sem); } -#else /* CONFIG_ISA */ +#else /* CONFIG_PCMCIA_PROBE */ -void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long), - int force_low, socket_info_t *s) +void validate_mem(socket_info_t *s) { resource_map_t *m; static int done = 0; - if (!probe_mem || done++) - return; - for (m = mem_db.next; m != &mem_db; m = m->next) - if (do_mem_probe(m->base, m->num, is_valid, do_cksum, s)) - return; + if (probe_mem && done++ == 0) { + down(&rsrc_sem); + for (m = mem_db.next; m != &mem_db; m = m->next) + if (do_mem_probe(m->base, m->num, s)) + break; + up(&rsrc_sem); + } } -#endif /* CONFIG_ISA */ +#endif /* CONFIG_PCMCIA_PROBE */ /*====================================================================== @@ -467,7 +531,9 @@ { ioaddr_t try; resource_map_t *m; - + int ret = -1; + + down(&rsrc_sem); for (m = io_db.next; m != &io_db; m = m->next) { try = (m->base & ~(align-1)) + *base; for (try = (try >= m->base) ? try : try+align; @@ -475,12 +541,16 @@ try += align) { if (request_io_resource(try, num, name, s->cap.cb_dev) == 0) { *base = try; - return 0; + ret = 0; + goto out; } - if (!align) break; + if (!align) + break; } } - return -1; + out: + up(&rsrc_sem); + return ret; } int find_mem_region(u_long *base, u_long num, u_long align, @@ -488,26 +558,35 @@ { u_long try; resource_map_t *m; + int ret = -1; + down(&rsrc_sem); while (1) { for (m = mem_db.next; m != &mem_db; m = m->next) { /* first pass >1MB, second pass <1MB */ - if ((force_low != 0) ^ (m->base < 0x100000)) continue; + if ((force_low != 0) ^ (m->base < 0x100000)) + continue; + try = (m->base & ~(align-1)) + *base; for (try = (try >= m->base) ? try : try+align; (try >= m->base) && (try+num <= m->base+m->num); try += align) { if (request_mem_resource(try, num, name, s->cap.cb_dev) == 0) { *base = try; - return 0; + ret = 0; + goto out; } - if (!align) break; + if (!align) + break; } } - if (force_low) break; + if (force_low) + break; force_low++; } - return -1; + out: + up(&rsrc_sem); + return ret; } /*====================================================================== @@ -518,7 +597,7 @@ ======================================================================*/ -#ifdef CONFIG_ISA +#ifdef CONFIG_PCMCIA_PROBE static void fake_irq(int i, void *d, struct pt_regs *r) { } static inline int check_irq(int irq) @@ -532,66 +611,89 @@ int try_irq(u_int Attributes, int irq, int specific) { irq_info_t *info = &irq_table[irq]; + int ret = 0; + + down(&rsrc_sem); if (info->Attributes & RES_ALLOCATED) { switch (Attributes & IRQ_TYPE) { case IRQ_TYPE_EXCLUSIVE: - return CS_IN_USE; + ret = CS_IN_USE; + break; case IRQ_TYPE_TIME: if ((info->Attributes & RES_IRQ_TYPE) - != RES_IRQ_TYPE_TIME) - return CS_IN_USE; - if (Attributes & IRQ_FIRST_SHARED) - return CS_BAD_ATTRIBUTE; + != RES_IRQ_TYPE_TIME) { + ret = CS_IN_USE; + break; + } + if (Attributes & IRQ_FIRST_SHARED) { + ret = CS_BAD_ATTRIBUTE; + break; + } info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED; info->time_share++; break; case IRQ_TYPE_DYNAMIC_SHARING: if ((info->Attributes & RES_IRQ_TYPE) - != RES_IRQ_TYPE_DYNAMIC) - return CS_IN_USE; - if (Attributes & IRQ_FIRST_SHARED) - return CS_BAD_ATTRIBUTE; + != RES_IRQ_TYPE_DYNAMIC) { + ret = CS_IN_USE; + break; + } + if (Attributes & IRQ_FIRST_SHARED) { + ret = CS_BAD_ATTRIBUTE; + break; + } info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED; info->dyn_share++; break; } } else { - if ((info->Attributes & RES_RESERVED) && !specific) - return CS_IN_USE; - if (check_irq(irq) != 0) - return CS_IN_USE; + if ((info->Attributes & RES_RESERVED) && !specific) { + ret = CS_IN_USE; + goto out; + } + if (check_irq(irq) != 0) { + ret = CS_IN_USE; + goto out; + } switch (Attributes & IRQ_TYPE) { case IRQ_TYPE_EXCLUSIVE: info->Attributes |= RES_ALLOCATED; break; case IRQ_TYPE_TIME: - if (!(Attributes & IRQ_FIRST_SHARED)) - return CS_BAD_ATTRIBUTE; + if (!(Attributes & IRQ_FIRST_SHARED)) { + ret = CS_BAD_ATTRIBUTE; + break; + } info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED; info->time_share = 1; break; case IRQ_TYPE_DYNAMIC_SHARING: - if (!(Attributes & IRQ_FIRST_SHARED)) - return CS_BAD_ATTRIBUTE; + if (!(Attributes & IRQ_FIRST_SHARED)) { + ret = CS_BAD_ATTRIBUTE; + break; + } info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED; info->dyn_share = 1; break; } } - return 0; + out: + up(&rsrc_sem); + return ret; } #endif /*====================================================================*/ -#ifdef CONFIG_ISA +#ifdef CONFIG_PCMCIA_PROBE void undo_irq(u_int Attributes, int irq) { irq_info_t *info; info = &irq_table[irq]; + down(&rsrc_sem); switch (Attributes & IRQ_TYPE) { case IRQ_TYPE_EXCLUSIVE: info->Attributes &= RES_RESERVED; @@ -607,6 +709,7 @@ info->Attributes &= RES_RESERVED; break; } + up(&rsrc_sem); } #endif @@ -629,6 +732,8 @@ return CS_BAD_SIZE; ret = CS_SUCCESS; + + down(&rsrc_sem); switch (adj->Action) { case ADD_MANAGED_RESOURCE: ret = add_interval(&mem_db, base, num); @@ -647,6 +752,7 @@ default: ret = CS_UNSUPPORTED_FUNCTION; } + up(&rsrc_sem); return ret; } @@ -655,7 +761,7 @@ static int adjust_io(adjust_t *adj) { - int base, num; + int base, num, ret = CS_SUCCESS; base = adj->resource.io.BasePort; num = adj->resource.io.NumPorts; @@ -664,11 +770,14 @@ if ((num <= 0) || (base+num > 0x10000) || (base+num <= base)) return CS_BAD_SIZE; + down(&rsrc_sem); switch (adj->Action) { case ADD_MANAGED_RESOURCE: - if (add_interval(&io_db, base, num) != 0) - return CS_IN_USE; -#ifdef CONFIG_ISA + if (add_interval(&io_db, base, num) != 0) { + ret = CS_IN_USE; + break; + } +#ifdef CONFIG_PCMCIA_PROBE if (probe_io) do_io_probe(base, num); #endif @@ -677,18 +786,20 @@ sub_interval(&io_db, base, num); break; default: - return CS_UNSUPPORTED_FUNCTION; + ret = CS_UNSUPPORTED_FUNCTION; break; } + up(&rsrc_sem); - return CS_SUCCESS; + return ret; } /*====================================================================*/ static int adjust_irq(adjust_t *adj) { -#ifdef CONFIG_ISA + int ret = CS_SUCCESS; +#ifdef CONFIG_PCMCIA_PROBE int irq; irq_info_t *info; @@ -696,33 +807,41 @@ if ((irq < 0) || (irq > 15)) return CS_BAD_IRQ; info = &irq_table[irq]; - + + down(&rsrc_sem); switch (adj->Action) { case ADD_MANAGED_RESOURCE: if (info->Attributes & RES_REMOVED) info->Attributes &= ~(RES_REMOVED|RES_ALLOCATED); else - if (adj->Attributes & RES_ALLOCATED) - return CS_IN_USE; + if (adj->Attributes & RES_ALLOCATED) { + ret = CS_IN_USE; + break; + } if (adj->Attributes & RES_RESERVED) info->Attributes |= RES_RESERVED; else info->Attributes &= ~RES_RESERVED; break; case REMOVE_MANAGED_RESOURCE: - if (info->Attributes & RES_REMOVED) - return 0; - if (info->Attributes & RES_ALLOCATED) - return CS_IN_USE; + if (info->Attributes & RES_REMOVED) { + ret = 0; + break; + } + if (info->Attributes & RES_ALLOCATED) { + ret = CS_IN_USE; + break; + } info->Attributes |= RES_ALLOCATED|RES_REMOVED; info->Attributes &= ~RES_RESERVED; break; default: - return CS_UNSUPPORTED_FUNCTION; + ret = CS_UNSUPPORTED_FUNCTION; break; } + up(&rsrc_sem); #endif - return CS_SUCCESS; + return ret; } /*====================================================================*/ diff -Nru a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c --- a/drivers/pcmcia/sa1100_generic.c Thu Mar 6 08:48:29 2003 +++ b/drivers/pcmcia/sa1100_generic.c Mon Mar 17 07:43:04 2003 @@ -52,7 +52,6 @@ #include #include #include -#include #include #include @@ -567,31 +566,6 @@ } /* sa1100_pcmcia_set_socket() */ -/* sa1100_pcmcia_get_io_map() - * ^^^^^^^^^^^^^^^^^^^^^^^^^^ - * Implements the get_io_map() operation for the in-kernel PCMCIA - * service (formerly SS_GetIOMap in Card Services). Just returns an - * I/O map descriptor which was assigned earlier by a set_io_map(). - * - * Returns: 0 on success, -1 if the map index was out of range - */ -static int -sa1100_pcmcia_get_io_map(unsigned int sock, struct pccard_io_map *map) -{ - struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); - int ret = -1; - - DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock); - - if (map->map < MAX_IO_WIN) { - *map = skt->io_map[map->map]; - ret = 0; - } - - return ret; -} - - /* sa1100_pcmcia_set_io_map() * ^^^^^^^^^^^^^^^^^^^^^^^^^^ * Implements the set_io_map() operation for the in-kernel PCMCIA @@ -646,32 +620,6 @@ } /* sa1100_pcmcia_set_io_map() */ -/* sa1100_pcmcia_get_mem_map() - * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * Implements the get_mem_map() operation for the in-kernel PCMCIA - * service (formerly SS_GetMemMap in Card Services). Just returns a - * memory map descriptor which was assigned earlier by a - * set_mem_map() request. - * - * Returns: 0 on success, -1 if the map index was out of range - */ -static int -sa1100_pcmcia_get_mem_map(unsigned int sock, struct pccard_mem_map *map) -{ - struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); - int ret = -1; - - DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock); - - if (map->map < MAX_WIN) { - *map = skt->pc_mem_map[map->map]; - ret = 0; - } - - return ret; -} - - /* sa1100_pcmcia_set_mem_map() * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Implements the set_mem_map() operation for the in-kernel PCMCIA @@ -841,9 +789,7 @@ .get_status = sa1100_pcmcia_get_status, .get_socket = sa1100_pcmcia_get_socket, .set_socket = sa1100_pcmcia_set_socket, - .get_io_map = sa1100_pcmcia_get_io_map, .set_io_map = sa1100_pcmcia_set_io_map, - .get_mem_map = sa1100_pcmcia_get_mem_map, .set_mem_map = sa1100_pcmcia_set_mem_map, #ifdef CONFIG_PROC_FS .proc_setup = sa1100_pcmcia_proc_setup diff -Nru a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c --- a/drivers/pcmcia/tcic.c Sat Mar 22 06:26:14 2003 +++ b/drivers/pcmcia/tcic.c Wed Mar 26 08:49:34 2003 @@ -806,44 +806,6 @@ /*====================================================================*/ -static int tcic_get_io_map(unsigned int lsock, struct pccard_io_map *io) -{ - u_short psock = socket_table[lsock].psock; - u_short base, ioctl; - u_int addr; - - if (io->map > 1) return -EINVAL; - tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT)); - addr = TCIC_IWIN(psock, io->map); - tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X); - base = tcic_getw(TCIC_DATA); - tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X); - ioctl = tcic_getw(TCIC_DATA); - - if (ioctl & TCIC_ICTL_TINY) - io->start = io->stop = base; - else { - io->start = base & (base-1); - io->stop = io->start + (base ^ (base-1)); - } - io->speed = to_ns(ioctl & TCIC_ICTL_WSCNT_MASK); - io->flags = (ioctl & TCIC_ICTL_ENA) ? MAP_ACTIVE : 0; - switch (ioctl & TCIC_ICTL_BW_MASK) { - case TCIC_ICTL_BW_DYN: - io->flags |= MAP_AUTOSZ; break; - case TCIC_ICTL_BW_16: - io->flags |= MAP_16BIT; break; - default: - break; - } - DEBUG(1, "tcic: GetIOMap(%d, %d) = %#2.2x, %d ns, " - "%#4.4x-%#4.4x\n", lsock, io->map, io->flags, - io->speed, io->start, io->stop); - return 0; -} /* tcic_get_io_map */ - -/*====================================================================*/ - static int tcic_set_io_map(unsigned int lsock, struct pccard_io_map *io) { u_short psock = socket_table[lsock].psock; @@ -881,51 +843,6 @@ /*====================================================================*/ -static int tcic_get_mem_map(unsigned int lsock, struct pccard_mem_map *mem) -{ - u_short psock = socket_table[lsock].psock; - u_short addr, ctl; - u_long base, mmap; - - if (mem->map > 3) return -EINVAL; - tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT)); - addr = TCIC_MWIN(psock, mem->map); - - tcic_setw(TCIC_ADDR, addr + TCIC_MBASE_X); - base = tcic_getw(TCIC_DATA); - if (base & TCIC_MBASE_4K_BIT) { - mem->sys_start = base & TCIC_MBASE_HA_MASK; - mem->sys_stop = mem->sys_start; - } else { - base &= TCIC_MBASE_HA_MASK; - mem->sys_start = (base & (base-1)); - mem->sys_stop = mem->sys_start + (base ^ (base-1)); - } - mem->sys_start = mem->sys_start << TCIC_MBASE_HA_SHFT; - mem->sys_stop = (mem->sys_stop << TCIC_MBASE_HA_SHFT) + 0x0fff; - - tcic_setw(TCIC_ADDR, addr + TCIC_MMAP_X); - mmap = tcic_getw(TCIC_DATA); - mem->flags = (mmap & TCIC_MMAP_REG) ? MAP_ATTRIB : 0; - mmap &= TCIC_MMAP_CA_MASK; - mem->card_start = mem->sys_start + (mmap << TCIC_MMAP_CA_SHFT); - mem->card_start &= 0x3ffffff; - - tcic_setw(TCIC_ADDR, addr + TCIC_MCTL_X); - ctl = tcic_getw(TCIC_DATA); - mem->flags |= (ctl & TCIC_MCTL_ENA) ? MAP_ACTIVE : 0; - mem->flags |= (ctl & TCIC_MCTL_B8) ? 0 : MAP_16BIT; - mem->flags |= (ctl & TCIC_MCTL_WP) ? MAP_WRPROT : 0; - mem->speed = to_ns(ctl & TCIC_MCTL_WSCNT_MASK); - - DEBUG(1, "tcic: GetMemMap(%d, %d) = %#2.2x, %d ns, " - "%#5.5lx-%#5.5lx, %#5.5x\n", lsock, mem->map, mem->flags, - mem->speed, mem->sys_start, mem->sys_stop, mem->card_start); - return 0; -} /* tcic_get_mem_map */ - -/*====================================================================*/ - static int tcic_set_mem_map(unsigned int lsock, struct pccard_mem_map *mem) { u_short psock = socket_table[lsock].psock; @@ -1007,9 +924,7 @@ .get_status = tcic_get_status, .get_socket = tcic_get_socket, .set_socket = tcic_set_socket, - .get_io_map = tcic_get_io_map, .set_io_map = tcic_set_io_map, - .get_mem_map = tcic_get_mem_map, .set_mem_map = tcic_set_mem_map, .proc_setup = tcic_proc_setup, }; diff -Nru a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h --- a/drivers/pcmcia/ti113x.h Fri Oct 18 16:11:25 2002 +++ b/drivers/pcmcia/ti113x.h Mon Mar 17 07:38:33 2003 @@ -185,9 +185,7 @@ yenta_get_status, yenta_get_socket, yenta_set_socket, - yenta_get_io_map, yenta_set_io_map, - yenta_get_mem_map, yenta_set_mem_map, yenta_proc_setup }; @@ -230,9 +228,7 @@ yenta_get_status, yenta_get_socket, yenta_set_socket, - yenta_get_io_map, yenta_set_io_map, - yenta_get_mem_map, yenta_set_mem_map, yenta_proc_setup }; @@ -272,9 +268,7 @@ yenta_get_status, yenta_get_socket, yenta_set_socket, - yenta_get_io_map, yenta_set_io_map, - yenta_get_mem_map, yenta_set_mem_map, yenta_proc_setup }; diff -Nru a/drivers/pcmcia/yenta.c b/drivers/pcmcia/yenta.c --- a/drivers/pcmcia/yenta.c Sat Feb 15 08:12:15 2003 +++ b/drivers/pcmcia/yenta.c Mon Mar 17 07:43:04 2003 @@ -27,7 +27,7 @@ #include "i82365.h" #if 0 -#define DEBUG(x,args...) printk(__FUNCTION__ ": " x,##args) +#define DEBUG(x,args...) printk("%s: " x, __FUNCTION__, ##args) #else #define DEBUG(x,args...) #endif @@ -300,29 +300,6 @@ return 0; } -static int yenta_get_io_map(pci_socket_t *socket, struct pccard_io_map *io) -{ - int map; - unsigned char ioctl, addr; - - map = io->map; - if (map > 1) - return -EINVAL; - - io->start = exca_readw(socket, I365_IO(map)+I365_W_START); - io->stop = exca_readw(socket, I365_IO(map)+I365_W_STOP); - - ioctl = exca_readb(socket, I365_IOCTL); - addr = exca_readb(socket, I365_ADDRWIN); - io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0; - io->flags = (addr & I365_ENA_IO(map)) ? MAP_ACTIVE : 0; - io->flags |= (ioctl & I365_IOCTL_0WS(map)) ? MAP_0WS : 0; - io->flags |= (ioctl & I365_IOCTL_16BIT(map)) ? MAP_16BIT : 0; - io->flags |= (ioctl & I365_IOCTL_IOCS16(map)) ? MAP_AUTOSZ : 0; - - return 0; -} - static int yenta_set_io_map(pci_socket_t *socket, struct pccard_io_map *io) { int map; @@ -356,41 +333,6 @@ return 0; } -static int yenta_get_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem) -{ - int map; - unsigned char addr; - unsigned int start, stop, page, offset; - - map = mem->map; - if (map > 4) - return -EINVAL; - - addr = exca_readb(socket, I365_ADDRWIN); - mem->flags = (addr & I365_ENA_MEM(map)) ? MAP_ACTIVE : 0; - - start = exca_readw(socket, I365_MEM(map) + I365_W_START); - mem->flags |= (start & I365_MEM_16BIT) ? MAP_16BIT : 0; - mem->flags |= (start & I365_MEM_0WS) ? MAP_0WS : 0; - start = (start & 0x0fff) << 12; - - stop = exca_readw(socket, I365_MEM(map) + I365_W_STOP); - mem->speed = to_ns(stop >> 14); - stop = ((stop & 0x0fff) << 12) + 0x0fff; - - offset = exca_readw(socket, I365_MEM(map) + I365_W_OFF); - mem->flags |= (offset & I365_MEM_WRPROT) ? MAP_WRPROT : 0; - mem->flags |= (offset & I365_MEM_REG) ? MAP_ATTRIB : 0; - offset = ((offset & 0x3fff) << 12) + start; - mem->card_start = offset & 0x3ffffff; - - page = exca_readb(socket, CB_MEM_PAGE(map)) << 24; - mem->sys_start = start + page; - mem->sys_stop = start + page; - - return 0; -} - static int yenta_set_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem) { int map; @@ -572,7 +514,6 @@ socket->cap.pci_irq = socket->cb_irq; socket->cap.irq_mask = yenta_probe_irq(socket, isa_irq_mask); socket->cap.cb_dev = socket->dev; - socket->cap.bus = NULL; printk("Yenta IRQ list %04x, PCI irq%d\n", socket->cap.irq_mask, socket->cb_irq); } @@ -935,9 +876,7 @@ yenta_get_status, yenta_get_socket, yenta_set_socket, - yenta_get_io_map, yenta_set_io_map, - yenta_get_mem_map, yenta_set_mem_map, yenta_proc_setup }; diff -Nru a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c --- a/drivers/s390/net/ctcmain.c Mon Feb 24 10:24:47 2003 +++ b/drivers/s390/net/ctcmain.c Mon Mar 24 17:11:17 2003 @@ -2761,7 +2761,6 @@ dev->addr_len = 0; dev->type = ARPHRD_SLIP; dev->tx_queue_len = 100; - dev_init_buffers(dev); dev->flags = IFF_POINTOPOINT | IFF_NOARP; return dev; } diff -Nru a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c --- a/drivers/s390/net/netiucv.c Mon Feb 24 10:24:29 2003 +++ b/drivers/s390/net/netiucv.c Mon Mar 24 17:11:17 2003 @@ -1630,7 +1630,6 @@ dev->addr_len = 0; dev->type = ARPHRD_SLIP; dev->tx_queue_len = NETIUCV_QUEUELEN_DEFAULT; - dev_init_buffers(dev); dev->flags = IFF_POINTOPOINT | IFF_NOARP; return dev; } diff -Nru a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c --- a/drivers/scsi/3w-xxxx.c Sun Mar 23 07:52:56 2003 +++ b/drivers/scsi/3w-xxxx.c Wed Mar 26 12:10:23 2003 @@ -677,7 +677,7 @@ dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_AEN_LISTEN.\n"); memset(tw_ioctl->data_buffer, 0, tw_ioctl->data_buffer_length); - spin_lock_irqsave(&tw_dev->host->host_lock, flags); + spin_lock_irqsave(tw_dev->host->host_lock, flags); if (tw_dev->aen_head == tw_dev->aen_tail) { tw_aen_code = TW_AEN_QUEUE_EMPTY; } else { @@ -688,7 +688,7 @@ tw_dev->aen_head = tw_dev->aen_head + 1; } } - spin_unlock_irqrestore(&tw_dev->tw_lock, flags); + spin_unlock_irqrestore(tw_dev->host->host_lock, flags); memcpy(tw_ioctl->data_buffer, &tw_aen_code, sizeof(tw_aen_code)); break; case TW_CMD_PACKET_WITH_DATA: diff -Nru a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c --- a/drivers/scsi/pcmcia/nsp_cs.c Sun Mar 23 03:30:39 2003 +++ b/drivers/scsi/pcmcia/nsp_cs.c Wed Mar 26 08:49:35 2003 @@ -62,7 +62,6 @@ #include #include #include -#include #include "nsp_cs.h" @@ -93,7 +92,6 @@ int ndev; dev_node_t node[8]; int stop; - struct bus_operations *bus; } scsi_info_t; @@ -1948,7 +1946,6 @@ case CS_EVENT_CARD_INSERTION: DEBUG(0, " event: insert\n"); link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - info->bus = args->bus; nsp_cs_config(link); break; diff -Nru a/drivers/serial/21285.c b/drivers/serial/21285.c --- a/drivers/serial/21285.c Thu Mar 6 09:27:42 2003 +++ b/drivers/serial/21285.c Wed Mar 26 06:51:09 2003 @@ -501,10 +501,11 @@ .index = -1, }; -static void __init rs285_console_init(void) +static int __init rs285_console_init(void) { serial21285_setup_ports(); register_console(&serial21285_console); + return 0; } console_initcall(rs285_console_init); diff -Nru a/drivers/serial/Kconfig b/drivers/serial/Kconfig --- a/drivers/serial/Kconfig Mon Mar 10 16:26:26 2003 +++ b/drivers/serial/Kconfig Tue Mar 18 09:05:10 2003 @@ -372,14 +372,25 @@ bool "Use NEC V850E on-chip UART for console" depends on V850E_NB85E_UART +config SERIAL98 + tristate "PC-9800 8251-based primary serial port support" + depends on X86_PC9800 + help + If you want to use standard primary serial ports on PC-9800, + say Y. Otherwise, say N. + +config SERIAL98_CONSOLE + bool "Support for console on PC-9800 standard serial port" + depends on SERIAL98=y + config SERIAL_CORE tristate - default m if SERIAL_AMBA!=y && SERIAL_CLPS711X!=y && SERIAL_21285!=y && !SERIAL_SA1100 && !SERIAL_ANAKIN && !SERIAL_UART00 && SERIAL_8250!=y && SERIAL_MUX!=y && !SERIAL_ROCKETPORT && !SERIAL_SUNCORE && !V850E_NB85E_UART && (SERIAL_AMBA=m || SERIAL_CLPS711X=m || SERIAL_21285=m || SERIAL_8250=m || SERIAL_MUX=m) - default y if SERIAL_AMBA=y || SERIAL_CLPS711X=y || SERIAL_21285=y || SERIAL_SA1100 || SERIAL_ANAKIN || SERIAL_UART00 || SERIAL_8250=y || SERIAL_MUX=y || SERIAL_ROCKETPORT || SERIAL_SUNCORE || V850E_NB85E_UART + default m if SERIAL_AMBA!=y && SERIAL_CLPS711X!=y && SERIAL_21285!=y && !SERIAL_SA1100 && !SERIAL_ANAKIN && !SERIAL_UART00 && SERIAL_8250!=y && SERIAL_MUX!=y && !SERIAL_ROCKETPORT && !SERIAL_SUNCORE && !V850E_NB85E_UART && (SERIAL_AMBA=m || SERIAL_CLPS711X=m || SERIAL_21285=m || SERIAL_8250=m || SERIAL_MUX=m || SERIAL98=m) + default y if SERIAL_AMBA=y || SERIAL_CLPS711X=y || SERIAL_21285=y || SERIAL_SA1100 || SERIAL_ANAKIN || SERIAL_UART00 || SERIAL_8250=y || SERIAL_MUX=y || SERIAL_ROCKETPORT || SERIAL_SUNCORE || V850E_NB85E_UART || SERIAL98=y config SERIAL_CORE_CONSOLE bool - depends on SERIAL_AMBA_CONSOLE || SERIAL_CLPS711X_CONSOLE || SERIAL_21285_CONSOLE || SERIAL_SA1100_CONSOLE || SERIAL_ANAKIN_CONSOLE || SERIAL_UART00_CONSOLE || SERIAL_8250_CONSOLE || SERIAL_MUX_CONSOLE || SERIAL_SUNCORE || V850E_NB85E_UART_CONSOLE + depends on SERIAL_AMBA_CONSOLE || SERIAL_CLPS711X_CONSOLE || SERIAL_21285_CONSOLE || SERIAL_SA1100_CONSOLE || SERIAL_ANAKIN_CONSOLE || SERIAL_UART00_CONSOLE || SERIAL_8250_CONSOLE || SERIAL_MUX_CONSOLE || SERIAL_SUNCORE || V850E_NB85E_UART_CONSOLE || SERIAL98_CONSOLE default y config SERIAL_68328 diff -Nru a/drivers/serial/Makefile b/drivers/serial/Makefile --- a/drivers/serial/Makefile Mon Feb 3 14:19:37 2003 +++ b/drivers/serial/Makefile Thu Mar 13 17:07:59 2003 @@ -27,3 +27,4 @@ obj-$(CONFIG_SERIAL_68360) += 68360serial.o obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o obj-$(CONFIG_V850E_NB85E_UART) += nb85e_uart.o +obj-$(CONFIG_SERIAL98) += serial98.o diff -Nru a/drivers/usb/Makefile b/drivers/usb/Makefile --- a/drivers/usb/Makefile Sat Dec 14 04:38:56 2002 +++ b/drivers/usb/Makefile Tue Mar 25 05:06:43 2003 @@ -14,6 +14,7 @@ obj-$(CONFIG_USB_ACM) += class/ obj-$(CONFIG_USB_AUDIO) += class/ obj-$(CONFIG_USB_BLUETOOTH_TTY) += class/ +obj-$(CONFIG_USB_MIDI) += class/ obj-$(CONFIG_USB_PRINTER) += class/ obj-$(CONFIG_USB_STORAGE) += storage/ diff -Nru a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c --- a/drivers/usb/class/audio.c Sat Jan 11 16:14:33 2003 +++ b/drivers/usb/class/audio.c Tue Mar 25 15:16:14 2003 @@ -172,7 +172,6 @@ /*****************************************************************************/ -#include #include #include #include diff -Nru a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c --- a/drivers/usb/class/cdc-acm.c Thu Mar 13 10:36:02 2003 +++ b/drivers/usb/class/cdc-acm.c Mon Mar 24 05:50:18 2003 @@ -538,7 +538,7 @@ cfacm = dev->config + i; - dbg("probing config %d", cfacm->bConfigurationValue); + dbg("probing config %d", cfacm->desc.bConfigurationValue); if (cfacm->desc.bNumInterfaces != 2 || usb_interface_claimed(cfacm->interface + 0) || diff -Nru a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c --- a/drivers/usb/core/buffer.c Tue Dec 24 05:41:22 2002 +++ b/drivers/usb/core/buffer.c Tue Mar 25 15:16:14 2003 @@ -7,7 +7,6 @@ #include #include -#include #include #include #include diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c --- a/drivers/usb/core/hcd.c Wed Jan 22 10:02:11 2003 +++ b/drivers/usb/core/hcd.c Thu Mar 20 04:01:59 2003 @@ -1024,9 +1024,7 @@ */ urb->transfer_flags |= URB_NO_DMA_MAP; status = rh_urb_enqueue (hcd, urb); - if (status) - urb_unlink (urb); - return status; + goto done; } /* lower level hcd code should use *_dma exclusively, @@ -1051,8 +1049,11 @@ } status = hcd->driver->urb_enqueue (hcd, urb, mem_flags); - if (status) +done: + if (status) { + usb_put_urb (urb); urb_unlink (urb); + } return status; } diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c --- a/drivers/usb/core/hub.c Fri Mar 14 14:59:45 2003 +++ b/drivers/usb/core/hub.c Sat Mar 22 12:02:59 2003 @@ -135,8 +135,7 @@ default: /* presumably an error */ /* Cause a hub reset after 10 consecutive errors */ - dbg("hub '%s' status %d for interrupt transfer", - urb->dev->devpath, urb->status); + dev_dbg (&hub->intf->dev, "transfer --> %d\n", urb->status); if ((++hub->nerrors < 10) || hub->error) goto resubmit; hub->error = urb->status; @@ -158,10 +157,10 @@ spin_unlock_irqrestore(&hub_event_lock, flags); resubmit: - if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0) - err ("hub '%s-%s' status %d for interrupt resubmit", - urb->dev->bus->bus_name, urb->dev->devpath, - status); + if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0 + /* ENODEV means we raced disconnect() */ + && status != -ENODEV) + dev_err (&hub->intf->dev, "resubmit --> %d\n", urb->status); } /* USB 2.0 spec Section 11.24.2.3 */ @@ -648,12 +647,13 @@ struct usb_port_status *portsts; int ret = -ENOMEM; - portsts = kmalloc(sizeof(*portsts), GFP_KERNEL); + portsts = kmalloc(sizeof(*portsts), GFP_NOIO); if (portsts) { ret = usb_get_port_status(hub, port + 1, portsts); if (ret < 0) - err("%s(%s-%s) failed (err = %d)", __FUNCTION__, - hub->bus->bus_name, hub->devpath, ret); + dev_err (hubdev (hub), + "%s failed (err = %d)\n", __FUNCTION__, + ret); else { *status = le16_to_cpu(portsts->wPortStatus); *change = le16_to_cpu(portsts->wPortChange); @@ -759,8 +759,8 @@ ret = usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_ENABLE); if (ret) - err("cannot disable port %d of hub %s (err = %d)", - port + 1, hub->devpath, ret); + dev_err(hubdev(hub), "cannot disable port %d (err = %d)\n", + port + 1, ret); } /* USB 2.0 spec, 7.1.7.3 / fig 7-29: @@ -983,12 +983,12 @@ spin_unlock_irqrestore(&hub_event_lock, flags); if (hub->error) { - dbg("resetting hub %s for error %d", - dev->devpath, hub->error); + dev_dbg (&hub->intf->dev, "resetting for error %d\n", + hub->error); if (usb_hub_reset(hub)) { - err("error resetting hub %s - disconnecting", - dev->devpath); + dev_dbg (&hub->intf->dev, + "can't reset; disconnecting\n"); up(&hub->khubd_sem); usb_hub_disconnect(dev); continue; @@ -1022,33 +1022,37 @@ if (!(portstatus & USB_PORT_STAT_ENABLE) && (portstatus & USB_PORT_STAT_CONNECTION) && (dev->children[i])) { - err("already running hub %s port %i " + dev_err (&hub->intf->dev, + "port %i " "disabled by hub (EMI?), " "re-enabling...", - dev->devpath, i + 1); + i + 1); usb_hub_port_connect_change(hub, i, portstatus, portchange); } } if (portchange & USB_PORT_STAT_C_SUSPEND) { - dbg("hub %s port %d suspend change", - dev->devpath, i + 1); + dev_dbg (&hub->intf->dev, + "suspend change on port %d\n", + i + 1); usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_SUSPEND); } if (portchange & USB_PORT_STAT_C_OVERCURRENT) { - err("hub %s port %d over-current change", - dev->devpath, i + 1); + dev_err (&hub->intf->dev, + "over-current change on port %d\n", + i + 1); usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT); usb_hub_power_on(hub); } if (portchange & USB_PORT_STAT_C_RESET) { - dbg("hub %s port %d reset change", - dev->devpath, i + 1); + dev_dbg (&hub->intf->dev, + "reset change on port %d\n", + i + 1); usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET); } @@ -1056,16 +1060,16 @@ /* deal with hub status changes */ if (usb_get_hub_status(dev, &hubsts) < 0) - err("get_hub_status %s failed", dev->devpath); + dev_err (&hub->intf->dev, "get_hub_status failed\n"); else { hubstatus = le16_to_cpup(&hubsts.wHubStatus); hubchange = le16_to_cpup(&hubsts.wHubChange); if (hubchange & HUB_CHANGE_LOCAL_POWER) { - dbg("hub %s power change", dev->devpath); + dev_dbg (&hub->intf->dev, "power change\n"); usb_clear_hub_feature(dev, C_HUB_LOCAL_POWER); } if (hubchange & HUB_CHANGE_OVERCURRENT) { - dbg("hub %s overcurrent change", dev->devpath); + dev_dbg (&hub->intf->dev, "overcurrent change\n"); wait_ms(500); /* Cool down */ usb_clear_hub_feature(dev, C_HUB_OVER_CURRENT); usb_hub_power_on(hub); diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c --- a/drivers/usb/core/message.c Tue Mar 18 02:21:55 2003 +++ b/drivers/usb/core/message.c Sat Mar 8 09:31:29 2003 @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "hcd.h" /* for usbcore internals */ diff -Nru a/drivers/usb/core/usb-debug.c b/drivers/usb/core/usb-debug.c --- a/drivers/usb/core/usb-debug.c Tue Jan 7 06:49:31 2003 +++ b/drivers/usb/core/usb-debug.c Tue Mar 25 15:16:15 2003 @@ -5,7 +5,6 @@ * face, but so that you can still use them.. */ #include -#include #include #include #include diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c --- a/drivers/usb/core/usb.c Wed Mar 5 07:29:53 2003 +++ b/drivers/usb/core/usb.c Thu Mar 20 02:21:34 2003 @@ -866,14 +866,11 @@ } /** - * usb_connect - connects a new device during enumeration (usbcore-internal) - * @dev: partially enumerated device - * - * Connect a new USB device. This basically just initializes - * the USB device information and sets up the topology - it's - * up to the low-level driver to reset the port and actually - * do the setup (the upper levels don't know how to do that). + * usb_connect - pick device address (usbcore-internal) + * @dev: newly detected device (in DEFAULT state) * + * Picks a device address. It's up to the hub (or root hub) driver + * to handle and manage enumeration, starting from the DEFAULT state. * Only hub drivers (including virtual root hub drivers for host * controllers) should ever call this. */ @@ -983,7 +980,7 @@ } /* - * By the time we get here, the device has gotten a new device ID + * By the time we get here, we chose a new device address * and is in the default state. We need to identify the thing and * get the ball rolling.. * diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c --- a/drivers/usb/host/ohci-hcd.c Mon Feb 24 03:56:31 2003 +++ b/drivers/usb/host/ohci-hcd.c Tue Mar 25 15:16:15 2003 @@ -94,7 +94,6 @@ #include #include /* for in_interrupt () */ #include -#include #include "../core/hcd.h" #include diff -Nru a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c --- a/drivers/usb/image/mdc800.c Tue Feb 25 10:47:47 2003 +++ b/drivers/usb/image/mdc800.c Tue Mar 25 15:16:15 2003 @@ -85,7 +85,6 @@ * (20/10/1999) */ -#include #include #include #include diff -Nru a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c --- a/drivers/usb/media/ov511.c Sun Feb 16 13:08:12 2003 +++ b/drivers/usb/media/ov511.c Tue Mar 25 15:16:15 2003 @@ -36,7 +36,6 @@ */ #include -#include #include #include #include diff -Nru a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c --- a/drivers/usb/media/stv680.c Fri Dec 27 05:20:06 2002 +++ b/drivers/usb/media/stv680.c Tue Mar 25 15:16:15 2003 @@ -60,7 +60,6 @@ #include #include -#include #include #include #include diff -Nru a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c --- a/drivers/usb/misc/emi26.c Mon Sep 16 14:40:32 2002 +++ b/drivers/usb/misc/emi26.c Sun Mar 23 18:27:29 2003 @@ -78,19 +78,28 @@ return response; } +#define FW_LOAD_SIZE 1023 + static int emi26_load_firmware (struct usb_device *dev) { int err; int i; int pos = 0; /* Position in hex record */ __u32 addr; /* Address to write */ - __u8 buf[1023]; + __u8 *buf; + + buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL); + if (!buf) { + err( "%s - error loading firmware: error = %d", __FUNCTION__, -ENOMEM); + err = -ENOMEM; + goto wraperr; + } /* Assert reset (stop the CPU in the EMI) */ err = emi26_set_reset(dev,1); if (err < 0) { err( "%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } /* 1. We need to put the loader for the FPGA into the EZ-USB */ @@ -98,7 +107,7 @@ err = emi26_writememory(dev, g_Loader[i].address, g_Loader[i].data, g_Loader[i].length, ANCHOR_LOAD_INTERNAL); if (err < 0) { err("%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } } @@ -113,7 +122,7 @@ addr = g_bitstream[pos].address; /* intel hex records are terminated with type 0 element */ - while ((g_bitstream[pos].type == 0) && (i + g_bitstream[pos].length < sizeof(buf))) { + while ((g_bitstream[pos].type == 0) && (i + g_bitstream[pos].length < FW_LOAD_SIZE)) { memcpy(buf + i, g_bitstream[pos].data, g_bitstream[pos].length); i += g_bitstream[pos].length; pos++; @@ -121,7 +130,7 @@ err = emi26_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA); if (err < 0) { err("%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } } while (i > 0); @@ -129,7 +138,7 @@ err = emi26_set_reset(dev,1); if (err < 0) { err("%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } /* 3. We need to put the loader for the firmware into the EZ-USB (again...) */ @@ -137,7 +146,7 @@ err = emi26_writememory(dev, g_Loader[i].address, g_Loader[i].data, g_Loader[i].length, ANCHOR_LOAD_INTERNAL); if (err < 0) { err("%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } } @@ -145,7 +154,7 @@ err = emi26_set_reset(dev,0); if (err < 0) { err("%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } /* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */ @@ -154,7 +163,7 @@ err = emi26_writememory(dev, g_Firmware[i].address, g_Firmware[i].data, g_Firmware[i].length, ANCHOR_LOAD_EXTERNAL); if (err < 0) { err("%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } } } @@ -163,7 +172,7 @@ err = emi26_set_reset(dev,1); if (err < 0) { err("%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } for (i=0; g_Firmware[i].type == 0; i++) { @@ -171,7 +180,7 @@ err = emi26_writememory(dev, g_Firmware[i].address, g_Firmware[i].data, g_Firmware[i].length, ANCHOR_LOAD_INTERNAL); if (err < 0) { err("%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } } } @@ -180,12 +189,16 @@ err = emi26_set_reset(dev,0); if (err < 0) { err("%s - error loading firmware: error = %d", __FUNCTION__, err); - return err; + goto wraperr; } /* return 1 to fail the driver inialization * and give real driver change to load */ return 1; + +wraperr: + kfree(buf); + return err; } static __devinitdata struct usb_device_id id_table [] = { diff -Nru a/drivers/usb/misc/speedtch.c b/drivers/usb/misc/speedtch.c --- a/drivers/usb/misc/speedtch.c Tue Mar 18 04:15:55 2003 +++ b/drivers/usb/misc/speedtch.c Tue Mar 25 02:27:35 2003 @@ -148,27 +148,15 @@ #define UDSL_SKB(x) ((struct udsl_control *)(x)->cb) -struct atmsar_vcc_data { - struct atmsar_vcc_data *next; - - /* general atmsar flags, per connection */ - int flags; - int type; - - /* connection specific non-atmsar data */ +struct udsl_vcc_data { + /* vpi/vci lookup */ + struct list_head list; + short vpi; + int vci; struct atm_vcc *vcc; - struct k_atm_aal_stats *stats; - unsigned short mtu; /* max is actually 65k for AAL5... */ - - /* cell data */ - unsigned int vp; - unsigned int vc; - unsigned char gfc; - unsigned char pti; - unsigned int headerFlags; - unsigned long atmHeader; /* raw cell reassembly */ + unsigned short mtu; struct sk_buff *reasBuffer; }; @@ -186,7 +174,7 @@ /* atm device part */ struct atm_dev *atm_dev; - struct atmsar_vcc_data *atmsar_vcc_list; + struct list_head vcc_list; /* receiving */ struct udsl_receiver all_receivers [UDSL_NUMBER_RCV_URBS]; @@ -258,73 +246,46 @@ ** decode ** *************/ -#define ATM_HDR_VPVC_MASK (ATM_HDR_VPI_MASK | ATM_HDR_VCI_MASK) -#define ATMSAR_USE_53BYTE_CELL 0x1L +static inline struct udsl_vcc_data *udsl_find_vcc (struct udsl_instance_data *instance, short vpi, int vci) +{ + struct udsl_vcc_data *vcc; -struct sk_buff *atmsar_decode_rawcell (struct atmsar_vcc_data *list, struct sk_buff *skb, - struct atmsar_vcc_data **ctx) + list_for_each_entry (vcc, &instance->vcc_list, list) + if ((vcc->vpi == vpi) && (vcc->vci == vci)) + return vcc; + return NULL; +} + +static struct sk_buff *udsl_decode_rawcell (struct udsl_instance_data *instance, struct sk_buff *skb, struct udsl_vcc_data **ctx) { + if (!instance || !skb || !ctx) + return NULL; + if (!skb->data || !skb->tail) + return NULL; + while (skb->len) { unsigned char *cell = skb->data; unsigned char *cell_payload; - struct atmsar_vcc_data *vcc = list; - unsigned long atmHeader = - ((unsigned long) (cell[0]) << 24) | ((unsigned long) (cell[1]) << 16) | - ((unsigned long) (cell[2]) << 8) | (cell[3] & 0xff); - - dbg ("atmsar_decode_rawcell (0x%p, 0x%p, 0x%p) called", list, skb, ctx); - dbg ("atmsar_decode_rawcell skb->data %p, skb->tail %p", skb->data, skb->tail); - - if (!list || !skb || !ctx) - return NULL; - if (!skb->data || !skb->tail) - return NULL; + struct udsl_vcc_data *vcc; + short vpi; + int vci; + + vpi = ((cell[0] & 0x0f) << 4) | (cell[1] >> 4); + vci = ((cell[1] & 0x0f) << 12) | (cell[2] << 4) | (cell[3] >> 4); + + dbg ("udsl_decode_rawcell (0x%p, 0x%p, 0x%p) called", instance, skb, ctx); + dbg ("udsl_decode_rawcell skb->data %p, skb->tail %p", skb->data, skb->tail); /* here should the header CRC check be... */ - /* look up correct vcc */ - for (; - vcc - && ((vcc->atmHeader & ATM_HDR_VPVC_MASK) != (atmHeader & ATM_HDR_VPVC_MASK)); - vcc = vcc->next); - - dbg ("atmsar_decode_rawcell found vcc %p for packet on vp %d, vc %d", vcc, - (int) ((atmHeader & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT), - (int) ((atmHeader & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT)); - - if (vcc && (skb->len >= (vcc->flags & ATMSAR_USE_53BYTE_CELL ? 53 : 52))) { - cell_payload = cell + (vcc->flags & ATMSAR_USE_53BYTE_CELL ? 5 : 4); - - switch (vcc->type) { - case ATM_AAL0: - /* case ATM_AAL1: when we have a decode AAL1 function... */ - { - struct sk_buff *tmp = dev_alloc_skb (vcc->mtu); - - if (tmp) { - memcpy (tmp->tail, cell_payload, 48); - skb_put (tmp, 48); - - if (vcc->stats) - atomic_inc (&vcc->stats->rx); - - skb_pull (skb, - (vcc-> - flags & ATMSAR_USE_53BYTE_CELL ? 53 : - 52)); - dbg - ("atmsar_decode_rawcell returns ATM_AAL0 pdu 0x%p with length %d", - tmp, tmp->len); - return tmp; - }; - } - break; - case ATM_AAL1: - case ATM_AAL2: - case ATM_AAL34: - /* not supported */ - break; - case ATM_AAL5: + if (!(vcc = udsl_find_vcc (instance, vpi, vci))) + dbg ("udsl_decode_rawcell: no vcc found for packet on vpi %d, vci %d", vpi, vci); + else { + dbg ("udsl_decode_rawcell found vcc %p for packet on vpi %d, vci %d", vcc, vpi, vci); + + if (skb->len >= 53) { + cell_payload = cell + 5; + if (!vcc->reasBuffer) vcc->reasBuffer = dev_alloc_skb (vcc->mtu); @@ -347,43 +308,36 @@ /* the aal5 buffer ends here, cut the buffer. */ /* buffer will always have at least one whole cell, so */ /* don't need to check return from skb_pull */ - skb_pull (skb, - (vcc-> - flags & ATMSAR_USE_53BYTE_CELL ? 53 : - 52)); + skb_pull (skb, 53); *ctx = vcc; tmp = vcc->reasBuffer; vcc->reasBuffer = NULL; - dbg - ("atmsar_decode_rawcell returns ATM_AAL5 pdu 0x%p with length %d", - tmp, tmp->len); + dbg ("udsl_decode_rawcell returns ATM_AAL5 pdu 0x%p with length %d", tmp, tmp->len); return tmp; } } - break; - }; - /* flush the cell */ - /* buffer will always contain at least one whole cell, so don't */ - /* need to check return value from skb_pull */ - skb_pull (skb, (vcc->flags & ATMSAR_USE_53BYTE_CELL ? 53 : 52)); - } else { - /* If data is corrupt and skb doesn't hold a whole cell, flush the lot */ - if (skb_pull (skb, (list->flags & ATMSAR_USE_53BYTE_CELL ? 53 : 52)) == - NULL) - return NULL; + /* flush the cell */ + /* buffer will always contain at least one whole cell, so don't */ + /* need to check return value from skb_pull */ + skb_pull (skb, 53); + } else { + /* If data is corrupt and skb doesn't hold a whole cell, flush the lot */ + if (skb_pull (skb, 53) == NULL) + return NULL; + } } } return NULL; -}; +} -struct sk_buff *atmsar_decode_aal5 (struct atmsar_vcc_data *ctx, struct sk_buff *skb) +static struct sk_buff *udsl_decode_aal5 (struct udsl_vcc_data *ctx, struct sk_buff *skb) { uint crc = 0xffffffff; uint length, pdu_crc, pdu_length; - dbg ("atmsar_decode_aal5 (0x%p, 0x%p) called", ctx, skb); + dbg ("udsl_decode_aal5 (0x%p, 0x%p) called", ctx, skb); if (skb->len && (skb->len % 48)) return NULL; @@ -393,20 +347,18 @@ (skb->tail[-4] << 24) + (skb->tail[-3] << 16) + (skb->tail[-2] << 8) + skb->tail[-1]; pdu_length = ((length + 47 + 8) / 48) * 48; - dbg ("atmsar_decode_aal5: skb->len = %d, length = %d, pdu_crc = 0x%x, pdu_length = %d", - skb->len, length, pdu_crc, pdu_length); + dbg ("udsl_decode_aal5: skb->len = %d, length = %d, pdu_crc = 0x%x, pdu_length = %d", skb->len, length, pdu_crc, pdu_length); /* is skb long enough ? */ if (skb->len < pdu_length) { - if (ctx->stats) - atomic_inc (&ctx->stats->rx_err); + if (ctx->vcc->stats) + atomic_inc (&ctx->vcc->stats->rx_err); return NULL; } /* is skb too long ? */ if (skb->len > pdu_length) { - dbg ("atmsar_decode_aal5: Warning: readjusting illeagl size %d -> %d", - skb->len, pdu_length); + dbg ("udsl_decode_aal5: Warning: readjusting illegal size %d -> %d", skb->len, pdu_length); /* buffer is too long. we can try to recover * if we discard the first part of the skb. * the crc will decide whether this was ok @@ -418,9 +370,9 @@ /* check crc */ if (pdu_crc != crc) { - dbg ("atmsar_decode_aal5: crc check failed!"); - if (ctx->stats) - atomic_inc (&ctx->stats->rx_err); + dbg ("udsl_decode_aal5: crc check failed!"); + if (ctx->vcc->stats) + atomic_inc (&ctx->vcc->stats->rx_err); return NULL; } @@ -428,19 +380,20 @@ skb_trim (skb, length); /* update stats */ - if (ctx->stats) - atomic_inc (&ctx->stats->rx); + if (ctx->vcc->stats) + atomic_inc (&ctx->vcc->stats->rx); - dbg ("atmsar_decode_aal5 returns pdu 0x%p with length %d", skb, skb->len); + dbg ("udsl_decode_aal5 returns pdu 0x%p with length %d", skb, skb->len); return skb; -}; +} /************* ** encode ** *************/ -static void udsl_groom_skb (struct atm_vcc *vcc, struct sk_buff *skb) { +static void udsl_groom_skb (struct atm_vcc *vcc, struct sk_buff *skb) +{ struct udsl_control *ctrl = UDSL_SKB (skb); unsigned int i, zero_padding; unsigned char zero = 0; @@ -480,7 +433,8 @@ ctrl->aal5_trailer [7] = crc; } -unsigned int udsl_write_cells (unsigned int howmany, struct sk_buff *skb, unsigned char **target_p) { +static unsigned int udsl_write_cells (unsigned int howmany, struct sk_buff *skb, unsigned char **target_p) +{ struct udsl_control *ctrl = UDSL_SKB (skb); unsigned char *target = *target_p; unsigned int nc, ne, i; @@ -569,7 +523,7 @@ unsigned char *data_start; struct sk_buff *skb; struct urb *urb; - struct atmsar_vcc_data *atmsar_vcc = NULL; + struct udsl_vcc_data *atmsar_vcc = NULL; struct sk_buff *new = NULL, *tmp = NULL; int err; @@ -597,40 +551,28 @@ dbg ("skb->len = %d", skb->len); PACKETDEBUG (skb->data, skb->len); - while ((new = - atmsar_decode_rawcell (instance->atmsar_vcc_list, skb, - &atmsar_vcc)) != NULL) { + while ((new = udsl_decode_rawcell (instance, skb, &atmsar_vcc))) { dbg ("(after cell processing)skb->len = %d", new->len); - switch (atmsar_vcc->type) { - case ATM_AAL5: - tmp = new; - new = atmsar_decode_aal5 (atmsar_vcc, new); - - /* we can't send NULL skbs upstream, the ATM layer would try to close the vcc... */ - if (new) { - dbg ("(after aal5 decap) skb->len = %d", new->len); - if (new->len && atm_charge (atmsar_vcc->vcc, new->truesize)) { - PACKETDEBUG (new->data, new->len); - atmsar_vcc->vcc->push (atmsar_vcc->vcc, new); - } else { - dbg - ("dropping incoming packet : rx_inuse = %d, vcc->sk->rcvbuf = %d, skb->true_size = %d", - atomic_read (&atmsar_vcc->vcc->rx_inuse), - atmsar_vcc->vcc->sk->rcvbuf, new->truesize); - dev_kfree_skb (new); - } + tmp = new; + new = udsl_decode_aal5 (atmsar_vcc, new); + + /* we can't send NULL skbs upstream, the ATM layer would try to close the vcc... */ + if (new) { + dbg ("(after aal5 decap) skb->len = %d", new->len); + if (new->len && atm_charge (atmsar_vcc->vcc, new->truesize)) { + PACKETDEBUG (new->data, new->len); + atmsar_vcc->vcc->push (atmsar_vcc->vcc, new); } else { - dbg ("atmsar_decode_aal5 returned NULL!"); - dev_kfree_skb (tmp); + dbg + ("dropping incoming packet : rx_inuse = %d, vcc->sk->rcvbuf = %d, skb->true_size = %d", + atomic_read (&atmsar_vcc->vcc->rx_inuse), + atmsar_vcc->vcc->sk->rcvbuf, new->truesize); + dev_kfree_skb (new); } - break; - default: - /* not supported. we delete the skb. */ - printk (KERN_INFO - "SpeedTouch USB: illegal vcc type. Dropping packet.\n"); - dev_kfree_skb (new); - break; + } else { + dbg ("udsl_decode_aal5 returned NULL!"); + dev_kfree_skb (tmp); } } @@ -901,95 +843,6 @@ ** ATM ** **********/ -#define ATMSAR_DEF_MTU_AAL0 48 -#define ATMSAR_DEF_MTU_AAL1 47 -#define ATMSAR_DEF_MTU_AAL2 0 /* not supported */ -#define ATMSAR_DEF_MTU_AAL34 0 /* not supported */ -#define ATMSAR_DEF_MTU_AAL5 65535 /* max mtu .. */ - -struct atmsar_vcc_data *atmsar_open (struct atmsar_vcc_data **list, struct atm_vcc *vcc, uint type, - ushort vpi, ushort vci, unchar pti, unchar gfc, uint flags) -{ - struct atmsar_vcc_data *new; - - if (!vcc) - return NULL; - - new = kmalloc (sizeof (struct atmsar_vcc_data), GFP_KERNEL); - - if (!new) - return NULL; - - memset (new, 0, sizeof (struct atmsar_vcc_data)); - new->vcc = vcc; - new->stats = vcc->stats; - new->type = type; - new->next = NULL; - new->gfc = gfc; - new->vp = vpi; - new->vc = vci; - new->pti = pti; - - switch (type) { - case ATM_AAL0: - new->mtu = ATMSAR_DEF_MTU_AAL0; - break; - case ATM_AAL1: - new->mtu = ATMSAR_DEF_MTU_AAL1; - break; - case ATM_AAL2: - new->mtu = ATMSAR_DEF_MTU_AAL2; - break; - case ATM_AAL34: - /* not supported */ - new->mtu = ATMSAR_DEF_MTU_AAL34; - break; - case ATM_AAL5: - new->mtu = ATMSAR_DEF_MTU_AAL5; - break; - } - - new->atmHeader = ((unsigned long) gfc << ATM_HDR_GFC_SHIFT) - | ((unsigned long) vpi << ATM_HDR_VPI_SHIFT) - | ((unsigned long) vci << ATM_HDR_VCI_SHIFT) - | ((unsigned long) pti << ATM_HDR_PTI_SHIFT); - new->flags = flags; - new->next = NULL; - new->reasBuffer = NULL; - - new->next = *list; - *list = new; - - dbg ("Allocated new SARLib vcc 0x%p with vp %d vc %d", new, vpi, vci); - - return new; -} - -void atmsar_close (struct atmsar_vcc_data **list, struct atmsar_vcc_data *vcc) -{ - struct atmsar_vcc_data *work; - - if (*list == vcc) { - *list = (*list)->next; - } else { - for (work = *list; work && work->next && (work->next != vcc); work = work->next); - - /* return if not found */ - if (work->next != vcc) - return; - - work->next = work->next->next; - } - - if (vcc->reasBuffer) { - dev_kfree_skb (vcc->reasBuffer); - } - - dbg ("Allocated SARLib vcc 0x%p with vp %d vc %d", vcc, vcc->vp, vcc->vc); - - kfree (vcc); -} - static void udsl_atm_dev_close (struct atm_dev *dev) { struct udsl_instance_data *instance = dev->dev_data; @@ -1061,11 +914,10 @@ return 0; } -#define ATMSAR_SET_PTI 0x2L - static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci) { struct udsl_instance_data *instance = vcc->dev->dev_data; + struct udsl_vcc_data *new; dbg ("udsl_atm_open called"); @@ -1074,63 +926,97 @@ return -ENODEV; } - /* at the moment only AAL5 support */ + if ((vpi == ATM_VPI_ANY) || (vci == ATM_VCI_ANY)) + return -EINVAL; + + /* only support AAL5 */ if (vcc->qos.aal != ATM_AAL5) return -EINVAL; - MOD_INC_USE_COUNT; + down (&instance->serialize); /* vs self, udsl_atm_close */ - vcc->dev_data = - atmsar_open (&(instance->atmsar_vcc_list), vcc, ATM_AAL5, vpi, vci, 0, 0, - ATMSAR_USE_53BYTE_CELL | ATMSAR_SET_PTI); - if (!vcc->dev_data) { - MOD_DEC_USE_COUNT; - return -ENOMEM; /* this is the only reason atmsar_open can fail... */ + if (udsl_find_vcc (instance, vpi, vci)) { + up (&instance->serialize); + return -EADDRINUSE; + } + + if (!(new = kmalloc (sizeof (struct udsl_vcc_data), GFP_KERNEL))) { + up (&instance->serialize); + return -ENOMEM; } + memset (new, 0, sizeof (struct udsl_vcc_data)); + new->vcc = vcc; + new->vpi = vpi; + new->vci = vci; + new->mtu = UDSL_MAX_AAL5_MRU; + + vcc->dev_data = new; vcc->vpi = vpi; vcc->vci = vci; + + tasklet_disable (&instance->receive_tasklet); + list_add (&new->list, &instance->vcc_list); + tasklet_enable (&instance->receive_tasklet); + set_bit (ATM_VF_ADDR, &vcc->flags); set_bit (ATM_VF_PARTIAL, &vcc->flags); set_bit (ATM_VF_READY, &vcc->flags); - ((struct atmsar_vcc_data *)vcc->dev_data)->mtu = UDSL_MAX_AAL5_MRU; + up (&instance->serialize); + + dbg ("Allocated new SARLib vcc 0x%p with vpi %d vci %d", new, vpi, vci); + + MOD_INC_USE_COUNT; if (instance->firmware_loaded) udsl_fire_receivers (instance); dbg ("udsl_atm_open successful"); + return 0; } static void udsl_atm_close (struct atm_vcc *vcc) { struct udsl_instance_data *instance = vcc->dev->dev_data; + struct udsl_vcc_data *vcc_data = vcc->dev_data; dbg ("udsl_atm_close called"); - if (!instance) { - dbg ("NULL instance!"); + if (!instance || !vcc_data) { + dbg ("NULL data!"); return; } - /* freeing resources */ - /* cancel all sends on this vcc */ + dbg ("Deallocating SARLib vcc 0x%p with vpi %d vci %d", vcc_data, vcc_data->vpi, vcc_data->vci); + udsl_cancel_send (instance, vcc); - atmsar_close (&(instance->atmsar_vcc_list), vcc->dev_data); + down (&instance->serialize); /* vs self, udsl_atm_open */ + + tasklet_disable (&instance->receive_tasklet); + list_del (&vcc_data->list); + tasklet_enable (&instance->receive_tasklet); + + if (vcc_data->reasBuffer) + kfree_skb (vcc_data->reasBuffer); + vcc_data->reasBuffer = NULL; + + kfree (vcc_data); vcc->dev_data = NULL; - clear_bit (ATM_VF_PARTIAL, &vcc->flags); - /* freeing address */ vcc->vpi = ATM_VPI_UNSPEC; vcc->vci = ATM_VCI_UNSPEC; + clear_bit (ATM_VF_READY, &vcc->flags); + clear_bit (ATM_VF_PARTIAL, &vcc->flags); clear_bit (ATM_VF_ADDR, &vcc->flags); + up (&instance->serialize); + MOD_DEC_USE_COUNT; dbg ("udsl_atm_close successful"); - return; } static int udsl_atm_ioctl (struct atm_dev *dev, unsigned int cmd, void *arg) @@ -1208,6 +1094,8 @@ init_MUTEX (&instance->serialize); instance->usb_dev = dev; + + INIT_LIST_HEAD (&instance->vcc_list); spin_lock_init (&instance->spare_receivers_lock); INIT_LIST_HEAD (&instance->spare_receivers); diff -Nru a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c --- a/drivers/usb/misc/usbtest.c Wed Feb 19 09:35:04 2003 +++ b/drivers/usb/misc/usbtest.c Sun Mar 23 07:10:10 2003 @@ -881,6 +881,8 @@ init_completion (&completion); urb = simple_alloc_urb (testdev_to_usbdev (dev), pipe, size); + if (!urb) + return -ENOMEM; if (async) urb->transfer_flags |= URB_ASYNC_UNLINK; urb->context = &completion; @@ -1404,6 +1406,11 @@ /* re-enumerated usb test device firmware */ { USB_DEVICE (0xfff0, 0xfff0), + .driver_info = (unsigned long) &fw_info, + }, + + /* "Gadget Zero" firmware runs under Linux */ + { USB_DEVICE (0x0525, 0xa4a0), .driver_info = (unsigned long) &fw_info, }, diff -Nru a/drivers/usb/net/cdc-ether.c b/drivers/usb/net/cdc-ether.c --- a/drivers/usb/net/cdc-ether.c Sun Mar 16 13:07:07 2003 +++ b/drivers/usb/net/cdc-ether.c Fri Mar 21 23:18:23 2003 @@ -269,22 +269,8 @@ static int CDCEther_start_xmit( struct sk_buff *skb, struct net_device *net ) { ether_dev_t *ether_dev = net->priv; - int count; int res; - // If we are told to transmit an ethernet frame that fits EXACTLY - // into an integer number of USB packets, we force it to send one - // more byte so the device will get a runt USB packet signalling the - // end of the ethernet frame - if ( (skb->len) ^ (ether_dev->data_ep_out_size) ) { - // It was not an exact multiple - // no need to add anything extra - count = skb->len; - } else { - // Add one to make it NOT an exact multiple - count = skb->len + 1; - } - // Tell the kernel, "No more frames 'til we are done // with this one.' netif_stop_queue( net ); @@ -299,7 +285,10 @@ write_bulk_callback, ether_dev ); // Tell the URB how much it will be transporting today - ether_dev->tx_urb->transfer_buffer_length = count; + ether_dev->tx_urb->transfer_buffer_length = skb->len; + + /* Deal with the zero length problem, I hope */ + ether_dev->tx_urb->transfer_flags |= URB_ZERO_PACKET; // Send the URB on its merry way. if ((res = usb_submit_urb(ether_dev->tx_urb, GFP_ATOMIC))) { diff -Nru a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c --- a/drivers/usb/serial/kobil_sct.c Wed Mar 12 14:57:33 2003 +++ b/drivers/usb/serial/kobil_sct.c Fri Mar 21 08:50:56 2003 @@ -406,8 +406,6 @@ int result = 0; int todo = 0; struct kobil_private * priv; - int i; - char *data; if (count == 0) { dbg("%s - port %d write request of 0 bytes", __FUNCTION__, port->number); @@ -421,19 +419,6 @@ return -ENOMEM; } - // BEGIN DEBUG - data = (unsigned char *) kmalloc((3 * count + 10) * sizeof(char), GFP_KERNEL); - if (! data) { - return (-1); - } - memset(data, 0, (3 * count + 10)); - for (i = 0; i < count; i++) { - sprintf(data +3*i, "%02X ", buf[i]); - } - dbg(" %d --> %s", port->number, data ); - kfree(data); - // END DEBUG - // Copy data to buffer if (from_user) { if (copy_from_user(priv->buf + priv->filled, buf, count)) { @@ -442,6 +427,8 @@ } else { memcpy (priv->buf + priv->filled, buf, count); } + + usb_serial_debug_data (__FILE__, __FUNCTION__, count, priv->buf + priv->filled); priv->filled = priv->filled + count; diff -Nru a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c --- a/drivers/usb/storage/isd200.c Thu Mar 13 10:36:02 2003 +++ b/drivers/usb/storage/isd200.c Wed Mar 19 23:46:53 2003 @@ -405,11 +405,14 @@ { union ata_cdb ata; struct scsi_cmnd srb; + struct scsi_device srb_dev; struct isd200_info *info = (struct isd200_info *)us->extra; int status; memset(&ata, 0, sizeof(ata)); memset(&srb, 0, sizeof(srb)); + memset(&srb_dev, 0, sizeof(srb_dev)); + srb.device = &srb_dev; ata.generic.SignatureByte0 = info->ConfigData.ATAMajorCommand; ata.generic.SignatureByte1 = info->ConfigData.ATAMinorCommand; @@ -479,6 +482,7 @@ } memcpy(srb.cmnd, &ata, sizeof(ata.generic)); + srb.cmd_len = sizeof(ata.generic); status = usb_stor_Bulk_transport(&srb, us); if (status == USB_STOR_TRANSPORT_GOOD) status = ISD200_GOOD; @@ -538,6 +542,7 @@ /* send the command to the transport layer */ srb->resid = 0; memcpy(srb->cmnd, ataCdb, sizeof(ataCdb->generic)); + srb->cmd_len = sizeof(ataCdb->generic); transferStatus = usb_stor_Bulk_transport(srb, us); /* if the command gets aborted by the higher layers, we need to diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c --- a/drivers/usb/storage/scsiglue.c Tue Feb 4 09:33:31 2003 +++ b/drivers/usb/storage/scsiglue.c Tue Mar 25 05:58:45 2003 @@ -209,21 +209,14 @@ return result; } -/* This resets the device port, and simulates the device - * disconnect/reconnect for all drivers which have claimed - * interfaces, including ourself. */ +/* This resets the device port */ +/* It refuses to work if there's more than one interface in + this device, so that other users are not affected. */ /* This is always called with scsi_lock(srb->host) held */ -/* FIXME: This needs to be re-examined in the face of the new - * hotplug system -- this will implicitly cause a detach/reattach of - * usb-storage, which is not what we want now. - * - * Can we just skip over usb-storage in the while loop? - */ static int usb_storage_bus_reset( Scsi_Cmnd *srb ) { struct us_data *us; - int i; int result; /* we use the usb_reset_device() function to handle this for us */ @@ -231,36 +224,25 @@ scsi_unlock(srb->device->host); us = (struct us_data *)srb->device->host->hostdata[0]; - /* attempt to reset the port */ - result = usb_reset_device(us->pusb_dev); - US_DEBUGP("usb_reset_device returns %d\n", result); - if (result < 0) { - scsi_lock(srb->device->host); - return FAILED; + /* The USB subsystem doesn't handle synchronisation between + a device's several drivers. Therefore we reset only devices + with one interface which we of course own. + */ + + //FIXME: needs locking against config changes + + if ( us->pusb_dev->actconfig->desc.bNumInterfaces == 1) { + /* attempt to reset the port */ + result = usb_reset_device(us->pusb_dev); + US_DEBUGP("usb_reset_device returns %d\n", result); + } else { + result = -EBUSY; + US_DEBUGP("cannot reset a multiinterface device. failing to reset.\n"); } - /* FIXME: This needs to lock out driver probing while it's working - * or we can have race conditions */ - /* This functionality really should be provided by the khubd thread */ - for (i = 0; i < us->pusb_dev->actconfig->desc.bNumInterfaces; i++) { - struct usb_interface *intf = - &us->pusb_dev->actconfig->interface[i]; - - /* if this is an unclaimed interface, skip it */ - if (!intf->driver) { - continue; - } - - US_DEBUGP("Examining driver %s...", intf->driver->name); - - /* simulate a disconnect and reconnect for all interfaces */ - US_DEBUGPX("simulating disconnect/reconnect.\n"); - usb_device_remove (&intf->dev); - usb_device_probe (&intf->dev); - } US_DEBUGP("bus_reset() complete\n"); scsi_lock(srb->device->host); - return SUCCESS; + return result < 0 ? FAILED : SUCCESS; } /*********************************************************************** diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c --- a/drivers/usb/storage/transport.c Tue Mar 4 01:58:24 2003 +++ b/drivers/usb/storage/transport.c Sat Mar 22 11:19:28 2003 @@ -126,6 +126,7 @@ us->current_urb->actual_length = 0; us->current_urb->error_count = 0; us->current_urb->transfer_flags = URB_ASYNC_UNLINK; + us->current_urb->status = 0; /* submit the URB */ status = usb_submit_urb(us->current_urb, GFP_NOIO); @@ -900,7 +901,7 @@ bcb.DataTransferLength = cpu_to_le32(transfer_length); bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0; bcb.Tag = srb->serial_number; - bcb.Lun = srb->cmnd[1] >> 5; + bcb.Lun = srb->device->lun; if (us->flags & US_FL_SCM_MULT_TARG) bcb.Lun |= srb->device->id << 4; bcb.Length = srb->cmd_len; diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c --- a/drivers/usb/storage/usb.c Tue Feb 11 14:57:53 2003 +++ b/drivers/usb/storage/usb.c Sun Mar 23 03:53:04 2003 @@ -360,7 +360,7 @@ } else if (us->srb->device->lun > us->max_lun) { - US_DEBUGP("Bad LUN (%d/%d)\n", + US_DEBUGP("Bad LUN (%d:%d)\n", us->srb->device->id, us->srb->device->lun); us->srb->result = DID_BAD_TARGET << 16; } @@ -475,8 +475,6 @@ */ static void usb_stor_deallocate_urbs(struct us_data *ss) { - int result; - /* free the scatter-gather request block */ if (ss->current_sg) { kfree(ss->current_sg); @@ -486,8 +484,6 @@ /* free up the main URB for this device */ if (ss->current_urb) { US_DEBUGP("-- releasing main URB\n"); - result = usb_unlink_urb(ss->current_urb); - US_DEBUGP("-- usb_unlink_urb() returned %d\n", result); usb_free_urb(ss->current_urb); ss->current_urb = NULL; } diff -Nru a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c --- a/drivers/usb/usb-skeleton.c Sat Mar 22 09:02:37 2003 +++ b/drivers/usb/usb-skeleton.c Mon Mar 24 13:03:56 2003 @@ -72,13 +72,15 @@ MODULE_PARM_DESC(debug, "Debug enabled or not"); -/* Define these values to match your device */ +/* Define these values to match your devices */ #define USB_SKEL_VENDOR_ID 0xfff0 #define USB_SKEL_PRODUCT_ID 0xfff0 /* table of devices that work with this driver */ static struct usb_device_id skel_table [] = { { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) }, + /* "Gadget Zero" firmware runs under Linux */ + { USB_DEVICE(0x0525, 0xa4a0) }, { } /* Terminating entry */ }; @@ -707,7 +709,7 @@ /* register this driver with the USB subsystem */ result = usb_register(&skel_driver); if (result < 0) { - err("usb_register failed for the "__FILE__" driver. Error number %d", + err("usb_register failed. Error number %d", result); return -1; } diff -Nru a/drivers/video/Makefile b/drivers/video/Makefile --- a/drivers/video/Makefile Fri Mar 21 14:20:23 2003 +++ b/drivers/video/Makefile Wed Mar 26 06:54:18 2003 @@ -31,7 +31,7 @@ obj-$(CONFIG_FB_ANAKIN) += anakinfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_CYBER) += cyberfb.o -obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o +obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_SGIVW) += sgivwfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_3DFX) += tdfxfb.o cfbimgblt.o obj-$(CONFIG_FB_MAC) += macfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o diff -Nru a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c --- a/drivers/video/cyber2000fb.c Mon Feb 24 12:16:15 2003 +++ b/drivers/video/cyber2000fb.c Wed Mar 26 06:55:17 2003 @@ -55,12 +55,6 @@ #include #include -#include