diff --git a/[refs] b/[refs]
index ed6fb35d1aea..c17374b83c68 100644
--- a/[refs]
+++ b/[refs]
@@ -1,2 +1,2 @@
---
-refs/heads/master: b6d00f0de9e932e2884b3b7af8e43c0a61a271ee
+refs/heads/master: b445e26cbf784cdba10f2b6c3e2cd3ee7bab360a
diff --git a/trunk/Documentation/Changes b/trunk/Documentation/Changes
index afebdbcd553a..b37600754762 100644
--- a/trunk/Documentation/Changes
+++ b/trunk/Documentation/Changes
@@ -44,9 +44,9 @@ running, the suggested command should tell you.
Again, keep in mind that this list assumes you are already
functionally running a Linux 2.4 kernel. Also, not all tools are
-necessary on all systems; obviously, if you don't have any ISDN
-hardware, for example, you probably needn't concern yourself with
-isdn4k-utils.
+necessary on all systems; obviously, if you don't have any PCMCIA (PC
+Card) hardware, for example, you probably needn't concern yourself
+with pcmcia-cs.
o Gnu C 2.95.3 # gcc --version
o Gnu make 3.79.1 # make --version
@@ -57,7 +57,6 @@ o e2fsprogs 1.29 # tune2fs
o jfsutils 1.1.3 # fsck.jfs -V
o reiserfsprogs 3.6.3 # reiserfsck -V 2>&1|grep reiserfsprogs
o xfsprogs 2.6.0 # xfs_db -V
-o pcmciautils 001
o pcmcia-cs 3.1.21 # cardmgr -V
o quota-tools 3.09 # quota -V
o PPP 2.4.0 # pppd --version
@@ -187,20 +186,13 @@ architecture independent and any version from 2.0.0 onward should
work correctly with this version of the XFS kernel code (2.6.0 or
later is recommended, due to some significant improvements).
-PCMCIAutils
------------
-
-PCMCIAutils replaces pcmcia-cs (see below). It properly sets up
-PCMCIA sockets at system startup and loads the appropriate modules
-for 16-bit PCMCIA devices if the kernel is modularized and the hotplug
-subsystem is used.
Pcmcia-cs
---------
PCMCIA (PC Card) support is now partially implemented in the main
-kernel source. The "pcmciautils" package (see above) replaces pcmcia-cs
-for newest kernels.
+kernel source. Pay attention when you recompile your kernel ;-).
+Also, be sure to upgrade to the latest pcmcia-cs release.
Quota-tools
-----------
@@ -357,13 +349,9 @@ Xfsprogs
--------
o
-Pcmciautils
------------
-o
-
Pcmcia-cs
---------
-o
+o
Quota-tools
----------
diff --git a/trunk/Documentation/block/ioprio.txt b/trunk/Documentation/block/ioprio.txt
deleted file mode 100644
index 96ccf681075e..000000000000
--- a/trunk/Documentation/block/ioprio.txt
+++ /dev/null
@@ -1,176 +0,0 @@
-Block io priorities
-===================
-
-
-Intro
------
-
-With the introduction of cfq v3 (aka cfq-ts or time sliced cfq), basic io
-priorities is supported for reads on files. This enables users to io nice
-processes or process groups, similar to what has been possible to cpu
-scheduling for ages. This document mainly details the current possibilites
-with cfq, other io schedulers do not support io priorities so far.
-
-Scheduling classes
-------------------
-
-CFQ implements three generic scheduling classes that determine how io is
-served for a process.
-
-IOPRIO_CLASS_RT: This is the realtime io class. This scheduling class is given
-higher priority than any other in the system, processes from this class are
-given first access to the disk every time. Thus it needs to be used with some
-care, one io RT process can starve the entire system. Within the RT class,
-there are 8 levels of class data that determine exactly how much time this
-process needs the disk for on each service. In the future this might change
-to be more directly mappable to performance, by passing in a wanted data
-rate instead.
-
-IOPRIO_CLASS_BE: This is the best-effort scheduling class, which is the default
-for any process that hasn't set a specific io priority. The class data
-determines how much io bandwidth the process will get, it's directly mappable
-to the cpu nice levels just more coarsely implemented. 0 is the highest
-BE prio level, 7 is the lowest. The mapping between cpu nice level and io
-nice level is determined as: io_nice = (cpu_nice + 20) / 5.
-
-IOPRIO_CLASS_IDLE: This is the idle scheduling class, processes running at this
-level only get io time when no one else needs the disk. The idle class has no
-class data, since it doesn't really apply here.
-
-Tools
------
-
-See below for a sample ionice tool. Usage:
-
-# ionice -c -n -p
-
-If pid isn't given, the current process is assumed. IO priority settings
-are inherited on fork, so you can use ionice to start the process at a given
-level:
-
-# ionice -c2 -n0 /bin/ls
-
-will run ls at the best-effort scheduling class at the highest priority.
-For a running process, you can give the pid instead:
-
-# ionice -c1 -n2 -p100
-
-will change pid 100 to run at the realtime scheduling class, at priority 2.
-
----> snip ionice.c tool <---
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-extern int sys_ioprio_set(int, int, int);
-extern int sys_ioprio_get(int, int);
-
-#if defined(__i386__)
-#define __NR_ioprio_set 289
-#define __NR_ioprio_get 290
-#elif defined(__ppc__)
-#define __NR_ioprio_set 273
-#define __NR_ioprio_get 274
-#elif defined(__x86_64__)
-#define __NR_ioprio_set 251
-#define __NR_ioprio_get 252
-#elif defined(__ia64__)
-#define __NR_ioprio_set 1274
-#define __NR_ioprio_get 1275
-#else
-#error "Unsupported arch"
-#endif
-
-_syscall3(int, ioprio_set, int, which, int, who, int, ioprio);
-_syscall2(int, ioprio_get, int, which, int, who);
-
-enum {
- IOPRIO_CLASS_NONE,
- IOPRIO_CLASS_RT,
- IOPRIO_CLASS_BE,
- IOPRIO_CLASS_IDLE,
-};
-
-enum {
- IOPRIO_WHO_PROCESS = 1,
- IOPRIO_WHO_PGRP,
- IOPRIO_WHO_USER,
-};
-
-#define IOPRIO_CLASS_SHIFT 13
-
-const char *to_prio[] = { "none", "realtime", "best-effort", "idle", };
-
-int main(int argc, char *argv[])
-{
- int ioprio = 4, set = 0, ioprio_class = IOPRIO_CLASS_BE;
- int c, pid = 0;
-
- while ((c = getopt(argc, argv, "+n:c:p:")) != EOF) {
- switch (c) {
- case 'n':
- ioprio = strtol(optarg, NULL, 10);
- set = 1;
- break;
- case 'c':
- ioprio_class = strtol(optarg, NULL, 10);
- set = 1;
- break;
- case 'p':
- pid = strtol(optarg, NULL, 10);
- break;
- }
- }
-
- switch (ioprio_class) {
- case IOPRIO_CLASS_NONE:
- ioprio_class = IOPRIO_CLASS_BE;
- break;
- case IOPRIO_CLASS_RT:
- case IOPRIO_CLASS_BE:
- break;
- case IOPRIO_CLASS_IDLE:
- ioprio = 7;
- break;
- default:
- printf("bad prio class %d\n", ioprio_class);
- return 1;
- }
-
- if (!set) {
- if (!pid && argv[optind])
- pid = strtol(argv[optind], NULL, 10);
-
- ioprio = ioprio_get(IOPRIO_WHO_PROCESS, pid);
-
- printf("pid=%d, %d\n", pid, ioprio);
-
- if (ioprio == -1)
- perror("ioprio_get");
- else {
- ioprio_class = ioprio >> IOPRIO_CLASS_SHIFT;
- ioprio = ioprio & 0xff;
- printf("%s: prio %d\n", to_prio[ioprio_class], ioprio);
- }
- } else {
- if (ioprio_set(IOPRIO_WHO_PROCESS, pid, ioprio | ioprio_class << IOPRIO_CLASS_SHIFT) == -1) {
- perror("ioprio_set");
- return 1;
- }
-
- if (argv[optind])
- execvp(argv[optind], &argv[optind]);
- }
-
- return 0;
-}
-
----> snip ionice.c tool <---
-
-
-March 11 2005, Jens Axboe
diff --git a/trunk/Documentation/cciss.txt b/trunk/Documentation/cciss.txt
index c8f9a73111da..d599beb9df8a 100644
--- a/trunk/Documentation/cciss.txt
+++ b/trunk/Documentation/cciss.txt
@@ -17,7 +17,6 @@ This driver is known to work with the following cards:
* SA P600
* SA P800
* SA E400
- * SA E300
If nodes are not already created in the /dev/cciss directory, run as root:
diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt
index 89cd417651e0..f44bb5567c5b 100644
--- a/trunk/Documentation/kernel-parameters.txt
+++ b/trunk/Documentation/kernel-parameters.txt
@@ -1115,7 +1115,7 @@ running once the system is up.
See Documentation/ramdisk.txt.
psmouse.proto= [HW,MOUSE] Highest PS2 mouse protocol extension to
- probe for (bare|imps|exps|lifebook|any).
+ probe for (bare|imps|exps).
psmouse.rate= [HW,MOUSE] Set desired mouse report rate, in reports
per second.
psmouse.resetafter=
diff --git a/trunk/Documentation/pcmcia/devicetable.txt b/trunk/Documentation/pcmcia/devicetable.txt
deleted file mode 100644
index 045511acafc9..000000000000
--- a/trunk/Documentation/pcmcia/devicetable.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-Matching of PCMCIA devices to drivers is done using one or more of the
-following criteria:
-
-- manufactor ID
-- card ID
-- product ID strings _and_ hashes of these strings
-- function ID
-- device function (actual and pseudo)
-
-You should use the helpers in include/pcmcia/device_id.h for generating the
-struct pcmcia_device_id[] entries which match devices to drivers.
-
-If you want to match product ID strings, you also need to pass the crc32
-hashes of the string to the macro, e.g. if you want to match the product ID
-string 1, you need to use
-
-PCMCIA_DEVICE_PROD_ID1("some_string", 0x(hash_of_some_string)),
-
-If the hash is incorrect, the kernel will inform you about this in "dmesg"
-upon module initialization, and tell you of the correct hash.
-
-You can determine the hash of the product ID strings by running
-"pcmcia-modalias %n.%m" [%n being replaced with the socket number and %m being
-replaced with the device function] from pcmciautils. It generates a string
-in the following form:
-pcmcia:m0149cC1ABf06pfn00fn00pa725B842DpbF1EFEE84pc0877B627pd00000000
-
-The hex value after "pa" is the hash of product ID string 1, after "pb" for
-string 2 and so on.
-
-Alternatively, you can use this small tool to determine the crc32 hash.
-simply pass the string you want to evaluate as argument to this program,
-e.g.
-$ ./crc32hash "Dual Speed"
-
--------------------------------------------------------------------------
-/* crc32hash.c - derived from linux/lib/crc32.c, GNU GPL v2 */
-#include
-#include
-#include
-#include
-
-unsigned int crc32(unsigned char const *p, unsigned int len)
-{
- int i;
- unsigned int crc = 0;
- while (len--) {
- crc ^= *p++;
- for (i = 0; i < 8; i++)
- crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
- }
- return crc;
-}
-
-int main(int argc, char **argv) {
- unsigned int result;
- if (argc != 2) {
- printf("no string passed as argument\n");
- return -1;
- }
- result = crc32(argv[1], strlen(argv[1]));
- printf("0x%x\n", result);
- return 0;
-}
diff --git a/trunk/Documentation/pcmcia/driver-changes.txt b/trunk/Documentation/pcmcia/driver-changes.txt
deleted file mode 100644
index 9c315ab48a02..000000000000
--- a/trunk/Documentation/pcmcia/driver-changes.txt
+++ /dev/null
@@ -1,51 +0,0 @@
-This file details changes in 2.6 which affect PCMCIA card driver authors:
-
-* in-kernel device<->driver matching
- PCMCIA devices and their correct drivers can now be matched in
- kernelspace. See 'devicetable.txt' for details.
-
-* Device model integration (as of 2.6.11)
- A struct pcmcia_device is registered with the device model core,
- and can be used (e.g. for SET_NETDEV_DEV) by using
- handle_to_dev(client_handle_t * handle).
-
-* Convert internal I/O port addresses to unsigned long (as of 2.6.11)
- ioaddr_t should be replaced by kio_addr_t in PCMCIA card drivers.
-
-* irq_mask and irq_list parameters (as of 2.6.11)
- The irq_mask and irq_list parameters should no longer be used in
- PCMCIA card drivers. Instead, it is the job of the PCMCIA core to
- determine which IRQ should be used. Therefore, link->irq.IRQInfo2
- is ignored.
-
-* client->PendingEvents is gone (as of 2.6.11)
- client->PendingEvents is no longer available.
-
-* client->Attributes are gone (as of 2.6.11)
- client->Attributes is unused, therefore it is removed from all
- PCMCIA card drivers
-
-* core functions no longer available (as of 2.6.11)
- The following functions have been removed from the kernel source
- because they are unused by all in-kernel drivers, and no external
- driver was reported to rely on them:
- pcmcia_get_first_region()
- pcmcia_get_next_region()
- pcmcia_modify_window()
- pcmcia_set_event_mask()
- pcmcia_get_first_window()
- pcmcia_get_next_window()
-
-* device list iteration upon module removal (as of 2.6.10)
- It is no longer necessary to iterate on the driver's internal
- client list and call the ->detach() function upon module removal.
-
-* Resource management. (as of 2.6.8)
- Although the PCMCIA subsystem will allocate resources for cards,
- it no longer marks these resources busy. This means that driver
- authors are now responsible for claiming your resources as per
- other drivers in Linux. You should use request_region() to mark
- your IO regions in-use, and request_mem_region() to mark your
- memory regions in-use. The name argument should be a pointer to
- your driver name. Eg, for pcnet_cs, name should point to the
- string "pcnet_cs".
diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS
index 4db63de9652a..a0b0d595d17c 100644
--- a/trunk/MAINTAINERS
+++ b/trunk/MAINTAINERS
@@ -1149,7 +1149,7 @@ S: Maintained
INFINIBAND SUBSYSTEM
P: Roland Dreier
-M: rolandd@cisco.com
+M: roland@topspin.com
P: Sean Hefty
M: mshefty@ichips.intel.com
P: Hal Rosenstock
diff --git a/trunk/arch/arm/kernel/process.c b/trunk/arch/arm/kernel/process.c
index bbea636ff687..8f146a4b4752 100644
--- a/trunk/arch/arm/kernel/process.c
+++ b/trunk/arch/arm/kernel/process.c
@@ -32,7 +32,6 @@
#include
#include
#include
-#include
extern const char *processor_modes[];
extern void setup_mm_for_reboot(char mode);
@@ -86,10 +85,8 @@ EXPORT_SYMBOL(pm_power_off);
void default_idle(void)
{
local_irq_disable();
- if (!need_resched() && !hlt_counter) {
- timer_dyn_reprogram();
+ if (!need_resched() && !hlt_counter)
arch_idle();
- }
local_irq_enable();
}
diff --git a/trunk/arch/arm/kernel/time.c b/trunk/arch/arm/kernel/time.c
index 1b7fcd50c3e2..06054c9ba074 100644
--- a/trunk/arch/arm/kernel/time.c
+++ b/trunk/arch/arm/kernel/time.c
@@ -424,19 +424,15 @@ static int timer_dyn_tick_disable(void)
return ret;
}
-/*
- * Reprogram the system timer for at least the calculated time interval.
- * This function should be called from the idle thread with IRQs disabled,
- * immediately before sleeping.
- */
void timer_dyn_reprogram(void)
{
struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
+ unsigned long flags;
- write_seqlock(&xtime_lock);
+ write_seqlock_irqsave(&xtime_lock, flags);
if (dyn_tick->state & DYN_TICK_ENABLED)
dyn_tick->reprogram(next_timer_interrupt() - jiffies);
- write_sequnlock(&xtime_lock);
+ write_sequnlock_irqrestore(&xtime_lock, flags);
}
static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
diff --git a/trunk/arch/arm/mach-aaec2000/Makefile.boot b/trunk/arch/arm/mach-aaec2000/Makefile.boot
deleted file mode 100644
index 8f5a8b7c53c7..000000000000
--- a/trunk/arch/arm/mach-aaec2000/Makefile.boot
+++ /dev/null
@@ -1 +0,0 @@
- zreladdr-y := 0xf0008000
diff --git a/trunk/arch/arm/mach-omap/usb.c b/trunk/arch/arm/mach-omap/usb.c
index 7f37857b1a28..6e805d451d0e 100644
--- a/trunk/arch/arm/mach-omap/usb.c
+++ b/trunk/arch/arm/mach-omap/usb.c
@@ -288,8 +288,8 @@ static void usb_release(struct device *dev)
static struct resource udc_resources[] = {
/* order is significant! */
{ /* registers */
- .start = UDC_BASE,
- .end = UDC_BASE + 0xff,
+ .start = IO_ADDRESS(UDC_BASE),
+ .end = IO_ADDRESS(UDC_BASE + 0xff),
.flags = IORESOURCE_MEM,
}, { /* general IRQ */
.start = IH2_BASE + 20,
@@ -355,8 +355,8 @@ static struct platform_device ohci_device = {
static struct resource otg_resources[] = {
/* order is significant! */
{
- .start = OTG_BASE,
- .end = OTG_BASE + 0xff,
+ .start = IO_ADDRESS(OTG_BASE),
+ .end = IO_ADDRESS(OTG_BASE + 0xff),
.flags = IORESOURCE_MEM,
}, {
.start = IH2_BASE + 8,
diff --git a/trunk/arch/arm/mm/init.c b/trunk/arch/arm/mm/init.c
index 6dcb23d64bf5..c08710b1ff02 100644
--- a/trunk/arch/arm/mm/init.c
+++ b/trunk/arch/arm/mm/init.c
@@ -522,69 +522,6 @@ static inline void free_area(unsigned long addr, unsigned long end, char *s)
printk(KERN_INFO "Freeing %s memory: %dK\n", s, size);
}
-static inline void
-free_memmap(int node, unsigned long start_pfn, unsigned long end_pfn)
-{
- struct page *start_pg, *end_pg;
- unsigned long pg, pgend;
-
- /*
- * Convert start_pfn/end_pfn to a struct page pointer.
- */
- start_pg = pfn_to_page(start_pfn);
- end_pg = pfn_to_page(end_pfn);
-
- /*
- * Convert to physical addresses, and
- * round start upwards and end downwards.
- */
- pg = PAGE_ALIGN(__pa(start_pg));
- pgend = __pa(end_pg) & PAGE_MASK;
-
- /*
- * If there are free pages between these,
- * free the section of the memmap array.
- */
- if (pg < pgend)
- free_bootmem_node(NODE_DATA(node), pg, pgend - pg);
-}
-
-/*
- * The mem_map array can get very big. Free the unused area of the memory map.
- */
-static void __init free_unused_memmap_node(int node, struct meminfo *mi)
-{
- unsigned long bank_start, prev_bank_end = 0;
- unsigned int i;
-
- /*
- * [FIXME] This relies on each bank being in address order. This
- * may not be the case, especially if the user has provided the
- * information on the command line.
- */
- for (i = 0; i < mi->nr_banks; i++) {
- if (mi->bank[i].size == 0 || mi->bank[i].node != node)
- continue;
-
- bank_start = mi->bank[i].start >> PAGE_SHIFT;
- if (bank_start < prev_bank_end) {
- printk(KERN_ERR "MEM: unordered memory banks. "
- "Not freeing memmap.\n");
- break;
- }
-
- /*
- * If we had a previous bank, and there is a space
- * between the current bank and the previous, free it.
- */
- if (prev_bank_end && prev_bank_end != bank_start)
- free_memmap(node, prev_bank_end, bank_start);
-
- prev_bank_end = (mi->bank[i].start +
- mi->bank[i].size) >> PAGE_SHIFT;
- }
-}
-
/*
* mem_init() marks the free areas in the mem_map and tells us how much
* memory is free. This is done after various parts of the system have
@@ -603,12 +540,16 @@ void __init mem_init(void)
max_mapnr = virt_to_page(high_memory) - mem_map;
#endif
+ /*
+ * We may have non-contiguous memory.
+ */
+ if (meminfo.nr_banks != 1)
+ create_memmap_holes(&meminfo);
+
/* this will put all unused low memory onto the freelists */
for_each_online_node(node) {
pg_data_t *pgdat = NODE_DATA(node);
- free_unused_memmap_node(node, &meminfo);
-
if (pgdat->node_spanned_pages != 0)
totalram_pages += free_all_bootmem_node(pgdat);
}
diff --git a/trunk/arch/arm/mm/mm-armv.c b/trunk/arch/arm/mm/mm-armv.c
index 052ab443ec4e..2c2b93d77d43 100644
--- a/trunk/arch/arm/mm/mm-armv.c
+++ b/trunk/arch/arm/mm/mm-armv.c
@@ -169,14 +169,7 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
memzero(new_pgd, FIRST_KERNEL_PGD_NR * sizeof(pgd_t));
- /*
- * Copy over the kernel and IO PGD entries
- */
init_pgd = pgd_offset_k(0);
- memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
- (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
-
- clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
if (!vectors_high()) {
/*
@@ -205,6 +198,14 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
spin_unlock(&mm->page_table_lock);
}
+ /*
+ * Copy over the kernel and IO PGD entries
+ */
+ memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
+ (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
+
+ clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
+
return new_pgd;
no_pte:
@@ -697,3 +698,75 @@ void __init iotable_init(struct map_desc *io_desc, int nr)
for (i = 0; i < nr; i++)
create_mapping(io_desc + i);
}
+
+static inline void
+free_memmap(int node, unsigned long start_pfn, unsigned long end_pfn)
+{
+ struct page *start_pg, *end_pg;
+ unsigned long pg, pgend;
+
+ /*
+ * Convert start_pfn/end_pfn to a struct page pointer.
+ */
+ start_pg = pfn_to_page(start_pfn);
+ end_pg = pfn_to_page(end_pfn);
+
+ /*
+ * Convert to physical addresses, and
+ * round start upwards and end downwards.
+ */
+ pg = PAGE_ALIGN(__pa(start_pg));
+ pgend = __pa(end_pg) & PAGE_MASK;
+
+ /*
+ * If there are free pages between these,
+ * free the section of the memmap array.
+ */
+ if (pg < pgend)
+ free_bootmem_node(NODE_DATA(node), pg, pgend - pg);
+}
+
+static inline void free_unused_memmap_node(int node, struct meminfo *mi)
+{
+ unsigned long bank_start, prev_bank_end = 0;
+ unsigned int i;
+
+ /*
+ * [FIXME] This relies on each bank being in address order. This
+ * may not be the case, especially if the user has provided the
+ * information on the command line.
+ */
+ for (i = 0; i < mi->nr_banks; i++) {
+ if (mi->bank[i].size == 0 || mi->bank[i].node != node)
+ continue;
+
+ bank_start = mi->bank[i].start >> PAGE_SHIFT;
+ if (bank_start < prev_bank_end) {
+ printk(KERN_ERR "MEM: unordered memory banks. "
+ "Not freeing memmap.\n");
+ break;
+ }
+
+ /*
+ * If we had a previous bank, and there is a space
+ * between the current bank and the previous, free it.
+ */
+ if (prev_bank_end && prev_bank_end != bank_start)
+ free_memmap(node, prev_bank_end, bank_start);
+
+ prev_bank_end = PAGE_ALIGN(mi->bank[i].start +
+ mi->bank[i].size) >> PAGE_SHIFT;
+ }
+}
+
+/*
+ * The mem_map array can get very big. Free
+ * the unused area of the memory map.
+ */
+void __init create_memmap_holes(struct meminfo *mi)
+{
+ int node;
+
+ for_each_online_node(node)
+ free_unused_memmap_node(node, mi);
+}
diff --git a/trunk/arch/arm/tools/mach-types b/trunk/arch/arm/tools/mach-types
index 6d3a79e5fef8..30c1dfbb052f 100644
--- a/trunk/arch/arm/tools/mach-types
+++ b/trunk/arch/arm/tools/mach-types
@@ -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: Thu Jun 23 20:19:33 2005
+# Last update: Thu Mar 24 14:34:50 2005
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
@@ -243,7 +243,7 @@ yoho ARCH_YOHO YOHO 231
jasper ARCH_JASPER JASPER 232
dsc25 ARCH_DSC25 DSC25 233
omap_innovator MACH_OMAP_INNOVATOR OMAP_INNOVATOR 234
-mnci ARCH_RAMSES RAMSES 235
+ramses ARCH_RAMSES RAMSES 235
s28x ARCH_S28X S28X 236
mport3 ARCH_MPORT3 MPORT3 237
pxa_eagle250 ARCH_PXA_EAGLE250 PXA_EAGLE250 238
@@ -323,7 +323,7 @@ nimbra29x ARCH_NIMBRA29X NIMBRA29X 311
nimbra210 ARCH_NIMBRA210 NIMBRA210 312
hhp_d95xx ARCH_HHP_D95XX HHP_D95XX 313
labarm ARCH_LABARM LABARM 314
-comcerto ARCH_M825XX M825XX 315
+m825xx ARCH_M825XX M825XX 315
m7100 SA1100_M7100 M7100 316
nipc2 ARCH_NIPC2 NIPC2 317
fu7202 ARCH_FU7202 FU7202 318
@@ -724,66 +724,3 @@ lpc22xx MACH_LPC22XX LPC22XX 715
omap_comet3 MACH_COMET3 COMET3 716
omap_comet4 MACH_COMET4 COMET4 717
csb625 MACH_CSB625 CSB625 718
-fortunet2 MACH_FORTUNET2 FORTUNET2 719
-s5h2200 MACH_S5H2200 S5H2200 720
-optorm920 MACH_OPTORM920 OPTORM920 721
-adsbitsyxb MACH_ADSBITSYXB ADSBITSYXB 722
-adssphere MACH_ADSSPHERE ADSSPHERE 723
-adsportal MACH_ADSPORTAL ADSPORTAL 724
-ln2410sbc MACH_LN2410SBC LN2410SBC 725
-cb3rufc MACH_CB3RUFC CB3RUFC 726
-mp2usb MACH_MP2USB MP2USB 727
-ntnp425c MACH_NTNP425C NTNP425C 728
-colibri MACH_COLIBRI COLIBRI 729
-pcm7220 MACH_PCM7220 PCM7220 730
-gateway7001 MACH_GATEWAY7001 GATEWAY7001 731
-pcm027 MACH_PCM027 PCM027 732
-cmpxa MACH_CMPXA CMPXA 733
-anubis MACH_ANUBIS ANUBIS 734
-ite8152 MACH_ITE8152 ITE8152 735
-lpc3xxx MACH_LPC3XXX LPC3XXX 736
-puppeteer MACH_PUPPETEER PUPPETEER 737
-vt001 MACH_MACH_VADATECH MACH_VADATECH 738
-e570 MACH_E570 E570 739
-x50 MACH_X50 X50 740
-recon MACH_RECON RECON 741
-xboardgp8 MACH_XBOARDGP8 XBOARDGP8 742
-fpic2 MACH_FPIC2 FPIC2 743
-akita MACH_AKITA AKITA 744
-a81 MACH_A81 A81 745
-svm_sc25x MACH_SVM_SC25X SVM_SC25X 746
-vt020 MACH_VADATECH020 VADATECH020 747
-tli MACH_TLI TLI 748
-edb9315lc MACH_EDB9315LC EDB9315LC 749
-passec MACH_PASSEC PASSEC 750
-ds_tiger MACH_DS_TIGER DS_TIGER 751
-e310 MACH_E310 E310 752
-e330 MACH_E330 E330 753
-rt3000 MACH_RT3000 RT3000 754
-nokia770 MACH_NOKIA770 NOKIA770 755
-pnx0106 MACH_PNX0106 PNX0106 756
-hx21xx MACH_HX21XX HX21XX 757
-faraday MACH_FARADAY FARADAY 758
-sbc9312 MACH_SBC9312 SBC9312 759
-batman MACH_BATMAN BATMAN 760
-jpd201 MACH_JPD201 JPD201 761
-mipsa MACH_MIPSA MIPSA 762
-kacom MACH_KACOM KACOM 763
-swarcocpu MACH_SWARCOCPU SWARCOCPU 764
-swarcodsl MACH_SWARCODSL SWARCODSL 765
-blueangel MACH_BLUEANGEL BLUEANGEL 766
-hairygrama MACH_HAIRYGRAMA HAIRYGRAMA 767
-banff MACH_BANFF BANFF 768
-carmeva MACH_CARMEVA CARMEVA 769
-sam255 MACH_SAM255 SAM255 770
-ppm10 MACH_PPM10 PPM10 771
-edb9315a MACH_EDB9315A EDB9315A 772
-sunset MACH_SUNSET SUNSET 773
-stargate2 MACH_STARGATE2 STARGATE2 774
-intelmote2 MACH_INTELMOTE2 INTELMOTE2 775
-trizeps4 MACH_TRIZEPS4 TRIZEPS4 776
-mainstone2 MACH_MAINSTONE2 MAINSTONE2 777
-ez_ixp42x MACH_EZ_IXP42X EZ_IXP42X 778
-tapwave_zodiac MACH_TAPWAVE_ZODIAC TAPWAVE_ZODIAC 779
-universalmeter MACH_UNIVERSALMETER UNIVERSALMETER 780
-hicoarm9 MACH_HICOARM9 HICOARM9 781
diff --git a/trunk/arch/i386/kernel/kprobes.c b/trunk/arch/i386/kernel/kprobes.c
index fc8b17521761..3762f6b35ab2 100644
--- a/trunk/arch/i386/kernel/kprobes.c
+++ b/trunk/arch/i386/kernel/kprobes.c
@@ -127,23 +127,48 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
regs->eip = (unsigned long)&p->ainsn.insn;
}
+struct task_struct *arch_get_kprobe_task(void *ptr)
+{
+ return ((struct thread_info *) (((unsigned long) ptr) &
+ (~(THREAD_SIZE -1))))->task;
+}
+
void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
{
unsigned long *sara = (unsigned long *)®s->esp;
- struct kretprobe_instance *ri;
-
- if ((ri = get_free_rp_inst(rp)) != NULL) {
- ri->rp = rp;
- ri->task = current;
- ri->ret_addr = (kprobe_opcode_t *) *sara;
+ struct kretprobe_instance *ri;
+ static void *orig_ret_addr;
+ /*
+ * Save the return address when the return probe hits
+ * the first time, and use it to populate the (krprobe
+ * instance)->ret_addr for subsequent return probes at
+ * the same addrress since stack address would have
+ * the kretprobe_trampoline by then.
+ */
+ if (((void*) *sara) != kretprobe_trampoline)
+ orig_ret_addr = (void*) *sara;
+
+ if ((ri = get_free_rp_inst(rp)) != NULL) {
+ ri->rp = rp;
+ ri->stack_addr = sara;
+ ri->ret_addr = orig_ret_addr;
+ add_rp_inst(ri);
/* Replace the return addr with trampoline addr */
*sara = (unsigned long) &kretprobe_trampoline;
+ } else {
+ rp->nmissed++;
+ }
+}
- add_rp_inst(ri);
- } else {
- rp->nmissed++;
- }
+void arch_kprobe_flush_task(struct task_struct *tk)
+{
+ struct kretprobe_instance *ri;
+ while ((ri = get_rp_inst_tsk(tk)) != NULL) {
+ *((unsigned long *)(ri->stack_addr)) =
+ (unsigned long) ri->ret_addr;
+ recycle_rp_inst(ri);
+ }
}
/*
@@ -261,59 +286,36 @@ static int kprobe_handler(struct pt_regs *regs)
*/
int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
{
- struct kretprobe_instance *ri = NULL;
- struct hlist_head *head;
- struct hlist_node *node, *tmp;
- unsigned long orig_ret_address = 0;
- unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
-
- head = kretprobe_inst_table_head(current);
-
- /*
- * It is possible to have multiple instances associated with a given
- * task either because an multiple functions in the call path
- * have a return probe installed on them, and/or more then one return
- * return probe was registered for a target function.
- *
- * We can handle this because:
- * - instances are always inserted at the head of the list
- * - when multiple return probes are registered for the same
- * function, the first instance's ret_addr will point to the
- * real return address, and all the rest will point to
- * kretprobe_trampoline
- */
- hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
- if (ri->task != current)
- /* another task is sharing our hash bucket */
- continue;
+ struct task_struct *tsk;
+ struct kretprobe_instance *ri;
+ struct hlist_head *head;
+ struct hlist_node *node;
+ unsigned long *sara = ((unsigned long *) ®s->esp) - 1;
+
+ tsk = arch_get_kprobe_task(sara);
+ head = kretprobe_inst_table_head(tsk);
+
+ hlist_for_each_entry(ri, node, head, hlist) {
+ if (ri->stack_addr == sara && ri->rp) {
+ if (ri->rp->handler)
+ ri->rp->handler(ri, regs);
+ }
+ }
+ return 0;
+}
- if (ri->rp && ri->rp->handler)
- ri->rp->handler(ri, regs);
+void trampoline_post_handler(struct kprobe *p, struct pt_regs *regs,
+ unsigned long flags)
+{
+ struct kretprobe_instance *ri;
+ /* RA already popped */
+ unsigned long *sara = ((unsigned long *)®s->esp) - 1;
- orig_ret_address = (unsigned long)ri->ret_addr;
+ while ((ri = get_rp_inst(sara))) {
+ regs->eip = (unsigned long)ri->ret_addr;
recycle_rp_inst(ri);
-
- if (orig_ret_address != trampoline_address)
- /*
- * This is the real return address. Any other
- * instances associated with this task are for
- * other calls deeper on the call stack
- */
- break;
}
-
- BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
- regs->eip = orig_ret_address;
-
- unlock_kprobes();
- preempt_enable_no_resched();
-
- /*
- * By returning a non-zero value, we are telling
- * kprobe_handler() that we have handled unlocking
- * and re-enabling preemption.
- */
- return 1;
+ regs->eflags &= ~TF_MASK;
}
/*
@@ -401,7 +403,8 @@ static inline int post_kprobe_handler(struct pt_regs *regs)
current_kprobe->post_handler(current_kprobe, regs, 0);
}
- resume_execution(current_kprobe, regs);
+ if (current_kprobe->post_handler != trampoline_post_handler)
+ resume_execution(current_kprobe, regs);
regs->eflags |= kprobe_saved_eflags;
/*Restore back the original saved kprobes variables and continue. */
@@ -531,13 +534,3 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
}
return 0;
}
-
-static struct kprobe trampoline_p = {
- .addr = (kprobe_opcode_t *) &kretprobe_trampoline,
- .pre_handler = trampoline_probe_handler
-};
-
-int __init arch_init(void)
-{
- return register_kprobe(&trampoline_p);
-}
diff --git a/trunk/arch/i386/kernel/process.c b/trunk/arch/i386/kernel/process.c
index ba243a4cc119..5f8cfa6b7940 100644
--- a/trunk/arch/i386/kernel/process.c
+++ b/trunk/arch/i386/kernel/process.c
@@ -616,33 +616,6 @@ handle_io_bitmap(struct thread_struct *next, struct tss_struct *tss)
tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY;
}
-/*
- * This function selects if the context switch from prev to next
- * has to tweak the TSC disable bit in the cr4.
- */
-static inline void disable_tsc(struct task_struct *prev_p,
- struct task_struct *next_p)
-{
- struct thread_info *prev, *next;
-
- /*
- * gcc should eliminate the ->thread_info dereference if
- * has_secure_computing returns 0 at compile time (SECCOMP=n).
- */
- prev = prev_p->thread_info;
- next = next_p->thread_info;
-
- if (has_secure_computing(prev) || has_secure_computing(next)) {
- /* slow path here */
- if (has_secure_computing(prev) &&
- !has_secure_computing(next)) {
- write_cr4(read_cr4() & ~X86_CR4_TSD);
- } else if (!has_secure_computing(prev) &&
- has_secure_computing(next))
- write_cr4(read_cr4() | X86_CR4_TSD);
- }
-}
-
/*
* switch_to(x,yn) should switch tasks from x to y.
*
@@ -722,8 +695,6 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr))
handle_io_bitmap(next, tss);
- disable_tsc(prev_p, next_p);
-
return prev_p;
}
diff --git a/trunk/arch/i386/kernel/syscall_table.S b/trunk/arch/i386/kernel/syscall_table.S
index 3db9a04aec6e..442a6e937b19 100644
--- a/trunk/arch/i386/kernel/syscall_table.S
+++ b/trunk/arch/i386/kernel/syscall_table.S
@@ -289,5 +289,3 @@ ENTRY(sys_call_table)
.long sys_add_key
.long sys_request_key
.long sys_keyctl
- .long sys_ioprio_set
- .long sys_ioprio_get /* 290 */
diff --git a/trunk/arch/ia64/kernel/entry.S b/trunk/arch/ia64/kernel/entry.S
index 785a51b0ad8e..b1d5d3d5276c 100644
--- a/trunk/arch/ia64/kernel/entry.S
+++ b/trunk/arch/ia64/kernel/entry.S
@@ -1577,8 +1577,8 @@ sys_call_table:
data8 sys_add_key
data8 sys_request_key
data8 sys_keyctl
- data8 sys_ioprio_set
- data8 sys_ioprio_get // 1275
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall // 1275
data8 sys_set_zone_reclaim
data8 sys_ni_syscall
data8 sys_ni_syscall
diff --git a/trunk/arch/ia64/kernel/kprobes.c b/trunk/arch/ia64/kernel/kprobes.c
index 3aa3167edbec..5978823d5c63 100644
--- a/trunk/arch/ia64/kernel/kprobes.c
+++ b/trunk/arch/ia64/kernel/kprobes.c
@@ -34,7 +34,6 @@
#include
#include
-#include
extern void jprobe_inst_return(void);
@@ -264,33 +263,13 @@ static inline void get_kprobe_inst(bundle_t *bundle, uint slot,
}
}
-/* Returns non-zero if the addr is in the Interrupt Vector Table */
-static inline int in_ivt_functions(unsigned long addr)
-{
- return (addr >= (unsigned long)__start_ivt_text
- && addr < (unsigned long)__end_ivt_text);
-}
-
static int valid_kprobe_addr(int template, int slot, unsigned long addr)
{
if ((slot > 2) || ((bundle_encoding[template][1] == L) && slot > 1)) {
- printk(KERN_WARNING "Attempting to insert unaligned kprobe "
- "at 0x%lx\n", addr);
+ printk(KERN_WARNING "Attempting to insert unaligned kprobe at 0x%lx\n",
+ addr);
return -EINVAL;
}
-
- if (in_ivt_functions(addr)) {
- printk(KERN_WARNING "Kprobes can't be inserted inside "
- "IVT functions at 0x%lx\n", addr);
- return -EINVAL;
- }
-
- if (slot == 1 && bundle_encoding[template][1] != L) {
- printk(KERN_WARNING "Inserting kprobes on slot #1 "
- "is not supported\n");
- return -EINVAL;
- }
-
return 0;
}
@@ -311,94 +290,6 @@ static inline void set_current_kprobe(struct kprobe *p)
current_kprobe = p;
}
-static void kretprobe_trampoline(void)
-{
-}
-
-/*
- * At this point the target function has been tricked into
- * returning into our trampoline. Lookup the associated instance
- * and then:
- * - call the handler function
- * - cleanup by marking the instance as unused
- * - long jump back to the original return address
- */
-int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
-{
- struct kretprobe_instance *ri = NULL;
- struct hlist_head *head;
- struct hlist_node *node, *tmp;
- unsigned long orig_ret_address = 0;
- unsigned long trampoline_address =
- ((struct fnptr *)kretprobe_trampoline)->ip;
-
- head = kretprobe_inst_table_head(current);
-
- /*
- * It is possible to have multiple instances associated with a given
- * task either because an multiple functions in the call path
- * have a return probe installed on them, and/or more then one return
- * return probe was registered for a target function.
- *
- * We can handle this because:
- * - instances are always inserted at the head of the list
- * - when multiple return probes are registered for the same
- * function, the first instance's ret_addr will point to the
- * real return address, and all the rest will point to
- * kretprobe_trampoline
- */
- hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
- if (ri->task != current)
- /* another task is sharing our hash bucket */
- continue;
-
- if (ri->rp && ri->rp->handler)
- ri->rp->handler(ri, regs);
-
- orig_ret_address = (unsigned long)ri->ret_addr;
- recycle_rp_inst(ri);
-
- if (orig_ret_address != trampoline_address)
- /*
- * This is the real return address. Any other
- * instances associated with this task are for
- * other calls deeper on the call stack
- */
- break;
- }
-
- BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
- regs->cr_iip = orig_ret_address;
-
- unlock_kprobes();
- preempt_enable_no_resched();
-
- /*
- * By returning a non-zero value, we are telling
- * kprobe_handler() that we have handled unlocking
- * and re-enabling preemption.
- */
- return 1;
-}
-
-void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
-{
- struct kretprobe_instance *ri;
-
- if ((ri = get_free_rp_inst(rp)) != NULL) {
- ri->rp = rp;
- ri->task = current;
- ri->ret_addr = (kprobe_opcode_t *)regs->b0;
-
- /* Replace the return addr with trampoline addr */
- regs->b0 = ((struct fnptr *)kretprobe_trampoline)->ip;
-
- add_rp_inst(ri);
- } else {
- rp->nmissed++;
- }
-}
-
int arch_prepare_kprobe(struct kprobe *p)
{
unsigned long addr = (unsigned long) p->addr;
@@ -601,8 +492,8 @@ static int pre_kprobes_handler(struct die_args *args)
if (p->pre_handler && p->pre_handler(p, regs))
/*
* Our pre-handler is specifically requesting that we just
- * do a return. This is used for both the jprobe pre-handler
- * and the kretprobe trampoline
+ * do a return. This is handling the case where the
+ * pre-handler is really our special jprobe pre-handler.
*/
return 1;
@@ -708,14 +599,3 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
*regs = jprobe_saved_regs;
return 1;
}
-
-static struct kprobe trampoline_p = {
- .pre_handler = trampoline_probe_handler
-};
-
-int __init arch_init(void)
-{
- trampoline_p.addr =
- (kprobe_opcode_t *)((struct fnptr *)kretprobe_trampoline)->ip;
- return register_kprobe(&trampoline_p);
-}
diff --git a/trunk/arch/ia64/kernel/process.c b/trunk/arch/ia64/kernel/process.c
index 6e35bff05d59..ebb71f3d6d19 100644
--- a/trunk/arch/ia64/kernel/process.c
+++ b/trunk/arch/ia64/kernel/process.c
@@ -27,7 +27,6 @@
#include
#include
#include
-#include
#include
#include
@@ -708,13 +707,6 @@ kernel_thread_helper (int (*fn)(void *), void *arg)
void
flush_thread (void)
{
- /*
- * Remove function-return probe instances associated with this task
- * and put them back on the free list. Do not insert an exit probe for
- * this function, it will be disabled by kprobe_flush_task if you do.
- */
- kprobe_flush_task(current);
-
/* drop floating-point and debug-register state if it exists: */
current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID);
ia64_drop_fpu(current);
@@ -729,14 +721,6 @@ flush_thread (void)
void
exit_thread (void)
{
-
- /*
- * Remove function-return probe instances associated with this task
- * and put them back on the free list. Do not insert an exit probe for
- * this function, it will be disabled by kprobe_flush_task if you do.
- */
- kprobe_flush_task(current);
-
ia64_drop_fpu(current);
#ifdef CONFIG_PERFMON
/* if needed, stop monitoring and flush state to perfmon context */
diff --git a/trunk/arch/ia64/kernel/vmlinux.lds.S b/trunk/arch/ia64/kernel/vmlinux.lds.S
index a676e79e0681..b9f0db4c1b04 100644
--- a/trunk/arch/ia64/kernel/vmlinux.lds.S
+++ b/trunk/arch/ia64/kernel/vmlinux.lds.S
@@ -8,11 +8,6 @@
#define LOAD_OFFSET (KERNEL_START - KERNEL_TR_PAGE_SIZE)
#include
-#define IVT_TEXT \
- VMLINUX_SYMBOL(__start_ivt_text) = .; \
- *(.text.ivt) \
- VMLINUX_SYMBOL(__end_ivt_text) = .;
-
OUTPUT_FORMAT("elf64-ia64-little")
OUTPUT_ARCH(ia64)
ENTRY(phys_start)
@@ -44,7 +39,7 @@ SECTIONS
.text : AT(ADDR(.text) - LOAD_OFFSET)
{
- IVT_TEXT
+ *(.text.ivt)
*(.text)
SCHED_TEXT
LOCK_TEXT
diff --git a/trunk/arch/mips/kernel/signal.c b/trunk/arch/mips/kernel/signal.c
index 65ee15396ffd..508026ae5842 100644
--- a/trunk/arch/mips/kernel/signal.c
+++ b/trunk/arch/mips/kernel/signal.c
@@ -457,7 +457,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs)
if (!user_mode(regs))
return 1;
- if (try_to_freeze())
+ if (try_to_freeze(0))
goto no_signal;
if (!oldset)
diff --git a/trunk/arch/ppc/kernel/misc.S b/trunk/arch/ppc/kernel/misc.S
index 191a8def3bdb..b6a63a49a232 100644
--- a/trunk/arch/ppc/kernel/misc.S
+++ b/trunk/arch/ppc/kernel/misc.S
@@ -1449,5 +1449,3 @@ _GLOBAL(sys_call_table)
.long sys_request_key /* 270 */
.long sys_keyctl
.long sys_waitid
- .long sys_ioprio_set
- .long sys_ioprio_get
diff --git a/trunk/arch/ppc/mm/init.c b/trunk/arch/ppc/mm/init.c
index 6164a2b34733..334ef4150d92 100644
--- a/trunk/arch/ppc/mm/init.c
+++ b/trunk/arch/ppc/mm/init.c
@@ -606,19 +606,9 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
struct page *page = pfn_to_page(pfn);
if (!PageReserved(page)
&& !test_bit(PG_arch_1, &page->flags)) {
- if (vma->vm_mm == current->active_mm) {
-#ifdef CONFIG_8xx
- /* On 8xx, cache control instructions (particularly
- * "dcbst" from flush_dcache_icache) fault as write
- * operation if there is an unpopulated TLB entry
- * for the address in question. To workaround that,
- * we invalidate the TLB here, thus avoiding dcbst
- * misbehaviour.
- */
- _tlbie(address);
-#endif
+ if (vma->vm_mm == current->active_mm)
__flush_dcache_icache((void *) address);
- } else
+ else
flush_dcache_icache_page(page);
set_bit(PG_arch_1, &page->flags);
}
diff --git a/trunk/arch/ppc/platforms/pmac_sleep.S b/trunk/arch/ppc/platforms/pmac_sleep.S
index 016a74649155..f459ade1bd63 100644
--- a/trunk/arch/ppc/platforms/pmac_sleep.S
+++ b/trunk/arch/ppc/platforms/pmac_sleep.S
@@ -46,7 +46,7 @@
.section .text
.align 5
-#if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC)
+#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
@@ -382,7 +382,7 @@ turn_on_mmu:
isync
rfi
-#endif /* defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ) */
+#endif /* defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_CPU_FREQ) */
.section .data
.balign L1_CACHE_LINE_SIZE
diff --git a/trunk/arch/ppc/platforms/pmac_time.c b/trunk/arch/ppc/platforms/pmac_time.c
index 778ce4fec368..de60ccc7db9f 100644
--- a/trunk/arch/ppc/platforms/pmac_time.c
+++ b/trunk/arch/ppc/platforms/pmac_time.c
@@ -206,7 +206,7 @@ via_calibrate_decr(void)
return 1;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PMAC_PBOOK
/*
* Reset the time after a sleep.
*/
@@ -238,7 +238,7 @@ time_sleep_notify(struct pmu_sleep_notifier *self, int when)
static struct pmu_sleep_notifier time_sleep_notifier __pmacdata = {
time_sleep_notify, SLEEP_LEVEL_MISC,
};
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PMAC_PBOOK */
/*
* Query the OF and get the decr frequency.
@@ -251,9 +251,9 @@ pmac_calibrate_decr(void)
struct device_node *cpu;
unsigned int freq, *fp;
-#ifdef CONFIG_PM
+#ifdef CONFIG_PMAC_PBOOK
pmu_register_sleep_notifier(&time_sleep_notifier);
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PMAC_PBOOK */
/* We assume MacRISC2 machines have correct device-tree
* calibration. That's better since the VIA itself seems
diff --git a/trunk/arch/ppc/platforms/sandpoint.c b/trunk/arch/ppc/platforms/sandpoint.c
index 8b149c2fc54f..70e58f43f2b8 100644
--- a/trunk/arch/ppc/platforms/sandpoint.c
+++ b/trunk/arch/ppc/platforms/sandpoint.c
@@ -324,7 +324,6 @@ sandpoint_setup_arch(void)
pdata[1].irq = 0;
pdata[1].mapbase = 0;
}
- }
printk(KERN_INFO "Motorola SPS Sandpoint Test Platform\n");
printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
diff --git a/trunk/arch/ppc/syslib/open_pic.c b/trunk/arch/ppc/syslib/open_pic.c
index ad39b86ca92c..b45d8268bf93 100644
--- a/trunk/arch/ppc/syslib/open_pic.c
+++ b/trunk/arch/ppc/syslib/open_pic.c
@@ -370,9 +370,8 @@ void __init openpic_init(int offset)
/* Initialize IPI interrupts */
if ( ppc_md.progress ) ppc_md.progress("openpic: ipi",0x3bb);
for (i = 0; i < OPENPIC_NUM_IPI; i++) {
- /* Disabled, increased priorities 10..13 */
- openpic_initipi(i, OPENPIC_PRIORITY_IPI_BASE+i,
- OPENPIC_VEC_IPI+i+offset);
+ /* Disabled, Priority 10..13 */
+ openpic_initipi(i, 10+i, OPENPIC_VEC_IPI+i+offset);
/* IPIs are per-CPU */
irq_desc[OPENPIC_VEC_IPI+i+offset].status |= IRQ_PER_CPU;
irq_desc[OPENPIC_VEC_IPI+i+offset].handler = &open_pic_ipi;
@@ -400,9 +399,8 @@ void __init openpic_init(int offset)
if (sense & IRQ_SENSE_MASK)
irq_desc[i+offset].status = IRQ_LEVEL;
- /* Enabled, Default priority */
- openpic_initirq(i, OPENPIC_PRIORITY_DEFAULT, i+offset,
- (sense & IRQ_POLARITY_MASK),
+ /* Enabled, Priority 8 */
+ openpic_initirq(i, 8, i+offset, (sense & IRQ_POLARITY_MASK),
(sense & IRQ_SENSE_MASK));
/* Processor 0 */
openpic_mapirq(i, CPU_MASK_CPU0, CPU_MASK_NONE);
@@ -657,18 +655,6 @@ static void __init openpic_maptimer(u_int timer, cpumask_t cpumask)
cpus_addr(phys)[0]);
}
-/*
- * Change the priority of an interrupt
- */
-void __init
-openpic_set_irq_priority(u_int irq, u_int pri)
-{
- check_arg_irq(irq);
- openpic_safe_writefield(&ISR[irq - open_pic_irq_offset]->Vector_Priority,
- OPENPIC_PRIORITY_MASK,
- pri << OPENPIC_PRIORITY_SHIFT);
-}
-
/*
* Initalize the interrupt source which will generate an NMI.
* This raises the interrupt's priority from 8 to 9.
@@ -679,7 +665,9 @@ void __init
openpic_init_nmi_irq(u_int irq)
{
check_arg_irq(irq);
- openpic_set_irq_priority(irq, OPENPIC_PRIORITY_NMI);
+ openpic_safe_writefield(&ISR[irq - open_pic_irq_offset]->Vector_Priority,
+ OPENPIC_PRIORITY_MASK,
+ 9 << OPENPIC_PRIORITY_SHIFT);
}
/*
diff --git a/trunk/arch/ppc64/kernel/kprobes.c b/trunk/arch/ppc64/kernel/kprobes.c
index 1d2ff6d6b0b3..782ce3efa2c1 100644
--- a/trunk/arch/ppc64/kernel/kprobes.c
+++ b/trunk/arch/ppc64/kernel/kprobes.c
@@ -36,8 +36,6 @@
#include
#include
-static DECLARE_MUTEX(kprobe_mutex);
-
static struct kprobe *current_kprobe;
static unsigned long kprobe_status, kprobe_saved_msr;
static struct kprobe *kprobe_prev;
@@ -56,15 +54,6 @@ int arch_prepare_kprobe(struct kprobe *p)
printk("Cannot register a kprobe on rfid or mtmsrd\n");
ret = -EINVAL;
}
-
- /* insn must be on a special executable page on ppc64 */
- if (!ret) {
- up(&kprobe_mutex);
- p->ainsn.insn = get_insn_slot();
- down(&kprobe_mutex);
- if (!p->ainsn.insn)
- ret = -ENOMEM;
- }
return ret;
}
@@ -90,22 +79,16 @@ void arch_disarm_kprobe(struct kprobe *p)
void arch_remove_kprobe(struct kprobe *p)
{
- up(&kprobe_mutex);
- free_insn_slot(p->ainsn.insn);
- down(&kprobe_mutex);
}
static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
- kprobe_opcode_t insn = *p->ainsn.insn;
-
regs->msr |= MSR_SE;
-
- /* single step inline if it is a trap variant */
- if (IS_TW(insn) || IS_TD(insn) || IS_TWI(insn) || IS_TDI(insn))
+ /*single step inline if it a breakpoint instruction*/
+ if (p->opcode == BREAKPOINT_INSTRUCTION)
regs->nip = (unsigned long)p->addr;
else
- regs->nip = (unsigned long)p->ainsn.insn;
+ regs->nip = (unsigned long)&p->ainsn.insn;
}
static inline void save_previous_kprobe(void)
@@ -122,23 +105,6 @@ static inline void restore_previous_kprobe(void)
kprobe_saved_msr = kprobe_saved_msr_prev;
}
-void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
-{
- struct kretprobe_instance *ri;
-
- if ((ri = get_free_rp_inst(rp)) != NULL) {
- ri->rp = rp;
- ri->task = current;
- ri->ret_addr = (kprobe_opcode_t *)regs->link;
-
- /* Replace the return addr with trampoline addr */
- regs->link = (unsigned long)kretprobe_trampoline;
- add_rp_inst(ri);
- } else {
- rp->nmissed++;
- }
-}
-
static inline int kprobe_handler(struct pt_regs *regs)
{
struct kprobe *p;
@@ -228,78 +194,6 @@ static inline int kprobe_handler(struct pt_regs *regs)
return ret;
}
-/*
- * Function return probe trampoline:
- * - init_kprobes() establishes a probepoint here
- * - When the probed function returns, this probe
- * causes the handlers to fire
- */
-void kretprobe_trampoline_holder(void)
-{
- asm volatile(".global kretprobe_trampoline\n"
- "kretprobe_trampoline:\n"
- "nop\n");
-}
-
-/*
- * Called when the probe at kretprobe trampoline is hit
- */
-int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
-{
- struct kretprobe_instance *ri = NULL;
- struct hlist_head *head;
- struct hlist_node *node, *tmp;
- unsigned long orig_ret_address = 0;
- unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
-
- head = kretprobe_inst_table_head(current);
-
- /*
- * It is possible to have multiple instances associated with a given
- * task either because an multiple functions in the call path
- * have a return probe installed on them, and/or more then one return
- * return probe was registered for a target function.
- *
- * We can handle this because:
- * - instances are always inserted at the head of the list
- * - when multiple return probes are registered for the same
- * function, the first instance's ret_addr will point to the
- * real return address, and all the rest will point to
- * kretprobe_trampoline
- */
- hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
- if (ri->task != current)
- /* another task is sharing our hash bucket */
- continue;
-
- if (ri->rp && ri->rp->handler)
- ri->rp->handler(ri, regs);
-
- orig_ret_address = (unsigned long)ri->ret_addr;
- recycle_rp_inst(ri);
-
- if (orig_ret_address != trampoline_address)
- /*
- * This is the real return address. Any other
- * instances associated with this task are for
- * other calls deeper on the call stack
- */
- break;
- }
-
- BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
- regs->nip = orig_ret_address;
-
- unlock_kprobes();
-
- /*
- * By returning a non-zero value, we are telling
- * kprobe_handler() that we have handled unlocking
- * and re-enabling preemption.
- */
- return 1;
-}
-
/*
* Called after single-stepping. p->addr is the address of the
* instruction whose first byte has been replaced by the "breakpoint"
@@ -311,10 +205,9 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
static void resume_execution(struct kprobe *p, struct pt_regs *regs)
{
int ret;
- unsigned int insn = *p->ainsn.insn;
regs->nip = (unsigned long)p->addr;
- ret = emulate_step(regs, insn);
+ ret = emulate_step(regs, p->ainsn.insn[0]);
if (ret == 0)
regs->nip = (unsigned long)p->addr + 4;
}
@@ -438,13 +331,3 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
memcpy(regs, &jprobe_saved_regs, sizeof(struct pt_regs));
return 1;
}
-
-static struct kprobe trampoline_p = {
- .addr = (kprobe_opcode_t *) &kretprobe_trampoline,
- .pre_handler = trampoline_probe_handler
-};
-
-int __init arch_init(void)
-{
- return register_kprobe(&trampoline_p);
-}
diff --git a/trunk/arch/ppc64/kernel/ppc_ksyms.c b/trunk/arch/ppc64/kernel/ppc_ksyms.c
index 705742f4eec6..b230a63fe4c8 100644
--- a/trunk/arch/ppc64/kernel/ppc_ksyms.c
+++ b/trunk/arch/ppc64/kernel/ppc_ksyms.c
@@ -75,7 +75,6 @@ EXPORT_SYMBOL(giveup_fpu);
EXPORT_SYMBOL(giveup_altivec);
#endif
EXPORT_SYMBOL(__flush_icache_range);
-EXPORT_SYMBOL(flush_dcache_range);
#ifdef CONFIG_SMP
#ifdef CONFIG_PPC_ISERIES
diff --git a/trunk/arch/ppc64/kernel/process.c b/trunk/arch/ppc64/kernel/process.c
index f7cae05e40fb..aba89554d89d 100644
--- a/trunk/arch/ppc64/kernel/process.c
+++ b/trunk/arch/ppc64/kernel/process.c
@@ -36,7 +36,6 @@
#include
#include
#include
-#include
#include
#include
@@ -308,8 +307,6 @@ void show_regs(struct pt_regs * regs)
void exit_thread(void)
{
- kprobe_flush_task(current);
-
#ifndef CONFIG_SMP
if (last_task_used_math == current)
last_task_used_math = NULL;
@@ -324,7 +321,6 @@ void flush_thread(void)
{
struct thread_info *t = current_thread_info();
- kprobe_flush_task(current);
if (t->flags & _TIF_ABI_PENDING)
t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT);
diff --git a/trunk/arch/ppc64/kernel/time.c b/trunk/arch/ppc64/kernel/time.c
index 2a532db9138a..2348a75e050d 100644
--- a/trunk/arch/ppc64/kernel/time.c
+++ b/trunk/arch/ppc64/kernel/time.c
@@ -91,7 +91,6 @@ unsigned long tb_to_xs;
unsigned tb_to_us;
unsigned long processor_freq;
DEFINE_SPINLOCK(rtc_lock);
-EXPORT_SYMBOL_GPL(rtc_lock);
unsigned long tb_to_ns_scale;
unsigned long tb_to_ns_shift;
diff --git a/trunk/arch/sparc64/kernel/entry.S b/trunk/arch/sparc64/kernel/entry.S
index a47f2d0b1a29..ffe717ab7f83 100644
--- a/trunk/arch/sparc64/kernel/entry.S
+++ b/trunk/arch/sparc64/kernel/entry.S
@@ -271,8 +271,9 @@ cplus_fptrap_insn_1:
fmuld %f0, %f2, %f26
faddd %f0, %f2, %f28
fmuld %f0, %f2, %f30
+ membar #Sync
b,pt %xcc, fpdis_exit
- membar #Sync
+ nop
2: andcc %g5, FPRS_DU, %g0
bne,pt %icc, 3f
fzero %f32
@@ -301,8 +302,9 @@ cplus_fptrap_insn_2:
fmuld %f32, %f34, %f58
faddd %f32, %f34, %f60
fmuld %f32, %f34, %f62
+ membar #Sync
ba,pt %xcc, fpdis_exit
- membar #Sync
+ nop
3: mov SECONDARY_CONTEXT, %g3
add %g6, TI_FPREGS, %g1
ldxa [%g3] ASI_DMMU, %g5
diff --git a/trunk/arch/sparc64/kernel/semaphore.c b/trunk/arch/sparc64/kernel/semaphore.c
index 63496c43fe17..a809e63f03ef 100644
--- a/trunk/arch/sparc64/kernel/semaphore.c
+++ b/trunk/arch/sparc64/kernel/semaphore.c
@@ -32,8 +32,9 @@ static __inline__ int __sem_update_count(struct semaphore *sem, int incr)
" add %1, %4, %1\n"
" cas [%3], %0, %1\n"
" cmp %0, %1\n"
+" membar #StoreLoad | #StoreStore\n"
" bne,pn %%icc, 1b\n"
-" membar #StoreLoad | #StoreStore\n"
+" nop\n"
: "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
: "r" (&sem->count), "r" (incr), "m" (sem->count)
: "cc");
@@ -71,8 +72,9 @@ void up(struct semaphore *sem)
" cmp %%g1, %%g7\n"
" bne,pn %%icc, 1b\n"
" addcc %%g7, 1, %%g0\n"
+" membar #StoreLoad | #StoreStore\n"
" ble,pn %%icc, 3f\n"
-" membar #StoreLoad | #StoreStore\n"
+" nop\n"
"2:\n"
" .subsection 2\n"
"3: mov %0, %%g1\n"
@@ -128,8 +130,9 @@ void __sched down(struct semaphore *sem)
" cmp %%g1, %%g7\n"
" bne,pn %%icc, 1b\n"
" cmp %%g7, 1\n"
+" membar #StoreLoad | #StoreStore\n"
" bl,pn %%icc, 3f\n"
-" membar #StoreLoad | #StoreStore\n"
+" nop\n"
"2:\n"
" .subsection 2\n"
"3: mov %0, %%g1\n"
@@ -233,8 +236,9 @@ int __sched down_interruptible(struct semaphore *sem)
" cmp %%g1, %%g7\n"
" bne,pn %%icc, 1b\n"
" cmp %%g7, 1\n"
+" membar #StoreLoad | #StoreStore\n"
" bl,pn %%icc, 3f\n"
-" membar #StoreLoad | #StoreStore\n"
+" nop\n"
"2:\n"
" .subsection 2\n"
"3: mov %2, %%g1\n"
diff --git a/trunk/arch/sparc64/kernel/trampoline.S b/trunk/arch/sparc64/kernel/trampoline.S
index 2c8f9344b4ee..3a145fc39cf2 100644
--- a/trunk/arch/sparc64/kernel/trampoline.S
+++ b/trunk/arch/sparc64/kernel/trampoline.S
@@ -98,8 +98,9 @@ startup_continue:
sethi %hi(prom_entry_lock), %g2
1: ldstub [%g2 + %lo(prom_entry_lock)], %g1
+ membar #StoreLoad | #StoreStore
brnz,pn %g1, 1b
- membar #StoreLoad | #StoreStore
+ nop
sethi %hi(p1275buf), %g2
or %g2, %lo(p1275buf), %g2
diff --git a/trunk/arch/sparc64/lib/U1memcpy.S b/trunk/arch/sparc64/lib/U1memcpy.S
index da9b520c7189..bafd2fc07acb 100644
--- a/trunk/arch/sparc64/lib/U1memcpy.S
+++ b/trunk/arch/sparc64/lib/U1memcpy.S
@@ -87,14 +87,17 @@
#define LOOP_CHUNK3(src, dest, len, branch_dest) \
MAIN_LOOP_CHUNK(src, dest, f32, f48, len, branch_dest)
+#define DO_SYNC membar #Sync;
#define STORE_SYNC(dest, fsrc) \
EX_ST(STORE_BLK(%fsrc, %dest)); \
- add %dest, 0x40, %dest;
+ add %dest, 0x40, %dest; \
+ DO_SYNC
#define STORE_JUMP(dest, fsrc, target) \
EX_ST(STORE_BLK(%fsrc, %dest)); \
add %dest, 0x40, %dest; \
- ba,pt %xcc, target;
+ ba,pt %xcc, target; \
+ nop;
#define FINISH_VISCHUNK(dest, f0, f1, left) \
subcc %left, 8, %left;\
@@ -239,17 +242,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */
ba,pt %xcc, 1b+4
faligndata %f0, %f2, %f48
1: FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)
- STORE_JUMP(o0, f48, 40f) membar #Sync
+ STORE_JUMP(o0, f48, 40f)
2: FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16)
- STORE_JUMP(o0, f48, 48f) membar #Sync
+ STORE_JUMP(o0, f48, 48f)
3: FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32)
- STORE_JUMP(o0, f48, 56f) membar #Sync
+ STORE_JUMP(o0, f48, 56f)
1: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18)
LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
@@ -260,17 +263,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */
ba,pt %xcc, 1b+4
faligndata %f2, %f4, %f48
1: FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)
- STORE_JUMP(o0, f48, 41f) membar #Sync
+ STORE_JUMP(o0, f48, 41f)
2: FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18)
- STORE_JUMP(o0, f48, 49f) membar #Sync
+ STORE_JUMP(o0, f48, 49f)
3: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34)
- STORE_JUMP(o0, f48, 57f) membar #Sync
+ STORE_JUMP(o0, f48, 57f)
1: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20)
LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
@@ -281,17 +284,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */
ba,pt %xcc, 1b+4
faligndata %f4, %f6, %f48
1: FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)
- STORE_JUMP(o0, f48, 42f) membar #Sync
+ STORE_JUMP(o0, f48, 42f)
2: FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20)
- STORE_JUMP(o0, f48, 50f) membar #Sync
+ STORE_JUMP(o0, f48, 50f)
3: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36)
- STORE_JUMP(o0, f48, 58f) membar #Sync
+ STORE_JUMP(o0, f48, 58f)
1: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22)
LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
@@ -302,17 +305,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */
ba,pt %xcc, 1b+4
faligndata %f6, %f8, %f48
1: FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)
- STORE_JUMP(o0, f48, 43f) membar #Sync
+ STORE_JUMP(o0, f48, 43f)
2: FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22)
- STORE_JUMP(o0, f48, 51f) membar #Sync
+ STORE_JUMP(o0, f48, 51f)
3: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38)
- STORE_JUMP(o0, f48, 59f) membar #Sync
+ STORE_JUMP(o0, f48, 59f)
1: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24)
LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
@@ -323,17 +326,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */
ba,pt %xcc, 1b+4
faligndata %f8, %f10, %f48
1: FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)
- STORE_JUMP(o0, f48, 44f) membar #Sync
+ STORE_JUMP(o0, f48, 44f)
2: FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24)
- STORE_JUMP(o0, f48, 52f) membar #Sync
+ STORE_JUMP(o0, f48, 52f)
3: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40)
- STORE_JUMP(o0, f48, 60f) membar #Sync
+ STORE_JUMP(o0, f48, 60f)
1: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26)
LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
@@ -344,17 +347,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */
ba,pt %xcc, 1b+4
faligndata %f10, %f12, %f48
1: FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10)
- STORE_JUMP(o0, f48, 45f) membar #Sync
+ STORE_JUMP(o0, f48, 45f)
2: FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26)
- STORE_JUMP(o0, f48, 53f) membar #Sync
+ STORE_JUMP(o0, f48, 53f)
3: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42)
- STORE_JUMP(o0, f48, 61f) membar #Sync
+ STORE_JUMP(o0, f48, 61f)
1: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28)
LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
@@ -365,17 +368,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */
ba,pt %xcc, 1b+4
faligndata %f12, %f14, %f48
1: FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12)
- STORE_JUMP(o0, f48, 46f) membar #Sync
+ STORE_JUMP(o0, f48, 46f)
2: FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28)
- STORE_JUMP(o0, f48, 54f) membar #Sync
+ STORE_JUMP(o0, f48, 54f)
3: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44)
- STORE_JUMP(o0, f48, 62f) membar #Sync
+ STORE_JUMP(o0, f48, 62f)
1: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30)
LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
@@ -386,17 +389,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */
ba,pt %xcc, 1b+4
faligndata %f14, %f16, %f48
1: FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14)
- STORE_JUMP(o0, f48, 47f) membar #Sync
+ STORE_JUMP(o0, f48, 47f)
2: FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30)
- STORE_JUMP(o0, f48, 55f) membar #Sync
+ STORE_JUMP(o0, f48, 55f)
3: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30)
- STORE_SYNC(o0, f48) membar #Sync
+ STORE_SYNC(o0, f48)
FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46)
- STORE_JUMP(o0, f48, 63f) membar #Sync
+ STORE_JUMP(o0, f48, 63f)
40: FINISH_VISCHUNK(o0, f0, f2, g3)
41: FINISH_VISCHUNK(o0, f2, f4, g3)
diff --git a/trunk/arch/sparc64/lib/VISsave.S b/trunk/arch/sparc64/lib/VISsave.S
index 65e328d600a8..4e18989bd602 100644
--- a/trunk/arch/sparc64/lib/VISsave.S
+++ b/trunk/arch/sparc64/lib/VISsave.S
@@ -72,7 +72,11 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3
stda %f48, [%g3 + %g1] ASI_BLK_P
5: membar #Sync
- jmpl %g7 + %g0, %g0
+ ba,pt %xcc, 80f
+ nop
+
+ .align 32
+80: jmpl %g7 + %g0, %g0
nop
6: ldub [%g3 + TI_FPSAVED], %o5
@@ -87,8 +91,11 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3
stda %f32, [%g2 + %g1] ASI_BLK_P
stda %f48, [%g3 + %g1] ASI_BLK_P
membar #Sync
- jmpl %g7 + %g0, %g0
+ ba,pt %xcc, 80f
+ nop
+ .align 32
+80: jmpl %g7 + %g0, %g0
nop
.align 32
@@ -126,6 +133,10 @@ VISenterhalf:
stda %f0, [%g2 + %g1] ASI_BLK_P
stda %f16, [%g3 + %g1] ASI_BLK_P
membar #Sync
+ ba,pt %xcc, 4f
+ nop
+
+ .align 32
4: and %o5, FPRS_DU, %o5
jmpl %g7 + %g0, %g0
wr %o5, FPRS_FEF, %fprs
diff --git a/trunk/arch/sparc64/lib/atomic.S b/trunk/arch/sparc64/lib/atomic.S
index e528b8d1a3e6..faf87c31598b 100644
--- a/trunk/arch/sparc64/lib/atomic.S
+++ b/trunk/arch/sparc64/lib/atomic.S
@@ -7,18 +7,6 @@
#include
#include
- /* On SMP we need to use memory barriers to ensure
- * correct memory operation ordering, nop these out
- * for uniprocessor.
- */
-#ifdef CONFIG_SMP
-#define ATOMIC_PRE_BARRIER membar #StoreLoad | #LoadLoad
-#define ATOMIC_POST_BARRIER membar #StoreLoad | #StoreStore
-#else
-#define ATOMIC_PRE_BARRIER nop
-#define ATOMIC_POST_BARRIER nop
-#endif
-
.text
/* Two versions of the atomic routines, one that
@@ -52,6 +40,24 @@ atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */
nop
.size atomic_sub, .-atomic_sub
+ /* On SMP we need to use memory barriers to ensure
+ * correct memory operation ordering, nop these out
+ * for uniprocessor.
+ */
+#ifdef CONFIG_SMP
+
+#define ATOMIC_PRE_BARRIER membar #StoreLoad | #LoadLoad;
+#define ATOMIC_POST_BARRIER \
+ ba,pt %xcc, 80b; \
+ membar #StoreLoad | #StoreStore
+
+80: retl
+ nop
+#else
+#define ATOMIC_PRE_BARRIER
+#define ATOMIC_POST_BARRIER
+#endif
+
.globl atomic_add_ret
.type atomic_add_ret,#function
atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
@@ -62,9 +68,10 @@ atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
cmp %g1, %g7
bne,pn %icc, 1b
add %g7, %o0, %g7
+ sra %g7, 0, %o0
ATOMIC_POST_BARRIER
retl
- sra %g7, 0, %o0
+ nop
.size atomic_add_ret, .-atomic_add_ret
.globl atomic_sub_ret
@@ -77,9 +84,10 @@ atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
cmp %g1, %g7
bne,pn %icc, 1b
sub %g7, %o0, %g7
+ sra %g7, 0, %o0
ATOMIC_POST_BARRIER
retl
- sra %g7, 0, %o0
+ nop
.size atomic_sub_ret, .-atomic_sub_ret
.globl atomic64_add
@@ -118,9 +126,10 @@ atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
cmp %g1, %g7
bne,pn %xcc, 1b
add %g7, %o0, %g7
+ mov %g7, %o0
ATOMIC_POST_BARRIER
retl
- mov %g7, %o0
+ nop
.size atomic64_add_ret, .-atomic64_add_ret
.globl atomic64_sub_ret
@@ -133,7 +142,8 @@ atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
cmp %g1, %g7
bne,pn %xcc, 1b
sub %g7, %o0, %g7
+ mov %g7, %o0
ATOMIC_POST_BARRIER
retl
- mov %g7, %o0
+ nop
.size atomic64_sub_ret, .-atomic64_sub_ret
diff --git a/trunk/arch/sparc64/lib/bitops.S b/trunk/arch/sparc64/lib/bitops.S
index 886dcd2b376a..31afbfe6c1e8 100644
--- a/trunk/arch/sparc64/lib/bitops.S
+++ b/trunk/arch/sparc64/lib/bitops.S
@@ -7,20 +7,26 @@
#include
#include
+ .text
+
/* On SMP we need to use memory barriers to ensure
* correct memory operation ordering, nop these out
* for uniprocessor.
*/
+
#ifdef CONFIG_SMP
#define BITOP_PRE_BARRIER membar #StoreLoad | #LoadLoad
-#define BITOP_POST_BARRIER membar #StoreLoad | #StoreStore
+#define BITOP_POST_BARRIER \
+ ba,pt %xcc, 80b; \
+ membar #StoreLoad | #StoreStore
+
+80: retl
+ nop
#else
-#define BITOP_PRE_BARRIER nop
-#define BITOP_POST_BARRIER nop
+#define BITOP_PRE_BARRIER
+#define BITOP_POST_BARRIER
#endif
- .text
-
.globl test_and_set_bit
.type test_and_set_bit,#function
test_and_set_bit: /* %o0=nr, %o1=addr */
@@ -37,10 +43,11 @@ test_and_set_bit: /* %o0=nr, %o1=addr */
cmp %g7, %g1
bne,pn %xcc, 1b
and %g7, %o2, %g2
- BITOP_POST_BARRIER
clr %o0
+ movrne %g2, 1, %o0
+ BITOP_POST_BARRIER
retl
- movrne %g2, 1, %o0
+ nop
.size test_and_set_bit, .-test_and_set_bit
.globl test_and_clear_bit
@@ -59,10 +66,11 @@ test_and_clear_bit: /* %o0=nr, %o1=addr */
cmp %g7, %g1
bne,pn %xcc, 1b
and %g7, %o2, %g2
- BITOP_POST_BARRIER
clr %o0
+ movrne %g2, 1, %o0
+ BITOP_POST_BARRIER
retl
- movrne %g2, 1, %o0
+ nop
.size test_and_clear_bit, .-test_and_clear_bit
.globl test_and_change_bit
@@ -81,10 +89,11 @@ test_and_change_bit: /* %o0=nr, %o1=addr */
cmp %g7, %g1
bne,pn %xcc, 1b
and %g7, %o2, %g2
- BITOP_POST_BARRIER
clr %o0
+ movrne %g2, 1, %o0
+ BITOP_POST_BARRIER
retl
- movrne %g2, 1, %o0
+ nop
.size test_and_change_bit, .-test_and_change_bit
.globl set_bit
diff --git a/trunk/arch/sparc64/lib/debuglocks.c b/trunk/arch/sparc64/lib/debuglocks.c
index c421e0c65325..f03344cf784e 100644
--- a/trunk/arch/sparc64/lib/debuglocks.c
+++ b/trunk/arch/sparc64/lib/debuglocks.c
@@ -252,8 +252,9 @@ void _do_write_lock (rwlock_t *rw, char *str)
" andn %%g1, %%g3, %%g7\n"
" casx [%0], %%g1, %%g7\n"
" cmp %%g1, %%g7\n"
+" membar #StoreLoad | #StoreStore\n"
" bne,pn %%xcc, 1b\n"
-" membar #StoreLoad | #StoreStore"
+" nop"
: /* no outputs */
: "r" (&(rw->lock))
: "g3", "g1", "g7", "cc", "memory");
@@ -351,8 +352,9 @@ int _do_write_trylock (rwlock_t *rw, char *str)
" andn %%g1, %%g3, %%g7\n"
" casx [%0], %%g1, %%g7\n"
" cmp %%g1, %%g7\n"
+" membar #StoreLoad | #StoreStore\n"
" bne,pn %%xcc, 1b\n"
-" membar #StoreLoad | #StoreStore"
+" nop"
: /* no outputs */
: "r" (&(rw->lock))
: "g3", "g1", "g7", "cc", "memory");
diff --git a/trunk/arch/sparc64/lib/dec_and_lock.S b/trunk/arch/sparc64/lib/dec_and_lock.S
index 7e6fdaebedba..8ee288dd0afc 100644
--- a/trunk/arch/sparc64/lib/dec_and_lock.S
+++ b/trunk/arch/sparc64/lib/dec_and_lock.S
@@ -48,8 +48,9 @@ start_to_zero:
#endif
to_zero:
ldstub [%o1], %g3
+ membar #StoreLoad | #StoreStore
brnz,pn %g3, spin_on_lock
- membar #StoreLoad | #StoreStore
+ nop
loop2: cas [%o0], %g2, %g7 /* ASSERT(g7 == 0) */
cmp %g2, %g7
@@ -71,8 +72,9 @@ loop2: cas [%o0], %g2, %g7 /* ASSERT(g7 == 0) */
nop
spin_on_lock:
ldub [%o1], %g3
+ membar #LoadLoad
brnz,pt %g3, spin_on_lock
- membar #LoadLoad
+ nop
ba,pt %xcc, to_zero
nop
nop
diff --git a/trunk/arch/sparc64/lib/rwsem.S b/trunk/arch/sparc64/lib/rwsem.S
index 174ff7b9164c..75f0e6b951d6 100644
--- a/trunk/arch/sparc64/lib/rwsem.S
+++ b/trunk/arch/sparc64/lib/rwsem.S
@@ -17,8 +17,9 @@ __down_read:
bne,pn %icc, 1b
add %g7, 1, %g7
cmp %g7, 0
+ membar #StoreLoad | #StoreStore
bl,pn %icc, 3f
- membar #StoreLoad | #StoreStore
+ nop
2:
retl
nop
@@ -57,8 +58,9 @@ __down_write:
cmp %g3, %g7
bne,pn %icc, 1b
cmp %g7, 0
+ membar #StoreLoad | #StoreStore
bne,pn %icc, 3f
- membar #StoreLoad | #StoreStore
+ nop
2: retl
nop
3:
@@ -97,8 +99,9 @@ __up_read:
cmp %g1, %g7
bne,pn %icc, 1b
cmp %g7, 0
+ membar #StoreLoad | #StoreStore
bl,pn %icc, 3f
- membar #StoreLoad | #StoreStore
+ nop
2: retl
nop
3: sethi %hi(RWSEM_ACTIVE_MASK), %g1
@@ -126,8 +129,9 @@ __up_write:
bne,pn %icc, 1b
sub %g7, %g1, %g7
cmp %g7, 0
+ membar #StoreLoad | #StoreStore
bl,pn %icc, 3f
- membar #StoreLoad | #StoreStore
+ nop
2:
retl
nop
@@ -151,8 +155,9 @@ __downgrade_write:
bne,pn %icc, 1b
sub %g7, %g1, %g7
cmp %g7, 0
+ membar #StoreLoad | #StoreStore
bl,pn %icc, 3f
- membar #StoreLoad | #StoreStore
+ nop
2:
retl
nop
diff --git a/trunk/arch/sparc64/mm/init.c b/trunk/arch/sparc64/mm/init.c
index 9c5222075da9..8fc413cb6acd 100644
--- a/trunk/arch/sparc64/mm/init.c
+++ b/trunk/arch/sparc64/mm/init.c
@@ -136,8 +136,9 @@ static __inline__ void set_dcache_dirty(struct page *page, int this_cpu)
"or %%g1, %0, %%g1\n\t"
"casx [%2], %%g7, %%g1\n\t"
"cmp %%g7, %%g1\n\t"
+ "membar #StoreLoad | #StoreStore\n\t"
"bne,pn %%xcc, 1b\n\t"
- " membar #StoreLoad | #StoreStore"
+ " nop"
: /* no outputs */
: "r" (mask), "r" (non_cpu_bits), "r" (&page->flags)
: "g1", "g7");
@@ -157,8 +158,9 @@ static __inline__ void clear_dcache_dirty_cpu(struct page *page, unsigned long c
" andn %%g7, %1, %%g1\n\t"
"casx [%2], %%g7, %%g1\n\t"
"cmp %%g7, %%g1\n\t"
+ "membar #StoreLoad | #StoreStore\n\t"
"bne,pn %%xcc, 1b\n\t"
- " membar #StoreLoad | #StoreStore\n"
+ " nop\n"
"2:"
: /* no outputs */
: "r" (cpu), "r" (mask), "r" (&page->flags),
diff --git a/trunk/arch/sparc64/mm/ultra.S b/trunk/arch/sparc64/mm/ultra.S
index 7a0934321010..7a2431d3abc7 100644
--- a/trunk/arch/sparc64/mm/ultra.S
+++ b/trunk/arch/sparc64/mm/ultra.S
@@ -266,8 +266,9 @@ __cheetah_flush_tlb_pending: /* 22 insns */
andn %o3, 1, %o3
stxa %g0, [%o3] ASI_IMMU_DEMAP
2: stxa %g0, [%o3] ASI_DMMU_DEMAP
+ membar #Sync
brnz,pt %o1, 1b
- membar #Sync
+ nop
stxa %g2, [%o4] ASI_DMMU
flush %g6
wrpr %g0, 0, %tl
diff --git a/trunk/arch/x86_64/kernel/kprobes.c b/trunk/arch/x86_64/kernel/kprobes.c
index acd2a778ebe6..4e680f87a75f 100644
--- a/trunk/arch/x86_64/kernel/kprobes.c
+++ b/trunk/arch/x86_64/kernel/kprobes.c
@@ -38,7 +38,7 @@
#include
#include
#include
-
+#include
#include
#include
#include
@@ -51,6 +51,8 @@ static struct kprobe *kprobe_prev;
static unsigned long kprobe_status_prev, kprobe_old_rflags_prev, kprobe_saved_rflags_prev;
static struct pt_regs jprobe_saved_regs;
static long *jprobe_saved_rsp;
+static kprobe_opcode_t *get_insn_slot(void);
+static void free_insn_slot(kprobe_opcode_t *slot);
void jprobe_return_end(void);
/* copy of the kernel stack at the probe fire time */
@@ -272,23 +274,48 @@ static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
regs->rip = (unsigned long)p->ainsn.insn;
}
+struct task_struct *arch_get_kprobe_task(void *ptr)
+{
+ return ((struct thread_info *) (((unsigned long) ptr) &
+ (~(THREAD_SIZE -1))))->task;
+}
+
void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
{
unsigned long *sara = (unsigned long *)regs->rsp;
- struct kretprobe_instance *ri;
-
- if ((ri = get_free_rp_inst(rp)) != NULL) {
- ri->rp = rp;
- ri->task = current;
- ri->ret_addr = (kprobe_opcode_t *) *sara;
+ struct kretprobe_instance *ri;
+ static void *orig_ret_addr;
+ /*
+ * Save the return address when the return probe hits
+ * the first time, and use it to populate the (krprobe
+ * instance)->ret_addr for subsequent return probes at
+ * the same addrress since stack address would have
+ * the kretprobe_trampoline by then.
+ */
+ if (((void*) *sara) != kretprobe_trampoline)
+ orig_ret_addr = (void*) *sara;
+
+ if ((ri = get_free_rp_inst(rp)) != NULL) {
+ ri->rp = rp;
+ ri->stack_addr = sara;
+ ri->ret_addr = orig_ret_addr;
+ add_rp_inst(ri);
/* Replace the return addr with trampoline addr */
*sara = (unsigned long) &kretprobe_trampoline;
+ } else {
+ rp->nmissed++;
+ }
+}
- add_rp_inst(ri);
- } else {
- rp->nmissed++;
- }
+void arch_kprobe_flush_task(struct task_struct *tk)
+{
+ struct kretprobe_instance *ri;
+ while ((ri = get_rp_inst_tsk(tk)) != NULL) {
+ *((unsigned long *)(ri->stack_addr)) =
+ (unsigned long) ri->ret_addr;
+ recycle_rp_inst(ri);
+ }
}
/*
@@ -401,59 +428,36 @@ int kprobe_handler(struct pt_regs *regs)
*/
int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
{
- struct kretprobe_instance *ri = NULL;
- struct hlist_head *head;
- struct hlist_node *node, *tmp;
- unsigned long orig_ret_address = 0;
- unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
-
- head = kretprobe_inst_table_head(current);
-
- /*
- * It is possible to have multiple instances associated with a given
- * task either because an multiple functions in the call path
- * have a return probe installed on them, and/or more then one return
- * return probe was registered for a target function.
- *
- * We can handle this because:
- * - instances are always inserted at the head of the list
- * - when multiple return probes are registered for the same
- * function, the first instance's ret_addr will point to the
- * real return address, and all the rest will point to
- * kretprobe_trampoline
- */
- hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
- if (ri->task != current)
- /* another task is sharing our hash bucket */
- continue;
+ struct task_struct *tsk;
+ struct kretprobe_instance *ri;
+ struct hlist_head *head;
+ struct hlist_node *node;
+ unsigned long *sara = (unsigned long *)regs->rsp - 1;
+
+ tsk = arch_get_kprobe_task(sara);
+ head = kretprobe_inst_table_head(tsk);
+
+ hlist_for_each_entry(ri, node, head, hlist) {
+ if (ri->stack_addr == sara && ri->rp) {
+ if (ri->rp->handler)
+ ri->rp->handler(ri, regs);
+ }
+ }
+ return 0;
+}
- if (ri->rp && ri->rp->handler)
- ri->rp->handler(ri, regs);
+void trampoline_post_handler(struct kprobe *p, struct pt_regs *regs,
+ unsigned long flags)
+{
+ struct kretprobe_instance *ri;
+ /* RA already popped */
+ unsigned long *sara = ((unsigned long *)regs->rsp) - 1;
- orig_ret_address = (unsigned long)ri->ret_addr;
+ while ((ri = get_rp_inst(sara))) {
+ regs->rip = (unsigned long)ri->ret_addr;
recycle_rp_inst(ri);
-
- if (orig_ret_address != trampoline_address)
- /*
- * This is the real return address. Any other
- * instances associated with this task are for
- * other calls deeper on the call stack
- */
- break;
}
-
- BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
- regs->rip = orig_ret_address;
-
- unlock_kprobes();
- preempt_enable_no_resched();
-
- /*
- * By returning a non-zero value, we are telling
- * kprobe_handler() that we have handled unlocking
- * and re-enabling preemption.
- */
- return 1;
+ regs->eflags &= ~TF_MASK;
}
/*
@@ -546,7 +550,8 @@ int post_kprobe_handler(struct pt_regs *regs)
current_kprobe->post_handler(current_kprobe, regs, 0);
}
- resume_execution(current_kprobe, regs);
+ if (current_kprobe->post_handler != trampoline_post_handler)
+ resume_execution(current_kprobe, regs);
regs->eflags |= kprobe_saved_rflags;
/* Restore the original saved kprobes variables and continue. */
@@ -677,12 +682,111 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
return 0;
}
-static struct kprobe trampoline_p = {
- .addr = (kprobe_opcode_t *) &kretprobe_trampoline,
- .pre_handler = trampoline_probe_handler
+/*
+ * kprobe->ainsn.insn points to the copy of the instruction to be single-stepped.
+ * By default on x86_64, pages we get from kmalloc or vmalloc are not
+ * executable. Single-stepping an instruction on such a page yields an
+ * oops. So instead of storing the instruction copies in their respective
+ * kprobe objects, we allocate a page, map it executable, and store all the
+ * instruction copies there. (We can allocate additional pages if somebody
+ * inserts a huge number of probes.) Each page can hold up to INSNS_PER_PAGE
+ * instruction slots, each of which is MAX_INSN_SIZE*sizeof(kprobe_opcode_t)
+ * bytes.
+ */
+#define INSNS_PER_PAGE (PAGE_SIZE/(MAX_INSN_SIZE*sizeof(kprobe_opcode_t)))
+struct kprobe_insn_page {
+ struct hlist_node hlist;
+ kprobe_opcode_t *insns; /* page of instruction slots */
+ char slot_used[INSNS_PER_PAGE];
+ int nused;
};
-int __init arch_init(void)
+static struct hlist_head kprobe_insn_pages;
+
+/**
+ * get_insn_slot() - Find a slot on an executable page for an instruction.
+ * We allocate an executable page if there's no room on existing ones.
+ */
+static kprobe_opcode_t *get_insn_slot(void)
+{
+ struct kprobe_insn_page *kip;
+ struct hlist_node *pos;
+
+ hlist_for_each(pos, &kprobe_insn_pages) {
+ kip = hlist_entry(pos, struct kprobe_insn_page, hlist);
+ if (kip->nused < INSNS_PER_PAGE) {
+ int i;
+ for (i = 0; i < INSNS_PER_PAGE; i++) {
+ if (!kip->slot_used[i]) {
+ kip->slot_used[i] = 1;
+ kip->nused++;
+ return kip->insns + (i*MAX_INSN_SIZE);
+ }
+ }
+ /* Surprise! No unused slots. Fix kip->nused. */
+ kip->nused = INSNS_PER_PAGE;
+ }
+ }
+
+ /* All out of space. Need to allocate a new page. Use slot 0.*/
+ kip = kmalloc(sizeof(struct kprobe_insn_page), GFP_KERNEL);
+ if (!kip) {
+ return NULL;
+ }
+
+ /*
+ * For the %rip-relative displacement fixups to be doable, we
+ * need our instruction copy to be within +/- 2GB of any data it
+ * might access via %rip. That is, within 2GB of where the
+ * kernel image and loaded module images reside. So we allocate
+ * a page in the module loading area.
+ */
+ kip->insns = module_alloc(PAGE_SIZE);
+ if (!kip->insns) {
+ kfree(kip);
+ return NULL;
+ }
+ INIT_HLIST_NODE(&kip->hlist);
+ hlist_add_head(&kip->hlist, &kprobe_insn_pages);
+ memset(kip->slot_used, 0, INSNS_PER_PAGE);
+ kip->slot_used[0] = 1;
+ kip->nused = 1;
+ return kip->insns;
+}
+
+/**
+ * free_insn_slot() - Free instruction slot obtained from get_insn_slot().
+ */
+static void free_insn_slot(kprobe_opcode_t *slot)
{
- return register_kprobe(&trampoline_p);
+ struct kprobe_insn_page *kip;
+ struct hlist_node *pos;
+
+ hlist_for_each(pos, &kprobe_insn_pages) {
+ kip = hlist_entry(pos, struct kprobe_insn_page, hlist);
+ if (kip->insns <= slot
+ && slot < kip->insns+(INSNS_PER_PAGE*MAX_INSN_SIZE)) {
+ int i = (slot - kip->insns) / MAX_INSN_SIZE;
+ kip->slot_used[i] = 0;
+ kip->nused--;
+ if (kip->nused == 0) {
+ /*
+ * Page is no longer in use. Free it unless
+ * it's the last one. We keep the last one
+ * so as not to have to set it up again the
+ * next time somebody inserts a probe.
+ */
+ hlist_del(&kip->hlist);
+ if (hlist_empty(&kprobe_insn_pages)) {
+ INIT_HLIST_NODE(&kip->hlist);
+ hlist_add_head(&kip->hlist,
+ &kprobe_insn_pages);
+ } else {
+ module_free(NULL, kip->insns);
+ kfree(kip);
+ }
+ }
+ return;
+ }
+ }
}
diff --git a/trunk/arch/x86_64/kernel/process.c b/trunk/arch/x86_64/kernel/process.c
index 7577f9d7a75d..1d91271796e5 100644
--- a/trunk/arch/x86_64/kernel/process.c
+++ b/trunk/arch/x86_64/kernel/process.c
@@ -481,33 +481,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
return err;
}
-/*
- * This function selects if the context switch from prev to next
- * has to tweak the TSC disable bit in the cr4.
- */
-static inline void disable_tsc(struct task_struct *prev_p,
- struct task_struct *next_p)
-{
- struct thread_info *prev, *next;
-
- /*
- * gcc should eliminate the ->thread_info dereference if
- * has_secure_computing returns 0 at compile time (SECCOMP=n).
- */
- prev = prev_p->thread_info;
- next = next_p->thread_info;
-
- if (has_secure_computing(prev) || has_secure_computing(next)) {
- /* slow path here */
- if (has_secure_computing(prev) &&
- !has_secure_computing(next)) {
- write_cr4(read_cr4() & ~X86_CR4_TSD);
- } else if (!has_secure_computing(prev) &&
- has_secure_computing(next))
- write_cr4(read_cr4() | X86_CR4_TSD);
- }
-}
-
/*
* This special macro can be used to load a debugging register
*/
@@ -626,8 +599,6 @@ struct task_struct *__switch_to(struct task_struct *prev_p, struct task_struct *
}
}
- disable_tsc(prev_p, next_p);
-
return prev_p;
}
diff --git a/trunk/drivers/block/as-iosched.c b/trunk/drivers/block/as-iosched.c
index 91aeb678135d..3410b4d294b9 100644
--- a/trunk/drivers/block/as-iosched.c
+++ b/trunk/drivers/block/as-iosched.c
@@ -1806,8 +1806,7 @@ static void as_put_request(request_queue_t *q, struct request *rq)
rq->elevator_private = NULL;
}
-static int as_set_request(request_queue_t *q, struct request *rq,
- struct bio *bio, int gfp_mask)
+static int as_set_request(request_queue_t *q, struct request *rq, int gfp_mask)
{
struct as_data *ad = q->elevator->elevator_data;
struct as_rq *arq = mempool_alloc(ad->arq_pool, gfp_mask);
@@ -1828,7 +1827,7 @@ static int as_set_request(request_queue_t *q, struct request *rq,
return 1;
}
-static int as_may_queue(request_queue_t *q, int rw, struct bio *bio)
+static int as_may_queue(request_queue_t *q, int rw)
{
int ret = ELV_MQUEUE_MAY;
struct as_data *ad = q->elevator->elevator_data;
diff --git a/trunk/drivers/block/cciss.c b/trunk/drivers/block/cciss.c
index 653512b77570..abde27027c06 100644
--- a/trunk/drivers/block/cciss.c
+++ b/trunk/drivers/block/cciss.c
@@ -1,6 +1,6 @@
/*
* Disk Array driver for HP SA 5xxx and 6xxx Controllers
- * Copyright 2000, 2005 Hewlett-Packard Development Company, L.P.
+ * Copyright 2000, 2002 Hewlett-Packard Development Company, L.P.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -54,7 +54,7 @@
MODULE_AUTHOR("Hewlett-Packard Company");
MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.6");
MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"
- " SA6i P600 P800 E400 E300");
+ " SA6i P600 P800 E400");
MODULE_LICENSE("GPL");
#include "cciss_cmd.h"
@@ -85,10 +85,8 @@ static const struct pci_device_id cciss_pci_device_id[] = {
0x103C, 0x3225, 0, 0, 0},
{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSB,
0x103c, 0x3223, 0, 0, 0},
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSB,
0x103c, 0x3231, 0, 0, 0},
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
- 0x103c, 0x3233, 0, 0, 0},
{0,}
};
MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
@@ -112,7 +110,6 @@ static struct board_type products[] = {
{ 0x3225103C, "Smart Array P600", &SA5_access},
{ 0x3223103C, "Smart Array P800", &SA5_access},
{ 0x3231103C, "Smart Array E400", &SA5_access},
- { 0x3233103C, "Smart Array E300", &SA5_access},
};
/* How long to wait (in millesconds) for board to go into simple mode */
@@ -638,7 +635,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
cciss_pci_info_struct pciinfo;
if (!arg) return -EINVAL;
- pciinfo.domain = pci_domain_nr(host->pdev->bus);
pciinfo.bus = host->pdev->bus->number;
pciinfo.dev_fn = host->pdev->devfn;
pciinfo.board_id = host->board_id;
@@ -791,6 +787,13 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
luninfo.LunID = drv->LunID;
luninfo.num_opens = drv->usage_count;
luninfo.num_parts = 0;
+ /* count partitions 1 to 15 with sizes > 0 */
+ for (i = 0; i < MAX_PART - 1; i++) {
+ if (!disk->part[i])
+ continue;
+ if (disk->part[i]->nr_sects != 0)
+ luninfo.num_parts++;
+ }
if (copy_to_user(argp, &luninfo,
sizeof(LogvolInfo_struct)))
return -EFAULT;
diff --git a/trunk/drivers/block/cfq-iosched.c b/trunk/drivers/block/cfq-iosched.c
index ff1cc968f96d..3ac47dde64da 100644
--- a/trunk/drivers/block/cfq-iosched.c
+++ b/trunk/drivers/block/cfq-iosched.c
@@ -21,34 +21,22 @@
#include
#include
#include
-#include
-#include
+
+static unsigned long max_elapsed_crq;
+static unsigned long max_elapsed_dispatch;
/*
* tunables
*/
static int cfq_quantum = 4; /* max queue in one round of service */
static int cfq_queued = 8; /* minimum rq allocate limit per-queue*/
-static int cfq_fifo_expire[2] = { HZ / 4, HZ / 8 };
+static int cfq_service = HZ; /* period over which service is avg */
+static int cfq_fifo_expire_r = HZ / 2; /* fifo timeout for sync requests */
+static int cfq_fifo_expire_w = 5 * HZ; /* fifo timeout for async requests */
+static int cfq_fifo_rate = HZ / 8; /* fifo expiry rate */
static int cfq_back_max = 16 * 1024; /* maximum backwards seek, in KiB */
static int cfq_back_penalty = 2; /* penalty of a backwards seek */
-static int cfq_slice_sync = HZ / 10;
-static int cfq_slice_async = HZ / 25;
-static int cfq_slice_async_rq = 2;
-static int cfq_slice_idle = HZ / 100;
-
-#define CFQ_IDLE_GRACE (HZ / 10)
-#define CFQ_SLICE_SCALE (5)
-
-#define CFQ_KEY_ASYNC (0)
-#define CFQ_KEY_ANY (0xffff)
-
-/*
- * disable queueing at the driver/hardware level
- */
-static int cfq_max_depth = 1;
-
/*
* for the hash of cfqq inside the cfqd
*/
@@ -67,7 +55,6 @@ static int cfq_max_depth = 1;
#define list_entry_hash(ptr) hlist_entry((ptr), struct cfq_rq, hash)
#define list_entry_cfqq(ptr) list_entry((ptr), struct cfq_queue, cfq_list)
-#define list_entry_fifo(ptr) list_entry((ptr), struct request, queuelist)
#define RQ_DATA(rq) (rq)->elevator_private
@@ -88,110 +75,78 @@ static int cfq_max_depth = 1;
#define rb_entry_crq(node) rb_entry((node), struct cfq_rq, rb_node)
#define rq_rb_key(rq) (rq)->sector
-static kmem_cache_t *crq_pool;
-static kmem_cache_t *cfq_pool;
-static kmem_cache_t *cfq_ioc_pool;
-
-#define CFQ_PRIO_LISTS IOPRIO_BE_NR
-#define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE)
-#define cfq_class_be(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_BE)
-#define cfq_class_rt(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_RT)
-
-#define ASYNC (0)
-#define SYNC (1)
-
-#define cfq_cfqq_dispatched(cfqq) \
- ((cfqq)->on_dispatch[ASYNC] + (cfqq)->on_dispatch[SYNC])
-
-#define cfq_cfqq_class_sync(cfqq) ((cfqq)->key != CFQ_KEY_ASYNC)
-
-#define cfq_cfqq_sync(cfqq) \
- (cfq_cfqq_class_sync(cfqq) || (cfqq)->on_dispatch[SYNC])
+/*
+ * threshold for switching off non-tag accounting
+ */
+#define CFQ_MAX_TAG (4)
/*
- * Per block device queue structure
+ * sort key types and names
*/
-struct cfq_data {
- atomic_t ref;
- request_queue_t *queue;
+enum {
+ CFQ_KEY_PGID,
+ CFQ_KEY_TGID,
+ CFQ_KEY_UID,
+ CFQ_KEY_GID,
+ CFQ_KEY_LAST,
+};
- /*
- * rr list of queues with requests and the count of them
- */
- struct list_head rr_list[CFQ_PRIO_LISTS];
- struct list_head busy_rr;
- struct list_head cur_rr;
- struct list_head idle_rr;
- unsigned int busy_queues;
+static char *cfq_key_types[] = { "pgid", "tgid", "uid", "gid", NULL };
- /*
- * non-ordered list of empty cfqq's
- */
+static kmem_cache_t *crq_pool;
+static kmem_cache_t *cfq_pool;
+static kmem_cache_t *cfq_ioc_pool;
+
+struct cfq_data {
+ struct list_head rr_list;
struct list_head empty_list;
- /*
- * cfqq lookup hash
- */
struct hlist_head *cfq_hash;
-
- /*
- * global crq hash for all queues
- */
struct hlist_head *crq_hash;
- unsigned int max_queued;
+ /* queues on rr_list (ie they have pending requests */
+ unsigned int busy_queues;
- mempool_t *crq_pool;
+ unsigned int max_queued;
- int rq_in_driver;
+ atomic_t ref;
- /*
- * schedule slice state info
- */
- /*
- * idle window management
- */
- struct timer_list idle_slice_timer;
- struct work_struct unplug_work;
+ int key_type;
- struct cfq_queue *active_queue;
- struct cfq_io_context *active_cic;
- int cur_prio, cur_end_prio;
- unsigned int dispatch_slice;
+ mempool_t *crq_pool;
- struct timer_list idle_class_timer;
+ request_queue_t *queue;
sector_t last_sector;
- unsigned long last_end_request;
- unsigned int rq_starved;
+ int rq_in_driver;
/*
* tunables, see top of file
*/
unsigned int cfq_quantum;
unsigned int cfq_queued;
- unsigned int cfq_fifo_expire[2];
+ unsigned int cfq_fifo_expire_r;
+ unsigned int cfq_fifo_expire_w;
+ unsigned int cfq_fifo_batch_expire;
unsigned int cfq_back_penalty;
unsigned int cfq_back_max;
- unsigned int cfq_slice[2];
- unsigned int cfq_slice_async_rq;
- unsigned int cfq_slice_idle;
- unsigned int cfq_max_depth;
+ unsigned int find_best_crq;
+
+ unsigned int cfq_tagged;
};
-/*
- * Per process-grouping structure
- */
struct cfq_queue {
/* reference count */
atomic_t ref;
/* parent cfq_data */
struct cfq_data *cfqd;
- /* cfqq lookup hash */
+ /* hash of mergeable requests */
struct hlist_node cfq_hash;
/* hash key */
- unsigned int key;
+ unsigned long key;
+ /* whether queue is on rr (or empty) list */
+ int on_rr;
/* on either rr or empty list of cfqd */
struct list_head cfq_list;
/* sorted list of pending requests */
@@ -203,22 +158,21 @@ struct cfq_queue {
/* currently allocated requests */
int allocated[2];
/* fifo list of requests in sort_list */
- struct list_head fifo;
+ struct list_head fifo[2];
+ /* last time fifo expired */
+ unsigned long last_fifo_expire;
- unsigned long slice_start;
- unsigned long slice_end;
- unsigned long slice_left;
- unsigned long service_last;
+ int key_type;
- /* number of requests that are on the dispatch list */
- int on_dispatch[2];
+ unsigned long service_start;
+ unsigned long service_used;
- /* io prio of this group */
- unsigned short ioprio, org_ioprio;
- unsigned short ioprio_class, org_ioprio_class;
+ unsigned int max_rate;
- /* various state flags, see below */
- unsigned int flags;
+ /* number of requests that have been handed to the driver */
+ int in_flight;
+ /* number of currently allocated requests */
+ int alloc_limit[2];
};
struct cfq_rq {
@@ -230,79 +184,42 @@ struct cfq_rq {
struct cfq_queue *cfq_queue;
struct cfq_io_context *io_context;
- unsigned int crq_flags;
-};
-
-enum cfqq_state_flags {
- CFQ_CFQQ_FLAG_on_rr = 0,
- CFQ_CFQQ_FLAG_wait_request,
- CFQ_CFQQ_FLAG_must_alloc,
- CFQ_CFQQ_FLAG_must_alloc_slice,
- CFQ_CFQQ_FLAG_must_dispatch,
- CFQ_CFQQ_FLAG_fifo_expire,
- CFQ_CFQQ_FLAG_idle_window,
- CFQ_CFQQ_FLAG_prio_changed,
- CFQ_CFQQ_FLAG_expired,
-};
+ unsigned long service_start;
+ unsigned long queue_start;
-#define CFQ_CFQQ_FNS(name) \
-static inline void cfq_mark_cfqq_##name(struct cfq_queue *cfqq) \
-{ \
- cfqq->flags |= (1 << CFQ_CFQQ_FLAG_##name); \
-} \
-static inline void cfq_clear_cfqq_##name(struct cfq_queue *cfqq) \
-{ \
- cfqq->flags &= ~(1 << CFQ_CFQQ_FLAG_##name); \
-} \
-static inline int cfq_cfqq_##name(const struct cfq_queue *cfqq) \
-{ \
- return (cfqq->flags & (1 << CFQ_CFQQ_FLAG_##name)) != 0; \
-}
-
-CFQ_CFQQ_FNS(on_rr);
-CFQ_CFQQ_FNS(wait_request);
-CFQ_CFQQ_FNS(must_alloc);
-CFQ_CFQQ_FNS(must_alloc_slice);
-CFQ_CFQQ_FNS(must_dispatch);
-CFQ_CFQQ_FNS(fifo_expire);
-CFQ_CFQQ_FNS(idle_window);
-CFQ_CFQQ_FNS(prio_changed);
-CFQ_CFQQ_FNS(expired);
-#undef CFQ_CFQQ_FNS
-
-enum cfq_rq_state_flags {
- CFQ_CRQ_FLAG_in_flight = 0,
- CFQ_CRQ_FLAG_in_driver,
- CFQ_CRQ_FLAG_is_sync,
- CFQ_CRQ_FLAG_requeued,
+ unsigned int in_flight : 1;
+ unsigned int accounted : 1;
+ unsigned int is_sync : 1;
+ unsigned int is_write : 1;
};
-#define CFQ_CRQ_FNS(name) \
-static inline void cfq_mark_crq_##name(struct cfq_rq *crq) \
-{ \
- crq->crq_flags |= (1 << CFQ_CRQ_FLAG_##name); \
-} \
-static inline void cfq_clear_crq_##name(struct cfq_rq *crq) \
-{ \
- crq->crq_flags &= ~(1 << CFQ_CRQ_FLAG_##name); \
-} \
-static inline int cfq_crq_##name(const struct cfq_rq *crq) \
-{ \
- return (crq->crq_flags & (1 << CFQ_CRQ_FLAG_##name)) != 0; \
-}
-
-CFQ_CRQ_FNS(in_flight);
-CFQ_CRQ_FNS(in_driver);
-CFQ_CRQ_FNS(is_sync);
-CFQ_CRQ_FNS(requeued);
-#undef CFQ_CRQ_FNS
-
-static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short);
+static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned long);
static void cfq_dispatch_sort(request_queue_t *, struct cfq_rq *);
+static void cfq_update_next_crq(struct cfq_rq *);
static void cfq_put_cfqd(struct cfq_data *cfqd);
-static inline int cfq_pending_requests(struct cfq_data *cfqd);
-#define process_sync(tsk) ((tsk)->flags & PF_SYNCWRITE)
+/*
+ * what the fairness is based on (ie how processes are grouped and
+ * differentiated)
+ */
+static inline unsigned long
+cfq_hash_key(struct cfq_data *cfqd, struct task_struct *tsk)
+{
+ /*
+ * optimize this so that ->key_type is the offset into the struct
+ */
+ switch (cfqd->key_type) {
+ case CFQ_KEY_PGID:
+ return process_group(tsk);
+ default:
+ case CFQ_KEY_TGID:
+ return tsk->tgid;
+ case CFQ_KEY_UID:
+ return tsk->uid;
+ case CFQ_KEY_GID:
+ return tsk->gid;
+ }
+}
/*
* lots of deadline iosched dupes, can be abstracted later...
@@ -318,12 +235,16 @@ static void cfq_remove_merge_hints(request_queue_t *q, struct cfq_rq *crq)
if (q->last_merge == crq->request)
q->last_merge = NULL;
+
+ cfq_update_next_crq(crq);
}
static inline void cfq_add_crq_hash(struct cfq_data *cfqd, struct cfq_rq *crq)
{
const int hash_idx = CFQ_MHASH_FN(rq_hash_key(crq->request));
+ BUG_ON(!hlist_unhashed(&crq->hash));
+
hlist_add_head(&crq->hash, &cfqd->crq_hash[hash_idx]);
}
@@ -336,6 +257,8 @@ static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset)
struct cfq_rq *crq = list_entry_hash(entry);
struct request *__rq = crq->request;
+ BUG_ON(hlist_unhashed(&crq->hash));
+
if (!rq_mergeable(__rq)) {
cfq_del_crq_hash(crq);
continue;
@@ -364,16 +287,36 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2)
return crq2;
if (crq2 == NULL)
return crq1;
- if (cfq_crq_requeued(crq1))
- return crq1;
- if (cfq_crq_requeued(crq2))
- return crq2;
s1 = crq1->request->sector;
s2 = crq2->request->sector;
last = cfqd->last_sector;
+#if 0
+ if (!list_empty(&cfqd->queue->queue_head)) {
+ struct list_head *entry = &cfqd->queue->queue_head;
+ unsigned long distance = ~0UL;
+ struct request *rq;
+
+ while ((entry = entry->prev) != &cfqd->queue->queue_head) {
+ rq = list_entry_rq(entry);
+
+ if (blk_barrier_rq(rq))
+ break;
+
+ if (distance < abs(s1 - rq->sector + rq->nr_sectors)) {
+ distance = abs(s1 - rq->sector +rq->nr_sectors);
+ last = rq->sector + rq->nr_sectors;
+ }
+ if (distance < abs(s2 - rq->sector + rq->nr_sectors)) {
+ distance = abs(s2 - rq->sector +rq->nr_sectors);
+ last = rq->sector + rq->nr_sectors;
+ }
+ }
+ }
+#endif
+
/*
* by definition, 1KiB is 2 sectors
*/
@@ -434,14 +377,11 @@ cfq_find_next_crq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
struct cfq_rq *crq_next = NULL, *crq_prev = NULL;
struct rb_node *rbnext, *rbprev;
- rbnext = NULL;
- if (ON_RB(&last->rb_node))
- rbnext = rb_next(&last->rb_node);
- if (!rbnext) {
+ if (!ON_RB(&last->rb_node))
+ return NULL;
+
+ if ((rbnext = rb_next(&last->rb_node)) == NULL)
rbnext = rb_first(&cfqq->sort_list);
- if (rbnext == &last->rb_node)
- rbnext = NULL;
- }
rbprev = rb_prev(&last->rb_node);
@@ -461,53 +401,67 @@ static void cfq_update_next_crq(struct cfq_rq *crq)
cfqq->next_crq = cfq_find_next_crq(cfqq->cfqd, cfqq, crq);
}
-static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
+static int cfq_check_sort_rr_list(struct cfq_queue *cfqq)
{
- struct cfq_data *cfqd = cfqq->cfqd;
- struct list_head *list, *entry;
+ struct list_head *head = &cfqq->cfqd->rr_list;
+ struct list_head *next, *prev;
- BUG_ON(!cfq_cfqq_on_rr(cfqq));
+ /*
+ * list might still be ordered
+ */
+ next = cfqq->cfq_list.next;
+ if (next != head) {
+ struct cfq_queue *cnext = list_entry_cfqq(next);
- list_del(&cfqq->cfq_list);
+ if (cfqq->service_used > cnext->service_used)
+ return 1;
+ }
- if (cfq_class_rt(cfqq))
- list = &cfqd->cur_rr;
- else if (cfq_class_idle(cfqq))
- list = &cfqd->idle_rr;
- else {
- /*
- * if cfqq has requests in flight, don't allow it to be
- * found in cfq_set_active_queue before it has finished them.
- * this is done to increase fairness between a process that
- * has lots of io pending vs one that only generates one
- * sporadically or synchronously
- */
- if (cfq_cfqq_dispatched(cfqq))
- list = &cfqd->busy_rr;
- else
- list = &cfqd->rr_list[cfqq->ioprio];
+ prev = cfqq->cfq_list.prev;
+ if (prev != head) {
+ struct cfq_queue *cprev = list_entry_cfqq(prev);
+
+ if (cfqq->service_used < cprev->service_used)
+ return 1;
}
- /*
- * if queue was preempted, just add to front to be fair. busy_rr
- * isn't sorted.
- */
- if (preempted || list == &cfqd->busy_rr) {
- list_add(&cfqq->cfq_list, list);
+ return 0;
+}
+
+static void cfq_sort_rr_list(struct cfq_queue *cfqq, int new_queue)
+{
+ struct list_head *entry = &cfqq->cfqd->rr_list;
+
+ if (!cfqq->on_rr)
return;
- }
+ if (!new_queue && !cfq_check_sort_rr_list(cfqq))
+ return;
+
+ list_del(&cfqq->cfq_list);
/*
- * sort by when queue was last serviced
+ * sort by our mean service_used, sub-sort by in-flight requests
*/
- entry = list;
- while ((entry = entry->prev) != list) {
+ while ((entry = entry->prev) != &cfqq->cfqd->rr_list) {
struct cfq_queue *__cfqq = list_entry_cfqq(entry);
- if (!__cfqq->service_last)
- break;
- if (time_before(__cfqq->service_last, cfqq->service_last))
+ if (cfqq->service_used > __cfqq->service_used)
break;
+ else if (cfqq->service_used == __cfqq->service_used) {
+ struct list_head *prv;
+
+ while ((prv = entry->prev) != &cfqq->cfqd->rr_list) {
+ __cfqq = list_entry_cfqq(prv);
+
+ WARN_ON(__cfqq->service_used > cfqq->service_used);
+ if (cfqq->service_used != __cfqq->service_used)
+ break;
+ if (cfqq->in_flight > __cfqq->in_flight)
+ break;
+
+ entry = prv;
+ }
+ }
}
list_add(&cfqq->cfq_list, entry);
@@ -515,24 +469,28 @@ static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
/*
* add to busy list of queues for service, trying to be fair in ordering
- * the pending list according to last request service
+ * the pending list according to requests serviced
*/
static inline void
-cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq, int requeue)
+cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
{
- BUG_ON(cfq_cfqq_on_rr(cfqq));
- cfq_mark_cfqq_on_rr(cfqq);
+ /*
+ * it's currently on the empty list
+ */
+ cfqq->on_rr = 1;
cfqd->busy_queues++;
- cfq_resort_rr_list(cfqq, requeue);
+ if (time_after(jiffies, cfqq->service_start + cfq_service))
+ cfqq->service_used >>= 3;
+
+ cfq_sort_rr_list(cfqq, 1);
}
static inline void
cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
{
- BUG_ON(!cfq_cfqq_on_rr(cfqq));
- cfq_clear_cfqq_on_rr(cfqq);
list_move(&cfqq->cfq_list, &cfqd->empty_list);
+ cfqq->on_rr = 0;
BUG_ON(!cfqd->busy_queues);
cfqd->busy_queues--;
@@ -547,17 +505,16 @@ static inline void cfq_del_crq_rb(struct cfq_rq *crq)
if (ON_RB(&crq->rb_node)) {
struct cfq_data *cfqd = cfqq->cfqd;
- const int sync = cfq_crq_is_sync(crq);
- BUG_ON(!cfqq->queued[sync]);
- cfqq->queued[sync]--;
+ BUG_ON(!cfqq->queued[crq->is_sync]);
cfq_update_next_crq(crq);
+ cfqq->queued[crq->is_sync]--;
rb_erase(&crq->rb_node, &cfqq->sort_list);
RB_CLEAR_COLOR(&crq->rb_node);
- if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list))
+ if (RB_EMPTY(&cfqq->sort_list) && cfqq->on_rr)
cfq_del_cfqq_rr(cfqd, cfqq);
}
}
@@ -593,7 +550,7 @@ static void cfq_add_crq_rb(struct cfq_rq *crq)
struct cfq_rq *__alias;
crq->rb_key = rq_rb_key(rq);
- cfqq->queued[cfq_crq_is_sync(crq)]++;
+ cfqq->queued[crq->is_sync]++;
/*
* looks a little odd, but the first insert might return an alias.
@@ -604,8 +561,8 @@ static void cfq_add_crq_rb(struct cfq_rq *crq)
rb_insert_color(&crq->rb_node, &cfqq->sort_list);
- if (!cfq_cfqq_on_rr(cfqq))
- cfq_add_cfqq_rr(cfqd, cfqq, cfq_crq_requeued(crq));
+ if (!cfqq->on_rr)
+ cfq_add_cfqq_rr(cfqd, cfqq);
/*
* check if this request is a better next-serve candidate
@@ -618,16 +575,17 @@ cfq_reposition_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq)
{
if (ON_RB(&crq->rb_node)) {
rb_erase(&crq->rb_node, &cfqq->sort_list);
- cfqq->queued[cfq_crq_is_sync(crq)]--;
+ cfqq->queued[crq->is_sync]--;
}
cfq_add_crq_rb(crq);
}
-static struct request *cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector)
-
+static struct request *
+cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector)
{
- struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, current->pid, CFQ_KEY_ANY);
+ const unsigned long key = cfq_hash_key(cfqd, current);
+ struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, key);
struct rb_node *n;
if (!cfqq)
@@ -651,25 +609,20 @@ static struct request *cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector)
static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
{
- struct cfq_data *cfqd = q->elevator->elevator_data;
struct cfq_rq *crq = RQ_DATA(rq);
if (crq) {
struct cfq_queue *cfqq = crq->cfq_queue;
- if (cfq_crq_in_driver(crq)) {
- cfq_clear_crq_in_driver(crq);
- WARN_ON(!cfqd->rq_in_driver);
- cfqd->rq_in_driver--;
+ if (cfqq->cfqd->cfq_tagged) {
+ cfqq->service_used--;
+ cfq_sort_rr_list(cfqq, 0);
}
- if (cfq_crq_in_flight(crq)) {
- const int sync = cfq_crq_is_sync(crq);
- cfq_clear_crq_in_flight(crq);
- WARN_ON(!cfqq->on_dispatch[sync]);
- cfqq->on_dispatch[sync]--;
+ if (crq->accounted) {
+ crq->accounted = 0;
+ cfqq->cfqd->rq_in_driver--;
}
- cfq_mark_crq_requeued(crq);
}
}
@@ -687,10 +640,11 @@ static void cfq_remove_request(request_queue_t *q, struct request *rq)
struct cfq_rq *crq = RQ_DATA(rq);
if (crq) {
- list_del_init(&rq->queuelist);
- cfq_del_crq_rb(crq);
cfq_remove_merge_hints(q, crq);
+ list_del_init(&rq->queuelist);
+ if (crq->cfq_queue)
+ cfq_del_crq_rb(crq);
}
}
@@ -708,15 +662,21 @@ cfq_merge(request_queue_t *q, struct request **req, struct bio *bio)
}
__rq = cfq_find_rq_hash(cfqd, bio->bi_sector);
- if (__rq && elv_rq_merge_ok(__rq, bio)) {
- ret = ELEVATOR_BACK_MERGE;
- goto out;
+ if (__rq) {
+ BUG_ON(__rq->sector + __rq->nr_sectors != bio->bi_sector);
+
+ if (elv_rq_merge_ok(__rq, bio)) {
+ ret = ELEVATOR_BACK_MERGE;
+ goto out;
+ }
}
__rq = cfq_find_rq_rb(cfqd, bio->bi_sector + bio_sectors(bio));
- if (__rq && elv_rq_merge_ok(__rq, bio)) {
- ret = ELEVATOR_FRONT_MERGE;
- goto out;
+ if (__rq) {
+ if (elv_rq_merge_ok(__rq, bio)) {
+ ret = ELEVATOR_FRONT_MERGE;
+ goto out;
+ }
}
return ELEVATOR_NO_MERGE;
@@ -749,506 +709,235 @@ static void
cfq_merged_requests(request_queue_t *q, struct request *rq,
struct request *next)
{
- cfq_merged_request(q, rq);
-
- /*
- * reposition in fifo if next is older than rq
- */
- if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) &&
- time_before(next->start_time, rq->start_time))
- list_move(&rq->queuelist, &next->queuelist);
+ struct cfq_rq *crq = RQ_DATA(rq);
+ struct cfq_rq *cnext = RQ_DATA(next);
- cfq_remove_request(q, next);
-}
+ cfq_merged_request(q, rq);
-static inline void
-__cfq_set_active_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
-{
- if (cfqq) {
- /*
- * stop potential idle class queues waiting service
- */
- del_timer(&cfqd->idle_class_timer);
-
- cfqq->slice_start = jiffies;
- cfqq->slice_end = 0;
- cfqq->slice_left = 0;
- cfq_clear_cfqq_must_alloc_slice(cfqq);
- cfq_clear_cfqq_fifo_expire(cfqq);
- cfq_clear_cfqq_expired(cfqq);
+ if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist)) {
+ if (time_before(cnext->queue_start, crq->queue_start)) {
+ list_move(&rq->queuelist, &next->queuelist);
+ crq->queue_start = cnext->queue_start;
+ }
}
- cfqd->active_queue = cfqq;
+ cfq_update_next_crq(cnext);
+ cfq_remove_request(q, next);
}
/*
- * 0
- * 0,1
- * 0,1,2
- * 0,1,2,3
- * 0,1,2,3,4
- * 0,1,2,3,4,5
- * 0,1,2,3,4,5,6
- * 0,1,2,3,4,5,6,7
+ * we dispatch cfqd->cfq_quantum requests in total from the rr_list queues,
+ * this function sector sorts the selected request to minimize seeks. we start
+ * at cfqd->last_sector, not 0.
*/
-static int cfq_get_next_prio_level(struct cfq_data *cfqd)
+static void cfq_dispatch_sort(request_queue_t *q, struct cfq_rq *crq)
{
- int prio, wrap;
+ struct cfq_data *cfqd = q->elevator->elevator_data;
+ struct cfq_queue *cfqq = crq->cfq_queue;
+ struct list_head *head = &q->queue_head, *entry = head;
+ struct request *__rq;
+ sector_t last;
+
+ cfq_del_crq_rb(crq);
+ cfq_remove_merge_hints(q, crq);
+ list_del(&crq->request->queuelist);
- prio = -1;
- wrap = 0;
- do {
- int p;
+ last = cfqd->last_sector;
+ while ((entry = entry->prev) != head) {
+ __rq = list_entry_rq(entry);
- for (p = cfqd->cur_prio; p <= cfqd->cur_end_prio; p++) {
- if (!list_empty(&cfqd->rr_list[p])) {
- prio = p;
- break;
- }
- }
+ if (blk_barrier_rq(crq->request))
+ break;
+ if (!blk_fs_request(crq->request))
+ break;
- if (prio != -1)
+ if (crq->request->sector > __rq->sector)
+ break;
+ if (__rq->sector > last && crq->request->sector < last) {
+ last = crq->request->sector;
break;
- cfqd->cur_prio = 0;
- if (++cfqd->cur_end_prio == CFQ_PRIO_LISTS) {
- cfqd->cur_end_prio = 0;
- if (wrap)
- break;
- wrap = 1;
}
- } while (1);
+ }
- if (unlikely(prio == -1))
- return -1;
+ cfqd->last_sector = last;
+ crq->in_flight = 1;
+ cfqq->in_flight++;
+ list_add(&crq->request->queuelist, entry);
+}
- BUG_ON(prio >= CFQ_PRIO_LISTS);
+/*
+ * return expired entry, or NULL to just start from scratch in rbtree
+ */
+static inline struct cfq_rq *cfq_check_fifo(struct cfq_queue *cfqq)
+{
+ struct cfq_data *cfqd = cfqq->cfqd;
+ const int reads = !list_empty(&cfqq->fifo[0]);
+ const int writes = !list_empty(&cfqq->fifo[1]);
+ unsigned long now = jiffies;
+ struct cfq_rq *crq;
- list_splice_init(&cfqd->rr_list[prio], &cfqd->cur_rr);
+ if (time_before(now, cfqq->last_fifo_expire + cfqd->cfq_fifo_batch_expire))
+ return NULL;
- cfqd->cur_prio = prio + 1;
- if (cfqd->cur_prio > cfqd->cur_end_prio) {
- cfqd->cur_end_prio = cfqd->cur_prio;
- cfqd->cur_prio = 0;
+ crq = RQ_DATA(list_entry(cfqq->fifo[0].next, struct request, queuelist));
+ if (reads && time_after(now, crq->queue_start + cfqd->cfq_fifo_expire_r)) {
+ cfqq->last_fifo_expire = now;
+ return crq;
}
- if (cfqd->cur_end_prio == CFQ_PRIO_LISTS) {
- cfqd->cur_prio = 0;
- cfqd->cur_end_prio = 0;
+
+ crq = RQ_DATA(list_entry(cfqq->fifo[1].next, struct request, queuelist));
+ if (writes && time_after(now, crq->queue_start + cfqd->cfq_fifo_expire_w)) {
+ cfqq->last_fifo_expire = now;
+ return crq;
}
- return prio;
+ return NULL;
}
-static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd)
+/*
+ * dispatch a single request from given queue
+ */
+static inline void
+cfq_dispatch_request(request_queue_t *q, struct cfq_data *cfqd,
+ struct cfq_queue *cfqq)
{
- struct cfq_queue *cfqq;
+ struct cfq_rq *crq;
/*
- * if current queue is expired but not done with its requests yet,
- * wait for that to happen
+ * follow expired path, else get first next available
*/
- if ((cfqq = cfqd->active_queue) != NULL) {
- if (cfq_cfqq_expired(cfqq) && cfq_cfqq_dispatched(cfqq))
- return NULL;
+ if ((crq = cfq_check_fifo(cfqq)) == NULL) {
+ if (cfqd->find_best_crq)
+ crq = cfqq->next_crq;
+ else
+ crq = rb_entry_crq(rb_first(&cfqq->sort_list));
}
- /*
- * if current list is non-empty, grab first entry. if it is empty,
- * get next prio level and grab first entry then if any are spliced
- */
- if (!list_empty(&cfqd->cur_rr) || cfq_get_next_prio_level(cfqd) != -1)
- cfqq = list_entry_cfqq(cfqd->cur_rr.next);
+ cfqd->last_sector = crq->request->sector + crq->request->nr_sectors;
/*
- * if we have idle queues and no rt or be queues had pending
- * requests, either allow immediate service if the grace period
- * has passed or arm the idle grace timer
+ * finally, insert request into driver list
*/
- if (!cfqq && !list_empty(&cfqd->idle_rr)) {
- unsigned long end = cfqd->last_end_request + CFQ_IDLE_GRACE;
-
- if (time_after_eq(jiffies, end))
- cfqq = list_entry_cfqq(cfqd->idle_rr.next);
- else
- mod_timer(&cfqd->idle_class_timer, end);
- }
-
- __cfq_set_active_queue(cfqd, cfqq);
- return cfqq;
+ cfq_dispatch_sort(q, crq);
}
-/*
- * current cfqq expired its slice (or was too idle), select new one
- */
-static void
-__cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
- int preempted)
+static int cfq_dispatch_requests(request_queue_t *q, int max_dispatch)
{
- unsigned long now = jiffies;
+ struct cfq_data *cfqd = q->elevator->elevator_data;
+ struct cfq_queue *cfqq;
+ struct list_head *entry, *tmp;
+ int queued, busy_queues, first_round;
- if (cfq_cfqq_wait_request(cfqq))
- del_timer(&cfqd->idle_slice_timer);
+ if (list_empty(&cfqd->rr_list))
+ return 0;
- if (!preempted && !cfq_cfqq_dispatched(cfqq))
- cfqq->service_last = now;
+ queued = 0;
+ first_round = 1;
+restart:
+ busy_queues = 0;
+ list_for_each_safe(entry, tmp, &cfqd->rr_list) {
+ cfqq = list_entry_cfqq(entry);
- cfq_clear_cfqq_must_dispatch(cfqq);
- cfq_clear_cfqq_wait_request(cfqq);
+ BUG_ON(RB_EMPTY(&cfqq->sort_list));
- /*
- * store what was left of this slice, if the queue idled out
- * or was preempted
- */
- if (time_after(now, cfqq->slice_end))
- cfqq->slice_left = now - cfqq->slice_end;
- else
- cfqq->slice_left = 0;
+ /*
+ * first round of queueing, only select from queues that
+ * don't already have io in-flight
+ */
+ if (first_round && cfqq->in_flight)
+ continue;
- if (cfq_cfqq_on_rr(cfqq))
- cfq_resort_rr_list(cfqq, preempted);
+ cfq_dispatch_request(q, cfqd, cfqq);
- if (cfqq == cfqd->active_queue)
- cfqd->active_queue = NULL;
+ if (!RB_EMPTY(&cfqq->sort_list))
+ busy_queues++;
- if (cfqd->active_cic) {
- put_io_context(cfqd->active_cic->ioc);
- cfqd->active_cic = NULL;
+ queued++;
}
- cfqd->dispatch_slice = 0;
-}
-
-static inline void cfq_slice_expired(struct cfq_data *cfqd, int preempted)
-{
- struct cfq_queue *cfqq = cfqd->active_queue;
-
- if (cfqq) {
- /*
- * use deferred expiry, if there are requests in progress as
- * not to disturb the slice of the next queue
- */
- if (cfq_cfqq_dispatched(cfqq))
- cfq_mark_cfqq_expired(cfqq);
- else
- __cfq_slice_expired(cfqd, cfqq, preempted);
+ if ((queued < max_dispatch) && (busy_queues || first_round)) {
+ first_round = 0;
+ goto restart;
}
-}
-static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+ return queued;
+}
+static inline void cfq_account_dispatch(struct cfq_rq *crq)
{
- WARN_ON(!RB_EMPTY(&cfqq->sort_list));
- WARN_ON(cfqq != cfqd->active_queue);
+ struct cfq_queue *cfqq = crq->cfq_queue;
+ struct cfq_data *cfqd = cfqq->cfqd;
+ unsigned long now, elapsed;
+
+ if (!blk_fs_request(crq->request))
+ return;
/*
- * idle is disabled, either manually or by past process history
+ * accounted bit is necessary since some drivers will call
+ * elv_next_request() many times for the same request (eg ide)
*/
- if (!cfqd->cfq_slice_idle)
- return 0;
- if (!cfq_cfqq_idle_window(cfqq))
- return 0;
+ if (crq->accounted)
+ return;
+
+ now = jiffies;
+ if (cfqq->service_start == ~0UL)
+ cfqq->service_start = now;
+
/*
- * task has exited, don't wait
+ * on drives with tagged command queueing, command turn-around time
+ * doesn't necessarily reflect the time spent processing this very
+ * command inside the drive. so do the accounting differently there,
+ * by just sorting on the number of requests
*/
- if (cfqd->active_cic && !cfqd->active_cic->ioc->task)
- return 0;
+ if (cfqd->cfq_tagged) {
+ if (time_after(now, cfqq->service_start + cfq_service)) {
+ cfqq->service_start = now;
+ cfqq->service_used /= 10;
+ }
- cfq_mark_cfqq_must_dispatch(cfqq);
- cfq_mark_cfqq_wait_request(cfqq);
+ cfqq->service_used++;
+ cfq_sort_rr_list(cfqq, 0);
+ }
- if (!timer_pending(&cfqd->idle_slice_timer)) {
- unsigned long slice_left = min(cfqq->slice_end - 1, (unsigned long) cfqd->cfq_slice_idle);
+ elapsed = now - crq->queue_start;
+ if (elapsed > max_elapsed_dispatch)
+ max_elapsed_dispatch = elapsed;
- cfqd->idle_slice_timer.expires = jiffies + slice_left;
- add_timer(&cfqd->idle_slice_timer);
- }
+ crq->accounted = 1;
+ crq->service_start = now;
- return 1;
+ if (++cfqd->rq_in_driver >= CFQ_MAX_TAG && !cfqd->cfq_tagged) {
+ cfqq->cfqd->cfq_tagged = 1;
+ printk("cfq: depth %d reached, tagging now on\n", CFQ_MAX_TAG);
+ }
}
-/*
- * we dispatch cfqd->cfq_quantum requests in total from the rr_list queues,
- * this function sector sorts the selected request to minimize seeks. we start
- * at cfqd->last_sector, not 0.
- */
-static void cfq_dispatch_sort(request_queue_t *q, struct cfq_rq *crq)
+static inline void
+cfq_account_completion(struct cfq_queue *cfqq, struct cfq_rq *crq)
{
- struct cfq_data *cfqd = q->elevator->elevator_data;
- struct cfq_queue *cfqq = crq->cfq_queue;
- struct list_head *head = &q->queue_head, *entry = head;
- struct request *__rq;
- sector_t last;
+ struct cfq_data *cfqd = cfqq->cfqd;
- list_del(&crq->request->queuelist);
-
- last = cfqd->last_sector;
- list_for_each_entry_reverse(__rq, head, queuelist) {
- struct cfq_rq *__crq = RQ_DATA(__rq);
-
- if (blk_barrier_rq(__rq))
- break;
- if (!blk_fs_request(__rq))
- break;
- if (cfq_crq_requeued(__crq))
- break;
-
- if (__rq->sector <= crq->request->sector)
- break;
- if (__rq->sector > last && crq->request->sector < last) {
- last = crq->request->sector + crq->request->nr_sectors;
- break;
- }
- entry = &__rq->queuelist;
- }
-
- cfqd->last_sector = last;
-
- cfqq->next_crq = cfq_find_next_crq(cfqd, cfqq, crq);
-
- cfq_del_crq_rb(crq);
- cfq_remove_merge_hints(q, crq);
-
- cfq_mark_crq_in_flight(crq);
- cfq_clear_crq_requeued(crq);
-
- cfqq->on_dispatch[cfq_crq_is_sync(crq)]++;
- list_add_tail(&crq->request->queuelist, entry);
-}
-
-/*
- * return expired entry, or NULL to just start from scratch in rbtree
- */
-static inline struct cfq_rq *cfq_check_fifo(struct cfq_queue *cfqq)
-{
- struct cfq_data *cfqd = cfqq->cfqd;
- struct request *rq;
- struct cfq_rq *crq;
-
- if (cfq_cfqq_fifo_expire(cfqq))
- return NULL;
-
- if (!list_empty(&cfqq->fifo)) {
- int fifo = cfq_cfqq_class_sync(cfqq);
-
- crq = RQ_DATA(list_entry_fifo(cfqq->fifo.next));
- rq = crq->request;
- if (time_after(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo])) {
- cfq_mark_cfqq_fifo_expire(cfqq);
- return crq;
- }
- }
-
- return NULL;
-}
-
-/*
- * Scale schedule slice based on io priority. Use the sync time slice only
- * if a queue is marked sync and has sync io queued. A sync queue with async
- * io only, should not get full sync slice length.
- */
-static inline int
-cfq_prio_to_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
-{
- const int base_slice = cfqd->cfq_slice[cfq_cfqq_sync(cfqq)];
-
- WARN_ON(cfqq->ioprio >= IOPRIO_BE_NR);
-
- return base_slice + (base_slice/CFQ_SLICE_SCALE * (4 - cfqq->ioprio));
-}
-
-static inline void
-cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
-{
- cfqq->slice_end = cfq_prio_to_slice(cfqd, cfqq) + jiffies;
-}
-
-static inline int
-cfq_prio_to_maxrq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
-{
- const int base_rq = cfqd->cfq_slice_async_rq;
-
- WARN_ON(cfqq->ioprio >= IOPRIO_BE_NR);
-
- return 2 * (base_rq + base_rq * (CFQ_PRIO_LISTS - 1 - cfqq->ioprio));
-}
-
-/*
- * scheduler run of queue, if there are requests pending and no one in the
- * driver that will restart queueing
- */
-static inline void cfq_schedule_dispatch(struct cfq_data *cfqd)
-{
- if (!cfqd->rq_in_driver && cfq_pending_requests(cfqd))
- kblockd_schedule_work(&cfqd->unplug_work);
-}
-
-/*
- * get next queue for service
- */
-static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd, int force)
-{
- unsigned long now = jiffies;
- struct cfq_queue *cfqq;
-
- cfqq = cfqd->active_queue;
- if (!cfqq)
- goto new_queue;
-
- if (cfq_cfqq_expired(cfqq))
- goto new_queue;
-
- /*
- * slice has expired
- */
- if (!cfq_cfqq_must_dispatch(cfqq) && time_after(now, cfqq->slice_end))
- goto expire;
-
- /*
- * if queue has requests, dispatch one. if not, check if
- * enough slice is left to wait for one
- */
- if (!RB_EMPTY(&cfqq->sort_list))
- goto keep_queue;
- else if (!force && cfq_cfqq_class_sync(cfqq) &&
- time_before(now, cfqq->slice_end)) {
- if (cfq_arm_slice_timer(cfqd, cfqq))
- return NULL;
- }
-
-expire:
- cfq_slice_expired(cfqd, 0);
-new_queue:
- cfqq = cfq_set_active_queue(cfqd);
-keep_queue:
- return cfqq;
-}
-
-static int
-__cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
- int max_dispatch)
-{
- int dispatched = 0;
-
- BUG_ON(RB_EMPTY(&cfqq->sort_list));
-
- do {
- struct cfq_rq *crq;
-
- /*
- * follow expired path, else get first next available
- */
- if ((crq = cfq_check_fifo(cfqq)) == NULL)
- crq = cfqq->next_crq;
-
- /*
- * finally, insert request into driver dispatch list
- */
- cfq_dispatch_sort(cfqd->queue, crq);
-
- cfqd->dispatch_slice++;
- dispatched++;
-
- if (!cfqd->active_cic) {
- atomic_inc(&crq->io_context->ioc->refcount);
- cfqd->active_cic = crq->io_context;
- }
-
- if (RB_EMPTY(&cfqq->sort_list))
- break;
-
- } while (dispatched < max_dispatch);
-
- /*
- * if slice end isn't set yet, set it. if at least one request was
- * sync, use the sync time slice value
- */
- if (!cfqq->slice_end)
- cfq_set_prio_slice(cfqd, cfqq);
-
- /*
- * expire an async queue immediately if it has used up its slice. idle
- * queue always expire after 1 dispatch round.
- */
- if ((!cfq_cfqq_sync(cfqq) &&
- cfqd->dispatch_slice >= cfq_prio_to_maxrq(cfqd, cfqq)) ||
- cfq_class_idle(cfqq))
- cfq_slice_expired(cfqd, 0);
-
- return dispatched;
-}
-
-static int
-cfq_dispatch_requests(request_queue_t *q, int max_dispatch, int force)
-{
- struct cfq_data *cfqd = q->elevator->elevator_data;
- struct cfq_queue *cfqq;
-
- if (!cfqd->busy_queues)
- return 0;
-
- cfqq = cfq_select_queue(cfqd, force);
- if (cfqq) {
- cfq_clear_cfqq_must_dispatch(cfqq);
- cfq_clear_cfqq_wait_request(cfqq);
- del_timer(&cfqd->idle_slice_timer);
-
- if (cfq_class_idle(cfqq))
- max_dispatch = 1;
-
- return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
- }
-
- return 0;
-}
-
-static inline void cfq_account_dispatch(struct cfq_rq *crq)
-{
- struct cfq_queue *cfqq = crq->cfq_queue;
- struct cfq_data *cfqd = cfqq->cfqd;
-
- if (unlikely(!blk_fs_request(crq->request)))
- return;
-
- /*
- * accounted bit is necessary since some drivers will call
- * elv_next_request() many times for the same request (eg ide)
- */
- if (cfq_crq_in_driver(crq))
- return;
-
- cfq_mark_crq_in_driver(crq);
- cfqd->rq_in_driver++;
-}
-
-static inline void
-cfq_account_completion(struct cfq_queue *cfqq, struct cfq_rq *crq)
-{
- struct cfq_data *cfqd = cfqq->cfqd;
- unsigned long now;
-
- if (!cfq_crq_in_driver(crq))
- return;
-
- now = jiffies;
+ if (!crq->accounted)
+ return;
WARN_ON(!cfqd->rq_in_driver);
cfqd->rq_in_driver--;
- if (!cfq_class_idle(cfqq))
- cfqd->last_end_request = now;
+ if (!cfqd->cfq_tagged) {
+ unsigned long now = jiffies;
+ unsigned long duration = now - crq->service_start;
- if (!cfq_cfqq_dispatched(cfqq)) {
- if (cfq_cfqq_on_rr(cfqq)) {
- cfqq->service_last = now;
- cfq_resort_rr_list(cfqq, 0);
- }
- if (cfq_cfqq_expired(cfqq)) {
- __cfq_slice_expired(cfqd, cfqq, 0);
- cfq_schedule_dispatch(cfqd);
+ if (time_after(now, cfqq->service_start + cfq_service)) {
+ cfqq->service_start = now;
+ cfqq->service_used >>= 3;
}
- }
- if (cfq_crq_is_sync(crq))
- crq->io_context->last_end_request = now;
+ cfqq->service_used += duration;
+ cfq_sort_rr_list(cfqq, 0);
+
+ if (duration > max_elapsed_crq)
+ max_elapsed_crq = duration;
+ }
}
static struct request *cfq_next_request(request_queue_t *q)
@@ -1261,18 +950,7 @@ static struct request *cfq_next_request(request_queue_t *q)
dispatch:
rq = list_entry_rq(q->queue_head.next);
- crq = RQ_DATA(rq);
- if (crq) {
- struct cfq_queue *cfqq = crq->cfq_queue;
-
- /*
- * if idle window is disabled, allow queue buildup
- */
- if (!cfq_crq_in_driver(crq) &&
- !cfq_cfqq_idle_window(cfqq) &&
- cfqd->rq_in_driver >= cfqd->cfq_max_depth)
- return NULL;
-
+ if ((crq = RQ_DATA(rq)) != NULL) {
cfq_remove_merge_hints(q, crq);
cfq_account_dispatch(crq);
}
@@ -1280,7 +958,7 @@ static struct request *cfq_next_request(request_queue_t *q)
return rq;
}
- if (cfq_dispatch_requests(q, cfqd->cfq_quantum, 0))
+ if (cfq_dispatch_requests(q, cfqd->cfq_quantum))
goto dispatch;
return NULL;
@@ -1294,21 +972,13 @@ static struct request *cfq_next_request(request_queue_t *q)
*/
static void cfq_put_queue(struct cfq_queue *cfqq)
{
- struct cfq_data *cfqd = cfqq->cfqd;
-
- BUG_ON(atomic_read(&cfqq->ref) <= 0);
+ BUG_ON(!atomic_read(&cfqq->ref));
if (!atomic_dec_and_test(&cfqq->ref))
return;
BUG_ON(rb_first(&cfqq->sort_list));
- BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]);
- BUG_ON(cfq_cfqq_on_rr(cfqq));
-
- if (unlikely(cfqd->active_queue == cfqq)) {
- __cfq_slice_expired(cfqd, cfqq, 0);
- cfq_schedule_dispatch(cfqd);
- }
+ BUG_ON(cfqq->on_rr);
cfq_put_cfqd(cfqq->cfqd);
@@ -1321,17 +991,15 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
}
static inline struct cfq_queue *
-__cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned int prio,
- const int hashval)
+__cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned long key, const int hashval)
{
struct hlist_head *hash_list = &cfqd->cfq_hash[hashval];
struct hlist_node *entry, *next;
hlist_for_each_safe(entry, next, hash_list) {
struct cfq_queue *__cfqq = list_entry_qhash(entry);
- const unsigned short __p = IOPRIO_PRIO_VALUE(__cfqq->ioprio_class, __cfqq->ioprio);
- if (__cfqq->key == key && (__p == prio || prio == CFQ_KEY_ANY))
+ if (__cfqq->key == key)
return __cfqq;
}
@@ -1339,220 +1007,94 @@ __cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned int prio,
}
static struct cfq_queue *
-cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned short prio)
+cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned long key)
{
- return __cfq_find_cfq_hash(cfqd, key, prio, hash_long(key, CFQ_QHASH_SHIFT));
+ return __cfq_find_cfq_hash(cfqd, key, hash_long(key, CFQ_QHASH_SHIFT));
}
-static void cfq_free_io_context(struct cfq_io_context *cic)
+static inline void
+cfq_rehash_cfqq(struct cfq_data *cfqd, struct cfq_queue **cfqq,
+ struct cfq_io_context *cic)
{
- struct cfq_io_context *__cic;
- struct list_head *entry, *next;
+ unsigned long hashkey = cfq_hash_key(cfqd, current);
+ unsigned long hashval = hash_long(hashkey, CFQ_QHASH_SHIFT);
+ struct cfq_queue *__cfqq;
+ unsigned long flags;
- list_for_each_safe(entry, next, &cic->list) {
- __cic = list_entry(entry, struct cfq_io_context, list);
- kmem_cache_free(cfq_ioc_pool, __cic);
+ spin_lock_irqsave(cfqd->queue->queue_lock, flags);
+
+ hlist_del(&(*cfqq)->cfq_hash);
+
+ __cfqq = __cfq_find_cfq_hash(cfqd, hashkey, hashval);
+ if (!__cfqq || __cfqq == *cfqq) {
+ __cfqq = *cfqq;
+ hlist_add_head(&__cfqq->cfq_hash, &cfqd->cfq_hash[hashval]);
+ __cfqq->key_type = cfqd->key_type;
+ } else {
+ atomic_inc(&__cfqq->ref);
+ cic->cfqq = __cfqq;
+ cfq_put_queue(*cfqq);
+ *cfqq = __cfqq;
}
- kmem_cache_free(cfq_ioc_pool, cic);
+ cic->cfqq = __cfqq;
+ spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
}
-/*
- * Called with interrupts disabled
- */
-static void cfq_exit_single_io_context(struct cfq_io_context *cic)
+static void cfq_free_io_context(struct cfq_io_context *cic)
{
- struct cfq_data *cfqd = cic->cfqq->cfqd;
- request_queue_t *q = cfqd->queue;
-
- WARN_ON(!irqs_disabled());
-
- spin_lock(q->queue_lock);
-
- if (unlikely(cic->cfqq == cfqd->active_queue)) {
- __cfq_slice_expired(cfqd, cic->cfqq, 0);
- cfq_schedule_dispatch(cfqd);
- }
-
- cfq_put_queue(cic->cfqq);
- cic->cfqq = NULL;
- spin_unlock(q->queue_lock);
+ kmem_cache_free(cfq_ioc_pool, cic);
}
/*
- * Another task may update the task cic list, if it is doing a queue lookup
- * on its behalf. cfq_cic_lock excludes such concurrent updates
+ * locking hierarchy is: io_context lock -> queue locks
*/
static void cfq_exit_io_context(struct cfq_io_context *cic)
{
- struct cfq_io_context *__cic;
- struct list_head *entry;
+ struct cfq_queue *cfqq = cic->cfqq;
+ struct list_head *entry = &cic->list;
+ request_queue_t *q;
unsigned long flags;
- local_irq_save(flags);
-
/*
* put the reference this task is holding to the various queues
*/
- list_for_each(entry, &cic->list) {
+ spin_lock_irqsave(&cic->ioc->lock, flags);
+ while ((entry = cic->list.next) != &cic->list) {
+ struct cfq_io_context *__cic;
+
__cic = list_entry(entry, struct cfq_io_context, list);
- cfq_exit_single_io_context(__cic);
+ list_del(entry);
+
+ q = __cic->cfqq->cfqd->queue;
+ spin_lock(q->queue_lock);
+ cfq_put_queue(__cic->cfqq);
+ spin_unlock(q->queue_lock);
}
- cfq_exit_single_io_context(cic);
- local_irq_restore(flags);
+ q = cfqq->cfqd->queue;
+ spin_lock(q->queue_lock);
+ cfq_put_queue(cfqq);
+ spin_unlock(q->queue_lock);
+
+ cic->cfqq = NULL;
+ spin_unlock_irqrestore(&cic->ioc->lock, flags);
}
-static struct cfq_io_context *
-cfq_alloc_io_context(struct cfq_data *cfqd, int gfp_mask)
+static struct cfq_io_context *cfq_alloc_io_context(int gfp_flags)
{
- struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask);
+ struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_flags);
if (cic) {
- INIT_LIST_HEAD(&cic->list);
- cic->cfqq = NULL;
- cic->key = NULL;
- cic->last_end_request = jiffies;
- cic->ttime_total = 0;
- cic->ttime_samples = 0;
- cic->ttime_mean = 0;
cic->dtor = cfq_free_io_context;
cic->exit = cfq_exit_io_context;
+ INIT_LIST_HEAD(&cic->list);
+ cic->cfqq = NULL;
}
return cic;
}
-static void cfq_init_prio_data(struct cfq_queue *cfqq)
-{
- struct task_struct *tsk = current;
- int ioprio_class;
-
- if (!cfq_cfqq_prio_changed(cfqq))
- return;
-
- ioprio_class = IOPRIO_PRIO_CLASS(tsk->ioprio);
- switch (ioprio_class) {
- default:
- printk(KERN_ERR "cfq: bad prio %x\n", ioprio_class);
- case IOPRIO_CLASS_NONE:
- /*
- * no prio set, place us in the middle of the BE classes
- */
- cfqq->ioprio = task_nice_ioprio(tsk);
- cfqq->ioprio_class = IOPRIO_CLASS_BE;
- break;
- case IOPRIO_CLASS_RT:
- cfqq->ioprio = task_ioprio(tsk);
- cfqq->ioprio_class = IOPRIO_CLASS_RT;
- break;
- case IOPRIO_CLASS_BE:
- cfqq->ioprio = task_ioprio(tsk);
- cfqq->ioprio_class = IOPRIO_CLASS_BE;
- break;
- case IOPRIO_CLASS_IDLE:
- cfqq->ioprio_class = IOPRIO_CLASS_IDLE;
- cfqq->ioprio = 7;
- cfq_clear_cfqq_idle_window(cfqq);
- break;
- }
-
- /*
- * keep track of original prio settings in case we have to temporarily
- * elevate the priority of this queue
- */
- cfqq->org_ioprio = cfqq->ioprio;
- cfqq->org_ioprio_class = cfqq->ioprio_class;
-
- if (cfq_cfqq_on_rr(cfqq))
- cfq_resort_rr_list(cfqq, 0);
-
- cfq_clear_cfqq_prio_changed(cfqq);
-}
-
-static inline void changed_ioprio(struct cfq_queue *cfqq)
-{
- if (cfqq) {
- struct cfq_data *cfqd = cfqq->cfqd;
-
- spin_lock(cfqd->queue->queue_lock);
- cfq_mark_cfqq_prio_changed(cfqq);
- cfq_init_prio_data(cfqq);
- spin_unlock(cfqd->queue->queue_lock);
- }
-}
-
-/*
- * callback from sys_ioprio_set, irqs are disabled
- */
-static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio)
-{
- struct cfq_io_context *cic = ioc->cic;
-
- changed_ioprio(cic->cfqq);
-
- list_for_each_entry(cic, &cic->list, list)
- changed_ioprio(cic->cfqq);
-
- return 0;
-}
-
-static struct cfq_queue *
-cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio,
- int gfp_mask)
-{
- const int hashval = hash_long(key, CFQ_QHASH_SHIFT);
- struct cfq_queue *cfqq, *new_cfqq = NULL;
-
-retry:
- cfqq = __cfq_find_cfq_hash(cfqd, key, ioprio, hashval);
-
- if (!cfqq) {
- if (new_cfqq) {
- cfqq = new_cfqq;
- new_cfqq = NULL;
- } else if (gfp_mask & __GFP_WAIT) {
- spin_unlock_irq(cfqd->queue->queue_lock);
- new_cfqq = kmem_cache_alloc(cfq_pool, gfp_mask);
- spin_lock_irq(cfqd->queue->queue_lock);
- goto retry;
- } else {
- cfqq = kmem_cache_alloc(cfq_pool, gfp_mask);
- if (!cfqq)
- goto out;
- }
-
- memset(cfqq, 0, sizeof(*cfqq));
-
- INIT_HLIST_NODE(&cfqq->cfq_hash);
- INIT_LIST_HEAD(&cfqq->cfq_list);
- RB_CLEAR_ROOT(&cfqq->sort_list);
- INIT_LIST_HEAD(&cfqq->fifo);
-
- cfqq->key = key;
- hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]);
- atomic_set(&cfqq->ref, 0);
- cfqq->cfqd = cfqd;
- atomic_inc(&cfqd->ref);
- cfqq->service_last = 0;
- /*
- * set ->slice_left to allow preemption for a new process
- */
- cfqq->slice_left = 2 * cfqd->cfq_slice_idle;
- cfq_mark_cfqq_idle_window(cfqq);
- cfq_mark_cfqq_prio_changed(cfqq);
- cfq_init_prio_data(cfqq);
- }
-
- if (new_cfqq)
- kmem_cache_free(cfq_pool, new_cfqq);
-
- atomic_inc(&cfqq->ref);
-out:
- WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq);
- return cfqq;
-}
-
/*
* Setup general io context and cfq io context. There can be several cfq
* io contexts per general io context, if this process is doing io to more
@@ -1560,39 +1102,39 @@ cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio,
* cfqq, so we don't need to worry about it disappearing
*/
static struct cfq_io_context *
-cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, int gfp_mask)
+cfq_get_io_context(struct cfq_queue **cfqq, int gfp_flags)
{
- struct io_context *ioc = NULL;
+ struct cfq_data *cfqd = (*cfqq)->cfqd;
+ struct cfq_queue *__cfqq = *cfqq;
struct cfq_io_context *cic;
+ struct io_context *ioc;
- might_sleep_if(gfp_mask & __GFP_WAIT);
+ might_sleep_if(gfp_flags & __GFP_WAIT);
- ioc = get_io_context(gfp_mask);
+ ioc = get_io_context(gfp_flags);
if (!ioc)
return NULL;
if ((cic = ioc->cic) == NULL) {
- cic = cfq_alloc_io_context(cfqd, gfp_mask);
+ cic = cfq_alloc_io_context(gfp_flags);
if (cic == NULL)
goto err;
- /*
- * manually increment generic io_context usage count, it
- * cannot go away since we are already holding one ref to it
- */
ioc->cic = cic;
- ioc->set_ioprio = cfq_ioc_set_ioprio;
cic->ioc = ioc;
- cic->key = cfqd;
- atomic_inc(&cfqd->ref);
+ cic->cfqq = __cfqq;
+ atomic_inc(&__cfqq->ref);
} else {
struct cfq_io_context *__cic;
+ unsigned long flags;
/*
- * the first cic on the list is actually the head itself
+ * since the first cic on the list is actually the head
+ * itself, need to check this here or we'll duplicate an
+ * cic per ioc for no reason
*/
- if (cic->key == cfqd)
+ if (cic->cfqq == __cfqq)
goto out;
/*
@@ -1600,262 +1142,152 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, int gfp_mask)
* should be ok here, the list will usually not be more than
* 1 or a few entries long
*/
+ spin_lock_irqsave(&ioc->lock, flags);
list_for_each_entry(__cic, &cic->list, list) {
/*
* this process is already holding a reference to
* this queue, so no need to get one more
*/
- if (__cic->key == cfqd) {
+ if (__cic->cfqq == __cfqq) {
cic = __cic;
+ spin_unlock_irqrestore(&ioc->lock, flags);
goto out;
}
}
+ spin_unlock_irqrestore(&ioc->lock, flags);
/*
* nope, process doesn't have a cic assoicated with this
* cfqq yet. get a new one and add to list
*/
- __cic = cfq_alloc_io_context(cfqd, gfp_mask);
+ __cic = cfq_alloc_io_context(gfp_flags);
if (__cic == NULL)
goto err;
__cic->ioc = ioc;
- __cic->key = cfqd;
- atomic_inc(&cfqd->ref);
+ __cic->cfqq = __cfqq;
+ atomic_inc(&__cfqq->ref);
+ spin_lock_irqsave(&ioc->lock, flags);
list_add(&__cic->list, &cic->list);
- cic = __cic;
- }
+ spin_unlock_irqrestore(&ioc->lock, flags);
-out:
- return cic;
-err:
- put_io_context(ioc);
- return NULL;
-}
-
-static void
-cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic)
-{
- unsigned long elapsed, ttime;
-
- /*
- * if this context already has stuff queued, thinktime is from
- * last queue not last end
- */
-#if 0
- if (time_after(cic->last_end_request, cic->last_queue))
- elapsed = jiffies - cic->last_end_request;
- else
- elapsed = jiffies - cic->last_queue;
-#else
- elapsed = jiffies - cic->last_end_request;
-#endif
-
- ttime = min(elapsed, 2UL * cfqd->cfq_slice_idle);
-
- cic->ttime_samples = (7*cic->ttime_samples + 256) / 8;
- cic->ttime_total = (7*cic->ttime_total + 256*ttime) / 8;
- cic->ttime_mean = (cic->ttime_total + 128) / cic->ttime_samples;
-}
-
-#define sample_valid(samples) ((samples) > 80)
-
-/*
- * Disable idle window if the process thinks too long or seeks so much that
- * it doesn't matter
- */
-static void
-cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
- struct cfq_io_context *cic)
-{
- int enable_idle = cfq_cfqq_idle_window(cfqq);
-
- if (!cic->ioc->task || !cfqd->cfq_slice_idle)
- enable_idle = 0;
- else if (sample_valid(cic->ttime_samples)) {
- if (cic->ttime_mean > cfqd->cfq_slice_idle)
- enable_idle = 0;
- else
- enable_idle = 1;
+ cic = __cic;
+ *cfqq = __cfqq;
}
- if (enable_idle)
- cfq_mark_cfqq_idle_window(cfqq);
- else
- cfq_clear_cfqq_idle_window(cfqq);
-}
-
-
-/*
- * Check if new_cfqq should preempt the currently active queue. Return 0 for
- * no or if we aren't sure, a 1 will cause a preempt.
- */
-static int
-cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
- struct cfq_rq *crq)
-{
- struct cfq_queue *cfqq = cfqd->active_queue;
-
- if (cfq_class_idle(new_cfqq))
- return 0;
-
- if (!cfqq)
- return 1;
-
- if (cfq_class_idle(cfqq))
- return 1;
- if (!cfq_cfqq_wait_request(new_cfqq))
- return 0;
+out:
/*
- * if it doesn't have slice left, forget it
+ * if key_type has been changed on the fly, we lazily rehash
+ * each queue at lookup time
*/
- if (new_cfqq->slice_left < cfqd->cfq_slice_idle)
- return 0;
- if (cfq_crq_is_sync(crq) && !cfq_cfqq_sync(cfqq))
- return 1;
+ if ((*cfqq)->key_type != cfqd->key_type)
+ cfq_rehash_cfqq(cfqd, cfqq, cic);
- return 0;
+ return cic;
+err:
+ put_io_context(ioc);
+ return NULL;
}
-/*
- * cfqq preempts the active queue. if we allowed preempt with no slice left,
- * let it have half of its nominal slice.
- */
-static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+static struct cfq_queue *
+__cfq_get_queue(struct cfq_data *cfqd, unsigned long key, int gfp_mask)
{
- struct cfq_queue *__cfqq, *next;
-
- list_for_each_entry_safe(__cfqq, next, &cfqd->cur_rr, cfq_list)
- cfq_resort_rr_list(__cfqq, 1);
-
- if (!cfqq->slice_left)
- cfqq->slice_left = cfq_prio_to_slice(cfqd, cfqq) / 2;
-
- cfqq->slice_end = cfqq->slice_left + jiffies;
- __cfq_slice_expired(cfqd, cfqq, 1);
- __cfq_set_active_queue(cfqd, cfqq);
-}
+ const int hashval = hash_long(key, CFQ_QHASH_SHIFT);
+ struct cfq_queue *cfqq, *new_cfqq = NULL;
-/*
- * should really be a ll_rw_blk.c helper
- */
-static void cfq_start_queueing(struct cfq_data *cfqd, struct cfq_queue *cfqq)
-{
- request_queue_t *q = cfqd->queue;
+retry:
+ cfqq = __cfq_find_cfq_hash(cfqd, key, hashval);
- if (!blk_queue_plugged(q))
- q->request_fn(q);
- else
- __generic_unplug_device(q);
-}
+ if (!cfqq) {
+ if (new_cfqq) {
+ cfqq = new_cfqq;
+ new_cfqq = NULL;
+ } else {
+ spin_unlock_irq(cfqd->queue->queue_lock);
+ new_cfqq = kmem_cache_alloc(cfq_pool, gfp_mask);
+ spin_lock_irq(cfqd->queue->queue_lock);
-/*
- * Called when a new fs request (crq) is added (to cfqq). Check if there's
- * something we should do about it
- */
-static void
-cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
- struct cfq_rq *crq)
-{
- const int sync = cfq_crq_is_sync(crq);
+ if (!new_cfqq && !(gfp_mask & __GFP_WAIT))
+ goto out;
- cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq);
+ goto retry;
+ }
- if (sync) {
- struct cfq_io_context *cic = crq->io_context;
+ memset(cfqq, 0, sizeof(*cfqq));
- cfq_update_io_thinktime(cfqd, cic);
- cfq_update_idle_window(cfqd, cfqq, cic);
+ INIT_HLIST_NODE(&cfqq->cfq_hash);
+ INIT_LIST_HEAD(&cfqq->cfq_list);
+ RB_CLEAR_ROOT(&cfqq->sort_list);
+ INIT_LIST_HEAD(&cfqq->fifo[0]);
+ INIT_LIST_HEAD(&cfqq->fifo[1]);
- cic->last_queue = jiffies;
+ cfqq->key = key;
+ hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]);
+ atomic_set(&cfqq->ref, 0);
+ cfqq->cfqd = cfqd;
+ atomic_inc(&cfqd->ref);
+ cfqq->key_type = cfqd->key_type;
+ cfqq->service_start = ~0UL;
}
- if (cfqq == cfqd->active_queue) {
- /*
- * if we are waiting for a request for this queue, let it rip
- * immediately and flag that we must not expire this queue
- * just now
- */
- if (cfq_cfqq_wait_request(cfqq)) {
- cfq_mark_cfqq_must_dispatch(cfqq);
- del_timer(&cfqd->idle_slice_timer);
- cfq_start_queueing(cfqd, cfqq);
- }
- } else if (cfq_should_preempt(cfqd, cfqq, crq)) {
- /*
- * not the active queue - expire current slice if it is
- * idle and has expired it's mean thinktime or this new queue
- * has some old slice time left and is of higher priority
- */
- cfq_preempt_queue(cfqd, cfqq);
- cfq_mark_cfqq_must_dispatch(cfqq);
- cfq_start_queueing(cfqd, cfqq);
- }
+ if (new_cfqq)
+ kmem_cache_free(cfq_pool, new_cfqq);
+
+ atomic_inc(&cfqq->ref);
+out:
+ WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq);
+ return cfqq;
}
-static void cfq_enqueue(struct cfq_data *cfqd, struct request *rq)
+static void cfq_enqueue(struct cfq_data *cfqd, struct cfq_rq *crq)
{
- struct cfq_rq *crq = RQ_DATA(rq);
- struct cfq_queue *cfqq = crq->cfq_queue;
-
- cfq_init_prio_data(cfqq);
+ crq->is_sync = 0;
+ if (rq_data_dir(crq->request) == READ || current->flags & PF_SYNCWRITE)
+ crq->is_sync = 1;
cfq_add_crq_rb(crq);
+ crq->queue_start = jiffies;
- list_add_tail(&rq->queuelist, &cfqq->fifo);
-
- if (rq_mergeable(rq)) {
- cfq_add_crq_hash(cfqd, crq);
-
- if (!cfqd->queue->last_merge)
- cfqd->queue->last_merge = rq;
- }
-
- cfq_crq_enqueued(cfqd, cfqq, crq);
+ list_add_tail(&crq->request->queuelist, &crq->cfq_queue->fifo[crq->is_sync]);
}
static void
cfq_insert_request(request_queue_t *q, struct request *rq, int where)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
+ struct cfq_rq *crq = RQ_DATA(rq);
switch (where) {
case ELEVATOR_INSERT_BACK:
- while (cfq_dispatch_requests(q, INT_MAX, 1))
+ while (cfq_dispatch_requests(q, cfqd->cfq_quantum))
;
list_add_tail(&rq->queuelist, &q->queue_head);
- /*
- * If we were idling with pending requests on
- * inactive cfqqs, force dispatching will
- * remove the idle timer and the queue won't
- * be kicked by __make_request() afterward.
- * Kick it here.
- */
- cfq_schedule_dispatch(cfqd);
break;
case ELEVATOR_INSERT_FRONT:
list_add(&rq->queuelist, &q->queue_head);
break;
case ELEVATOR_INSERT_SORT:
BUG_ON(!blk_fs_request(rq));
- cfq_enqueue(cfqd, rq);
+ cfq_enqueue(cfqd, crq);
break;
default:
printk("%s: bad insert point %d\n", __FUNCTION__,where);
return;
}
-}
-static inline int cfq_pending_requests(struct cfq_data *cfqd)
-{
- return !list_empty(&cfqd->queue->queue_head) || cfqd->busy_queues;
+ if (rq_mergeable(rq)) {
+ cfq_add_crq_hash(cfqd, crq);
+
+ if (!q->last_merge)
+ q->last_merge = rq;
+ }
}
static int cfq_queue_empty(request_queue_t *q)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
- return !cfq_pending_requests(cfqd);
+ return list_empty(&q->queue_head) && list_empty(&cfqd->rr_list);
}
static void cfq_completed_request(request_queue_t *q, struct request *rq)
@@ -1868,11 +1300,9 @@ static void cfq_completed_request(request_queue_t *q, struct request *rq)
cfqq = crq->cfq_queue;
- if (cfq_crq_in_flight(crq)) {
- const int sync = cfq_crq_is_sync(crq);
-
- WARN_ON(!cfqq->on_dispatch[sync]);
- cfqq->on_dispatch[sync]--;
+ if (crq->in_flight) {
+ WARN_ON(!cfqq->in_flight);
+ cfqq->in_flight--;
}
cfq_account_completion(cfqq, crq);
@@ -1902,136 +1332,51 @@ cfq_latter_request(request_queue_t *q, struct request *rq)
return NULL;
}
-/*
- * we temporarily boost lower priority queues if they are holding fs exclusive
- * resources. they are boosted to normal prio (CLASS_BE/4)
- */
-static void cfq_prio_boost(struct cfq_queue *cfqq)
-{
- const int ioprio_class = cfqq->ioprio_class;
- const int ioprio = cfqq->ioprio;
-
- if (has_fs_excl()) {
- /*
- * boost idle prio on transactions that would lock out other
- * users of the filesystem
- */
- if (cfq_class_idle(cfqq))
- cfqq->ioprio_class = IOPRIO_CLASS_BE;
- if (cfqq->ioprio > IOPRIO_NORM)
- cfqq->ioprio = IOPRIO_NORM;
- } else {
- /*
- * check if we need to unboost the queue
- */
- if (cfqq->ioprio_class != cfqq->org_ioprio_class)
- cfqq->ioprio_class = cfqq->org_ioprio_class;
- if (cfqq->ioprio != cfqq->org_ioprio)
- cfqq->ioprio = cfqq->org_ioprio;
- }
-
- /*
- * refile between round-robin lists if we moved the priority class
- */
- if ((ioprio_class != cfqq->ioprio_class || ioprio != cfqq->ioprio) &&
- cfq_cfqq_on_rr(cfqq))
- cfq_resort_rr_list(cfqq, 0);
-}
-
-static inline pid_t cfq_queue_pid(struct task_struct *task, int rw)
+static int cfq_may_queue(request_queue_t *q, int rw)
{
- if (rw == READ || process_sync(task))
- return task->pid;
-
- return CFQ_KEY_ASYNC;
-}
-
-static inline int
-__cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq,
- struct task_struct *task, int rw)
-{
-#if 1
- if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) &&
- !cfq_cfqq_must_alloc_slice) {
- cfq_mark_cfqq_must_alloc_slice(cfqq);
- return ELV_MQUEUE_MUST;
- }
-
- return ELV_MQUEUE_MAY;
-#else
- if (!cfqq || task->flags & PF_MEMALLOC)
- return ELV_MQUEUE_MAY;
- if (!cfqq->allocated[rw] || cfq_cfqq_must_alloc(cfqq)) {
- if (cfq_cfqq_wait_request(cfqq))
- return ELV_MQUEUE_MUST;
-
- /*
- * only allow 1 ELV_MQUEUE_MUST per slice, otherwise we
- * can quickly flood the queue with writes from a single task
- */
- if (rw == READ || !cfq_cfqq_must_alloc_slice) {
- cfq_mark_cfqq_must_alloc_slice(cfqq);
- return ELV_MQUEUE_MUST;
- }
+ struct cfq_data *cfqd = q->elevator->elevator_data;
+ struct cfq_queue *cfqq;
+ int ret = ELV_MQUEUE_MAY;
+ if (current->flags & PF_MEMALLOC)
return ELV_MQUEUE_MAY;
- }
- if (cfq_class_idle(cfqq))
- return ELV_MQUEUE_NO;
- if (cfqq->allocated[rw] >= cfqd->max_queued) {
- struct io_context *ioc = get_io_context(GFP_ATOMIC);
- int ret = ELV_MQUEUE_NO;
- if (ioc && ioc->nr_batch_requests)
- ret = ELV_MQUEUE_MAY;
+ cfqq = cfq_find_cfq_hash(cfqd, cfq_hash_key(cfqd, current));
+ if (cfqq) {
+ int limit = cfqd->max_queued;
- put_io_context(ioc);
- return ret;
- }
+ if (cfqq->allocated[rw] < cfqd->cfq_queued)
+ return ELV_MQUEUE_MUST;
- return ELV_MQUEUE_MAY;
-#endif
-}
+ if (cfqd->busy_queues)
+ limit = q->nr_requests / cfqd->busy_queues;
-static int cfq_may_queue(request_queue_t *q, int rw, struct bio *bio)
-{
- struct cfq_data *cfqd = q->elevator->elevator_data;
- struct task_struct *tsk = current;
- struct cfq_queue *cfqq;
+ if (limit < cfqd->cfq_queued)
+ limit = cfqd->cfq_queued;
+ else if (limit > cfqd->max_queued)
+ limit = cfqd->max_queued;
- /*
- * don't force setup of a queue from here, as a call to may_queue
- * does not necessarily imply that a request actually will be queued.
- * so just lookup a possibly existing queue, or return 'may queue'
- * if that fails
- */
- cfqq = cfq_find_cfq_hash(cfqd, cfq_queue_pid(tsk, rw), tsk->ioprio);
- if (cfqq) {
- cfq_init_prio_data(cfqq);
- cfq_prio_boost(cfqq);
+ if (cfqq->allocated[rw] >= limit) {
+ if (limit > cfqq->alloc_limit[rw])
+ cfqq->alloc_limit[rw] = limit;
- return __cfq_may_queue(cfqd, cfqq, tsk, rw);
+ ret = ELV_MQUEUE_NO;
+ }
}
- return ELV_MQUEUE_MAY;
+ return ret;
}
static void cfq_check_waiters(request_queue_t *q, struct cfq_queue *cfqq)
{
- struct cfq_data *cfqd = q->elevator->elevator_data;
struct request_list *rl = &q->rq;
+ const int write = waitqueue_active(&rl->wait[WRITE]);
+ const int read = waitqueue_active(&rl->wait[READ]);
- if (cfqq->allocated[READ] <= cfqd->max_queued || cfqd->rq_starved) {
- smp_mb();
- if (waitqueue_active(&rl->wait[READ]))
- wake_up(&rl->wait[READ]);
- }
-
- if (cfqq->allocated[WRITE] <= cfqd->max_queued || cfqd->rq_starved) {
- smp_mb();
- if (waitqueue_active(&rl->wait[WRITE]))
- wake_up(&rl->wait[WRITE]);
- }
+ if (read && cfqq->allocated[READ] < cfqq->alloc_limit[READ])
+ wake_up(&rl->wait[READ]);
+ if (write && cfqq->allocated[WRITE] < cfqq->alloc_limit[WRITE])
+ wake_up(&rl->wait[WRITE]);
}
/*
@@ -2044,61 +1389,69 @@ static void cfq_put_request(request_queue_t *q, struct request *rq)
if (crq) {
struct cfq_queue *cfqq = crq->cfq_queue;
- const int rw = rq_data_dir(rq);
- BUG_ON(!cfqq->allocated[rw]);
- cfqq->allocated[rw]--;
+ BUG_ON(q->last_merge == rq);
+ BUG_ON(!hlist_unhashed(&crq->hash));
+
+ if (crq->io_context)
+ put_io_context(crq->io_context->ioc);
- put_io_context(crq->io_context->ioc);
+ BUG_ON(!cfqq->allocated[crq->is_write]);
+ cfqq->allocated[crq->is_write]--;
mempool_free(crq, cfqd->crq_pool);
rq->elevator_private = NULL;
+ smp_mb();
cfq_check_waiters(q, cfqq);
cfq_put_queue(cfqq);
}
}
/*
- * Allocate cfq data structures associated with this request.
+ * Allocate cfq data structures associated with this request. A queue and
*/
-static int
-cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
- int gfp_mask)
+static int cfq_set_request(request_queue_t *q, struct request *rq, int gfp_mask)
{
struct cfq_data *cfqd = q->elevator->elevator_data;
- struct task_struct *tsk = current;
struct cfq_io_context *cic;
const int rw = rq_data_dir(rq);
- pid_t key = cfq_queue_pid(tsk, rw);
- struct cfq_queue *cfqq;
+ struct cfq_queue *cfqq, *saved_cfqq;
struct cfq_rq *crq;
unsigned long flags;
might_sleep_if(gfp_mask & __GFP_WAIT);
- cic = cfq_get_io_context(cfqd, key, gfp_mask);
-
spin_lock_irqsave(q->queue_lock, flags);
- if (!cic)
- goto queue_fail;
-
- if (!cic->cfqq) {
- cfqq = cfq_get_queue(cfqd, key, tsk->ioprio, gfp_mask);
- if (!cfqq)
- goto queue_fail;
+ cfqq = __cfq_get_queue(cfqd, cfq_hash_key(cfqd, current), gfp_mask);
+ if (!cfqq)
+ goto out_lock;
- cic->cfqq = cfqq;
- } else
- cfqq = cic->cfqq;
+repeat:
+ if (cfqq->allocated[rw] >= cfqd->max_queued)
+ goto out_lock;
cfqq->allocated[rw]++;
- cfq_clear_cfqq_must_alloc(cfqq);
- cfqd->rq_starved = 0;
- atomic_inc(&cfqq->ref);
spin_unlock_irqrestore(q->queue_lock, flags);
+ /*
+ * if hashing type has changed, the cfq_queue might change here.
+ */
+ saved_cfqq = cfqq;
+ cic = cfq_get_io_context(&cfqq, gfp_mask);
+ if (!cic)
+ goto err;
+
+ /*
+ * repeat allocation checks on queue change
+ */
+ if (unlikely(saved_cfqq != cfqq)) {
+ spin_lock_irqsave(q->queue_lock, flags);
+ saved_cfqq->allocated[rw]--;
+ goto repeat;
+ }
+
crq = mempool_alloc(cfqd->crq_pool, gfp_mask);
if (crq) {
RB_CLEAR(&crq->rb_node);
@@ -2107,141 +1460,24 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
INIT_HLIST_NODE(&crq->hash);
crq->cfq_queue = cfqq;
crq->io_context = cic;
- cfq_clear_crq_in_flight(crq);
- cfq_clear_crq_in_driver(crq);
- cfq_clear_crq_requeued(crq);
-
- if (rw == READ || process_sync(tsk))
- cfq_mark_crq_is_sync(crq);
- else
- cfq_clear_crq_is_sync(crq);
-
+ crq->service_start = crq->queue_start = 0;
+ crq->in_flight = crq->accounted = crq->is_sync = 0;
+ crq->is_write = rw;
rq->elevator_private = crq;
+ cfqq->alloc_limit[rw] = 0;
return 0;
}
+ put_io_context(cic->ioc);
+err:
spin_lock_irqsave(q->queue_lock, flags);
cfqq->allocated[rw]--;
- if (!(cfqq->allocated[0] + cfqq->allocated[1]))
- cfq_mark_cfqq_must_alloc(cfqq);
cfq_put_queue(cfqq);
-queue_fail:
- if (cic)
- put_io_context(cic->ioc);
- /*
- * mark us rq allocation starved. we need to kickstart the process
- * ourselves if there are no pending requests that can do it for us.
- * that would be an extremely rare OOM situation
- */
- cfqd->rq_starved = 1;
- cfq_schedule_dispatch(cfqd);
+out_lock:
spin_unlock_irqrestore(q->queue_lock, flags);
return 1;
}
-static void cfq_kick_queue(void *data)
-{
- request_queue_t *q = data;
- struct cfq_data *cfqd = q->elevator->elevator_data;
- unsigned long flags;
-
- spin_lock_irqsave(q->queue_lock, flags);
-
- if (cfqd->rq_starved) {
- struct request_list *rl = &q->rq;
-
- /*
- * we aren't guaranteed to get a request after this, but we
- * have to be opportunistic
- */
- smp_mb();
- if (waitqueue_active(&rl->wait[READ]))
- wake_up(&rl->wait[READ]);
- if (waitqueue_active(&rl->wait[WRITE]))
- wake_up(&rl->wait[WRITE]);
- }
-
- blk_remove_plug(q);
- q->request_fn(q);
- spin_unlock_irqrestore(q->queue_lock, flags);
-}
-
-/*
- * Timer running if the active_queue is currently idling inside its time slice
- */
-static void cfq_idle_slice_timer(unsigned long data)
-{
- struct cfq_data *cfqd = (struct cfq_data *) data;
- struct cfq_queue *cfqq;
- unsigned long flags;
-
- spin_lock_irqsave(cfqd->queue->queue_lock, flags);
-
- if ((cfqq = cfqd->active_queue) != NULL) {
- unsigned long now = jiffies;
-
- /*
- * expired
- */
- if (time_after(now, cfqq->slice_end))
- goto expire;
-
- /*
- * only expire and reinvoke request handler, if there are
- * other queues with pending requests
- */
- if (!cfq_pending_requests(cfqd)) {
- cfqd->idle_slice_timer.expires = min(now + cfqd->cfq_slice_idle, cfqq->slice_end);
- add_timer(&cfqd->idle_slice_timer);
- goto out_cont;
- }
-
- /*
- * not expired and it has a request pending, let it dispatch
- */
- if (!RB_EMPTY(&cfqq->sort_list)) {
- cfq_mark_cfqq_must_dispatch(cfqq);
- goto out_kick;
- }
- }
-expire:
- cfq_slice_expired(cfqd, 0);
-out_kick:
- cfq_schedule_dispatch(cfqd);
-out_cont:
- spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
-}
-
-/*
- * Timer running if an idle class queue is waiting for service
- */
-static void cfq_idle_class_timer(unsigned long data)
-{
- struct cfq_data *cfqd = (struct cfq_data *) data;
- unsigned long flags, end;
-
- spin_lock_irqsave(cfqd->queue->queue_lock, flags);
-
- /*
- * race with a non-idle queue, reset timer
- */
- end = cfqd->last_end_request + CFQ_IDLE_GRACE;
- if (!time_after_eq(jiffies, end)) {
- cfqd->idle_class_timer.expires = end;
- add_timer(&cfqd->idle_class_timer);
- } else
- cfq_schedule_dispatch(cfqd);
-
- spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
-}
-
-static void cfq_shutdown_timer_wq(struct cfq_data *cfqd)
-{
- del_timer_sync(&cfqd->idle_slice_timer);
- del_timer_sync(&cfqd->idle_class_timer);
- blk_sync_queue(cfqd->queue);
-}
-
static void cfq_put_cfqd(struct cfq_data *cfqd)
{
request_queue_t *q = cfqd->queue;
@@ -2251,9 +1487,6 @@ static void cfq_put_cfqd(struct cfq_data *cfqd)
blk_put_queue(q);
- cfq_shutdown_timer_wq(cfqd);
- q->elevator->elevator_data = NULL;
-
mempool_destroy(cfqd->crq_pool);
kfree(cfqd->crq_hash);
kfree(cfqd->cfq_hash);
@@ -2262,10 +1495,7 @@ static void cfq_put_cfqd(struct cfq_data *cfqd)
static void cfq_exit_queue(elevator_t *e)
{
- struct cfq_data *cfqd = e->elevator_data;
-
- cfq_shutdown_timer_wq(cfqd);
- cfq_put_cfqd(cfqd);
+ cfq_put_cfqd(e->elevator_data);
}
static int cfq_init_queue(request_queue_t *q, elevator_t *e)
@@ -2278,13 +1508,7 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
return -ENOMEM;
memset(cfqd, 0, sizeof(*cfqd));
-
- for (i = 0; i < CFQ_PRIO_LISTS; i++)
- INIT_LIST_HEAD(&cfqd->rr_list[i]);
-
- INIT_LIST_HEAD(&cfqd->busy_rr);
- INIT_LIST_HEAD(&cfqd->cur_rr);
- INIT_LIST_HEAD(&cfqd->idle_rr);
+ INIT_LIST_HEAD(&cfqd->rr_list);
INIT_LIST_HEAD(&cfqd->empty_list);
cfqd->crq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL);
@@ -2309,32 +1533,24 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
cfqd->queue = q;
atomic_inc(&q->refcnt);
- cfqd->max_queued = q->nr_requests / 4;
+ /*
+ * just set it to some high value, we want anyone to be able to queue
+ * some requests. fairness is handled differently
+ */
+ q->nr_requests = 1024;
+ cfqd->max_queued = q->nr_requests / 16;
q->nr_batching = cfq_queued;
-
- init_timer(&cfqd->idle_slice_timer);
- cfqd->idle_slice_timer.function = cfq_idle_slice_timer;
- cfqd->idle_slice_timer.data = (unsigned long) cfqd;
-
- init_timer(&cfqd->idle_class_timer);
- cfqd->idle_class_timer.function = cfq_idle_class_timer;
- cfqd->idle_class_timer.data = (unsigned long) cfqd;
-
- INIT_WORK(&cfqd->unplug_work, cfq_kick_queue, q);
-
+ cfqd->key_type = CFQ_KEY_TGID;
+ cfqd->find_best_crq = 1;
atomic_set(&cfqd->ref, 1);
cfqd->cfq_queued = cfq_queued;
cfqd->cfq_quantum = cfq_quantum;
- cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0];
- cfqd->cfq_fifo_expire[1] = cfq_fifo_expire[1];
+ cfqd->cfq_fifo_expire_r = cfq_fifo_expire_r;
+ cfqd->cfq_fifo_expire_w = cfq_fifo_expire_w;
+ cfqd->cfq_fifo_batch_expire = cfq_fifo_rate;
cfqd->cfq_back_max = cfq_back_max;
cfqd->cfq_back_penalty = cfq_back_penalty;
- cfqd->cfq_slice[0] = cfq_slice_async;
- cfqd->cfq_slice[1] = cfq_slice_sync;
- cfqd->cfq_slice_async_rq = cfq_slice_async_rq;
- cfqd->cfq_slice_idle = cfq_slice_idle;
- cfqd->cfq_max_depth = cfq_max_depth;
return 0;
out_crqpool:
@@ -2379,6 +1595,7 @@ static int __init cfq_slab_setup(void)
return -ENOMEM;
}
+
/*
* sysfs parts below -->
*/
@@ -2403,6 +1620,45 @@ cfq_var_store(unsigned int *var, const char *page, size_t count)
return count;
}
+static ssize_t
+cfq_clear_elapsed(struct cfq_data *cfqd, const char *page, size_t count)
+{
+ max_elapsed_dispatch = max_elapsed_crq = 0;
+ return count;
+}
+
+static ssize_t
+cfq_set_key_type(struct cfq_data *cfqd, const char *page, size_t count)
+{
+ spin_lock_irq(cfqd->queue->queue_lock);
+ if (!strncmp(page, "pgid", 4))
+ cfqd->key_type = CFQ_KEY_PGID;
+ else if (!strncmp(page, "tgid", 4))
+ cfqd->key_type = CFQ_KEY_TGID;
+ else if (!strncmp(page, "uid", 3))
+ cfqd->key_type = CFQ_KEY_UID;
+ else if (!strncmp(page, "gid", 3))
+ cfqd->key_type = CFQ_KEY_GID;
+ spin_unlock_irq(cfqd->queue->queue_lock);
+ return count;
+}
+
+static ssize_t
+cfq_read_key_type(struct cfq_data *cfqd, char *page)
+{
+ ssize_t len = 0;
+ int i;
+
+ for (i = CFQ_KEY_PGID; i < CFQ_KEY_LAST; i++) {
+ if (cfqd->key_type == i)
+ len += sprintf(page+len, "[%s] ", cfq_key_types[i]);
+ else
+ len += sprintf(page+len, "%s ", cfq_key_types[i]);
+ }
+ len += sprintf(page+len, "\n");
+ return len;
+}
+
#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \
static ssize_t __FUNC(struct cfq_data *cfqd, char *page) \
{ \
@@ -2413,15 +1669,12 @@ static ssize_t __FUNC(struct cfq_data *cfqd, char *page) \
}
SHOW_FUNCTION(cfq_quantum_show, cfqd->cfq_quantum, 0);
SHOW_FUNCTION(cfq_queued_show, cfqd->cfq_queued, 0);
-SHOW_FUNCTION(cfq_fifo_expire_sync_show, cfqd->cfq_fifo_expire[1], 1);
-SHOW_FUNCTION(cfq_fifo_expire_async_show, cfqd->cfq_fifo_expire[0], 1);
+SHOW_FUNCTION(cfq_fifo_expire_r_show, cfqd->cfq_fifo_expire_r, 1);
+SHOW_FUNCTION(cfq_fifo_expire_w_show, cfqd->cfq_fifo_expire_w, 1);
+SHOW_FUNCTION(cfq_fifo_batch_expire_show, cfqd->cfq_fifo_batch_expire, 1);
+SHOW_FUNCTION(cfq_find_best_show, cfqd->find_best_crq, 0);
SHOW_FUNCTION(cfq_back_max_show, cfqd->cfq_back_max, 0);
SHOW_FUNCTION(cfq_back_penalty_show, cfqd->cfq_back_penalty, 0);
-SHOW_FUNCTION(cfq_slice_idle_show, cfqd->cfq_slice_idle, 1);
-SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1);
-SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1);
-SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0);
-SHOW_FUNCTION(cfq_max_depth_show, cfqd->cfq_max_depth, 0);
#undef SHOW_FUNCTION
#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \
@@ -2441,15 +1694,12 @@ static ssize_t __FUNC(struct cfq_data *cfqd, const char *page, size_t count) \
}
STORE_FUNCTION(cfq_quantum_store, &cfqd->cfq_quantum, 1, UINT_MAX, 0);
STORE_FUNCTION(cfq_queued_store, &cfqd->cfq_queued, 1, UINT_MAX, 0);
-STORE_FUNCTION(cfq_fifo_expire_sync_store, &cfqd->cfq_fifo_expire[1], 1, UINT_MAX, 1);
-STORE_FUNCTION(cfq_fifo_expire_async_store, &cfqd->cfq_fifo_expire[0], 1, UINT_MAX, 1);
+STORE_FUNCTION(cfq_fifo_expire_r_store, &cfqd->cfq_fifo_expire_r, 1, UINT_MAX, 1);
+STORE_FUNCTION(cfq_fifo_expire_w_store, &cfqd->cfq_fifo_expire_w, 1, UINT_MAX, 1);
+STORE_FUNCTION(cfq_fifo_batch_expire_store, &cfqd->cfq_fifo_batch_expire, 0, UINT_MAX, 1);
+STORE_FUNCTION(cfq_find_best_store, &cfqd->find_best_crq, 0, 1, 0);
STORE_FUNCTION(cfq_back_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0);
STORE_FUNCTION(cfq_back_penalty_store, &cfqd->cfq_back_penalty, 1, UINT_MAX, 0);
-STORE_FUNCTION(cfq_slice_idle_store, &cfqd->cfq_slice_idle, 0, UINT_MAX, 1);
-STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1);
-STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1);
-STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, UINT_MAX, 0);
-STORE_FUNCTION(cfq_max_depth_store, &cfqd->cfq_max_depth, 1, UINT_MAX, 0);
#undef STORE_FUNCTION
static struct cfq_fs_entry cfq_quantum_entry = {
@@ -2462,15 +1712,25 @@ static struct cfq_fs_entry cfq_queued_entry = {
.show = cfq_queued_show,
.store = cfq_queued_store,
};
-static struct cfq_fs_entry cfq_fifo_expire_sync_entry = {
+static struct cfq_fs_entry cfq_fifo_expire_r_entry = {
.attr = {.name = "fifo_expire_sync", .mode = S_IRUGO | S_IWUSR },
- .show = cfq_fifo_expire_sync_show,
- .store = cfq_fifo_expire_sync_store,
+ .show = cfq_fifo_expire_r_show,
+ .store = cfq_fifo_expire_r_store,
};
-static struct cfq_fs_entry cfq_fifo_expire_async_entry = {
+static struct cfq_fs_entry cfq_fifo_expire_w_entry = {
.attr = {.name = "fifo_expire_async", .mode = S_IRUGO | S_IWUSR },
- .show = cfq_fifo_expire_async_show,
- .store = cfq_fifo_expire_async_store,
+ .show = cfq_fifo_expire_w_show,
+ .store = cfq_fifo_expire_w_store,
+};
+static struct cfq_fs_entry cfq_fifo_batch_expire_entry = {
+ .attr = {.name = "fifo_batch_expire", .mode = S_IRUGO | S_IWUSR },
+ .show = cfq_fifo_batch_expire_show,
+ .store = cfq_fifo_batch_expire_store,
+};
+static struct cfq_fs_entry cfq_find_best_entry = {
+ .attr = {.name = "find_best_crq", .mode = S_IRUGO | S_IWUSR },
+ .show = cfq_find_best_show,
+ .store = cfq_find_best_store,
};
static struct cfq_fs_entry cfq_back_max_entry = {
.attr = {.name = "back_seek_max", .mode = S_IRUGO | S_IWUSR },
@@ -2482,44 +1742,27 @@ static struct cfq_fs_entry cfq_back_penalty_entry = {
.show = cfq_back_penalty_show,
.store = cfq_back_penalty_store,
};
-static struct cfq_fs_entry cfq_slice_sync_entry = {
- .attr = {.name = "slice_sync", .mode = S_IRUGO | S_IWUSR },
- .show = cfq_slice_sync_show,
- .store = cfq_slice_sync_store,
-};
-static struct cfq_fs_entry cfq_slice_async_entry = {
- .attr = {.name = "slice_async", .mode = S_IRUGO | S_IWUSR },
- .show = cfq_slice_async_show,
- .store = cfq_slice_async_store,
-};
-static struct cfq_fs_entry cfq_slice_async_rq_entry = {
- .attr = {.name = "slice_async_rq", .mode = S_IRUGO | S_IWUSR },
- .show = cfq_slice_async_rq_show,
- .store = cfq_slice_async_rq_store,
+static struct cfq_fs_entry cfq_clear_elapsed_entry = {
+ .attr = {.name = "clear_elapsed", .mode = S_IWUSR },
+ .store = cfq_clear_elapsed,
};
-static struct cfq_fs_entry cfq_slice_idle_entry = {
- .attr = {.name = "slice_idle", .mode = S_IRUGO | S_IWUSR },
- .show = cfq_slice_idle_show,
- .store = cfq_slice_idle_store,
-};
-static struct cfq_fs_entry cfq_max_depth_entry = {
- .attr = {.name = "max_depth", .mode = S_IRUGO | S_IWUSR },
- .show = cfq_max_depth_show,
- .store = cfq_max_depth_store,
+static struct cfq_fs_entry cfq_key_type_entry = {
+ .attr = {.name = "key_type", .mode = S_IRUGO | S_IWUSR },
+ .show = cfq_read_key_type,
+ .store = cfq_set_key_type,
};
static struct attribute *default_attrs[] = {
&cfq_quantum_entry.attr,
&cfq_queued_entry.attr,
- &cfq_fifo_expire_sync_entry.attr,
- &cfq_fifo_expire_async_entry.attr,
+ &cfq_fifo_expire_r_entry.attr,
+ &cfq_fifo_expire_w_entry.attr,
+ &cfq_fifo_batch_expire_entry.attr,
+ &cfq_key_type_entry.attr,
+ &cfq_find_best_entry.attr,
&cfq_back_max_entry.attr,
&cfq_back_penalty_entry.attr,
- &cfq_slice_sync_entry.attr,
- &cfq_slice_async_entry.attr,
- &cfq_slice_async_rq_entry.attr,
- &cfq_slice_idle_entry.attr,
- &cfq_max_depth_entry.attr,
+ &cfq_clear_elapsed_entry.attr,
NULL,
};
@@ -2589,46 +1832,21 @@ static int __init cfq_init(void)
{
int ret;
- /*
- * could be 0 on HZ < 1000 setups
- */
- if (!cfq_slice_async)
- cfq_slice_async = 1;
- if (!cfq_slice_idle)
- cfq_slice_idle = 1;
-
if (cfq_slab_setup())
return -ENOMEM;
ret = elv_register(&iosched_cfq);
- if (ret)
- cfq_slab_kill();
+ if (!ret) {
+ __module_get(THIS_MODULE);
+ return 0;
+ }
+ cfq_slab_kill();
return ret;
}
static void __exit cfq_exit(void)
{
- struct task_struct *g, *p;
- unsigned long flags;
-
- read_lock_irqsave(&tasklist_lock, flags);
-
- /*
- * iterate each process in the system, removing our io_context
- */
- do_each_thread(g, p) {
- struct io_context *ioc = p->io_context;
-
- if (ioc && ioc->cic) {
- ioc->cic->exit(ioc->cic);
- cfq_free_io_context(ioc->cic);
- ioc->cic = NULL;
- }
- } while_each_thread(g, p);
-
- read_unlock_irqrestore(&tasklist_lock, flags);
-
cfq_slab_kill();
elv_unregister(&iosched_cfq);
}
diff --git a/trunk/drivers/block/deadline-iosched.c b/trunk/drivers/block/deadline-iosched.c
index ff5201e02153..4bc2fea73273 100644
--- a/trunk/drivers/block/deadline-iosched.c
+++ b/trunk/drivers/block/deadline-iosched.c
@@ -760,8 +760,7 @@ static void deadline_put_request(request_queue_t *q, struct request *rq)
}
static int
-deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
- int gfp_mask)
+deadline_set_request(request_queue_t *q, struct request *rq, int gfp_mask)
{
struct deadline_data *dd = q->elevator->elevator_data;
struct deadline_rq *drq;
diff --git a/trunk/drivers/block/elevator.c b/trunk/drivers/block/elevator.c
index 98f0126a2deb..f831f08f839c 100644
--- a/trunk/drivers/block/elevator.c
+++ b/trunk/drivers/block/elevator.c
@@ -486,13 +486,12 @@ struct request *elv_former_request(request_queue_t *q, struct request *rq)
return NULL;
}
-int elv_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
- int gfp_mask)
+int elv_set_request(request_queue_t *q, struct request *rq, int gfp_mask)
{
elevator_t *e = q->elevator;
if (e->ops->elevator_set_req_fn)
- return e->ops->elevator_set_req_fn(q, rq, bio, gfp_mask);
+ return e->ops->elevator_set_req_fn(q, rq, gfp_mask);
rq->elevator_private = NULL;
return 0;
@@ -506,12 +505,12 @@ void elv_put_request(request_queue_t *q, struct request *rq)
e->ops->elevator_put_req_fn(q, rq);
}
-int elv_may_queue(request_queue_t *q, int rw, struct bio *bio)
+int elv_may_queue(request_queue_t *q, int rw)
{
elevator_t *e = q->elevator;
if (e->ops->elevator_may_queue_fn)
- return e->ops->elevator_may_queue_fn(q, rw, bio);
+ return e->ops->elevator_may_queue_fn(q, rw);
return ELV_MQUEUE_MAY;
}
diff --git a/trunk/drivers/block/ll_rw_blk.c b/trunk/drivers/block/ll_rw_blk.c
index 234fdcfbdf01..60e64091de1b 100644
--- a/trunk/drivers/block/ll_rw_blk.c
+++ b/trunk/drivers/block/ll_rw_blk.c
@@ -276,7 +276,6 @@ static inline void rq_init(request_queue_t *q, struct request *rq)
rq->errors = 0;
rq->rq_status = RQ_ACTIVE;
rq->bio = rq->biotail = NULL;
- rq->ioprio = 0;
rq->buffer = NULL;
rq->ref_count = 1;
rq->q = q;
@@ -1443,7 +1442,11 @@ void __generic_unplug_device(request_queue_t *q)
if (!blk_remove_plug(q))
return;
- q->request_fn(q);
+ /*
+ * was plugged, fire request_fn if queue has stuff to do
+ */
+ if (elv_next_request(q))
+ q->request_fn(q);
}
EXPORT_SYMBOL(__generic_unplug_device);
@@ -1773,8 +1776,8 @@ static inline void blk_free_request(request_queue_t *q, struct request *rq)
mempool_free(rq, q->rq.rq_pool);
}
-static inline struct request *
-blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, int gfp_mask)
+static inline struct request *blk_alloc_request(request_queue_t *q, int rw,
+ int gfp_mask)
{
struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask);
@@ -1787,7 +1790,7 @@ blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, int gfp_mask)
*/
rq->flags = rw;
- if (!elv_set_request(q, rq, bio, gfp_mask))
+ if (!elv_set_request(q, rq, gfp_mask))
return rq;
mempool_free(rq, q->rq.rq_pool);
@@ -1869,8 +1872,7 @@ static void freed_request(request_queue_t *q, int rw)
/*
* Get a free request, queue_lock must not be held
*/
-static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
- int gfp_mask)
+static struct request *get_request(request_queue_t *q, int rw, int gfp_mask)
{
struct request *rq = NULL;
struct request_list *rl = &q->rq;
@@ -1893,7 +1895,7 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
}
}
- switch (elv_may_queue(q, rw, bio)) {
+ switch (elv_may_queue(q, rw)) {
case ELV_MQUEUE_NO:
goto rq_starved;
case ELV_MQUEUE_MAY:
@@ -1918,7 +1920,7 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
set_queue_congested(q, rw);
spin_unlock_irq(q->queue_lock);
- rq = blk_alloc_request(q, rw, bio, gfp_mask);
+ rq = blk_alloc_request(q, rw, gfp_mask);
if (!rq) {
/*
* Allocation failed presumably due to memory. Undo anything
@@ -1959,8 +1961,7 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
* No available requests for this queue, unplug the device and wait for some
* requests to become available.
*/
-static struct request *get_request_wait(request_queue_t *q, int rw,
- struct bio *bio)
+static struct request *get_request_wait(request_queue_t *q, int rw)
{
DEFINE_WAIT(wait);
struct request *rq;
@@ -1971,7 +1972,7 @@ static struct request *get_request_wait(request_queue_t *q, int rw,
prepare_to_wait_exclusive(&rl->wait[rw], &wait,
TASK_UNINTERRUPTIBLE);
- rq = get_request(q, rw, bio, GFP_NOIO);
+ rq = get_request(q, rw, GFP_NOIO);
if (!rq) {
struct io_context *ioc;
@@ -2002,9 +2003,9 @@ struct request *blk_get_request(request_queue_t *q, int rw, int gfp_mask)
BUG_ON(rw != READ && rw != WRITE);
if (gfp_mask & __GFP_WAIT)
- rq = get_request_wait(q, rw, NULL);
+ rq = get_request_wait(q, rw);
else
- rq = get_request(q, rw, NULL, gfp_mask);
+ rq = get_request(q, rw, gfp_mask);
return rq;
}
@@ -2332,6 +2333,7 @@ static void __blk_put_request(request_queue_t *q, struct request *req)
return;
req->rq_status = RQ_INACTIVE;
+ req->q = NULL;
req->rl = NULL;
/*
@@ -2460,8 +2462,6 @@ static int attempt_merge(request_queue_t *q, struct request *req,
req->rq_disk->in_flight--;
}
- req->ioprio = ioprio_best(req->ioprio, next->ioprio);
-
__blk_put_request(q, next);
return 1;
}
@@ -2514,13 +2514,11 @@ static int __make_request(request_queue_t *q, struct bio *bio)
{
struct request *req, *freereq = NULL;
int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err, sync;
- unsigned short prio;
sector_t sector;
sector = bio->bi_sector;
nr_sectors = bio_sectors(bio);
cur_nr_sectors = bio_cur_sectors(bio);
- prio = bio_prio(bio);
rw = bio_data_dir(bio);
sync = bio_sync(bio);
@@ -2561,7 +2559,6 @@ static int __make_request(request_queue_t *q, struct bio *bio)
req->biotail->bi_next = bio;
req->biotail = bio;
req->nr_sectors = req->hard_nr_sectors += nr_sectors;
- req->ioprio = ioprio_best(req->ioprio, prio);
drive_stat_acct(req, nr_sectors, 0);
if (!attempt_back_merge(q, req))
elv_merged_request(q, req);
@@ -2586,7 +2583,6 @@ static int __make_request(request_queue_t *q, struct bio *bio)
req->hard_cur_sectors = cur_nr_sectors;
req->sector = req->hard_sector = sector;
req->nr_sectors = req->hard_nr_sectors += nr_sectors;
- req->ioprio = ioprio_best(req->ioprio, prio);
drive_stat_acct(req, nr_sectors, 0);
if (!attempt_front_merge(q, req))
elv_merged_request(q, req);
@@ -2614,7 +2610,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
freereq = NULL;
} else {
spin_unlock_irq(q->queue_lock);
- if ((freereq = get_request(q, rw, bio, GFP_ATOMIC)) == NULL) {
+ if ((freereq = get_request(q, rw, GFP_ATOMIC)) == NULL) {
/*
* READA bit set
*/
@@ -2622,7 +2618,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
if (bio_rw_ahead(bio))
goto end_io;
- freereq = get_request_wait(q, rw, bio);
+ freereq = get_request_wait(q, rw);
}
goto again;
}
@@ -2650,7 +2646,6 @@ static int __make_request(request_queue_t *q, struct bio *bio)
req->buffer = bio_data(bio); /* see ->buffer comment above */
req->waiting = NULL;
req->bio = req->biotail = bio;
- req->ioprio = prio;
req->rq_disk = bio->bi_bdev->bd_disk;
req->start_time = jiffies;
@@ -2679,7 +2674,7 @@ static inline void blk_partition_remap(struct bio *bio)
if (bdev != bdev->bd_contains) {
struct hd_struct *p = bdev->bd_part;
- switch (bio_data_dir(bio)) {
+ switch (bio->bi_rw) {
case READ:
p->read_sectors += bio_sectors(bio);
p->reads++;
@@ -2698,7 +2693,6 @@ void blk_finish_queue_drain(request_queue_t *q)
{
struct request_list *rl = &q->rq;
struct request *rq;
- int requeued = 0;
spin_lock_irq(q->queue_lock);
clear_bit(QUEUE_FLAG_DRAIN, &q->queue_flags);
@@ -2707,13 +2701,9 @@ void blk_finish_queue_drain(request_queue_t *q)
rq = list_entry_rq(q->drain_list.next);
list_del_init(&rq->queuelist);
- elv_requeue_request(q, rq);
- requeued++;
+ __elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
}
- if (requeued)
- q->request_fn(q);
-
spin_unlock_irq(q->queue_lock);
wake_up(&rl->wait[0]);
@@ -2910,7 +2900,7 @@ void submit_bio(int rw, struct bio *bio)
BIO_BUG_ON(!bio->bi_size);
BIO_BUG_ON(!bio->bi_io_vec);
- bio->bi_rw |= rw;
+ bio->bi_rw = rw;
if (rw & WRITE)
mod_page_state(pgpgout, count);
else
@@ -3267,11 +3257,8 @@ void exit_io_context(void)
struct io_context *ioc;
local_irq_save(flags);
- task_lock(current);
ioc = current->io_context;
current->io_context = NULL;
- ioc->task = NULL;
- task_unlock(current);
local_irq_restore(flags);
if (ioc->aic && ioc->aic->exit)
@@ -3306,12 +3293,12 @@ struct io_context *get_io_context(int gfp_flags)
ret = kmem_cache_alloc(iocontext_cachep, gfp_flags);
if (ret) {
atomic_set(&ret->refcount, 1);
- ret->task = current;
- ret->set_ioprio = NULL;
+ ret->pid = tsk->pid;
ret->last_waited = jiffies; /* doesn't matter... */
ret->nr_batch_requests = 0; /* because this is 0 */
ret->aic = NULL;
ret->cic = NULL;
+ spin_lock_init(&ret->lock);
local_irq_save(flags);
diff --git a/trunk/drivers/block/swim3.c b/trunk/drivers/block/swim3.c
index e5f7494c00ee..5b09cf154ac7 100644
--- a/trunk/drivers/block/swim3.c
+++ b/trunk/drivers/block/swim3.c
@@ -253,7 +253,7 @@ static int floppy_revalidate(struct gendisk *disk);
static int swim3_add_device(struct device_node *swims);
int swim3_init(void);
-#ifndef CONFIG_PMAC_MEDIABAY
+#ifndef CONFIG_PMAC_PBOOK
#define check_media_bay(which, what) 1
#endif
@@ -297,11 +297,9 @@ static void do_fd_request(request_queue_t * q)
int i;
for(i=0;imedia_bay && check_media_bay(fs->media_bay, MB_FD))
return -ENXIO;
-#endif
switch (cmd) {
case FDEJECT:
@@ -885,10 +881,8 @@ static int floppy_open(struct inode *inode, struct file *filp)
int n, err = 0;
if (fs->ref_count == 0) {
-#ifdef CONFIG_PMAC_MEDIABAY
if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
return -ENXIO;
-#endif
out_8(&sw->setup, S_IBM_DRIVE | S_FCLK_DIV2);
out_8(&sw->control_bic, 0xff);
out_8(&sw->mode, 0x95);
@@ -973,10 +967,8 @@ static int floppy_revalidate(struct gendisk *disk)
struct swim3 __iomem *sw;
int ret, n;
-#ifdef CONFIG_PMAC_MEDIABAY
if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD))
return -ENXIO;
-#endif
sw = fs->swim3;
grab_drive(fs, revalidating, 0);
diff --git a/trunk/drivers/block/sx8.c b/trunk/drivers/block/sx8.c
index 9db0a9e3e59c..5ed3a6379452 100644
--- a/trunk/drivers/block/sx8.c
+++ b/trunk/drivers/block/sx8.c
@@ -26,7 +26,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -1583,9 +1582,9 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out;
#if IF_64BIT_DMA_IS_POSSIBLE /* grrrr... */
- rc = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+ rc = pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
if (!rc) {
- rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+ rc = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
if (rc) {
printk(KERN_ERR DRV_NAME "(%s): consistent DMA mask failure\n",
pci_name(pdev));
@@ -1594,7 +1593,7 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
pci_dac = 1;
} else {
#endif
- rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ rc = pci_set_dma_mask(pdev, 0xffffffffULL);
if (rc) {
printk(KERN_ERR DRV_NAME "(%s): DMA mask failure\n",
pci_name(pdev));
diff --git a/trunk/drivers/bluetooth/bluecard_cs.c b/trunk/drivers/bluetooth/bluecard_cs.c
index 5ef9adb9fe73..e481cc411b5d 100644
--- a/trunk/drivers/bluetooth/bluecard_cs.c
+++ b/trunk/drivers/bluetooth/bluecard_cs.c
@@ -1089,14 +1089,6 @@ static int bluecard_event(event_t event, int priority, event_callback_args_t *ar
return 0;
}
-static struct pcmcia_device_id bluecard_ids[] = {
- PCMCIA_DEVICE_PROD_ID12("BlueCard", "LSE041", 0xbaf16fbf, 0x657cc15e),
- PCMCIA_DEVICE_PROD_ID12("BTCFCARD", "LSE139", 0xe3987764, 0x2524b59c),
- PCMCIA_DEVICE_PROD_ID12("WSS", "LSE039", 0x0a0736ec, 0x24e6dfab),
- PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, bluecard_ids);
-
static struct pcmcia_driver bluecard_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -1104,7 +1096,6 @@ static struct pcmcia_driver bluecard_driver = {
},
.attach = bluecard_attach,
.detach = bluecard_detach,
- .id_table = bluecard_ids,
};
static int __init init_bluecard_cs(void)
diff --git a/trunk/drivers/bluetooth/bt3c_cs.c b/trunk/drivers/bluetooth/bt3c_cs.c
index 9013cd759afb..f71e5c76963d 100644
--- a/trunk/drivers/bluetooth/bt3c_cs.c
+++ b/trunk/drivers/bluetooth/bt3c_cs.c
@@ -935,12 +935,6 @@ static int bt3c_event(event_t event, int priority, event_callback_args_t *args)
return 0;
}
-static struct pcmcia_device_id bt3c_ids[] = {
- PCMCIA_DEVICE_PROD_ID13("3COM", "Bluetooth PC Card", 0xefce0a31, 0xd4ce9b02),
- PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, bt3c_ids);
-
static struct pcmcia_driver bt3c_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -948,7 +942,6 @@ static struct pcmcia_driver bt3c_driver = {
},
.attach = bt3c_attach,
.detach = bt3c_detach,
- .id_table = bt3c_ids,
};
static int __init init_bt3c_cs(void)
diff --git a/trunk/drivers/bluetooth/btuart_cs.c b/trunk/drivers/bluetooth/btuart_cs.c
index c479484a1f7f..ad8d972444a5 100644
--- a/trunk/drivers/bluetooth/btuart_cs.c
+++ b/trunk/drivers/bluetooth/btuart_cs.c
@@ -855,12 +855,6 @@ static int btuart_event(event_t event, int priority, event_callback_args_t *args
return 0;
}
-static struct pcmcia_device_id btuart_ids[] = {
- /* don't use this driver. Use serial_cs + hci_uart instead */
- PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, btuart_ids);
-
static struct pcmcia_driver btuart_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -868,7 +862,6 @@ static struct pcmcia_driver btuart_driver = {
},
.attach = btuart_attach,
.detach = btuart_detach,
- .id_table = btuart_ids,
};
static int __init init_btuart_cs(void)
diff --git a/trunk/drivers/bluetooth/dtl1_cs.c b/trunk/drivers/bluetooth/dtl1_cs.c
index bb12f7daeb91..fe954e5d9a1d 100644
--- a/trunk/drivers/bluetooth/dtl1_cs.c
+++ b/trunk/drivers/bluetooth/dtl1_cs.c
@@ -807,13 +807,6 @@ static int dtl1_event(event_t event, int priority, event_callback_args_t *args)
return 0;
}
-static struct pcmcia_device_id dtl1_ids[] = {
- PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d),
- PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863),
- PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, dtl1_ids);
-
static struct pcmcia_driver dtl1_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -821,7 +814,6 @@ static struct pcmcia_driver dtl1_driver = {
},
.attach = dtl1_attach,
.detach = dtl1_detach,
- .id_table = dtl1_ids,
};
static int __init init_dtl1_cs(void)
diff --git a/trunk/drivers/char/misc.c b/trunk/drivers/char/misc.c
index 931efd58f87a..31cf84d69026 100644
--- a/trunk/drivers/char/misc.c
+++ b/trunk/drivers/char/misc.c
@@ -308,6 +308,9 @@ static int __init misc_init(void)
#endif
#ifdef CONFIG_BVME6000
rtc_DP8570A_init();
+#endif
+#ifdef CONFIG_PMAC_PBOOK
+ pmu_device_init();
#endif
if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
printk("unable to get major %d for misc devices\n",
diff --git a/trunk/drivers/char/pcmcia/synclink_cs.c b/trunk/drivers/char/pcmcia/synclink_cs.c
index 8f36b1758eb6..1c8d866a49dc 100644
--- a/trunk/drivers/char/pcmcia/synclink_cs.c
+++ b/trunk/drivers/char/pcmcia/synclink_cs.c
@@ -581,7 +581,7 @@ static dev_link_t *mgslpc_attach(void)
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
link->irq.Handler = NULL;
link->conf.Attributes = 0;
@@ -3081,12 +3081,6 @@ void mgslpc_remove_device(MGSLPC_INFO *remove_info)
}
}
-static struct pcmcia_device_id mgslpc_ids[] = {
- PCMCIA_DEVICE_MANF_CARD(0x02c5, 0x0050),
- PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, mgslpc_ids);
-
static struct pcmcia_driver mgslpc_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -3094,7 +3088,6 @@ static struct pcmcia_driver mgslpc_driver = {
},
.attach = mgslpc_attach,
.detach = mgslpc_detach,
- .id_table = mgslpc_ids,
};
static struct tty_operations mgslpc_ops = {
diff --git a/trunk/drivers/ide/Kconfig b/trunk/drivers/ide/Kconfig
index 5f33df47aa74..0273f124a4f7 100644
--- a/trunk/drivers/ide/Kconfig
+++ b/trunk/drivers/ide/Kconfig
@@ -606,12 +606,6 @@ config BLK_DEV_IT8172
; picture of the
board at .
-config BLK_DEV_IT821X
- tristate "IT821X IDE support"
- help
- This driver adds support for the ITE 8211 IDE controller and the
- IT 8212 IDE RAID controller in both RAID and pass-through mode.
-
config BLK_DEV_NS87415
tristate "NS87415 chipset support"
help
diff --git a/trunk/drivers/ide/ide-disk.c b/trunk/drivers/ide/ide-disk.c
index f9c1acb4ed6a..d6f934886b04 100644
--- a/trunk/drivers/ide/ide-disk.c
+++ b/trunk/drivers/ide/ide-disk.c
@@ -119,10 +119,6 @@ static int lba_capacity_is_ok (struct hd_driveid *id)
{
unsigned long lba_sects, chs_sects, head, tail;
- /* No non-LBA info .. so valid! */
- if (id->cyls == 0)
- return 1;
-
/*
* The ATA spec tells large drives to return
* C/H/S = 16383/16/63 independent of their size.
diff --git a/trunk/drivers/ide/ide-dma.c b/trunk/drivers/ide/ide-dma.c
index 1e1531334c25..2d2eefb610dd 100644
--- a/trunk/drivers/ide/ide-dma.c
+++ b/trunk/drivers/ide/ide-dma.c
@@ -132,6 +132,7 @@ static const struct drive_list_entry drive_blacklist [] = {
{ "SAMSUNG CD-ROM SC-148C", "ALL" },
{ "SAMSUNG CD-ROM SC", "ALL" },
{ "SanDisk SDP3B-64" , "ALL" },
+ { "SAMSUNG CD-ROM SN-124", "ALL" },
{ "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" },
{ "_NEC DV5800A", "ALL" },
{ NULL , NULL }
diff --git a/trunk/drivers/ide/ide-iops.c b/trunk/drivers/ide/ide-iops.c
index b443b04a4c5a..53024942a7eb 100644
--- a/trunk/drivers/ide/ide-iops.c
+++ b/trunk/drivers/ide/ide-iops.c
@@ -1181,8 +1181,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
pre_reset(drive);
SELECT_DRIVE(drive);
udelay (20);
- hwif->OUTBSYNC(drive, WIN_SRST, IDE_COMMAND_REG);
- ndelay(400);
+ hwif->OUTB(WIN_SRST, IDE_COMMAND_REG);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
hwgroup->polling = 1;
__ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
diff --git a/trunk/drivers/ide/legacy/ide-cs.c b/trunk/drivers/ide/legacy/ide-cs.c
index 978d27d6452d..e20327e54b1a 100644
--- a/trunk/drivers/ide/legacy/ide-cs.c
+++ b/trunk/drivers/ide/legacy/ide-cs.c
@@ -457,40 +457,6 @@ int ide_event(event_t event, int priority,
return 0;
} /* ide_event */
-static struct pcmcia_device_id ide_ids[] = {
- PCMCIA_DEVICE_FUNC_ID(4),
- PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
- PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
- PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
- PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),
- PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
- PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
- PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
- PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
- PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
- PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
- PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
- PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
- PCMCIA_DEVICE_PROD_ID12("EXP", "CD", 0x6f58c983, 0xaae5994f),
- PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591),
- PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
- PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
- PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
- PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b),
- PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
- PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
- PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2 ", 0xe37be2b5, 0x8671043b),
- PCMCIA_DEVICE_PROD_ID12(" ", "NinjaATA-", 0x3b6e20c8, 0xebe0bd79),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
- PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
- PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
- PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
- PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
- PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, ide_ids);
-
static struct pcmcia_driver ide_cs_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -498,7 +464,6 @@ static struct pcmcia_driver ide_cs_driver = {
},
.attach = ide_attach,
.detach = ide_detach,
- .id_table = ide_ids,
};
static int __init init_ide_cs(void)
diff --git a/trunk/drivers/ide/pci/Makefile b/trunk/drivers/ide/pci/Makefile
index af46226c1796..55e6e553e497 100644
--- a/trunk/drivers/ide/pci/Makefile
+++ b/trunk/drivers/ide/pci/Makefile
@@ -12,7 +12,6 @@ obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o
obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o
#obj-$(CONFIG_BLK_DEV_HPT37X) += hpt37x.o
obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o
-obj-$(CONFIG_BLK_DEV_IT821X) += it821x.o
obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o
obj-$(CONFIG_BLK_DEV_OPTI621) += opti621.o
obj-$(CONFIG_BLK_DEV_PDC202XX_OLD) += pdc202xx_old.o
diff --git a/trunk/drivers/ide/pci/generic.c b/trunk/drivers/ide/pci/generic.c
index da46577380f3..4565cc311ff3 100644
--- a/trunk/drivers/ide/pci/generic.c
+++ b/trunk/drivers/ide/pci/generic.c
@@ -39,17 +39,6 @@
#include
-static int ide_generic_all; /* Set to claim all devices */
-
-static int __init ide_generic_all_on(char *unused)
-{
- ide_generic_all = 1;
- printk(KERN_INFO "IDE generic will claim all unknown PCI IDE storage controllers.\n");
- return 1;
-}
-
-__setup("all-generic-ide", ide_generic_all_on);
-
static void __devinit init_hwif_generic (ide_hwif_t *hwif)
{
switch(hwif->pci_dev->device) {
@@ -89,85 +78,79 @@ static void __devinit init_hwif_generic (ide_hwif_t *hwif)
static ide_pci_device_t generic_chipsets[] __devinitdata = {
{ /* 0 */
- .name = "Unknown",
- .init_hwif = init_hwif_generic,
- .channels = 2,
- .autodma = AUTODMA,
- .bootable = ON_BOARD,
- },{ /* 1 */
.name = "NS87410",
.init_hwif = init_hwif_generic,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x43,0x08,0x08}, {0x47,0x08,0x08}},
.bootable = ON_BOARD,
- },{ /* 2 */
+ },{ /* 1 */
.name = "SAMURAI",
.init_hwif = init_hwif_generic,
.channels = 2,
.autodma = AUTODMA,
.bootable = ON_BOARD,
- },{ /* 3 */
+ },{ /* 2 */
.name = "HT6565",
.init_hwif = init_hwif_generic,
.channels = 2,
.autodma = AUTODMA,
.bootable = ON_BOARD,
- },{ /* 4 */
+ },{ /* 3 */
.name = "UM8673F",
.init_hwif = init_hwif_generic,
.channels = 2,
.autodma = NODMA,
.bootable = ON_BOARD,
- },{ /* 5 */
+ },{ /* 4 */
.name = "UM8886A",
.init_hwif = init_hwif_generic,
.channels = 2,
.autodma = NODMA,
.bootable = ON_BOARD,
- },{ /* 6 */
+ },{ /* 5 */
.name = "UM8886BF",
.init_hwif = init_hwif_generic,
.channels = 2,
.autodma = NODMA,
.bootable = ON_BOARD,
- },{ /* 7 */
+ },{ /* 6 */
.name = "HINT_IDE",
.init_hwif = init_hwif_generic,
.channels = 2,
.autodma = AUTODMA,
.bootable = ON_BOARD,
- },{ /* 8 */
+ },{ /* 7 */
.name = "VIA_IDE",
.init_hwif = init_hwif_generic,
.channels = 2,
.autodma = NOAUTODMA,
.bootable = ON_BOARD,
- },{ /* 9 */
+ },{ /* 8 */
.name = "OPTI621V",
.init_hwif = init_hwif_generic,
.channels = 2,
.autodma = NOAUTODMA,
.bootable = ON_BOARD,
- },{ /* 10 */
+ },{ /* 9 */
.name = "VIA8237SATA",
.init_hwif = init_hwif_generic,
.channels = 2,
.autodma = AUTODMA,
.bootable = OFF_BOARD,
- },{ /* 11 */
+ },{ /* 10 */
.name = "Piccolo0102",
.init_hwif = init_hwif_generic,
.channels = 2,
.autodma = NOAUTODMA,
.bootable = ON_BOARD,
- },{ /* 12 */
+ },{ /* 11 */
.name = "Piccolo0103",
.init_hwif = init_hwif_generic,
.channels = 2,
.autodma = NOAUTODMA,
.bootable = ON_BOARD,
- },{ /* 13 */
+ },{ /* 12 */
.name = "Piccolo0105",
.init_hwif = init_hwif_generic,
.channels = 2,
@@ -191,10 +174,6 @@ static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_devi
u16 command;
int ret = -ENODEV;
- /* Don't use the generic entry unless instructed to do so */
- if (id->driver_data == 0 && ide_generic_all == 0)
- goto out;
-
if (dev->vendor == PCI_VENDOR_ID_UMC &&
dev->device == PCI_DEVICE_ID_UMC_UM8886A &&
(!(PCI_FUNC(dev->devfn) & 1)))
@@ -216,23 +195,21 @@ static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_devi
}
static struct pci_device_id generic_pci_tbl[] = {
- { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
- { PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
- { PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
- { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
- { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
- { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6},
- { PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7},
- { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8},
- { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9},
+ { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+ { PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+ { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
+ { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
+ { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
+ { PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6},
+ { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7},
+ { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8},
#ifdef CONFIG_BLK_DEV_IDE_SATA
- { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10},
+ { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9},
#endif
- { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11},
- { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12},
- { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13},
- /* Must come last. If you add entries adjust this table appropriately and the init_one code */
- { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0},
+ { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10},
+ { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11},
+ { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12},
{ 0, },
};
MODULE_DEVICE_TABLE(pci, generic_pci_tbl);
diff --git a/trunk/drivers/ide/pci/hpt366.c b/trunk/drivers/ide/pci/hpt366.c
index 7b64db10d1b0..c8ee0b8c0292 100644
--- a/trunk/drivers/ide/pci/hpt366.c
+++ b/trunk/drivers/ide/pci/hpt366.c
@@ -10,11 +10,6 @@
* donation of an ABit BP6 mainboard, processor, and memory acellerated
* development and support.
*
- *
- * Highpoint have their own driver (source except for the raid part)
- * available from http://www.highpoint-tech.com/hpt3xx-opensource-v131.tgz
- * This may be useful to anyone wanting to work on the mainstream hpt IDE.
- *
* Note that final HPT370 support was done by force extraction of GPL.
*
* - add function for getting/setting power status of drive
@@ -451,29 +446,44 @@ static struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = {
#define F_LOW_PCI_50 0x2d
#define F_LOW_PCI_66 0x42
-/*
- * Hold all the highpoint quirks and revision information in one
- * place.
- */
-
-struct hpt_info
-{
- u8 max_mode; /* Speeds allowed */
- int revision; /* Chipset revision */
- int flags; /* Chipset properties */
-#define PLL_MODE 1
-#define IS_372N 2
- /* Speed table */
- struct chipset_bus_clock_list_entry *speed;
-};
-
-/*
- * This wants fixing so that we do everything not by classrev
- * (which breaks on the newest chips) but by creating an
- * enumeration of chip variants and using that
- */
+/* FIXME: compare with driver's code before removing */
+#if 0
+ if (hpt_minimum_revision(dev, 3)) {
+ u8 cbl;
+ cbl = inb(iobase + 0x7b);
+ outb(cbl | 1, iobase + 0x7b);
+ outb(cbl & ~1, iobase + 0x7b);
+ cbl = inb(iobase + 0x7a);
+ p += sprintf(p, "Cable: ATA-%d"
+ " ATA-%d\n",
+ (cbl & 0x02) ? 33 : 66,
+ (cbl & 0x01) ? 33 : 66);
+ p += sprintf(p, "\n");
+ }
+ {
+ u8 c2, c3;
+ /* older revs don't have these registers mapped
+ * into io space */
+ pci_read_config_byte(dev, 0x43, &c0);
+ pci_read_config_byte(dev, 0x47, &c1);
+ pci_read_config_byte(dev, 0x4b, &c2);
+ pci_read_config_byte(dev, 0x4f, &c3);
+
+ p += sprintf(p, "Mode: %s %s"
+ " %s %s\n",
+ (c0 & 0x10) ? "UDMA" : (c0 & 0x20) ? "DMA " :
+ (c0 & 0x80) ? "PIO " : "off ",
+ (c1 & 0x10) ? "UDMA" : (c1 & 0x20) ? "DMA " :
+ (c1 & 0x80) ? "PIO " : "off ",
+ (c2 & 0x10) ? "UDMA" : (c2 & 0x20) ? "DMA " :
+ (c2 & 0x80) ? "PIO " : "off ",
+ (c3 & 0x10) ? "UDMA" : (c3 & 0x20) ? "DMA " :
+ (c3 & 0x80) ? "PIO " : "off ");
+ }
+ }
+#endif
-static __devinit u32 hpt_revision (struct pci_dev *dev)
+static u32 hpt_revision (struct pci_dev *dev)
{
u32 class_rev;
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
@@ -497,33 +507,37 @@ static __devinit u32 hpt_revision (struct pci_dev *dev)
return class_rev;
}
+static u32 hpt_minimum_revision (struct pci_dev *dev, int revision)
+{
+ unsigned int class_rev = hpt_revision(dev);
+ revision--;
+ return ((int) (class_rev > revision) ? 1 : 0);
+}
+
static int check_in_drive_lists(ide_drive_t *drive, const char **list);
static u8 hpt3xx_ratemask (ide_drive_t *drive)
{
- ide_hwif_t *hwif = drive->hwif;
- struct hpt_info *info = ide_get_hwifdata(hwif);
+ struct pci_dev *dev = HWIF(drive)->pci_dev;
u8 mode = 0;
- /* FIXME: TODO - move this to set info->mode once at boot */
-
- if (info->revision >= 8) { /* HPT374 */
+ if (hpt_minimum_revision(dev, 8)) { /* HPT374 */
mode = (HPT374_ALLOW_ATA133_6) ? 4 : 3;
- } else if (info->revision >= 7) { /* HPT371 */
+ } else if (hpt_minimum_revision(dev, 7)) { /* HPT371 */
mode = (HPT371_ALLOW_ATA133_6) ? 4 : 3;
- } else if (info->revision >= 6) { /* HPT302 */
+ } else if (hpt_minimum_revision(dev, 6)) { /* HPT302 */
mode = (HPT302_ALLOW_ATA133_6) ? 4 : 3;
- } else if (info->revision >= 5) { /* HPT372 */
+ } else if (hpt_minimum_revision(dev, 5)) { /* HPT372 */
mode = (HPT372_ALLOW_ATA133_6) ? 4 : 3;
- } else if (info->revision >= 4) { /* HPT370A */
+ } else if (hpt_minimum_revision(dev, 4)) { /* HPT370A */
mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2;
- } else if (info->revision >= 3) { /* HPT370 */
+ } else if (hpt_minimum_revision(dev, 3)) { /* HPT370 */
mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2;
mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : mode;
} else { /* HPT366 and HPT368 */
mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : 2;
}
- if (!eighty_ninty_three(drive) && mode)
+ if (!eighty_ninty_three(drive) && (mode))
mode = min(mode, (u8)1);
return mode;
}
@@ -535,8 +549,7 @@ static u8 hpt3xx_ratemask (ide_drive_t *drive)
static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed)
{
- ide_hwif_t *hwif = drive->hwif;
- struct hpt_info *info = ide_get_hwifdata(hwif);
+ struct pci_dev *dev = HWIF(drive)->pci_dev;
u8 mode = hpt3xx_ratemask(drive);
if (drive->media != ide_disk)
@@ -548,7 +561,7 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed)
break;
case 0x03:
speed = min(speed, (u8)XFER_UDMA_5);
- if (info->revision >= 5)
+ if (hpt_minimum_revision(dev, 5))
break;
if (check_in_drive_lists(drive, bad_ata100_5))
speed = min(speed, (u8)XFER_UDMA_4);
@@ -558,7 +571,7 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed)
/*
* CHECK ME, Does this need to be set to 5 ??
*/
- if (info->revision >= 3)
+ if (hpt_minimum_revision(dev, 3))
break;
if ((check_in_drive_lists(drive, bad_ata66_4)) ||
(!(HPT366_ALLOW_ATA66_4)))
@@ -572,7 +585,7 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed)
/*
* CHECK ME, Does this need to be set to 5 ??
*/
- if (info->revision >= 3)
+ if (hpt_minimum_revision(dev, 3))
break;
if (check_in_drive_lists(drive, bad_ata33))
speed = min(speed, (u8)XFER_MW_DMA_2);
@@ -611,12 +624,11 @@ static unsigned int pci_bus_clock_list (u8 speed, struct chipset_bus_clock_list_
static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
{
- ide_hwif_t *hwif = drive->hwif;
- struct pci_dev *dev = hwif->pci_dev;
- struct hpt_info *info = ide_get_hwifdata(hwif);
+ struct pci_dev *dev = HWIF(drive)->pci_dev;
u8 speed = hpt3xx_ratefilter(drive, xferspeed);
+// u8 speed = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed);
u8 regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40;
- u8 regfast = (hwif->channel) ? 0x55 : 0x51;
+ u8 regfast = (HWIF(drive)->channel) ? 0x55 : 0x51;
u8 drive_fast = 0;
u32 reg1 = 0, reg2 = 0;
@@ -624,11 +636,16 @@ static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
* Disable the "fast interrupt" prediction.
*/
pci_read_config_byte(dev, regfast, &drive_fast);
+#if 0
+ if (drive_fast & 0x02)
+ pci_write_config_byte(dev, regfast, drive_fast & ~0x20);
+#else
if (drive_fast & 0x80)
pci_write_config_byte(dev, regfast, drive_fast & ~0x80);
+#endif
- reg2 = pci_bus_clock_list(speed, info->speed);
-
+ reg2 = pci_bus_clock_list(speed,
+ (struct chipset_bus_clock_list_entry *) pci_get_drvdata(dev));
/*
* Disable on-chip PIO FIFO/buffer
* (to avoid problems handling I/O errors later)
@@ -648,11 +665,10 @@ static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed)
{
- ide_hwif_t *hwif = drive->hwif;
- struct pci_dev *dev = hwif->pci_dev;
- struct hpt_info *info = ide_get_hwifdata(hwif);
+ struct pci_dev *dev = HWIF(drive)->pci_dev;
u8 speed = hpt3xx_ratefilter(drive, xferspeed);
- u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51;
+// u8 speed = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed);
+ u8 regfast = (HWIF(drive)->channel) ? 0x55 : 0x51;
u8 drive_pci = 0x40 + (drive->dn * 4);
u8 new_fast = 0, drive_fast = 0;
u32 list_conf = 0, drive_conf = 0;
@@ -677,13 +693,17 @@ static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed)
if (new_fast != drive_fast)
pci_write_config_byte(dev, regfast, new_fast);
- list_conf = pci_bus_clock_list(speed, info->speed);
+ list_conf = pci_bus_clock_list(speed,
+ (struct chipset_bus_clock_list_entry *)
+ pci_get_drvdata(dev));
pci_read_config_dword(dev, drive_pci, &drive_conf);
list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask);
- if (speed < XFER_MW_DMA_0)
+ if (speed < XFER_MW_DMA_0) {
list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
+ }
+
pci_write_config_dword(dev, drive_pci, list_conf);
return ide_config_drive_speed(drive, speed);
@@ -691,11 +711,10 @@ static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed)
static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed)
{
- ide_hwif_t *hwif = drive->hwif;
- struct pci_dev *dev = hwif->pci_dev;
- struct hpt_info *info = ide_get_hwifdata(hwif);
+ struct pci_dev *dev = HWIF(drive)->pci_dev;
u8 speed = hpt3xx_ratefilter(drive, xferspeed);
- u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51;
+// u8 speed = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed);
+ u8 regfast = (HWIF(drive)->channel) ? 0x55 : 0x51;
u8 drive_fast = 0, drive_pci = 0x40 + (drive->dn * 4);
u32 list_conf = 0, drive_conf = 0;
u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000;
@@ -707,8 +726,10 @@ static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed)
pci_read_config_byte(dev, regfast, &drive_fast);
drive_fast &= ~0x07;
pci_write_config_byte(dev, regfast, drive_fast);
-
- list_conf = pci_bus_clock_list(speed, info->speed);
+
+ list_conf = pci_bus_clock_list(speed,
+ (struct chipset_bus_clock_list_entry *)
+ pci_get_drvdata(dev));
pci_read_config_dword(dev, drive_pci, &drive_conf);
list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask);
if (speed < XFER_MW_DMA_0)
@@ -720,14 +741,19 @@ static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed)
static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed)
{
- ide_hwif_t *hwif = drive->hwif;
- struct hpt_info *info = ide_get_hwifdata(hwif);
+ struct pci_dev *dev = HWIF(drive)->pci_dev;
- if (info->revision >= 8)
+ if (hpt_minimum_revision(dev, 8))
return hpt372_tune_chipset(drive, speed); /* not a typo */
- else if (info->revision >= 5)
+#if 0
+ else if (hpt_minimum_revision(dev, 7))
+ hpt371_tune_chipset(drive, speed);
+ else if (hpt_minimum_revision(dev, 6))
+ hpt302_tune_chipset(drive, speed);
+#endif
+ else if (hpt_minimum_revision(dev, 5))
return hpt372_tune_chipset(drive, speed);
- else if (info->revision >= 3)
+ else if (hpt_minimum_revision(dev, 3))
return hpt370_tune_chipset(drive, speed);
else /* hpt368: hpt_minimum_revision(dev, 2) */
return hpt36x_tune_chipset(drive, speed);
@@ -753,14 +779,8 @@ static void hpt3xx_tune_drive (ide_drive_t *drive, u8 pio)
static int config_chipset_for_dma (ide_drive_t *drive)
{
u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive));
- ide_hwif_t *hwif = drive->hwif;
- struct hpt_info *info = ide_get_hwifdata(hwif);
- if (!speed)
- return 0;
-
- /* If we don't have any timings we can't do a lot */
- if (info->speed == NULL)
+ if (!(speed))
return 0;
(void) hpt3xx_tune_chipset(drive, speed);
@@ -774,7 +794,7 @@ static int hpt3xx_quirkproc (ide_drive_t *drive)
static void hpt3xx_intrproc (ide_drive_t *drive)
{
- ide_hwif_t *hwif = drive->hwif;
+ ide_hwif_t *hwif = HWIF(drive);
if (drive->quirk_list)
return;
@@ -784,26 +804,24 @@ static void hpt3xx_intrproc (ide_drive_t *drive)
static void hpt3xx_maskproc (ide_drive_t *drive, int mask)
{
- ide_hwif_t *hwif = drive->hwif;
- struct hpt_info *info = ide_get_hwifdata(hwif);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = HWIF(drive)->pci_dev;
if (drive->quirk_list) {
- if (info->revision >= 3) {
+ if (hpt_minimum_revision(dev,3)) {
u8 reg5a = 0;
pci_read_config_byte(dev, 0x5a, ®5a);
if (((reg5a & 0x10) >> 4) != mask)
pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10));
} else {
if (mask) {
- disable_irq(hwif->irq);
+ disable_irq(HWIF(drive)->irq);
} else {
- enable_irq(hwif->irq);
+ enable_irq(HWIF(drive)->irq);
}
}
} else {
if (IDE_CONTROL_REG)
- hwif->OUTB(mask ? (drive->ctl | 2) :
+ HWIF(drive)->OUTB(mask ? (drive->ctl | 2) :
(drive->ctl & ~2),
IDE_CONTROL_REG);
}
@@ -811,12 +829,12 @@ static void hpt3xx_maskproc (ide_drive_t *drive, int mask)
static int hpt366_config_drive_xfer_rate (ide_drive_t *drive)
{
- ide_hwif_t *hwif = drive->hwif;
+ ide_hwif_t *hwif = HWIF(drive);
struct hd_driveid *id = drive->id;
drive->init_speed = 0;
- if ((id->capability & 1) && drive->autodma) {
+ if (id && (id->capability & 1) && drive->autodma) {
if (ide_use_dma(drive)) {
if (config_chipset_for_dma(drive))
@@ -850,6 +868,15 @@ static int hpt366_ide_dma_lostirq (ide_drive_t *drive)
drive->name, __FUNCTION__, reg50h, reg52h, reg5ah);
if (reg5ah & 0x10)
pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10);
+#if 0
+ /* how about we flush and reset, mmmkay? */
+ pci_write_config_byte(dev, 0x51, 0x1F);
+ /* fall through to a reset */
+ case dma_start:
+ case ide_dma_end:
+ /* reset the chips state over and over.. */
+ pci_write_config_byte(dev, 0x51, 0x13);
+#endif
return __ide_dma_lostirq(drive);
}
@@ -892,7 +919,7 @@ static void hpt370_lostirq_timeout (ide_drive_t *drive)
u8 dma_stat = 0, dma_cmd = 0;
pci_read_config_byte(HWIF(drive)->pci_dev, reginfo, &bfifo);
- printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo);
+ printk("%s: %d bytes in FIFO\n", drive->name, bfifo);
hpt370_clear_engine(drive);
/* get dma command mode */
dma_cmd = hwif->INB(hwif->dma_command);
@@ -1020,6 +1047,15 @@ static void hpt372n_rw_disk(ide_drive_t *drive, struct request *rq)
static void hpt3xx_reset (ide_drive_t *drive)
{
+#if 0
+ unsigned long high_16 = pci_resource_start(HWIF(drive)->pci_dev, 4);
+ u8 reset = (HWIF(drive)->channel) ? 0x80 : 0x40;
+ u8 reg59h = 0;
+
+ pci_read_config_byte(HWIF(drive)->pci_dev, 0x59, ®59h);
+ pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h|reset);
+ pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h);
+#endif
}
static int hpt3xx_tristate (ide_drive_t * drive, int state)
@@ -1029,6 +1065,8 @@ static int hpt3xx_tristate (ide_drive_t * drive, int state)
u8 reg59h = 0, reset = (hwif->channel) ? 0x80 : 0x40;
u8 regXXh = 0, state_reg= (hwif->channel) ? 0x57 : 0x53;
+// hwif->bus_state = state;
+
pci_read_config_byte(dev, 0x59, ®59h);
pci_read_config_byte(dev, state_reg, ®XXh);
@@ -1055,7 +1093,7 @@ static int hpt3xx_tristate (ide_drive_t * drive, int state)
#define TRISTATE_BIT 0x8000
static int hpt370_busproc(ide_drive_t * drive, int state)
{
- ide_hwif_t *hwif = drive->hwif;
+ ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
u8 tristate = 0, resetmask = 0, bus_reg = 0;
u16 tri_reg;
@@ -1110,44 +1148,33 @@ static int hpt370_busproc(ide_drive_t * drive, int state)
return 0;
}
-static void __devinit hpt366_clocking(ide_hwif_t *hwif)
-{
- u32 reg1 = 0;
- struct hpt_info *info = ide_get_hwifdata(hwif);
-
- pci_read_config_dword(hwif->pci_dev, 0x40, ®1);
-
- /* detect bus speed by looking at control reg timing: */
- switch((reg1 >> 8) & 7) {
- case 5:
- info->speed = forty_base_hpt366;
- break;
- case 9:
- info->speed = twenty_five_base_hpt366;
- break;
- case 7:
- default:
- info->speed = thirty_three_base_hpt366;
- break;
- }
-}
-
-static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
+static int __devinit init_hpt37x(struct pci_dev *dev)
{
- struct hpt_info *info = ide_get_hwifdata(hwif);
- struct pci_dev *dev = hwif->pci_dev;
int adjust, i;
u16 freq;
u32 pll;
u8 reg5bh;
+ u8 reg5ah = 0;
+ unsigned long dmabase = pci_resource_start(dev, 4);
+ u8 did, rid;
+ int is_372n = 0;
+ pci_read_config_byte(dev, 0x5a, ®5ah);
+ /* interrupt force enable */
+ pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10));
+
+ if(dmabase)
+ {
+ did = inb(dmabase + 0x22);
+ rid = inb(dmabase + 0x28);
+
+ if((did == 4 && rid == 6) || (did == 5 && rid > 1))
+ is_372n = 1;
+ }
+
/*
* default to pci clock. make sure MA15/16 are set to output
- * to prevent drives having problems with 40-pin cables. Needed
- * for some drives such as IBM-DTLA which will not enter ready
- * state on reset when PDIAG is a input.
- *
- * ToDo: should we set 0x21 when using PLL mode ?
+ * to prevent drives having problems with 40-pin cables.
*/
pci_write_config_byte(dev, 0x5b, 0x23);
@@ -1170,7 +1197,9 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
* Currently we always set up the PLL for the 372N
*/
- if(info->flags & IS_372N)
+ pci_set_drvdata(dev, NULL);
+
+ if(is_372n)
{
printk(KERN_INFO "hpt: HPT372N detected, using 372N timing.\n");
if(freq < 0x55)
@@ -1198,38 +1227,39 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
pll = F_LOW_PCI_66;
if (pll == F_LOW_PCI_33) {
- if (info->revision >= 8)
- info->speed = thirty_three_base_hpt374;
- else if (info->revision >= 5)
- info->speed = thirty_three_base_hpt372;
- else if (info->revision >= 4)
- info->speed = thirty_three_base_hpt370a;
+ if (hpt_minimum_revision(dev,8))
+ pci_set_drvdata(dev, (void *) thirty_three_base_hpt374);
+ else if (hpt_minimum_revision(dev,5))
+ pci_set_drvdata(dev, (void *) thirty_three_base_hpt372);
+ else if (hpt_minimum_revision(dev,4))
+ pci_set_drvdata(dev, (void *) thirty_three_base_hpt370a);
else
- info->speed = thirty_three_base_hpt370;
- printk(KERN_DEBUG "HPT37X: using 33MHz PCI clock\n");
+ pci_set_drvdata(dev, (void *) thirty_three_base_hpt370);
+ printk("HPT37X: using 33MHz PCI clock\n");
} else if (pll == F_LOW_PCI_40) {
/* Unsupported */
} else if (pll == F_LOW_PCI_50) {
- if (info->revision >= 8)
- info->speed = fifty_base_hpt370a;
- else if (info->revision >= 5)
- info->speed = fifty_base_hpt372;
- else if (info->revision >= 4)
- info->speed = fifty_base_hpt370a;
+ if (hpt_minimum_revision(dev,8))
+ pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
+ else if (hpt_minimum_revision(dev,5))
+ pci_set_drvdata(dev, (void *) fifty_base_hpt372);
+ else if (hpt_minimum_revision(dev,4))
+ pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
else
- info->speed = fifty_base_hpt370a;
- printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n");
+ pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
+ printk("HPT37X: using 50MHz PCI clock\n");
} else {
- if (info->revision >= 8) {
+ if (hpt_minimum_revision(dev,8))
+ {
printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n");
}
- else if (info->revision >= 5)
- info->speed = sixty_six_base_hpt372;
- else if (info->revision >= 4)
- info->speed = sixty_six_base_hpt370a;
+ else if (hpt_minimum_revision(dev,5))
+ pci_set_drvdata(dev, (void *) sixty_six_base_hpt372);
+ else if (hpt_minimum_revision(dev,4))
+ pci_set_drvdata(dev, (void *) sixty_six_base_hpt370a);
else
- info->speed = sixty_six_base_hpt370;
- printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n");
+ pci_set_drvdata(dev, (void *) sixty_six_base_hpt370);
+ printk("HPT37X: using 66MHz PCI clock\n");
}
}
@@ -1239,19 +1269,11 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
* result in slow reads when using a 33MHz PCI clock. we also
* don't like to use the PLL because it will cause glitches
* on PRST/SRST when the HPT state engine gets reset.
- *
- * ToDo: Use 66MHz PLL when ATA133 devices are present on a
- * 372 device so we can get ATA133 support
*/
- if (info->speed)
+ if (pci_get_drvdata(dev))
goto init_hpt37X_done;
-
- info->flags |= PLL_MODE;
/*
- * FIXME: make this work correctly, esp with 372N as per
- * reference driver code.
- *
* adjust PLL based upon PCI clock, enable it, and wait for
* stabilization.
*/
@@ -1276,14 +1298,14 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
pci_write_config_dword(dev, 0x5c,
pll & ~0x100);
pci_write_config_byte(dev, 0x5b, 0x21);
- if (info->revision >= 8)
- info->speed = fifty_base_hpt370a;
- else if (info->revision >= 5)
- info->speed = fifty_base_hpt372;
- else if (info->revision >= 4)
- info->speed = fifty_base_hpt370a;
+ if (hpt_minimum_revision(dev,8))
+ pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
+ else if (hpt_minimum_revision(dev,5))
+ pci_set_drvdata(dev, (void *) fifty_base_hpt372);
+ else if (hpt_minimum_revision(dev,4))
+ pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
else
- info->speed = fifty_base_hpt370a;
+ pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
printk("HPT37X: using 50MHz internal PLL\n");
goto init_hpt37X_done;
}
@@ -1296,22 +1318,10 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
}
init_hpt37X_done:
- if (!info->speed)
- printk(KERN_ERR "HPT37X%s: unknown bus timing [%d %d].\n",
- (info->flags & IS_372N)?"N":"", pll, freq);
/* reset state engine */
pci_write_config_byte(dev, 0x50, 0x37);
pci_write_config_byte(dev, 0x54, 0x37);
udelay(100);
-}
-
-static int __devinit init_hpt37x(struct pci_dev *dev)
-{
- u8 reg5ah;
-
- pci_read_config_byte(dev, 0x5a, ®5ah);
- /* interrupt force enable */
- pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10));
return 0;
}
@@ -1328,27 +1338,59 @@ static int __devinit init_hpt366(struct pci_dev *dev)
pci_write_config_byte(dev, 0x51, drive_fast & ~0x80);
pci_read_config_dword(dev, 0x40, ®1);
+ /* detect bus speed by looking at control reg timing: */
+ switch((reg1 >> 8) & 7) {
+ case 5:
+ pci_set_drvdata(dev, (void *) forty_base_hpt366);
+ break;
+ case 9:
+ pci_set_drvdata(dev, (void *) twenty_five_base_hpt366);
+ break;
+ case 7:
+ default:
+ pci_set_drvdata(dev, (void *) thirty_three_base_hpt366);
+ break;
+ }
+
+ if (!pci_get_drvdata(dev))
+ {
+ printk(KERN_ERR "hpt366: unknown bus timing.\n");
+ pci_set_drvdata(dev, NULL);
+ }
return 0;
}
static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name)
{
int ret = 0;
- /* FIXME: Not portable */
+ u8 test = 0;
+
if (dev->resource[PCI_ROM_RESOURCE].start)
pci_write_config_byte(dev, PCI_ROM_ADDRESS,
dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
- pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
- pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
- pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
- pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
+ pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &test);
+ if (test != (L1_CACHE_BYTES / 4))
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
+ (L1_CACHE_BYTES / 4));
- if (hpt_revision(dev) >= 3)
- ret = init_hpt37x(dev);
- else
- ret = init_hpt366(dev);
+ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &test);
+ if (test != 0x78)
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
+
+ pci_read_config_byte(dev, PCI_MIN_GNT, &test);
+ if (test != 0x08)
+ pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
+
+ pci_read_config_byte(dev, PCI_MAX_LAT, &test);
+ if (test != 0x08)
+ pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
+ if (hpt_minimum_revision(dev, 3)) {
+ ret = init_hpt37x(dev);
+ } else {
+ ret =init_hpt366(dev);
+ }
if (ret)
return ret;
@@ -1358,16 +1400,27 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
- struct hpt_info *info = ide_get_hwifdata(hwif);
u8 ata66 = 0, regmask = (hwif->channel) ? 0x01 : 0x02;
+ u8 did, rid;
+ unsigned long dmabase = hwif->dma_base;
+ int is_372n = 0;
+ if(dmabase)
+ {
+ did = inb(dmabase + 0x22);
+ rid = inb(dmabase + 0x28);
+
+ if((did == 4 && rid == 6) || (did == 5 && rid > 1))
+ is_372n = 1;
+ }
+
hwif->tuneproc = &hpt3xx_tune_drive;
hwif->speedproc = &hpt3xx_tune_chipset;
hwif->quirkproc = &hpt3xx_quirkproc;
hwif->intrproc = &hpt3xx_intrproc;
hwif->maskproc = &hpt3xx_maskproc;
- if(info->flags & IS_372N)
+ if(is_372n)
hwif->rw_disk = &hpt372n_rw_disk;
/*
@@ -1375,7 +1428,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
* address lines to access an external eeprom. To read valid
* cable detect state the pins must be enabled as inputs.
*/
- if (info->revision >= 8 && (PCI_FUNC(dev->devfn) & 1)) {
+ if (hpt_minimum_revision(dev, 8) && PCI_FUNC(dev->devfn) & 1) {
/*
* HPT374 PCI function 1
* - set bit 15 of reg 0x52 to enable TCBLID as input
@@ -1390,7 +1443,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
pci_read_config_byte(dev, 0x5a, &ata66);
pci_write_config_word(dev, 0x52, mcr3);
pci_write_config_word(dev, 0x56, mcr6);
- } else if (info->revision >= 3) {
+ } else if (hpt_minimum_revision(dev, 3)) {
/*
* HPT370/372 and 374 pcifn 0
* - clear bit 0 of 0x5b to enable P/SCBLID as inputs
@@ -1417,7 +1470,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
hwif->serialized = hwif->mate->serialized = 1;
#endif
- if (info->revision >= 3) {
+ if (hpt_minimum_revision(dev,3)) {
u8 reg5ah = 0;
pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10);
/*
@@ -1427,7 +1480,8 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
*/
hwif->resetproc = &hpt3xx_reset;
hwif->busproc = &hpt370_busproc;
- } else if (info->revision >= 2) {
+// hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
+ } else if (hpt_minimum_revision(dev,2)) {
hwif->resetproc = &hpt3xx_reset;
hwif->busproc = &hpt3xx_tristate;
} else {
@@ -1448,18 +1502,18 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
hwif->udma_four = ((ata66 & regmask) ? 0 : 1);
hwif->ide_dma_check = &hpt366_config_drive_xfer_rate;
- if (info->revision >= 8) {
+ if (hpt_minimum_revision(dev,8)) {
hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
hwif->ide_dma_end = &hpt374_ide_dma_end;
- } else if (info->revision >= 5) {
+ } else if (hpt_minimum_revision(dev,5)) {
hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
hwif->ide_dma_end = &hpt374_ide_dma_end;
- } else if (info->revision >= 3) {
+ } else if (hpt_minimum_revision(dev,3)) {
hwif->dma_start = &hpt370_ide_dma_start;
hwif->ide_dma_end = &hpt370_ide_dma_end;
hwif->ide_dma_timeout = &hpt370_ide_dma_timeout;
hwif->ide_dma_lostirq = &hpt370_ide_dma_lostirq;
- } else if (info->revision >= 2)
+ } else if (hpt_minimum_revision(dev,2))
hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
else
hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
@@ -1472,7 +1526,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
{
- struct hpt_info *info = ide_get_hwifdata(hwif);
u8 masterdma = 0, slavedma = 0;
u8 dma_new = 0, dma_old = 0;
u8 primary = hwif->channel ? 0x4b : 0x43;
@@ -1482,7 +1535,8 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
if (!dmabase)
return;
- if(info->speed == NULL) {
+ if(pci_get_drvdata(hwif->pci_dev) == NULL)
+ {
printk(KERN_WARNING "hpt: no known IDE timings, disabling DMA.\n");
return;
}
@@ -1505,40 +1559,6 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
ide_setup_dma(hwif, dmabase, 8);
}
-/*
- * We "borrow" this hook in order to set the data structures
- * up early enough before dma or init_hwif calls are made.
- */
-
-static void __devinit init_iops_hpt366(ide_hwif_t *hwif)
-{
- struct hpt_info *info = kmalloc(sizeof(struct hpt_info), GFP_KERNEL);
- unsigned long dmabase = pci_resource_start(hwif->pci_dev, 4);
- u8 did, rid;
-
- if(info == NULL) {
- printk(KERN_WARNING "hpt366: out of memory.\n");
- return;
- }
- memset(info, 0, sizeof(struct hpt_info));
- ide_set_hwifdata(hwif, info);
-
- if(dmabase) {
- did = inb(dmabase + 0x22);
- rid = inb(dmabase + 0x28);
-
- if((did == 4 && rid == 6) || (did == 5 && rid > 1))
- info->flags |= IS_372N;
- }
-
- info->revision = hpt_revision(hwif->pci_dev);
-
- if (info->revision >= 3)
- hpt37x_clocking(hwif);
- else
- hpt366_clocking(hwif);
-}
-
static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d)
{
struct pci_dev *findev = NULL;
@@ -1626,7 +1646,6 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.name = "HPT366",
.init_setup = init_setup_hpt366,
.init_chipset = init_chipset_hpt366,
- .init_iops = init_iops_hpt366,
.init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366,
.channels = 2,
@@ -1637,7 +1656,6 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.name = "HPT372A",
.init_setup = init_setup_hpt37x,
.init_chipset = init_chipset_hpt366,
- .init_iops = init_iops_hpt366,
.init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366,
.channels = 2,
@@ -1647,7 +1665,6 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.name = "HPT302",
.init_setup = init_setup_hpt37x,
.init_chipset = init_chipset_hpt366,
- .init_iops = init_iops_hpt366,
.init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366,
.channels = 2,
@@ -1657,7 +1674,6 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.name = "HPT371",
.init_setup = init_setup_hpt37x,
.init_chipset = init_chipset_hpt366,
- .init_iops = init_iops_hpt366,
.init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366,
.channels = 2,
@@ -1667,7 +1683,6 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.name = "HPT374",
.init_setup = init_setup_hpt374,
.init_chipset = init_chipset_hpt366,
- .init_iops = init_iops_hpt366,
.init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366,
.channels = 2, /* 4 */
@@ -1677,7 +1692,6 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.name = "HPT372N",
.init_setup = init_setup_hpt37x,
.init_chipset = init_chipset_hpt366,
- .init_iops = init_iops_hpt366,
.init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366,
.channels = 2, /* 4 */
diff --git a/trunk/drivers/ide/pci/it821x.c b/trunk/drivers/ide/pci/it821x.c
deleted file mode 100644
index e440036e651f..000000000000
--- a/trunk/drivers/ide/pci/it821x.c
+++ /dev/null
@@ -1,812 +0,0 @@
-
-/*
- * linux/drivers/ide/pci/it821x.c Version 0.09 December 2004
- *
- * Copyright (C) 2004 Red Hat
- *
- * May be copied or modified under the terms of the GNU General Public License
- * Based in part on the ITE vendor provided SCSI driver.
- *
- * Documentation available from
- * http://www.ite.com.tw/pc/IT8212F_V04.pdf
- * Some other documents are NDA.
- *
- * The ITE8212 isn't exactly a standard IDE controller. It has two
- * modes. In pass through mode then it is an IDE controller. In its smart
- * mode its actually quite a capable hardware raid controller disguised
- * as an IDE controller. Smart mode only understands DMA read/write and
- * identify, none of the fancier commands apply. The IT8211 is identical
- * in other respects but lacks the raid mode.
- *
- * Errata:
- * o Rev 0x10 also requires master/slave hold the same DMA timings and
- * cannot do ATAPI MWDMA.
- * o The identify data for raid volumes lacks CHS info (technically ok)
- * but also fails to set the LBA28 and other bits. We fix these in
- * the IDE probe quirk code.
- * o If you write LBA48 sized I/O's (ie > 256 sector) in smart mode
- * raid then the controller firmware dies
- * o Smart mode without RAID doesn't clear all the necessary identify
- * bits to reduce the command set to the one used
- *
- * This has a few impacts on the driver
- * - In pass through mode we do all the work you would expect
- * - In smart mode the clocking set up is done by the controller generally
- * but we must watch the other limits and filter.
- * - There are a few extra vendor commands that actually talk to the
- * controller but only work PIO with no IRQ.
- *
- * Vendor areas of the identify block in smart mode are used for the
- * timing and policy set up. Each HDD in raid mode also has a serial
- * block on the disk. The hardware extra commands are get/set chip status,
- * rebuild, get rebuild status.
- *
- * In Linux the driver supports pass through mode as if the device was
- * just another IDE controller. If the smart mode is running then
- * volumes are managed by the controller firmware and each IDE "disk"
- * is a raid volume. Even more cute - the controller can do automated
- * hotplug and rebuild.
- *
- * The pass through controller itself is a little demented. It has a
- * flaw that it has a single set of PIO/MWDMA timings per channel so
- * non UDMA devices restrict each others performance. It also has a
- * single clock source per channel so mixed UDMA100/133 performance
- * isn't perfect and we have to pick a clock. Thankfully none of this
- * matters in smart mode. ATAPI DMA is not currently supported.
- *
- * It seems the smart mode is a win for RAID1/RAID10 but otherwise not.
- *
- * TODO
- * - ATAPI UDMA is ok but not MWDMA it seems
- * - RAID configuration ioctls
- * - Move to libata once it grows up
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-struct it821x_dev
-{
- unsigned int smart:1, /* Are we in smart raid mode */
- timing10:1; /* Rev 0x10 */
- u8 clock_mode; /* 0, ATA_50 or ATA_66 */
- u8 want[2][2]; /* Mode/Pri log for master slave */
- /* We need these for switching the clock when DMA goes on/off
- The high byte is the 66Mhz timing */
- u16 pio[2]; /* Cached PIO values */
- u16 mwdma[2]; /* Cached MWDMA values */
- u16 udma[2]; /* Cached UDMA values (per drive) */
-};
-
-#define ATA_66 0
-#define ATA_50 1
-#define ATA_ANY 2
-
-#define UDMA_OFF 0
-#define MWDMA_OFF 0
-
-/*
- * We allow users to force the card into non raid mode without
- * flashing the alternative BIOS. This is also neccessary right now
- * for embedded platforms that cannot run a PC BIOS but are using this
- * device.
- */
-
-static int it8212_noraid;
-
-/**
- * it821x_program - program the PIO/MWDMA registers
- * @drive: drive to tune
- *
- * Program the PIO/MWDMA timing for this channel according to the
- * current clock.
- */
-
-static void it821x_program(ide_drive_t *drive, u16 timing)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- int channel = hwif->channel;
- u8 conf;
-
- /* Program PIO/MWDMA timing bits */
- if(itdev->clock_mode == ATA_66)
- conf = timing >> 8;
- else
- conf = timing & 0xFF;
- pci_write_config_byte(hwif->pci_dev, 0x54 + 4 * channel, conf);
-}
-
-/**
- * it821x_program_udma - program the UDMA registers
- * @drive: drive to tune
- *
- * Program the UDMA timing for this drive according to the
- * current clock.
- */
-
-static void it821x_program_udma(ide_drive_t *drive, u16 timing)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- int channel = hwif->channel;
- int unit = drive->select.b.unit;
- u8 conf;
-
- /* Program UDMA timing bits */
- if(itdev->clock_mode == ATA_66)
- conf = timing >> 8;
- else
- conf = timing & 0xFF;
- if(itdev->timing10 == 0)
- pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + unit, conf);
- else {
- pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel, conf);
- pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + 1, conf);
- }
-}
-
-
-/**
- * it821x_clock_strategy
- * @hwif: hardware interface
- *
- * Select between the 50 and 66Mhz base clocks to get the best
- * results for this interface.
- */
-
-static void it821x_clock_strategy(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct it821x_dev *itdev = ide_get_hwifdata(hwif);
-
- u8 unit = drive->select.b.unit;
- ide_drive_t *pair = &hwif->drives[1-unit];
-
- int clock, altclock;
- u8 v;
- int sel = 0;
-
- if(itdev->want[0][0] > itdev->want[1][0]) {
- clock = itdev->want[0][1];
- altclock = itdev->want[1][1];
- } else {
- clock = itdev->want[1][1];
- altclock = itdev->want[0][1];
- }
-
- /* Master doesn't care does the slave ? */
- if(clock == ATA_ANY)
- clock = altclock;
-
- /* Nobody cares - keep the same clock */
- if(clock == ATA_ANY)
- return;
- /* No change */
- if(clock == itdev->clock_mode)
- return;
-
- /* Load this into the controller ? */
- if(clock == ATA_66)
- itdev->clock_mode = ATA_66;
- else {
- itdev->clock_mode = ATA_50;
- sel = 1;
- }
- pci_read_config_byte(hwif->pci_dev, 0x50, &v);
- v &= ~(1 << (1 + hwif->channel));
- v |= sel << (1 + hwif->channel);
- pci_write_config_byte(hwif->pci_dev, 0x50, v);
-
- /*
- * Reprogram the UDMA/PIO of the pair drive for the switch
- * MWDMA will be dealt with by the dma switcher
- */
- if(pair && itdev->udma[1-unit] != UDMA_OFF) {
- it821x_program_udma(pair, itdev->udma[1-unit]);
- it821x_program(pair, itdev->pio[1-unit]);
- }
- /*
- * Reprogram the UDMA/PIO of our drive for the switch.
- * MWDMA will be dealt with by the dma switcher
- */
- if(itdev->udma[unit] != UDMA_OFF) {
- it821x_program_udma(drive, itdev->udma[unit]);
- it821x_program(drive, itdev->pio[unit]);
- }
-}
-
-/**
- * it821x_ratemask - Compute available modes
- * @drive: IDE drive
- *
- * Compute the available speeds for the devices on the interface. This
- * is all modes to ATA133 clipped by drive cable setup.
- */
-
-static u8 it821x_ratemask (ide_drive_t *drive)
-{
- u8 mode = 4;
- if (!eighty_ninty_three(drive))
- mode = min(mode, (u8)1);
- return mode;
-}
-
-/**
- * it821x_tuneproc - tune a drive
- * @drive: drive to tune
- * @mode_wanted: the target operating mode
- *
- * Load the timing settings for this device mode into the
- * controller. By the time we are called the mode has been
- * modified as neccessary to handle the absence of seperate
- * master/slave timers for MWDMA/PIO.
- *
- * This code is only used in pass through mode.
- */
-
-static void it821x_tuneproc (ide_drive_t *drive, byte mode_wanted)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- int unit = drive->select.b.unit;
-
- /* Spec says 89 ref driver uses 88 */
- static u16 pio[] = { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 };
- static u8 pio_want[] = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY };
-
- if(itdev->smart)
- return;
-
- /* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */
- itdev->want[unit][1] = pio_want[mode_wanted];
- itdev->want[unit][0] = 1; /* PIO is lowest priority */
- itdev->pio[unit] = pio[mode_wanted];
- it821x_clock_strategy(drive);
- it821x_program(drive, itdev->pio[unit]);
-}
-
-/**
- * it821x_tune_mwdma - tune a channel for MWDMA
- * @drive: drive to set up
- * @mode_wanted: the target operating mode
- *
- * Load the timing settings for this device mode into the
- * controller when doing MWDMA in pass through mode. The caller
- * must manage the whole lack of per device MWDMA/PIO timings and
- * the shared MWDMA/PIO timing register.
- */
-
-static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct it821x_dev *itdev = (void *)ide_get_hwifdata(hwif);
- int unit = drive->select.b.unit;
- int channel = hwif->channel;
- u8 conf;
-
- static u16 dma[] = { 0x8866, 0x3222, 0x3121 };
- static u8 mwdma_want[] = { ATA_ANY, ATA_66, ATA_ANY };
-
- itdev->want[unit][1] = mwdma_want[mode_wanted];
- itdev->want[unit][0] = 2; /* MWDMA is low priority */
- itdev->mwdma[unit] = dma[mode_wanted];
- itdev->udma[unit] = UDMA_OFF;
-
- /* UDMA bits off - Revision 0x10 do them in pairs */
- pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
- if(itdev->timing10)
- conf |= channel ? 0x60: 0x18;
- else
- conf |= 1 << (3 + 2 * channel + unit);
- pci_write_config_byte(hwif->pci_dev, 0x50, conf);
-
- it821x_clock_strategy(drive);
- /* FIXME: do we need to program this ? */
- /* it821x_program(drive, itdev->mwdma[unit]); */
-}
-
-/**
- * it821x_tune_udma - tune a channel for UDMA
- * @drive: drive to set up
- * @mode_wanted: the target operating mode
- *
- * Load the timing settings for this device mode into the
- * controller when doing UDMA modes in pass through.
- */
-
-static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- int unit = drive->select.b.unit;
- int channel = hwif->channel;
- u8 conf;
-
- static u16 udma[] = { 0x4433, 0x4231, 0x3121, 0x2121, 0x1111, 0x2211, 0x1111 };
- static u8 udma_want[] = { ATA_ANY, ATA_50, ATA_ANY, ATA_66, ATA_66, ATA_50, ATA_66 };
-
- itdev->want[unit][1] = udma_want[mode_wanted];
- itdev->want[unit][0] = 3; /* UDMA is high priority */
- itdev->mwdma[unit] = MWDMA_OFF;
- itdev->udma[unit] = udma[mode_wanted];
- if(mode_wanted >= 5)
- itdev->udma[unit] |= 0x8080; /* UDMA 5/6 select on */
-
- /* UDMA on. Again revision 0x10 must do the pair */
- pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
- if(itdev->timing10)
- conf &= channel ? 0x9F: 0xE7;
- else
- conf &= ~ (1 << (3 + 2 * channel + unit));
- pci_write_config_byte(hwif->pci_dev, 0x50, conf);
-
- it821x_clock_strategy(drive);
- it821x_program_udma(drive, itdev->udma[unit]);
-
-}
-
-/**
- * config_it821x_chipset_for_pio - set drive timings
- * @drive: drive to tune
- * @speed we want
- *
- * Compute the best pio mode we can for a given device. We must
- * pick a speed that does not cause problems with the other device
- * on the cable.
- */
-
-static void config_it821x_chipset_for_pio (ide_drive_t *drive, byte set_speed)
-{
- u8 unit = drive->select.b.unit;
- ide_hwif_t *hwif = drive->hwif;
- ide_drive_t *pair = &hwif->drives[1-unit];
- u8 speed = 0, set_pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
- u8 pair_pio;
-
- /* We have to deal with this mess in pairs */
- if(pair != NULL) {
- pair_pio = ide_get_best_pio_mode(pair, 255, 5, NULL);
- /* Trim PIO to the slowest of the master/slave */
- if(pair_pio < set_pio)
- set_pio = pair_pio;
- }
- it821x_tuneproc(drive, set_pio);
- speed = XFER_PIO_0 + set_pio;
- /* XXX - We trim to the lowest of the pair so the other drive
- will always be fine at this point until we do hotplug passthru */
-
- if (set_speed)
- (void) ide_config_drive_speed(drive, speed);
-}
-
-/**
- * it821x_dma_read - DMA hook
- * @drive: drive for DMA
- *
- * The IT821x has a single timing register for MWDMA and for PIO
- * operations. As we flip back and forth we have to reload the
- * clock. In addition the rev 0x10 device only works if the same
- * timing value is loaded into the master and slave UDMA clock
- * so we must also reload that.
- *
- * FIXME: we could figure out in advance if we need to do reloads
- */
-
-static void it821x_dma_start(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- int unit = drive->select.b.unit;
- if(itdev->mwdma[unit] != MWDMA_OFF)
- it821x_program(drive, itdev->mwdma[unit]);
- else if(itdev->udma[unit] != UDMA_OFF && itdev->timing10)
- it821x_program_udma(drive, itdev->udma[unit]);
- ide_dma_start(drive);
-}
-
-/**
- * it821x_dma_write - DMA hook
- * @drive: drive for DMA stop
- *
- * The IT821x has a single timing register for MWDMA and for PIO
- * operations. As we flip back and forth we have to reload the
- * clock.
- */
-
-static int it821x_dma_end(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- int unit = drive->select.b.unit;
- struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- int ret = __ide_dma_end(drive);
- if(itdev->mwdma[unit] != MWDMA_OFF)
- it821x_program(drive, itdev->pio[unit]);
- return ret;
-}
-
-
-/**
- * it821x_tune_chipset - set controller timings
- * @drive: Drive to set up
- * @xferspeed: speed we want to achieve
- *
- * Tune the ITE chipset for the desired mode. If we can't achieve
- * the desired mode then tune for a lower one, but ultimately
- * make the thing work.
- */
-
-static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed)
-{
-
- ide_hwif_t *hwif = drive->hwif;
- struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- u8 speed = ide_rate_filter(it821x_ratemask(drive), xferspeed);
-
- if(!itdev->smart) {
- switch(speed) {
- case XFER_PIO_4:
- case XFER_PIO_3:
- case XFER_PIO_2:
- case XFER_PIO_1:
- case XFER_PIO_0:
- it821x_tuneproc(drive, (speed - XFER_PIO_0));
- break;
- /* MWDMA tuning is really hard because our MWDMA and PIO
- timings are kept in the same place. We can switch in the
- host dma on/off callbacks */
- case XFER_MW_DMA_2:
- case XFER_MW_DMA_1:
- case XFER_MW_DMA_0:
- it821x_tune_mwdma(drive, (speed - XFER_MW_DMA_0));
- break;
- case XFER_UDMA_6:
- case XFER_UDMA_5:
- case XFER_UDMA_4:
- case XFER_UDMA_3:
- case XFER_UDMA_2:
- case XFER_UDMA_1:
- case XFER_UDMA_0:
- it821x_tune_udma(drive, (speed - XFER_UDMA_0));
- break;
- default:
- return 1;
- }
- }
- /*
- * In smart mode the clocking is done by the host controller
- * snooping the mode we picked. The rest of it is not our problem
- */
- return ide_config_drive_speed(drive, speed);
-}
-
-/**
- * config_chipset_for_dma - configure for DMA
- * @drive: drive to configure
- *
- * Called by the IDE layer when it wants the timings set up.
- */
-
-static int config_chipset_for_dma (ide_drive_t *drive)
-{
- u8 speed = ide_dma_speed(drive, it821x_ratemask(drive));
-
- config_it821x_chipset_for_pio(drive, !speed);
- it821x_tune_chipset(drive, speed);
- return ide_dma_enable(drive);
-}
-
-/**
- * it821x_configure_drive_for_dma - set up for DMA transfers
- * @drive: drive we are going to set up
- *
- * Set up the drive for DMA, tune the controller and drive as
- * required. If the drive isn't suitable for DMA or we hit
- * other problems then we will drop down to PIO and set up
- * PIO appropriately
- */
-
-static int it821x_config_drive_for_dma (ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
-
- if (ide_use_dma(drive)) {
- if (config_chipset_for_dma(drive))
- return hwif->ide_dma_on(drive);
- }
- config_it821x_chipset_for_pio(drive, 1);
- return hwif->ide_dma_off_quietly(drive);
-}
-
-/**
- * ata66_it821x - check for 80 pin cable
- * @hwif: interface to check
- *
- * Check for the presence of an ATA66 capable cable on the
- * interface. Problematic as it seems some cards don't have
- * the needed logic onboard.
- */
-
-static unsigned int __devinit ata66_it821x(ide_hwif_t *hwif)
-{
- /* The reference driver also only does disk side */
- return 1;
-}
-
-/**
- * it821x_fixup - post init callback
- * @hwif: interface
- *
- * This callback is run after the drives have been probed but
- * before anything gets attached. It allows drivers to do any
- * final tuning that is needed, or fixups to work around bugs.
- */
-
-static void __devinit it821x_fixups(ide_hwif_t *hwif)
-{
- struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- int i;
-
- if(!itdev->smart) {
- /*
- * If we are in pass through mode then not much
- * needs to be done, but we do bother to clear the
- * IRQ mask as we may well be in PIO (eg rev 0x10)
- * for now and we know unmasking is safe on this chipset.
- */
- for (i = 0; i < 2; i++) {
- ide_drive_t *drive = &hwif->drives[i];
- if(drive->present)
- drive->unmask = 1;
- }
- return;
- }
- /*
- * Perform fixups on smart mode. We need to "lose" some
- * capabilities the firmware lacks but does not filter, and
- * also patch up some capability bits that it forgets to set
- * in RAID mode.
- */
-
- for(i = 0; i < 2; i++) {
- ide_drive_t *drive = &hwif->drives[i];
- struct hd_driveid *id;
- u16 *idbits;
-
- if(!drive->present)
- continue;
- id = drive->id;
- idbits = (u16 *)drive->id;
-
- /* Check for RAID v native */
- if(strstr(id->model, "Integrated Technology Express")) {
- /* In raid mode the ident block is slightly buggy
- We need to set the bits so that the IDE layer knows
- LBA28. LBA48 and DMA ar valid */
- id->capability |= 3; /* LBA28, DMA */
- id->command_set_2 |= 0x0400; /* LBA48 valid */
- id->cfs_enable_2 |= 0x0400; /* LBA48 on */
- /* Reporting logic */
- printk(KERN_INFO "%s: IT8212 %sRAID %d volume",
- drive->name,
- idbits[147] ? "Bootable ":"",
- idbits[129]);
- if(idbits[129] != 1)
- printk("(%dK stripe)", idbits[146]);
- printk(".\n");
- /* Now the core code will have wrongly decided no DMA
- so we need to fix this */
- hwif->ide_dma_off_quietly(drive);
-#ifdef CONFIG_IDEDMA_ONLYDISK
- if (drive->media == ide_disk)
-#endif
- hwif->ide_dma_check(drive);
- } else {
- /* Non RAID volume. Fixups to stop the core code
- doing unsupported things */
- id->field_valid &= 1;
- id->queue_depth = 0;
- id->command_set_1 = 0;
- id->command_set_2 &= 0xC400;
- id->cfsse &= 0xC000;
- id->cfs_enable_1 = 0;
- id->cfs_enable_2 &= 0xC400;
- id->csf_default &= 0xC000;
- id->word127 = 0;
- id->dlf = 0;
- id->csfo = 0;
- id->cfa_power = 0;
- printk(KERN_INFO "%s: Performing identify fixups.\n",
- drive->name);
- }
- }
-
-}
-
-/**
- * init_hwif_it821x - set up hwif structs
- * @hwif: interface to set up
- *
- * We do the basic set up of the interface structure. The IT8212
- * requires several custom handlers so we override the default
- * ide DMA handlers appropriately
- */
-
-static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
-{
- struct it821x_dev *idev = kmalloc(sizeof(struct it821x_dev), GFP_KERNEL);
- u8 conf;
-
- if(idev == NULL) {
- printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n");
- goto fallback;
- }
- memset(idev, 0, sizeof(struct it821x_dev));
- ide_set_hwifdata(hwif, idev);
-
- pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
- if(conf & 1) {
- idev->smart = 1;
- hwif->atapi_dma = 0;
- /* Long I/O's although allowed in LBA48 space cause the
- onboard firmware to enter the twighlight zone */
- hwif->rqsize = 256;
- }
-
- /* Pull the current clocks from 0x50 also */
- if (conf & (1 << (1 + hwif->channel)))
- idev->clock_mode = ATA_50;
- else
- idev->clock_mode = ATA_66;
-
- idev->want[0][1] = ATA_ANY;
- idev->want[1][1] = ATA_ANY;
-
- /*
- * Not in the docs but according to the reference driver
- * this is neccessary.
- */
-
- pci_read_config_byte(hwif->pci_dev, 0x08, &conf);
- if(conf == 0x10) {
- idev->timing10 = 1;
- hwif->atapi_dma = 0;
- if(!idev->smart)
- printk(KERN_WARNING "it821x: Revision 0x10, workarounds activated.\n");
- }
-
- hwif->speedproc = &it821x_tune_chipset;
- hwif->tuneproc = &it821x_tuneproc;
-
- /* MWDMA/PIO clock switching for pass through mode */
- if(!idev->smart) {
- hwif->dma_start = &it821x_dma_start;
- hwif->ide_dma_end = &it821x_dma_end;
- }
-
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
-
- if (!hwif->dma_base)
- goto fallback;
-
- hwif->ultra_mask = 0x7f;
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x07;
-
- hwif->ide_dma_check = &it821x_config_drive_for_dma;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_it821x(hwif);
-
- /*
- * The BIOS often doesn't set up DMA on this controller
- * so we always do it.
- */
-
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
- return;
-fallback:
- hwif->autodma = 0;
- return;
-}
-
-static void __devinit it8212_disable_raid(struct pci_dev *dev)
-{
- /* Reset local CPU, and set BIOS not ready */
- pci_write_config_byte(dev, 0x5E, 0x01);
-
- /* Set to bypass mode, and reset PCI bus */
- pci_write_config_byte(dev, 0x50, 0x00);
- pci_write_config_word(dev, PCI_COMMAND,
- PCI_COMMAND_PARITY | PCI_COMMAND_IO |
- PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
- pci_write_config_word(dev, 0x40, 0xA0F3);
-
- pci_write_config_dword(dev,0x4C, 0x02040204);
- pci_write_config_byte(dev, 0x42, 0x36);
- pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0);
-}
-
-static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const char *name)
-{
- u8 conf;
- static char *mode[2] = { "pass through", "smart" };
-
- /* Force the card into bypass mode if so requested */
- if (it8212_noraid) {
- printk(KERN_INFO "it8212: forcing bypass mode.\n");
- it8212_disable_raid(dev);
- }
- pci_read_config_byte(dev, 0x50, &conf);
- printk(KERN_INFO "it821x: controller in %s mode.\n", mode[conf & 1]);
- return 0;
-}
-
-
-#define DECLARE_ITE_DEV(name_str) \
- { \
- .name = name_str, \
- .init_chipset = init_chipset_it821x, \
- .init_hwif = init_hwif_it821x, \
- .channels = 2, \
- .autodma = AUTODMA, \
- .bootable = ON_BOARD, \
- .fixup = it821x_fixups \
- }
-
-static ide_pci_device_t it821x_chipsets[] __devinitdata = {
- /* 0 */ DECLARE_ITE_DEV("IT8212"),
-};
-
-/**
- * it821x_init_one - pci layer discovery entry
- * @dev: PCI device
- * @id: ident table entry
- *
- * Called by the PCI code when it finds an ITE821x controller.
- * We then use the IDE PCI generic helper to do most of the work.
- */
-
-static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
- ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
- return 0;
-}
-
-static struct pci_device_id it821x_pci_tbl[] = {
- { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8212, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { 0, },
-};
-
-MODULE_DEVICE_TABLE(pci, it821x_pci_tbl);
-
-static struct pci_driver driver = {
- .name = "ITE821x IDE",
- .id_table = it821x_pci_tbl,
- .probe = it821x_init_one,
-};
-
-static int __init it821x_ide_init(void)
-{
- return ide_pci_register_driver(&driver);
-}
-
-module_init(it821x_ide_init);
-
-module_param_named(noraid, it8212_noraid, int, S_IRUGO);
-MODULE_PARM_DESC(it8212_noraid, "Force card into bypass mode");
-
-MODULE_AUTHOR("Alan Cox");
-MODULE_DESCRIPTION("PCI driver module for the ITE 821x");
-MODULE_LICENSE("GPL");
diff --git a/trunk/drivers/ide/pci/serverworks.c b/trunk/drivers/ide/pci/serverworks.c
index c6f5fa4b4ca6..82a1103b2413 100644
--- a/trunk/drivers/ide/pci/serverworks.c
+++ b/trunk/drivers/ide/pci/serverworks.c
@@ -442,7 +442,7 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha
return (dev->irq) ? dev->irq : 0;
}
-static unsigned int __devinit ata66_svwks_svwks (ide_hwif_t *hwif)
+static unsigned int __init ata66_svwks_svwks (ide_hwif_t *hwif)
{
return 1;
}
@@ -454,7 +454,7 @@ static unsigned int __devinit ata66_svwks_svwks (ide_hwif_t *hwif)
* Bit 14 clear = primary IDE channel does not have 80-pin cable.
* Bit 14 set = primary IDE channel has 80-pin cable.
*/
-static unsigned int __devinit ata66_svwks_dell (ide_hwif_t *hwif)
+static unsigned int __init ata66_svwks_dell (ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
@@ -472,7 +472,7 @@ static unsigned int __devinit ata66_svwks_dell (ide_hwif_t *hwif)
*
* WARNING: this only works on Alpine hardware!
*/
-static unsigned int __devinit ata66_svwks_cobalt (ide_hwif_t *hwif)
+static unsigned int __init ata66_svwks_cobalt (ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN &&
@@ -483,7 +483,7 @@ static unsigned int __devinit ata66_svwks_cobalt (ide_hwif_t *hwif)
return 0;
}
-static unsigned int __devinit ata66_svwks (ide_hwif_t *hwif)
+static unsigned int __init ata66_svwks (ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
@@ -573,7 +573,7 @@ static int __devinit init_setup_svwks (struct pci_dev *dev, ide_pci_device_t *d)
return ide_setup_pci_device(dev, d);
}
-static int __devinit init_setup_csb6 (struct pci_dev *dev, ide_pci_device_t *d)
+static int __init init_setup_csb6 (struct pci_dev *dev, ide_pci_device_t *d)
{
if (!(PCI_FUNC(dev->devfn) & 1)) {
d->bootable = NEVER_BOARD;
diff --git a/trunk/drivers/ide/ppc/pmac.c b/trunk/drivers/ide/ppc/pmac.c
index 818380b5fd27..569f16767442 100644
--- a/trunk/drivers/ide/ppc/pmac.c
+++ b/trunk/drivers/ide/ppc/pmac.c
@@ -1324,9 +1324,9 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
/* XXX FIXME: Media bay stuff need re-organizing */
if (np->parent && np->parent->name
&& strcasecmp(np->parent->name, "media-bay") == 0) {
-#ifdef CONFIG_PMAC_MEDIABAY
+#ifdef CONFIG_PMAC_PBOOK
media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq, hwif->index);
-#endif /* CONFIG_PMAC_MEDIABAY */
+#endif /* CONFIG_PMAC_PBOOK */
pmif->mediabay = 1;
if (!bidp)
pmif->aapl_bus_id = 1;
@@ -1382,10 +1382,10 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
hwif->index, model_name[pmif->kind], pmif->aapl_bus_id,
pmif->mediabay ? " (mediabay)" : "", hwif->irq);
-#ifdef CONFIG_PMAC_MEDIABAY
+#ifdef CONFIG_PMAC_PBOOK
if (pmif->mediabay && check_media_bay_by_base(pmif->regbase, MB_CD) == 0)
hwif->noprobe = 0;
-#endif /* CONFIG_PMAC_MEDIABAY */
+#endif /* CONFIG_PMAC_PBOOK */
hwif->sg_max_nents = MAX_DCMDS;
diff --git a/trunk/drivers/ieee1394/ohci1394.c b/trunk/drivers/ieee1394/ohci1394.c
index b3d3d22fde64..36e25ac823dc 100644
--- a/trunk/drivers/ieee1394/ohci1394.c
+++ b/trunk/drivers/ieee1394/ohci1394.c
@@ -3538,8 +3538,8 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
static int ohci1394_pci_resume (struct pci_dev *pdev)
{
-#ifdef CONFIG_PPC_PMAC
- if (_machine == _MACH_Pmac) {
+#ifdef CONFIG_PMAC_PBOOK
+ {
struct device_node *of_node;
/* Re-enable 1394 */
@@ -3547,7 +3547,7 @@ static int ohci1394_pci_resume (struct pci_dev *pdev)
if (of_node)
pmac_call_feature (PMAC_FTR_1394_ENABLE, of_node, 0, 1);
}
-#endif /* CONFIG_PPC_PMAC */
+#endif
pci_enable_device(pdev);
@@ -3557,8 +3557,8 @@ static int ohci1394_pci_resume (struct pci_dev *pdev)
static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state)
{
-#ifdef CONFIG_PPC_PMAC
- if (_machine == _MACH_Pmac) {
+#ifdef CONFIG_PMAC_PBOOK
+ {
struct device_node *of_node;
/* Disable 1394 */
diff --git a/trunk/drivers/infiniband/core/packer.c b/trunk/drivers/infiniband/core/packer.c
index eb5ff54c10d7..5f15feffeae2 100644
--- a/trunk/drivers/infiniband/core/packer.c
+++ b/trunk/drivers/infiniband/core/packer.c
@@ -96,7 +96,7 @@ void ib_pack(const struct ib_field *desc,
else
val = 0;
- mask = cpu_to_be64((~0ull >> (64 - desc[i].size_bits)) << shift);
+ mask = cpu_to_be64(((1ull << desc[i].size_bits) - 1) << shift);
addr = (__be64 *) ((__be32 *) buf + desc[i].offset_words);
*addr = (*addr & ~mask) | (cpu_to_be64(val) & mask);
} else {
@@ -176,7 +176,7 @@ void ib_unpack(const struct ib_field *desc,
__be64 *addr;
shift = 64 - desc[i].offset_bits - desc[i].size_bits;
- mask = (~0ull >> (64 - desc[i].size_bits)) << shift;
+ mask = ((1ull << desc[i].size_bits) - 1) << shift;
addr = (__be64 *) buf + desc[i].offset_words;
val = (be64_to_cpup(addr) & mask) >> shift;
value_write(desc[i].struct_offset_bytes,
diff --git a/trunk/drivers/infiniband/core/sa_query.c b/trunk/drivers/infiniband/core/sa_query.c
index 5a08e81fa827..276e1a53010d 100644
--- a/trunk/drivers/infiniband/core/sa_query.c
+++ b/trunk/drivers/infiniband/core/sa_query.c
@@ -507,13 +507,7 @@ static int send_mad(struct ib_sa_query *query, int timeout_ms)
spin_unlock_irqrestore(&idr_lock, flags);
}
- /*
- * It's not safe to dereference query any more, because the
- * send may already have completed and freed the query in
- * another context. So use wr.wr_id, which has a copy of the
- * query's id.
- */
- return ret ? ret : wr.wr_id;
+ return ret;
}
static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,
@@ -604,15 +598,14 @@ int ib_sa_path_rec_get(struct ib_device *device, u8 port_num,
rec, query->sa_query.mad->data);
*sa_query = &query->sa_query;
-
ret = send_mad(&query->sa_query, timeout_ms);
- if (ret < 0) {
+ if (ret) {
*sa_query = NULL;
kfree(query->sa_query.mad);
kfree(query);
}
- return ret;
+ return ret ? ret : query->sa_query.id;
}
EXPORT_SYMBOL(ib_sa_path_rec_get);
@@ -681,15 +674,14 @@ int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num,
rec, query->sa_query.mad->data);
*sa_query = &query->sa_query;
-
ret = send_mad(&query->sa_query, timeout_ms);
- if (ret < 0) {
+ if (ret) {
*sa_query = NULL;
kfree(query->sa_query.mad);
kfree(query);
}
- return ret;
+ return ret ? ret : query->sa_query.id;
}
EXPORT_SYMBOL(ib_sa_mcmember_rec_query);
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_av.c b/trunk/drivers/infiniband/hw/mthca/mthca_av.c
index d58dcbe66488..085baf393ca4 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_av.c
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_av.c
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c b/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c
index 1557a522d831..cd9ed958d92f 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -431,36 +431,6 @@ static int mthca_cmd_imm(struct mthca_dev *dev,
timeout, status);
}
-int mthca_cmd_init(struct mthca_dev *dev)
-{
- sema_init(&dev->cmd.hcr_sem, 1);
- sema_init(&dev->cmd.poll_sem, 1);
- dev->cmd.use_events = 0;
-
- dev->hcr = ioremap(pci_resource_start(dev->pdev, 0) + MTHCA_HCR_BASE,
- MTHCA_HCR_SIZE);
- if (!dev->hcr) {
- mthca_err(dev, "Couldn't map command register.");
- return -ENOMEM;
- }
-
- dev->cmd.pool = pci_pool_create("mthca_cmd", dev->pdev,
- MTHCA_MAILBOX_SIZE,
- MTHCA_MAILBOX_SIZE, 0);
- if (!dev->cmd.pool) {
- iounmap(dev->hcr);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-void mthca_cmd_cleanup(struct mthca_dev *dev)
-{
- pci_pool_destroy(dev->cmd.pool);
- iounmap(dev->hcr);
-}
-
/*
* Switch to using events to issue FW commands (should be called after
* event queue to command events has been initialized).
@@ -519,33 +489,6 @@ void mthca_cmd_use_polling(struct mthca_dev *dev)
up(&dev->cmd.poll_sem);
}
-struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev,
- unsigned int gfp_mask)
-{
- struct mthca_mailbox *mailbox;
-
- mailbox = kmalloc(sizeof *mailbox, gfp_mask);
- if (!mailbox)
- return ERR_PTR(-ENOMEM);
-
- mailbox->buf = pci_pool_alloc(dev->cmd.pool, gfp_mask, &mailbox->dma);
- if (!mailbox->buf) {
- kfree(mailbox);
- return ERR_PTR(-ENOMEM);
- }
-
- return mailbox;
-}
-
-void mthca_free_mailbox(struct mthca_dev *dev, struct mthca_mailbox *mailbox)
-{
- if (!mailbox)
- return;
-
- pci_pool_free(dev->cmd.pool, mailbox->buf, mailbox->dma);
- kfree(mailbox);
-}
-
int mthca_SYS_EN(struct mthca_dev *dev, u8 *status)
{
u64 out;
@@ -570,20 +513,20 @@ int mthca_SYS_DIS(struct mthca_dev *dev, u8 *status)
static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
u64 virt, u8 *status)
{
- struct mthca_mailbox *mailbox;
+ u32 *inbox;
+ dma_addr_t indma;
struct mthca_icm_iter iter;
- __be64 *pages;
int lg;
int nent = 0;
int i;
int err = 0;
int ts = 0, tc = 0;
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- memset(mailbox->buf, 0, MTHCA_MAILBOX_SIZE);
- pages = mailbox->buf;
+ inbox = pci_alloc_consistent(dev->pdev, PAGE_SIZE, &indma);
+ if (!inbox)
+ return -ENOMEM;
+
+ memset(inbox, 0, PAGE_SIZE);
for (mthca_icm_first(icm, &iter);
!mthca_icm_last(&iter);
@@ -603,17 +546,19 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
}
for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i, ++nent) {
if (virt != -1) {
- pages[nent * 2] = cpu_to_be64(virt);
+ *((__be64 *) (inbox + nent * 4)) =
+ cpu_to_be64(virt);
virt += 1 << lg;
}
- pages[nent * 2 + 1] = cpu_to_be64((mthca_icm_addr(&iter) +
- (i << lg)) | (lg - 12));
+ *((__be64 *) (inbox + nent * 4 + 2)) =
+ cpu_to_be64((mthca_icm_addr(&iter) +
+ (i << lg)) | (lg - 12));
ts += 1 << (lg - 10);
++tc;
- if (nent == MTHCA_MAILBOX_SIZE / 16) {
- err = mthca_cmd(dev, mailbox->dma, nent, 0, op,
+ if (nent == PAGE_SIZE / 16) {
+ err = mthca_cmd(dev, indma, nent, 0, op,
CMD_TIME_CLASS_B, status);
if (err || *status)
goto out;
@@ -623,7 +568,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
}
if (nent)
- err = mthca_cmd(dev, mailbox->dma, nent, 0, op,
+ err = mthca_cmd(dev, indma, nent, 0, op,
CMD_TIME_CLASS_B, status);
switch (op) {
@@ -640,7 +585,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
}
out:
- mthca_free_mailbox(dev, mailbox);
+ pci_free_consistent(dev->pdev, PAGE_SIZE, inbox, indma);
return err;
}
@@ -661,8 +606,8 @@ int mthca_RUN_FW(struct mthca_dev *dev, u8 *status)
int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
{
- struct mthca_mailbox *mailbox;
u32 *outbox;
+ dma_addr_t outdma;
int err = 0;
u8 lg;
@@ -680,12 +625,12 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
#define QUERY_FW_EQ_ARM_BASE_OFFSET 0x40
#define QUERY_FW_EQ_SET_CI_BASE_OFFSET 0x48
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- outbox = mailbox->buf;
+ outbox = pci_alloc_consistent(dev->pdev, QUERY_FW_OUT_SIZE, &outdma);
+ if (!outbox) {
+ return -ENOMEM;
+ }
- err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_FW,
+ err = mthca_cmd_box(dev, 0, outdma, 0, 0, CMD_QUERY_FW,
CMD_TIME_CLASS_A, status);
if (err)
@@ -736,15 +681,15 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
}
out:
- mthca_free_mailbox(dev, mailbox);
+ pci_free_consistent(dev->pdev, QUERY_FW_OUT_SIZE, outbox, outdma);
return err;
}
int mthca_ENABLE_LAM(struct mthca_dev *dev, u8 *status)
{
- struct mthca_mailbox *mailbox;
u8 info;
u32 *outbox;
+ dma_addr_t outdma;
int err = 0;
#define ENABLE_LAM_OUT_SIZE 0x100
@@ -755,12 +700,11 @@ int mthca_ENABLE_LAM(struct mthca_dev *dev, u8 *status)
#define ENABLE_LAM_INFO_HIDDEN_FLAG (1 << 4)
#define ENABLE_LAM_INFO_ECC_MASK 0x3
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- outbox = mailbox->buf;
+ outbox = pci_alloc_consistent(dev->pdev, ENABLE_LAM_OUT_SIZE, &outdma);
+ if (!outbox)
+ return -ENOMEM;
- err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_ENABLE_LAM,
+ err = mthca_cmd_box(dev, 0, outdma, 0, 0, CMD_ENABLE_LAM,
CMD_TIME_CLASS_C, status);
if (err)
@@ -789,7 +733,7 @@ int mthca_ENABLE_LAM(struct mthca_dev *dev, u8 *status)
(unsigned long long) dev->ddr_end);
out:
- mthca_free_mailbox(dev, mailbox);
+ pci_free_consistent(dev->pdev, ENABLE_LAM_OUT_SIZE, outbox, outdma);
return err;
}
@@ -800,9 +744,9 @@ int mthca_DISABLE_LAM(struct mthca_dev *dev, u8 *status)
int mthca_QUERY_DDR(struct mthca_dev *dev, u8 *status)
{
- struct mthca_mailbox *mailbox;
u8 info;
u32 *outbox;
+ dma_addr_t outdma;
int err = 0;
#define QUERY_DDR_OUT_SIZE 0x100
@@ -813,12 +757,11 @@ int mthca_QUERY_DDR(struct mthca_dev *dev, u8 *status)
#define QUERY_DDR_INFO_HIDDEN_FLAG (1 << 4)
#define QUERY_DDR_INFO_ECC_MASK 0x3
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- outbox = mailbox->buf;
+ outbox = pci_alloc_consistent(dev->pdev, QUERY_DDR_OUT_SIZE, &outdma);
+ if (!outbox)
+ return -ENOMEM;
- err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_DDR,
+ err = mthca_cmd_box(dev, 0, outdma, 0, 0, CMD_QUERY_DDR,
CMD_TIME_CLASS_A, status);
if (err)
@@ -844,15 +787,15 @@ int mthca_QUERY_DDR(struct mthca_dev *dev, u8 *status)
(unsigned long long) dev->ddr_end);
out:
- mthca_free_mailbox(dev, mailbox);
+ pci_free_consistent(dev->pdev, QUERY_DDR_OUT_SIZE, outbox, outdma);
return err;
}
int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
struct mthca_dev_lim *dev_lim, u8 *status)
{
- struct mthca_mailbox *mailbox;
u32 *outbox;
+ dma_addr_t outdma;
u8 field;
u16 size;
int err;
@@ -917,12 +860,11 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
#define QUERY_DEV_LIM_LAMR_OFFSET 0x9f
#define QUERY_DEV_LIM_MAX_ICM_SZ_OFFSET 0xa0
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- outbox = mailbox->buf;
+ outbox = pci_alloc_consistent(dev->pdev, QUERY_DEV_LIM_OUT_SIZE, &outdma);
+ if (!outbox)
+ return -ENOMEM;
- err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_DEV_LIM,
+ err = mthca_cmd_box(dev, 0, outdma, 0, 0, CMD_QUERY_DEV_LIM,
CMD_TIME_CLASS_A, status);
if (err)
@@ -1078,15 +1020,15 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
}
out:
- mthca_free_mailbox(dev, mailbox);
+ pci_free_consistent(dev->pdev, QUERY_DEV_LIM_OUT_SIZE, outbox, outdma);
return err;
}
int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
struct mthca_adapter *adapter, u8 *status)
{
- struct mthca_mailbox *mailbox;
u32 *outbox;
+ dma_addr_t outdma;
int err;
#define QUERY_ADAPTER_OUT_SIZE 0x100
@@ -1095,24 +1037,23 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
#define QUERY_ADAPTER_REVISION_ID_OFFSET 0x08
#define QUERY_ADAPTER_INTA_PIN_OFFSET 0x10
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- outbox = mailbox->buf;
+ outbox = pci_alloc_consistent(dev->pdev, QUERY_ADAPTER_OUT_SIZE, &outdma);
+ if (!outbox)
+ return -ENOMEM;
- err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_ADAPTER,
+ err = mthca_cmd_box(dev, 0, outdma, 0, 0, CMD_QUERY_ADAPTER,
CMD_TIME_CLASS_A, status);
if (err)
goto out;
- MTHCA_GET(adapter->vendor_id, outbox, QUERY_ADAPTER_VENDOR_ID_OFFSET);
- MTHCA_GET(adapter->device_id, outbox, QUERY_ADAPTER_DEVICE_ID_OFFSET);
+ MTHCA_GET(adapter->vendor_id, outbox, QUERY_ADAPTER_VENDOR_ID_OFFSET);
+ MTHCA_GET(adapter->device_id, outbox, QUERY_ADAPTER_DEVICE_ID_OFFSET);
MTHCA_GET(adapter->revision_id, outbox, QUERY_ADAPTER_REVISION_ID_OFFSET);
- MTHCA_GET(adapter->inta_pin, outbox, QUERY_ADAPTER_INTA_PIN_OFFSET);
+ MTHCA_GET(adapter->inta_pin, outbox, QUERY_ADAPTER_INTA_PIN_OFFSET);
out:
- mthca_free_mailbox(dev, mailbox);
+ pci_free_consistent(dev->pdev, QUERY_DEV_LIM_OUT_SIZE, outbox, outdma);
return err;
}
@@ -1120,8 +1061,8 @@ int mthca_INIT_HCA(struct mthca_dev *dev,
struct mthca_init_hca_param *param,
u8 *status)
{
- struct mthca_mailbox *mailbox;
u32 *inbox;
+ dma_addr_t indma;
int err;
#define INIT_HCA_IN_SIZE 0x200
@@ -1161,10 +1102,9 @@ int mthca_INIT_HCA(struct mthca_dev *dev,
#define INIT_HCA_UAR_SCATCH_BASE_OFFSET (INIT_HCA_UAR_OFFSET + 0x10)
#define INIT_HCA_UAR_CTX_BASE_OFFSET (INIT_HCA_UAR_OFFSET + 0x18)
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- inbox = mailbox->buf;
+ inbox = pci_alloc_consistent(dev->pdev, INIT_HCA_IN_SIZE, &indma);
+ if (!inbox)
+ return -ENOMEM;
memset(inbox, 0, INIT_HCA_IN_SIZE);
@@ -1227,9 +1167,10 @@ int mthca_INIT_HCA(struct mthca_dev *dev,
MTHCA_PUT(inbox, param->uarc_base, INIT_HCA_UAR_CTX_BASE_OFFSET);
}
- err = mthca_cmd(dev, mailbox->dma, 0, 0, CMD_INIT_HCA, HZ, status);
+ err = mthca_cmd(dev, indma, 0, 0, CMD_INIT_HCA,
+ HZ, status);
- mthca_free_mailbox(dev, mailbox);
+ pci_free_consistent(dev->pdev, INIT_HCA_IN_SIZE, inbox, indma);
return err;
}
@@ -1237,8 +1178,8 @@ int mthca_INIT_IB(struct mthca_dev *dev,
struct mthca_init_ib_param *param,
int port, u8 *status)
{
- struct mthca_mailbox *mailbox;
u32 *inbox;
+ dma_addr_t indma;
int err;
u32 flags;
@@ -1258,10 +1199,9 @@ int mthca_INIT_IB(struct mthca_dev *dev,
#define INIT_IB_NODE_GUID_OFFSET 0x18
#define INIT_IB_SI_GUID_OFFSET 0x20
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- inbox = mailbox->buf;
+ inbox = pci_alloc_consistent(dev->pdev, INIT_IB_IN_SIZE, &indma);
+ if (!inbox)
+ return -ENOMEM;
memset(inbox, 0, INIT_IB_IN_SIZE);
@@ -1281,10 +1221,10 @@ int mthca_INIT_IB(struct mthca_dev *dev,
MTHCA_PUT(inbox, param->node_guid, INIT_IB_NODE_GUID_OFFSET);
MTHCA_PUT(inbox, param->si_guid, INIT_IB_SI_GUID_OFFSET);
- err = mthca_cmd(dev, mailbox->dma, port, 0, CMD_INIT_IB,
+ err = mthca_cmd(dev, indma, port, 0, CMD_INIT_IB,
CMD_TIME_CLASS_A, status);
- mthca_free_mailbox(dev, mailbox);
+ pci_free_consistent(dev->pdev, INIT_HCA_IN_SIZE, inbox, indma);
return err;
}
@@ -1301,8 +1241,8 @@ int mthca_CLOSE_HCA(struct mthca_dev *dev, int panic, u8 *status)
int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param,
int port, u8 *status)
{
- struct mthca_mailbox *mailbox;
u32 *inbox;
+ dma_addr_t indma;
int err;
u32 flags = 0;
@@ -1313,10 +1253,9 @@ int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param,
#define SET_IB_CAP_MASK_OFFSET 0x04
#define SET_IB_SI_GUID_OFFSET 0x08
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- inbox = mailbox->buf;
+ inbox = pci_alloc_consistent(dev->pdev, SET_IB_IN_SIZE, &indma);
+ if (!inbox)
+ return -ENOMEM;
memset(inbox, 0, SET_IB_IN_SIZE);
@@ -1327,10 +1266,10 @@ int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param,
MTHCA_PUT(inbox, param->cap_mask, SET_IB_CAP_MASK_OFFSET);
MTHCA_PUT(inbox, param->si_guid, SET_IB_SI_GUID_OFFSET);
- err = mthca_cmd(dev, mailbox->dma, port, 0, CMD_SET_IB,
+ err = mthca_cmd(dev, indma, port, 0, CMD_SET_IB,
CMD_TIME_CLASS_B, status);
- mthca_free_mailbox(dev, mailbox);
+ pci_free_consistent(dev->pdev, INIT_HCA_IN_SIZE, inbox, indma);
return err;
}
@@ -1341,22 +1280,20 @@ int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt, u8 *st
int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status)
{
- struct mthca_mailbox *mailbox;
u64 *inbox;
+ dma_addr_t indma;
int err;
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- inbox = mailbox->buf;
+ inbox = pci_alloc_consistent(dev->pdev, 16, &indma);
+ if (!inbox)
+ return -ENOMEM;
inbox[0] = cpu_to_be64(virt);
inbox[1] = cpu_to_be64(dma_addr);
- err = mthca_cmd(dev, mailbox->dma, 1, 0, CMD_MAP_ICM,
- CMD_TIME_CLASS_B, status);
+ err = mthca_cmd(dev, indma, 1, 0, CMD_MAP_ICM, CMD_TIME_CLASS_B, status);
- mthca_free_mailbox(dev, mailbox);
+ pci_free_consistent(dev->pdev, 16, inbox, indma);
if (!err)
mthca_dbg(dev, "Mapped page at %llx to %llx for ICM.\n",
@@ -1401,26 +1338,69 @@ int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages,
return 0;
}
-int mthca_SW2HW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+int mthca_SW2HW_MPT(struct mthca_dev *dev, void *mpt_entry,
int mpt_index, u8 *status)
{
- return mthca_cmd(dev, mailbox->dma, mpt_index, 0, CMD_SW2HW_MPT,
- CMD_TIME_CLASS_B, status);
+ dma_addr_t indma;
+ int err;
+
+ indma = pci_map_single(dev->pdev, mpt_entry,
+ MTHCA_MPT_ENTRY_SIZE,
+ PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(indma))
+ return -ENOMEM;
+
+ err = mthca_cmd(dev, indma, mpt_index, 0, CMD_SW2HW_MPT,
+ CMD_TIME_CLASS_B, status);
+
+ pci_unmap_single(dev->pdev, indma,
+ MTHCA_MPT_ENTRY_SIZE, PCI_DMA_TODEVICE);
+ return err;
}
-int mthca_HW2SW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+int mthca_HW2SW_MPT(struct mthca_dev *dev, void *mpt_entry,
int mpt_index, u8 *status)
{
- return mthca_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, mpt_index,
- !mailbox, CMD_HW2SW_MPT,
- CMD_TIME_CLASS_B, status);
+ dma_addr_t outdma = 0;
+ int err;
+
+ if (mpt_entry) {
+ outdma = pci_map_single(dev->pdev, mpt_entry,
+ MTHCA_MPT_ENTRY_SIZE,
+ PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(outdma))
+ return -ENOMEM;
+ }
+
+ err = mthca_cmd_box(dev, 0, outdma, mpt_index, !mpt_entry,
+ CMD_HW2SW_MPT,
+ CMD_TIME_CLASS_B, status);
+
+ if (mpt_entry)
+ pci_unmap_single(dev->pdev, outdma,
+ MTHCA_MPT_ENTRY_SIZE,
+ PCI_DMA_FROMDEVICE);
+ return err;
}
-int mthca_WRITE_MTT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+int mthca_WRITE_MTT(struct mthca_dev *dev, u64 *mtt_entry,
int num_mtt, u8 *status)
{
- return mthca_cmd(dev, mailbox->dma, num_mtt, 0, CMD_WRITE_MTT,
- CMD_TIME_CLASS_B, status);
+ dma_addr_t indma;
+ int err;
+
+ indma = pci_map_single(dev->pdev, mtt_entry,
+ (num_mtt + 2) * 8,
+ PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(indma))
+ return -ENOMEM;
+
+ err = mthca_cmd(dev, indma, num_mtt, 0, CMD_WRITE_MTT,
+ CMD_TIME_CLASS_B, status);
+
+ pci_unmap_single(dev->pdev, indma,
+ (num_mtt + 2) * 8, PCI_DMA_TODEVICE);
+ return err;
}
int mthca_SYNC_TPT(struct mthca_dev *dev, u8 *status)
@@ -1438,38 +1418,92 @@ int mthca_MAP_EQ(struct mthca_dev *dev, u64 event_mask, int unmap,
0, CMD_MAP_EQ, CMD_TIME_CLASS_B, status);
}
-int mthca_SW2HW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+int mthca_SW2HW_EQ(struct mthca_dev *dev, void *eq_context,
int eq_num, u8 *status)
{
- return mthca_cmd(dev, mailbox->dma, eq_num, 0, CMD_SW2HW_EQ,
- CMD_TIME_CLASS_A, status);
+ dma_addr_t indma;
+ int err;
+
+ indma = pci_map_single(dev->pdev, eq_context,
+ MTHCA_EQ_CONTEXT_SIZE,
+ PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(indma))
+ return -ENOMEM;
+
+ err = mthca_cmd(dev, indma, eq_num, 0, CMD_SW2HW_EQ,
+ CMD_TIME_CLASS_A, status);
+
+ pci_unmap_single(dev->pdev, indma,
+ MTHCA_EQ_CONTEXT_SIZE, PCI_DMA_TODEVICE);
+ return err;
}
-int mthca_HW2SW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+int mthca_HW2SW_EQ(struct mthca_dev *dev, void *eq_context,
int eq_num, u8 *status)
{
- return mthca_cmd_box(dev, 0, mailbox->dma, eq_num, 0,
- CMD_HW2SW_EQ,
- CMD_TIME_CLASS_A, status);
+ dma_addr_t outdma = 0;
+ int err;
+
+ outdma = pci_map_single(dev->pdev, eq_context,
+ MTHCA_EQ_CONTEXT_SIZE,
+ PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(outdma))
+ return -ENOMEM;
+
+ err = mthca_cmd_box(dev, 0, outdma, eq_num, 0,
+ CMD_HW2SW_EQ,
+ CMD_TIME_CLASS_A, status);
+
+ pci_unmap_single(dev->pdev, outdma,
+ MTHCA_EQ_CONTEXT_SIZE,
+ PCI_DMA_FROMDEVICE);
+ return err;
}
-int mthca_SW2HW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+int mthca_SW2HW_CQ(struct mthca_dev *dev, void *cq_context,
int cq_num, u8 *status)
{
- return mthca_cmd(dev, mailbox->dma, cq_num, 0, CMD_SW2HW_CQ,
+ dma_addr_t indma;
+ int err;
+
+ indma = pci_map_single(dev->pdev, cq_context,
+ MTHCA_CQ_CONTEXT_SIZE,
+ PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(indma))
+ return -ENOMEM;
+
+ err = mthca_cmd(dev, indma, cq_num, 0, CMD_SW2HW_CQ,
CMD_TIME_CLASS_A, status);
+
+ pci_unmap_single(dev->pdev, indma,
+ MTHCA_CQ_CONTEXT_SIZE, PCI_DMA_TODEVICE);
+ return err;
}
-int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+int mthca_HW2SW_CQ(struct mthca_dev *dev, void *cq_context,
int cq_num, u8 *status)
{
- return mthca_cmd_box(dev, 0, mailbox->dma, cq_num, 0,
- CMD_HW2SW_CQ,
- CMD_TIME_CLASS_A, status);
+ dma_addr_t outdma = 0;
+ int err;
+
+ outdma = pci_map_single(dev->pdev, cq_context,
+ MTHCA_CQ_CONTEXT_SIZE,
+ PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(outdma))
+ return -ENOMEM;
+
+ err = mthca_cmd_box(dev, 0, outdma, cq_num, 0,
+ CMD_HW2SW_CQ,
+ CMD_TIME_CLASS_A, status);
+
+ pci_unmap_single(dev->pdev, outdma,
+ MTHCA_CQ_CONTEXT_SIZE,
+ PCI_DMA_FROMDEVICE);
+ return err;
}
int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
- int is_ee, struct mthca_mailbox *mailbox, u32 optmask,
+ int is_ee, void *qp_context, u32 optmask,
u8 *status)
{
static const u16 op[] = {
@@ -1486,34 +1520,36 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
[MTHCA_TRANS_ANY2RST] = CMD_ERR2RST_QPEE
};
u8 op_mod = 0;
- int my_mailbox = 0;
+
+ dma_addr_t indma;
int err;
if (trans < 0 || trans >= ARRAY_SIZE(op))
return -EINVAL;
if (trans == MTHCA_TRANS_ANY2RST) {
+ indma = 0;
op_mod = 3; /* don't write outbox, any->reset */
/* For debugging */
- if (!mailbox) {
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (!IS_ERR(mailbox)) {
- my_mailbox = 1;
- op_mod = 2; /* write outbox, any->reset */
- } else
- mailbox = NULL;
- }
+ qp_context = pci_alloc_consistent(dev->pdev, MTHCA_QP_CONTEXT_SIZE,
+ &indma);
+ op_mod = 2; /* write outbox, any->reset */
} else {
+ indma = pci_map_single(dev->pdev, qp_context,
+ MTHCA_QP_CONTEXT_SIZE,
+ PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(indma))
+ return -ENOMEM;
+
if (0) {
int i;
mthca_dbg(dev, "Dumping QP context:\n");
- printk(" opt param mask: %08x\n", be32_to_cpup(mailbox->buf));
+ printk(" opt param mask: %08x\n", be32_to_cpup(qp_context));
for (i = 0; i < 0x100 / 4; ++i) {
if (i % 8 == 0)
printk(" [%02x] ", i * 4);
- printk(" %08x",
- be32_to_cpu(((u32 *) mailbox->buf)[i + 2]));
+ printk(" %08x", be32_to_cpu(((u32 *) qp_context)[i + 2]));
if ((i + 1) % 8 == 0)
printk("\n");
}
@@ -1521,39 +1557,55 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
}
if (trans == MTHCA_TRANS_ANY2RST) {
- err = mthca_cmd_box(dev, 0, mailbox ? mailbox->dma : 0,
- (!!is_ee << 24) | num, op_mod,
- op[trans], CMD_TIME_CLASS_C, status);
+ err = mthca_cmd_box(dev, 0, indma, (!!is_ee << 24) | num,
+ op_mod, op[trans], CMD_TIME_CLASS_C, status);
- if (0 && mailbox) {
+ if (0) {
int i;
mthca_dbg(dev, "Dumping QP context:\n");
- printk(" %08x\n", be32_to_cpup(mailbox->buf));
+ printk(" %08x\n", be32_to_cpup(qp_context));
for (i = 0; i < 0x100 / 4; ++i) {
if (i % 8 == 0)
printk("[%02x] ", i * 4);
- printk(" %08x",
- be32_to_cpu(((u32 *) mailbox->buf)[i + 2]));
+ printk(" %08x", be32_to_cpu(((u32 *) qp_context)[i + 2]));
if ((i + 1) % 8 == 0)
printk("\n");
}
}
} else
- err = mthca_cmd(dev, mailbox->dma, (!!is_ee << 24) | num,
+ err = mthca_cmd(dev, indma, (!!is_ee << 24) | num,
op_mod, op[trans], CMD_TIME_CLASS_C, status);
- if (my_mailbox)
- mthca_free_mailbox(dev, mailbox);
-
+ if (trans != MTHCA_TRANS_ANY2RST)
+ pci_unmap_single(dev->pdev, indma,
+ MTHCA_QP_CONTEXT_SIZE, PCI_DMA_TODEVICE);
+ else
+ pci_free_consistent(dev->pdev, MTHCA_QP_CONTEXT_SIZE,
+ qp_context, indma);
return err;
}
int mthca_QUERY_QP(struct mthca_dev *dev, u32 num, int is_ee,
- struct mthca_mailbox *mailbox, u8 *status)
+ void *qp_context, u8 *status)
{
- return mthca_cmd_box(dev, 0, mailbox->dma, (!!is_ee << 24) | num, 0,
- CMD_QUERY_QPEE, CMD_TIME_CLASS_A, status);
+ dma_addr_t outdma = 0;
+ int err;
+
+ outdma = pci_map_single(dev->pdev, qp_context,
+ MTHCA_QP_CONTEXT_SIZE,
+ PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(outdma))
+ return -ENOMEM;
+
+ err = mthca_cmd_box(dev, 0, outdma, (!!is_ee << 24) | num, 0,
+ CMD_QUERY_QPEE,
+ CMD_TIME_CLASS_A, status);
+
+ pci_unmap_single(dev->pdev, outdma,
+ MTHCA_QP_CONTEXT_SIZE,
+ PCI_DMA_FROMDEVICE);
+ return err;
}
int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn,
@@ -1583,11 +1635,11 @@ int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn,
}
int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
- int port, struct ib_wc *in_wc, struct ib_grh *in_grh,
+ int port, struct ib_wc* in_wc, struct ib_grh* in_grh,
void *in_mad, void *response_mad, u8 *status)
{
- struct mthca_mailbox *inmailbox, *outmailbox;
- void *inbox;
+ void *box;
+ dma_addr_t dma;
int err;
u32 in_modifier = port;
u8 op_modifier = 0;
@@ -1601,18 +1653,11 @@ int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
#define MAD_IFC_PKEY_OFFSET 0x10e
#define MAD_IFC_GRH_OFFSET 0x140
- inmailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(inmailbox))
- return PTR_ERR(inmailbox);
- inbox = inmailbox->buf;
-
- outmailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(outmailbox)) {
- mthca_free_mailbox(dev, inmailbox);
- return PTR_ERR(outmailbox);
- }
+ box = pci_alloc_consistent(dev->pdev, MAD_IFC_BOX_SIZE, &dma);
+ if (!box)
+ return -ENOMEM;
- memcpy(inbox, in_mad, 256);
+ memcpy(box, in_mad, 256);
/*
* Key check traps can't be generated unless we have in_wc to
@@ -1626,65 +1671,97 @@ int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
if (in_wc) {
u8 val;
- memset(inbox + 256, 0, 256);
+ memset(box + 256, 0, 256);
- MTHCA_PUT(inbox, in_wc->qp_num, MAD_IFC_MY_QPN_OFFSET);
- MTHCA_PUT(inbox, in_wc->src_qp, MAD_IFC_RQPN_OFFSET);
+ MTHCA_PUT(box, in_wc->qp_num, MAD_IFC_MY_QPN_OFFSET);
+ MTHCA_PUT(box, in_wc->src_qp, MAD_IFC_RQPN_OFFSET);
val = in_wc->sl << 4;
- MTHCA_PUT(inbox, val, MAD_IFC_SL_OFFSET);
+ MTHCA_PUT(box, val, MAD_IFC_SL_OFFSET);
val = in_wc->dlid_path_bits |
(in_wc->wc_flags & IB_WC_GRH ? 0x80 : 0);
- MTHCA_PUT(inbox, val, MAD_IFC_GRH_OFFSET);
+ MTHCA_PUT(box, val, MAD_IFC_GRH_OFFSET);
- MTHCA_PUT(inbox, in_wc->slid, MAD_IFC_RLID_OFFSET);
- MTHCA_PUT(inbox, in_wc->pkey_index, MAD_IFC_PKEY_OFFSET);
+ MTHCA_PUT(box, in_wc->slid, MAD_IFC_RLID_OFFSET);
+ MTHCA_PUT(box, in_wc->pkey_index, MAD_IFC_PKEY_OFFSET);
if (in_grh)
- memcpy(inbox + MAD_IFC_GRH_OFFSET, in_grh, 40);
+ memcpy((u8 *) box + MAD_IFC_GRH_OFFSET, in_grh, 40);
op_modifier |= 0x10;
in_modifier |= in_wc->slid << 16;
}
- err = mthca_cmd_box(dev, inmailbox->dma, outmailbox->dma,
- in_modifier, op_modifier,
+ err = mthca_cmd_box(dev, dma, dma + 512, in_modifier, op_modifier,
CMD_MAD_IFC, CMD_TIME_CLASS_C, status);
if (!err && !*status)
- memcpy(response_mad, outmailbox->buf, 256);
+ memcpy(response_mad, box + 512, 256);
- mthca_free_mailbox(dev, inmailbox);
- mthca_free_mailbox(dev, outmailbox);
+ pci_free_consistent(dev->pdev, MAD_IFC_BOX_SIZE, box, dma);
return err;
}
-int mthca_READ_MGM(struct mthca_dev *dev, int index,
- struct mthca_mailbox *mailbox, u8 *status)
+int mthca_READ_MGM(struct mthca_dev *dev, int index, void *mgm,
+ u8 *status)
{
- return mthca_cmd_box(dev, 0, mailbox->dma, index, 0,
- CMD_READ_MGM, CMD_TIME_CLASS_A, status);
+ dma_addr_t outdma = 0;
+ int err;
+
+ outdma = pci_map_single(dev->pdev, mgm,
+ MTHCA_MGM_ENTRY_SIZE,
+ PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(outdma))
+ return -ENOMEM;
+
+ err = mthca_cmd_box(dev, 0, outdma, index, 0,
+ CMD_READ_MGM,
+ CMD_TIME_CLASS_A, status);
+
+ pci_unmap_single(dev->pdev, outdma,
+ MTHCA_MGM_ENTRY_SIZE,
+ PCI_DMA_FROMDEVICE);
+ return err;
}
-int mthca_WRITE_MGM(struct mthca_dev *dev, int index,
- struct mthca_mailbox *mailbox, u8 *status)
+int mthca_WRITE_MGM(struct mthca_dev *dev, int index, void *mgm,
+ u8 *status)
{
- return mthca_cmd(dev, mailbox->dma, index, 0, CMD_WRITE_MGM,
- CMD_TIME_CLASS_A, status);
+ dma_addr_t indma;
+ int err;
+
+ indma = pci_map_single(dev->pdev, mgm,
+ MTHCA_MGM_ENTRY_SIZE,
+ PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(indma))
+ return -ENOMEM;
+
+ err = mthca_cmd(dev, indma, index, 0, CMD_WRITE_MGM,
+ CMD_TIME_CLASS_A, status);
+
+ pci_unmap_single(dev->pdev, indma,
+ MTHCA_MGM_ENTRY_SIZE, PCI_DMA_TODEVICE);
+ return err;
}
-int mthca_MGID_HASH(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- u16 *hash, u8 *status)
+int mthca_MGID_HASH(struct mthca_dev *dev, void *gid, u16 *hash,
+ u8 *status)
{
+ dma_addr_t indma;
u64 imm;
int err;
- err = mthca_cmd_imm(dev, mailbox->dma, &imm, 0, 0, CMD_MGID_HASH,
- CMD_TIME_CLASS_A, status);
+ indma = pci_map_single(dev->pdev, gid, 16, PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(indma))
+ return -ENOMEM;
+ err = mthca_cmd_imm(dev, indma, &imm, 0, 0, CMD_MGID_HASH,
+ CMD_TIME_CLASS_A, status);
*hash = imm;
+
+ pci_unmap_single(dev->pdev, indma, 16, PCI_DMA_TODEVICE);
return err;
}
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_cmd.h b/trunk/drivers/infiniband/hw/mthca/mthca_cmd.h
index ed517f175dd6..adf039b3c540 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_cmd.h
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_cmd.h
@@ -37,7 +37,8 @@
#include
-#define MTHCA_MAILBOX_SIZE 4096
+#define MTHCA_CMD_MAILBOX_ALIGN 16UL
+#define MTHCA_CMD_MAILBOX_EXTRA (MTHCA_CMD_MAILBOX_ALIGN - 1)
enum {
/* command completed successfully: */
@@ -111,11 +112,6 @@ enum {
DEV_LIM_FLAG_UD_MULTI = 1 << 21,
};
-struct mthca_mailbox {
- dma_addr_t dma;
- void *buf;
-};
-
struct mthca_dev_lim {
int max_srq_sz;
int max_qp_sz;
@@ -239,17 +235,11 @@ struct mthca_set_ib_param {
u32 cap_mask;
};
-int mthca_cmd_init(struct mthca_dev *dev);
-void mthca_cmd_cleanup(struct mthca_dev *dev);
int mthca_cmd_use_events(struct mthca_dev *dev);
void mthca_cmd_use_polling(struct mthca_dev *dev);
void mthca_cmd_event(struct mthca_dev *dev, u16 token,
u8 status, u64 out_param);
-struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev,
- unsigned int gfp_mask);
-void mthca_free_mailbox(struct mthca_dev *dev, struct mthca_mailbox *mailbox);
-
int mthca_SYS_EN(struct mthca_dev *dev, u8 *status);
int mthca_SYS_DIS(struct mthca_dev *dev, u8 *status);
int mthca_MAP_FA(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status);
@@ -280,39 +270,41 @@ int mthca_MAP_ICM_AUX(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status);
int mthca_UNMAP_ICM_AUX(struct mthca_dev *dev, u8 *status);
int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages,
u8 *status);
-int mthca_SW2HW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+int mthca_SW2HW_MPT(struct mthca_dev *dev, void *mpt_entry,
int mpt_index, u8 *status);
-int mthca_HW2SW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+int mthca_HW2SW_MPT(struct mthca_dev *dev, void *mpt_entry,
int mpt_index, u8 *status);
-int mthca_WRITE_MTT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+int mthca_WRITE_MTT(struct mthca_dev *dev, u64 *mtt_entry,
int num_mtt, u8 *status);
int mthca_SYNC_TPT(struct mthca_dev *dev, u8 *status);
int mthca_MAP_EQ(struct mthca_dev *dev, u64 event_mask, int unmap,
int eq_num, u8 *status);
-int mthca_SW2HW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+int mthca_SW2HW_EQ(struct mthca_dev *dev, void *eq_context,
int eq_num, u8 *status);
-int mthca_HW2SW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+int mthca_HW2SW_EQ(struct mthca_dev *dev, void *eq_context,
int eq_num, u8 *status);
-int mthca_SW2HW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+int mthca_SW2HW_CQ(struct mthca_dev *dev, void *cq_context,
int cq_num, u8 *status);
-int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
+int mthca_HW2SW_CQ(struct mthca_dev *dev, void *cq_context,
int cq_num, u8 *status);
int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
- int is_ee, struct mthca_mailbox *mailbox, u32 optmask,
+ int is_ee, void *qp_context, u32 optmask,
u8 *status);
int mthca_QUERY_QP(struct mthca_dev *dev, u32 num, int is_ee,
- struct mthca_mailbox *mailbox, u8 *status);
+ void *qp_context, u8 *status);
int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn,
u8 *status);
int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
- int port, struct ib_wc *in_wc, struct ib_grh *in_grh,
+ int port, struct ib_wc* in_wc, struct ib_grh* in_grh,
void *in_mad, void *response_mad, u8 *status);
-int mthca_READ_MGM(struct mthca_dev *dev, int index,
- struct mthca_mailbox *mailbox, u8 *status);
-int mthca_WRITE_MGM(struct mthca_dev *dev, int index,
- struct mthca_mailbox *mailbox, u8 *status);
-int mthca_MGID_HASH(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
- u16 *hash, u8 *status);
+int mthca_READ_MGM(struct mthca_dev *dev, int index, void *mgm,
+ u8 *status);
+int mthca_WRITE_MGM(struct mthca_dev *dev, int index, void *mgm,
+ u8 *status);
+int mthca_MGID_HASH(struct mthca_dev *dev, void *gid, u16 *hash,
+ u8 *status);
int mthca_NOP(struct mthca_dev *dev, u8 *status);
+#define MAILBOX_ALIGN(x) ((void *) ALIGN((unsigned long) (x), MTHCA_CMD_MAILBOX_ALIGN))
+
#endif /* MTHCA_CMD_H */
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_cq.c b/trunk/drivers/infiniband/hw/mthca/mthca_cq.c
index 766e9031ec45..2bf347b84c31 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -172,17 +171,6 @@ static inline void set_cqe_hw(struct mthca_cqe *cqe)
cqe->owner = MTHCA_CQ_ENTRY_OWNER_HW;
}
-static void dump_cqe(struct mthca_dev *dev, void *cqe_ptr)
-{
- __be32 *cqe = cqe_ptr;
-
- (void) cqe; /* avoid warning if mthca_dbg compiled away... */
- mthca_dbg(dev, "CQE contents %08x %08x %08x %08x %08x %08x %08x %08x\n",
- be32_to_cpu(cqe[0]), be32_to_cpu(cqe[1]), be32_to_cpu(cqe[2]),
- be32_to_cpu(cqe[3]), be32_to_cpu(cqe[4]), be32_to_cpu(cqe[5]),
- be32_to_cpu(cqe[6]), be32_to_cpu(cqe[7]));
-}
-
/*
* incr is ignored in native Arbel (mem-free) mode, so cq->cons_index
* should be correct before calling update_cons_index().
@@ -292,12 +280,16 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
int dbd;
u32 new_wqe;
- if (cqe->syndrome == SYNDROME_LOCAL_QP_OP_ERR) {
- mthca_dbg(dev, "local QP operation err "
- "(QPN %06x, WQE @ %08x, CQN %06x, index %d)\n",
- be32_to_cpu(cqe->my_qpn), be32_to_cpu(cqe->wqe),
- cq->cqn, cq->cons_index);
- dump_cqe(dev, cqe);
+ if (1 && cqe->syndrome != SYNDROME_WR_FLUSH_ERR) {
+ int j;
+
+ mthca_dbg(dev, "%x/%d: error CQE -> QPN %06x, WQE @ %08x\n",
+ cq->cqn, cq->cons_index, be32_to_cpu(cqe->my_qpn),
+ be32_to_cpu(cqe->wqe));
+
+ for (j = 0; j < 8; ++j)
+ printk(KERN_DEBUG " [%2x] %08x\n",
+ j * 4, be32_to_cpu(((u32 *) cqe)[j]));
}
/*
@@ -385,6 +377,15 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
return 0;
}
+static void dump_cqe(struct mthca_cqe *cqe)
+{
+ int j;
+
+ for (j = 0; j < 8; ++j)
+ printk(KERN_DEBUG " [%2x] %08x\n",
+ j * 4, be32_to_cpu(((u32 *) cqe)[j]));
+}
+
static inline int mthca_poll_one(struct mthca_dev *dev,
struct mthca_cq *cq,
struct mthca_qp **cur_qp,
@@ -413,7 +414,8 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
mthca_dbg(dev, "%x/%d: CQE -> QPN %06x, WQE @ %08x\n",
cq->cqn, cq->cons_index, be32_to_cpu(cqe->my_qpn),
be32_to_cpu(cqe->wqe));
- dump_cqe(dev, cqe);
+
+ dump_cqe(cqe);
}
is_error = (cqe->opcode & MTHCA_ERROR_CQE_OPCODE_MASK) ==
@@ -636,19 +638,19 @@ static void mthca_free_cq_buf(struct mthca_dev *dev, struct mthca_cq *cq)
int size;
if (cq->is_direct)
- dma_free_coherent(&dev->pdev->dev,
- (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE,
- cq->queue.direct.buf,
- pci_unmap_addr(&cq->queue.direct,
- mapping));
+ pci_free_consistent(dev->pdev,
+ (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE,
+ cq->queue.direct.buf,
+ pci_unmap_addr(&cq->queue.direct,
+ mapping));
else {
size = (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE;
for (i = 0; i < (size + PAGE_SIZE - 1) / PAGE_SIZE; ++i)
if (cq->queue.page_list[i].buf)
- dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
- cq->queue.page_list[i].buf,
- pci_unmap_addr(&cq->queue.page_list[i],
- mapping));
+ pci_free_consistent(dev->pdev, PAGE_SIZE,
+ cq->queue.page_list[i].buf,
+ pci_unmap_addr(&cq->queue.page_list[i],
+ mapping));
kfree(cq->queue.page_list);
}
@@ -668,8 +670,8 @@ static int mthca_alloc_cq_buf(struct mthca_dev *dev, int size,
npages = 1;
shift = get_order(size) + PAGE_SHIFT;
- cq->queue.direct.buf = dma_alloc_coherent(&dev->pdev->dev,
- size, &t, GFP_KERNEL);
+ cq->queue.direct.buf = pci_alloc_consistent(dev->pdev,
+ size, &t);
if (!cq->queue.direct.buf)
return -ENOMEM;
@@ -707,8 +709,7 @@ static int mthca_alloc_cq_buf(struct mthca_dev *dev, int size,
for (i = 0; i < npages; ++i) {
cq->queue.page_list[i].buf =
- dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE,
- &t, GFP_KERNEL);
+ pci_alloc_consistent(dev->pdev, PAGE_SIZE, &t);
if (!cq->queue.page_list[i].buf)
goto err_free;
@@ -745,7 +746,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
struct mthca_cq *cq)
{
int size = nent * MTHCA_CQ_ENTRY_SIZE;
- struct mthca_mailbox *mailbox;
+ void *mailbox = NULL;
struct mthca_cq_context *cq_context;
int err = -ENOMEM;
u8 status;
@@ -779,11 +780,12 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
goto err_out_ci;
}
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
- goto err_out_arm;
+ mailbox = kmalloc(sizeof (struct mthca_cq_context) + MTHCA_CMD_MAILBOX_EXTRA,
+ GFP_KERNEL);
+ if (!mailbox)
+ goto err_out_mailbox;
- cq_context = mailbox->buf;
+ cq_context = MAILBOX_ALIGN(mailbox);
err = mthca_alloc_cq_buf(dev, size, cq);
if (err)
@@ -814,7 +816,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
cq_context->state_db = cpu_to_be32(cq->arm_db_index);
}
- err = mthca_SW2HW_CQ(dev, mailbox, cq->cqn, &status);
+ err = mthca_SW2HW_CQ(dev, cq_context, cq->cqn, &status);
if (err) {
mthca_warn(dev, "SW2HW_CQ failed (%d)\n", err);
goto err_out_free_mr;
@@ -838,7 +840,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
cq->cons_index = 0;
- mthca_free_mailbox(dev, mailbox);
+ kfree(mailbox);
return 0;
@@ -847,9 +849,8 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
mthca_free_cq_buf(dev, cq);
err_out_mailbox:
- mthca_free_mailbox(dev, mailbox);
+ kfree(mailbox);
-err_out_arm:
if (mthca_is_memfree(dev))
mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index);
@@ -869,26 +870,28 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
void mthca_free_cq(struct mthca_dev *dev,
struct mthca_cq *cq)
{
- struct mthca_mailbox *mailbox;
+ void *mailbox;
int err;
u8 status;
might_sleep();
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox)) {
+ mailbox = kmalloc(sizeof (struct mthca_cq_context) + MTHCA_CMD_MAILBOX_EXTRA,
+ GFP_KERNEL);
+ if (!mailbox) {
mthca_warn(dev, "No memory for mailbox to free CQ.\n");
return;
}
- err = mthca_HW2SW_CQ(dev, mailbox, cq->cqn, &status);
+ err = mthca_HW2SW_CQ(dev, MAILBOX_ALIGN(mailbox), cq->cqn, &status);
if (err)
mthca_warn(dev, "HW2SW_CQ failed (%d)\n", err);
else if (status)
- mthca_warn(dev, "HW2SW_CQ returned status 0x%02x\n", status);
+ mthca_warn(dev, "HW2SW_CQ returned status 0x%02x\n",
+ status);
if (0) {
- u32 *ctx = mailbox->buf;
+ u32 *ctx = MAILBOX_ALIGN(mailbox);
int j;
printk(KERN_ERR "context for CQN %x (cons index %x, next sw %d)\n",
@@ -916,11 +919,11 @@ void mthca_free_cq(struct mthca_dev *dev,
if (mthca_is_memfree(dev)) {
mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index);
mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index);
+ mthca_table_put(dev, dev->cq_table.table, cq->cqn);
}
- mthca_table_put(dev, dev->cq_table.table, cq->cqn);
mthca_free(&dev->cq_table.alloc, cq->cqn);
- mthca_free_mailbox(dev, mailbox);
+ kfree(mailbox);
}
int __devinit mthca_init_cq_table(struct mthca_dev *dev)
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_dev.h b/trunk/drivers/infiniband/hw/mthca/mthca_dev.h
index 4127f09dc5ec..e3d79e267dc9 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -47,8 +46,8 @@
#define DRV_NAME "ib_mthca"
#define PFX DRV_NAME ": "
-#define DRV_VERSION "0.06"
-#define DRV_RELDATE "June 23, 2005"
+#define DRV_VERSION "0.06-pre"
+#define DRV_RELDATE "November 8, 2004"
enum {
MTHCA_FLAG_DDR_HIDDEN = 1 << 1,
@@ -99,7 +98,6 @@ enum {
};
struct mthca_cmd {
- struct pci_pool *pool;
int use_events;
struct semaphore hcr_sem;
struct semaphore poll_sem;
@@ -381,12 +379,6 @@ void mthca_uar_free(struct mthca_dev *dev, struct mthca_uar *uar);
int mthca_pd_alloc(struct mthca_dev *dev, struct mthca_pd *pd);
void mthca_pd_free(struct mthca_dev *dev, struct mthca_pd *pd);
-struct mthca_mtt *mthca_alloc_mtt(struct mthca_dev *dev, int size);
-void mthca_free_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt);
-int mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
- int start_index, u64 *buffer_list, int list_len);
-int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift,
- u64 iova, u64 total_size, u32 access, struct mthca_mr *mr);
int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd,
u32 access, struct mthca_mr *mr);
int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd,
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_doorbell.h b/trunk/drivers/infiniband/hw/mthca/mthca_doorbell.h
index 535fad7710fb..821039a49049 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_doorbell.h
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_doorbell.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_eq.c b/trunk/drivers/infiniband/hw/mthca/mthca_eq.c
index cbcf2b4722e4..f46d615d396f 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -469,7 +469,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
PAGE_SIZE;
u64 *dma_list = NULL;
dma_addr_t t;
- struct mthca_mailbox *mailbox;
+ void *mailbox = NULL;
struct mthca_eq_context *eq_context;
int err = -ENOMEM;
int i;
@@ -494,16 +494,17 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
if (!dma_list)
goto err_out_free;
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
+ mailbox = kmalloc(sizeof *eq_context + MTHCA_CMD_MAILBOX_EXTRA,
+ GFP_KERNEL);
+ if (!mailbox)
goto err_out_free;
- eq_context = mailbox->buf;
+ eq_context = MAILBOX_ALIGN(mailbox);
for (i = 0; i < npages; ++i) {
- eq->page_list[i].buf = dma_alloc_coherent(&dev->pdev->dev,
- PAGE_SIZE, &t, GFP_KERNEL);
+ eq->page_list[i].buf = pci_alloc_consistent(dev->pdev,
+ PAGE_SIZE, &t);
if (!eq->page_list[i].buf)
- goto err_out_free_pages;
+ goto err_out_free;
dma_list[i] = t;
pci_unmap_addr_set(&eq->page_list[i], mapping, t);
@@ -516,7 +517,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
eq->eqn = mthca_alloc(&dev->eq_table.alloc);
if (eq->eqn == -1)
- goto err_out_free_pages;
+ goto err_out_free;
err = mthca_mr_alloc_phys(dev, dev->driver_pd.pd_num,
dma_list, PAGE_SHIFT, npages,
@@ -547,7 +548,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
eq_context->intr = intr;
eq_context->lkey = cpu_to_be32(eq->mr.ibmr.lkey);
- err = mthca_SW2HW_EQ(dev, mailbox, eq->eqn, &status);
+ err = mthca_SW2HW_EQ(dev, eq_context, eq->eqn, &status);
if (err) {
mthca_warn(dev, "SW2HW_EQ failed (%d)\n", err);
goto err_out_free_mr;
@@ -560,7 +561,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
}
kfree(dma_list);
- mthca_free_mailbox(dev, mailbox);
+ kfree(mailbox);
eq->eqn_mask = swab32(1 << eq->eqn);
eq->cons_index = 0;
@@ -578,19 +579,17 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
err_out_free_eq:
mthca_free(&dev->eq_table.alloc, eq->eqn);
- err_out_free_pages:
+ err_out_free:
for (i = 0; i < npages; ++i)
if (eq->page_list[i].buf)
- dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
- eq->page_list[i].buf,
- pci_unmap_addr(&eq->page_list[i],
- mapping));
-
- mthca_free_mailbox(dev, mailbox);
+ pci_free_consistent(dev->pdev, PAGE_SIZE,
+ eq->page_list[i].buf,
+ pci_unmap_addr(&eq->page_list[i],
+ mapping));
- err_out_free:
kfree(eq->page_list);
kfree(dma_list);
+ kfree(mailbox);
err_out:
return err;
@@ -599,22 +598,25 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
static void mthca_free_eq(struct mthca_dev *dev,
struct mthca_eq *eq)
{
- struct mthca_mailbox *mailbox;
+ void *mailbox = NULL;
int err;
u8 status;
int npages = (eq->nent * MTHCA_EQ_ENTRY_SIZE + PAGE_SIZE - 1) /
PAGE_SIZE;
int i;
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
+ mailbox = kmalloc(sizeof (struct mthca_eq_context) + MTHCA_CMD_MAILBOX_EXTRA,
+ GFP_KERNEL);
+ if (!mailbox)
return;
- err = mthca_HW2SW_EQ(dev, mailbox, eq->eqn, &status);
+ err = mthca_HW2SW_EQ(dev, MAILBOX_ALIGN(mailbox),
+ eq->eqn, &status);
if (err)
mthca_warn(dev, "HW2SW_EQ failed (%d)\n", err);
if (status)
- mthca_warn(dev, "HW2SW_EQ returned status 0x%02x\n", status);
+ mthca_warn(dev, "HW2SW_EQ returned status 0x%02x\n",
+ status);
dev->eq_table.arm_mask &= ~eq->eqn_mask;
@@ -623,7 +625,7 @@ static void mthca_free_eq(struct mthca_dev *dev,
for (i = 0; i < sizeof (struct mthca_eq_context) / 4; ++i) {
if (i % 4 == 0)
printk("[%02x] ", i * 4);
- printk(" %08x", be32_to_cpup(mailbox->buf + i * 4));
+ printk(" %08x", be32_to_cpup(MAILBOX_ALIGN(mailbox) + i * 4));
if ((i + 1) % 4 == 0)
printk("\n");
}
@@ -636,7 +638,7 @@ static void mthca_free_eq(struct mthca_dev *dev,
pci_unmap_addr(&eq->page_list[i], mapping));
kfree(eq->page_list);
- mthca_free_mailbox(dev, mailbox);
+ kfree(mailbox);
}
static void mthca_free_irqs(struct mthca_dev *dev)
@@ -707,7 +709,8 @@ static int __devinit mthca_map_eq_regs(struct mthca_dev *dev)
if (mthca_map_reg(dev, ((pci_resource_len(dev->pdev, 0) - 1) &
dev->fw.arbel.eq_arm_base) + 4, 4,
&dev->eq_regs.arbel.eq_arm)) {
- mthca_err(dev, "Couldn't map EQ arm register, aborting.\n");
+ mthca_err(dev, "Couldn't map interrupt clear register, "
+ "aborting.\n");
mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
dev->fw.arbel.clr_int_base, MTHCA_CLR_INT_SIZE,
dev->clr_base);
@@ -718,7 +721,8 @@ static int __devinit mthca_map_eq_regs(struct mthca_dev *dev)
dev->fw.arbel.eq_set_ci_base,
MTHCA_EQ_SET_CI_SIZE,
&dev->eq_regs.arbel.eq_set_ci_base)) {
- mthca_err(dev, "Couldn't map EQ CI register, aborting.\n");
+ mthca_err(dev, "Couldn't map interrupt clear register, "
+ "aborting.\n");
mthca_unmap_reg(dev, ((pci_resource_len(dev->pdev, 0) - 1) &
dev->fw.arbel.eq_arm_base) + 4, 4,
dev->eq_regs.arbel.eq_arm);
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_main.c b/trunk/drivers/infiniband/hw/mthca/mthca_main.c
index 09519b604c08..d40590356df8 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_main.c
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -70,7 +69,7 @@ MODULE_PARM_DESC(msi, "attempt to use MSI if nonzero");
#endif /* CONFIG_PCI_MSI */
static const char mthca_version[] __devinitdata =
- DRV_NAME ": Mellanox InfiniBand HCA driver v"
+ "ib_mthca: Mellanox InfiniBand HCA driver v"
DRV_VERSION " (" DRV_RELDATE ")\n";
static struct mthca_profile default_profile = {
@@ -928,13 +927,13 @@ static int __devinit mthca_init_one(struct pci_dev *pdev,
*/
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) ||
pci_resource_len(pdev, 0) != 1 << 20) {
- dev_err(&pdev->dev, "Missing DCS, aborting.\n");
+ dev_err(&pdev->dev, "Missing DCS, aborting.");
err = -ENODEV;
goto err_disable_pdev;
}
if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM) ||
pci_resource_len(pdev, 2) != 1 << 23) {
- dev_err(&pdev->dev, "Missing UAR, aborting.\n");
+ dev_err(&pdev->dev, "Missing UAR, aborting.");
err = -ENODEV;
goto err_disable_pdev;
}
@@ -1005,18 +1004,25 @@ static int __devinit mthca_init_one(struct pci_dev *pdev,
!pci_enable_msi(pdev))
mdev->mthca_flags |= MTHCA_FLAG_MSI;
- if (mthca_cmd_init(mdev)) {
- mthca_err(mdev, "Failed to init command interface, aborting.\n");
+ sema_init(&mdev->cmd.hcr_sem, 1);
+ sema_init(&mdev->cmd.poll_sem, 1);
+ mdev->cmd.use_events = 0;
+
+ mdev->hcr = ioremap(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE, MTHCA_HCR_SIZE);
+ if (!mdev->hcr) {
+ mthca_err(mdev, "Couldn't map command register, "
+ "aborting.\n");
+ err = -ENOMEM;
goto err_free_dev;
}
err = mthca_tune_pci(mdev);
if (err)
- goto err_cmd;
+ goto err_iounmap;
err = mthca_init_hca(mdev);
if (err)
- goto err_cmd;
+ goto err_iounmap;
if (mdev->fw_ver < mthca_hca_table[id->driver_data].latest_fw) {
mthca_warn(mdev, "HCA FW version %x.%x.%x is old (%x.%x.%x is current).\n",
@@ -1064,8 +1070,8 @@ static int __devinit mthca_init_one(struct pci_dev *pdev,
err_close:
mthca_close_hca(mdev);
-err_cmd:
- mthca_cmd_cleanup(mdev);
+err_iounmap:
+ iounmap(mdev->hcr);
err_free_dev:
if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)
@@ -1112,8 +1118,10 @@ static void __devexit mthca_remove_one(struct pci_dev *pdev)
iounmap(mdev->kar);
mthca_uar_free(mdev, &mdev->driver_uar);
mthca_cleanup_uar_table(mdev);
+
mthca_close_hca(mdev);
- mthca_cmd_cleanup(mdev);
+
+ iounmap(mdev->hcr);
if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)
pci_disable_msix(pdev);
@@ -1155,7 +1163,7 @@ static struct pci_device_id mthca_pci_table[] = {
MODULE_DEVICE_TABLE(pci, mthca_pci_table);
static struct pci_driver mthca_driver = {
- .name = DRV_NAME,
+ .name = "ib_mthca",
.id_table = mthca_pci_table,
.probe = mthca_init_one,
.remove = __devexit_p(mthca_remove_one)
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_mcg.c b/trunk/drivers/infiniband/hw/mthca/mthca_mcg.c
index 5be7d949dbf6..70a6553a588e 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_mcg.c
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_mcg.c
@@ -66,23 +66,22 @@ static const u8 zero_gid[16]; /* automatically initialized to 0 */
* entry in hash chain and *mgm holds end of hash chain.
*/
static int find_mgm(struct mthca_dev *dev,
- u8 *gid, struct mthca_mailbox *mgm_mailbox,
+ u8 *gid, struct mthca_mgm *mgm,
u16 *hash, int *prev, int *index)
{
- struct mthca_mailbox *mailbox;
- struct mthca_mgm *mgm = mgm_mailbox->buf;
+ void *mailbox;
u8 *mgid;
int err;
u8 status;
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
+ mailbox = kmalloc(16 + MTHCA_CMD_MAILBOX_EXTRA, GFP_KERNEL);
+ if (!mailbox)
return -ENOMEM;
- mgid = mailbox->buf;
+ mgid = MAILBOX_ALIGN(mailbox);
memcpy(mgid, gid, 16);
- err = mthca_MGID_HASH(dev, mailbox, hash, &status);
+ err = mthca_MGID_HASH(dev, mgid, hash, &status);
if (err)
goto out;
if (status) {
@@ -104,7 +103,7 @@ static int find_mgm(struct mthca_dev *dev,
*prev = -1;
do {
- err = mthca_READ_MGM(dev, *index, mgm_mailbox, &status);
+ err = mthca_READ_MGM(dev, *index, mgm, &status);
if (err)
goto out;
if (status) {
@@ -130,14 +129,14 @@ static int find_mgm(struct mthca_dev *dev,
*index = -1;
out:
- mthca_free_mailbox(dev, mailbox);
+ kfree(mailbox);
return err;
}
int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
{
struct mthca_dev *dev = to_mdev(ibqp->device);
- struct mthca_mailbox *mailbox;
+ void *mailbox;
struct mthca_mgm *mgm;
u16 hash;
int index, prev;
@@ -146,15 +145,15 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
int err;
u8 status;
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- mgm = mailbox->buf;
+ mailbox = kmalloc(sizeof *mgm + MTHCA_CMD_MAILBOX_EXTRA, GFP_KERNEL);
+ if (!mailbox)
+ return -ENOMEM;
+ mgm = MAILBOX_ALIGN(mailbox);
if (down_interruptible(&dev->mcg_table.sem))
return -EINTR;
- err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index);
+ err = find_mgm(dev, gid->raw, mgm, &hash, &prev, &index);
if (err)
goto out;
@@ -171,7 +170,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
goto out;
}
- err = mthca_READ_MGM(dev, index, mailbox, &status);
+ err = mthca_READ_MGM(dev, index, mgm, &status);
if (err)
goto out;
if (status) {
@@ -196,7 +195,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
goto out;
}
- err = mthca_WRITE_MGM(dev, index, mailbox, &status);
+ err = mthca_WRITE_MGM(dev, index, mgm, &status);
if (err)
goto out;
if (status) {
@@ -207,7 +206,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
if (!link)
goto out;
- err = mthca_READ_MGM(dev, prev, mailbox, &status);
+ err = mthca_READ_MGM(dev, prev, mgm, &status);
if (err)
goto out;
if (status) {
@@ -218,7 +217,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
mgm->next_gid_index = cpu_to_be32(index << 5);
- err = mthca_WRITE_MGM(dev, prev, mailbox, &status);
+ err = mthca_WRITE_MGM(dev, prev, mgm, &status);
if (err)
goto out;
if (status) {
@@ -228,14 +227,14 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
out:
up(&dev->mcg_table.sem);
- mthca_free_mailbox(dev, mailbox);
+ kfree(mailbox);
return err;
}
int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
{
struct mthca_dev *dev = to_mdev(ibqp->device);
- struct mthca_mailbox *mailbox;
+ void *mailbox;
struct mthca_mgm *mgm;
u16 hash;
int prev, index;
@@ -243,15 +242,15 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
int err;
u8 status;
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- mgm = mailbox->buf;
+ mailbox = kmalloc(sizeof *mgm + MTHCA_CMD_MAILBOX_EXTRA, GFP_KERNEL);
+ if (!mailbox)
+ return -ENOMEM;
+ mgm = MAILBOX_ALIGN(mailbox);
if (down_interruptible(&dev->mcg_table.sem))
return -EINTR;
- err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index);
+ err = find_mgm(dev, gid->raw, mgm, &hash, &prev, &index);
if (err)
goto out;
@@ -286,7 +285,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
mgm->qp[loc] = mgm->qp[i - 1];
mgm->qp[i - 1] = 0;
- err = mthca_WRITE_MGM(dev, index, mailbox, &status);
+ err = mthca_WRITE_MGM(dev, index, mgm, &status);
if (err)
goto out;
if (status) {
@@ -305,7 +304,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
if (be32_to_cpu(mgm->next_gid_index) >> 5) {
err = mthca_READ_MGM(dev,
be32_to_cpu(mgm->next_gid_index) >> 5,
- mailbox, &status);
+ mgm, &status);
if (err)
goto out;
if (status) {
@@ -317,7 +316,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
} else
memset(mgm->gid, 0, 16);
- err = mthca_WRITE_MGM(dev, index, mailbox, &status);
+ err = mthca_WRITE_MGM(dev, index, mgm, &status);
if (err)
goto out;
if (status) {
@@ -328,7 +327,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
} else {
/* Remove entry from AMGM */
index = be32_to_cpu(mgm->next_gid_index) >> 5;
- err = mthca_READ_MGM(dev, prev, mailbox, &status);
+ err = mthca_READ_MGM(dev, prev, mgm, &status);
if (err)
goto out;
if (status) {
@@ -339,7 +338,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
mgm->next_gid_index = cpu_to_be32(index << 5);
- err = mthca_WRITE_MGM(dev, prev, mailbox, &status);
+ err = mthca_WRITE_MGM(dev, prev, mgm, &status);
if (err)
goto out;
if (status) {
@@ -351,7 +350,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
out:
up(&dev->mcg_table.sem);
- mthca_free_mailbox(dev, mailbox);
+ kfree(mailbox);
return err;
}
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_memfree.c b/trunk/drivers/infiniband/hw/mthca/mthca_memfree.c
index 6d3b05dd9e3f..637b30e35592 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -179,14 +179,9 @@ int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int ob
void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int obj)
{
- int i;
+ int i = (obj & (table->num_obj - 1)) * table->obj_size / MTHCA_TABLE_CHUNK_SIZE;
u8 status;
- if (!mthca_is_memfree(dev))
- return;
-
- i = (obj & (table->num_obj - 1)) * table->obj_size / MTHCA_TABLE_CHUNK_SIZE;
-
down(&table->mutex);
if (--table->icm[i]->refcount == 0) {
@@ -261,9 +256,6 @@ void mthca_table_put_range(struct mthca_dev *dev, struct mthca_icm_table *table,
{
int i;
- if (!mthca_is_memfree(dev))
- return;
-
for (i = start; i <= end; i += MTHCA_TABLE_CHUNK_SIZE / table->obj_size)
mthca_table_put(dev, table, i);
}
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_mr.c b/trunk/drivers/infiniband/hw/mthca/mthca_mr.c
index cbe50feaf680..8960fc2306be 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -40,12 +40,6 @@
#include "mthca_cmd.h"
#include "mthca_memfree.h"
-struct mthca_mtt {
- struct mthca_buddy *buddy;
- int order;
- u32 first_seg;
-};
-
/*
* Must be packed because mtt_seg is 64 bits but only aligned to 32 bits.
*/
@@ -179,8 +173,8 @@ static void __devexit mthca_buddy_cleanup(struct mthca_buddy *buddy)
kfree(buddy->bits);
}
-static u32 mthca_alloc_mtt_range(struct mthca_dev *dev, int order,
- struct mthca_buddy *buddy)
+static u32 mthca_alloc_mtt(struct mthca_dev *dev, int order,
+ struct mthca_buddy *buddy)
{
u32 seg = mthca_buddy_alloc(buddy, order);
@@ -197,102 +191,14 @@ static u32 mthca_alloc_mtt_range(struct mthca_dev *dev, int order,
return seg;
}
-static struct mthca_mtt *__mthca_alloc_mtt(struct mthca_dev *dev, int size,
- struct mthca_buddy *buddy)
-{
- struct mthca_mtt *mtt;
- int i;
-
- if (size <= 0)
- return ERR_PTR(-EINVAL);
-
- mtt = kmalloc(sizeof *mtt, GFP_KERNEL);
- if (!mtt)
- return ERR_PTR(-ENOMEM);
-
- mtt->buddy = buddy;
- mtt->order = 0;
- for (i = MTHCA_MTT_SEG_SIZE / 8; i < size; i <<= 1)
- ++mtt->order;
-
- mtt->first_seg = mthca_alloc_mtt_range(dev, mtt->order, buddy);
- if (mtt->first_seg == -1) {
- kfree(mtt);
- return ERR_PTR(-ENOMEM);
- }
-
- return mtt;
-}
-
-struct mthca_mtt *mthca_alloc_mtt(struct mthca_dev *dev, int size)
-{
- return __mthca_alloc_mtt(dev, size, &dev->mr_table.mtt_buddy);
-}
-
-void mthca_free_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt)
-{
- if (!mtt)
- return;
-
- mthca_buddy_free(mtt->buddy, mtt->first_seg, mtt->order);
-
- mthca_table_put_range(dev, dev->mr_table.mtt_table,
- mtt->first_seg,
- mtt->first_seg + (1 << mtt->order) - 1);
-
- kfree(mtt);
-}
-
-int mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
- int start_index, u64 *buffer_list, int list_len)
+static void mthca_free_mtt(struct mthca_dev *dev, u32 seg, int order,
+ struct mthca_buddy* buddy)
{
- struct mthca_mailbox *mailbox;
- u64 *mtt_entry;
- int err = 0;
- u8 status;
- int i;
+ mthca_buddy_free(buddy, seg, order);
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- mtt_entry = mailbox->buf;
-
- while (list_len > 0) {
- mtt_entry[0] = cpu_to_be64(dev->mr_table.mtt_base +
- mtt->first_seg * MTHCA_MTT_SEG_SIZE +
- start_index * 8);
- mtt_entry[1] = 0;
- for (i = 0; i < list_len && i < MTHCA_MAILBOX_SIZE / 8 - 2; ++i)
- mtt_entry[i + 2] = cpu_to_be64(buffer_list[i] |
- MTHCA_MTT_FLAG_PRESENT);
-
- /*
- * If we have an odd number of entries to write, add
- * one more dummy entry for firmware efficiency.
- */
- if (i & 1)
- mtt_entry[i + 2] = 0;
-
- err = mthca_WRITE_MTT(dev, mailbox, (i + 1) & ~1, &status);
- if (err) {
- mthca_warn(dev, "WRITE_MTT failed (%d)\n", err);
- goto out;
- }
- if (status) {
- mthca_warn(dev, "WRITE_MTT returned status 0x%02x\n",
- status);
- err = -EINVAL;
- goto out;
- }
-
- list_len -= i;
- start_index += i;
- buffer_list += i;
- }
-
-out:
- mthca_free_mailbox(dev, mailbox);
- return err;
+ if (mthca_is_memfree(dev))
+ mthca_table_put_range(dev, dev->mr_table.mtt_table, seg,
+ seg + (1 << order) - 1);
}
static inline u32 tavor_hw_index_to_key(u32 ind)
@@ -331,20 +237,18 @@ static inline u32 key_to_hw_index(struct mthca_dev *dev, u32 key)
return tavor_key_to_hw_index(key);
}
-int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift,
- u64 iova, u64 total_size, u32 access, struct mthca_mr *mr)
+int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd,
+ u32 access, struct mthca_mr *mr)
{
- struct mthca_mailbox *mailbox;
+ void *mailbox = NULL;
struct mthca_mpt_entry *mpt_entry;
u32 key;
- int i;
int err;
u8 status;
might_sleep();
- WARN_ON(buffer_size_shift >= 32);
-
+ mr->order = -1;
key = mthca_alloc(&dev->mr_table.mpt_alloc);
if (key == -1)
return -ENOMEM;
@@ -356,109 +260,201 @@ int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift,
goto err_out_mpt_free;
}
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox)) {
- err = PTR_ERR(mailbox);
+ mailbox = kmalloc(sizeof *mpt_entry + MTHCA_CMD_MAILBOX_EXTRA,
+ GFP_KERNEL);
+ if (!mailbox) {
+ err = -ENOMEM;
goto err_out_table;
}
- mpt_entry = mailbox->buf;
+ mpt_entry = MAILBOX_ALIGN(mailbox);
mpt_entry->flags = cpu_to_be32(MTHCA_MPT_FLAG_SW_OWNS |
MTHCA_MPT_FLAG_MIO |
+ MTHCA_MPT_FLAG_PHYSICAL |
MTHCA_MPT_FLAG_REGION |
access);
- if (!mr->mtt)
- mpt_entry->flags |= cpu_to_be32(MTHCA_MPT_FLAG_PHYSICAL);
-
- mpt_entry->page_size = cpu_to_be32(buffer_size_shift - 12);
+ mpt_entry->page_size = 0;
mpt_entry->key = cpu_to_be32(key);
mpt_entry->pd = cpu_to_be32(pd);
- mpt_entry->start = cpu_to_be64(iova);
- mpt_entry->length = cpu_to_be64(total_size);
+ mpt_entry->start = 0;
+ mpt_entry->length = ~0ULL;
memset(&mpt_entry->lkey, 0,
sizeof *mpt_entry - offsetof(struct mthca_mpt_entry, lkey));
- if (mr->mtt)
- mpt_entry->mtt_seg =
- cpu_to_be64(dev->mr_table.mtt_base +
- mr->mtt->first_seg * MTHCA_MTT_SEG_SIZE);
-
- if (0) {
- mthca_dbg(dev, "Dumping MPT entry %08x:\n", mr->ibmr.lkey);
- for (i = 0; i < sizeof (struct mthca_mpt_entry) / 4; ++i) {
- if (i % 4 == 0)
- printk("[%02x] ", i * 4);
- printk(" %08x", be32_to_cpu(((u32 *) mpt_entry)[i]));
- if ((i + 1) % 4 == 0)
- printk("\n");
- }
- }
-
- err = mthca_SW2HW_MPT(dev, mailbox,
+ err = mthca_SW2HW_MPT(dev, mpt_entry,
key & (dev->limits.num_mpts - 1),
&status);
if (err) {
mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err);
- goto err_out_mailbox;
+ goto err_out_table;
} else if (status) {
mthca_warn(dev, "SW2HW_MPT returned status 0x%02x\n",
status);
err = -EINVAL;
- goto err_out_mailbox;
+ goto err_out_table;
}
- mthca_free_mailbox(dev, mailbox);
+ kfree(mailbox);
return err;
-err_out_mailbox:
- mthca_free_mailbox(dev, mailbox);
-
err_out_table:
- mthca_table_put(dev, dev->mr_table.mpt_table, key);
+ if (mthca_is_memfree(dev))
+ mthca_table_put(dev, dev->mr_table.mpt_table, key);
err_out_mpt_free:
mthca_free(&dev->mr_table.mpt_alloc, key);
+ kfree(mailbox);
return err;
}
-int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd,
- u32 access, struct mthca_mr *mr)
-{
- mr->mtt = NULL;
- return mthca_mr_alloc(dev, pd, 12, 0, ~0ULL, access, mr);
-}
-
int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd,
u64 *buffer_list, int buffer_size_shift,
int list_len, u64 iova, u64 total_size,
u32 access, struct mthca_mr *mr)
{
- int err;
+ void *mailbox;
+ u64 *mtt_entry;
+ struct mthca_mpt_entry *mpt_entry;
+ u32 key;
+ int err = -ENOMEM;
+ u8 status;
+ int i;
+
+ might_sleep();
+ WARN_ON(buffer_size_shift >= 32);
+
+ key = mthca_alloc(&dev->mr_table.mpt_alloc);
+ if (key == -1)
+ return -ENOMEM;
+ mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key);
+
+ if (mthca_is_memfree(dev)) {
+ err = mthca_table_get(dev, dev->mr_table.mpt_table, key);
+ if (err)
+ goto err_out_mpt_free;
+ }
- mr->mtt = mthca_alloc_mtt(dev, list_len);
- if (IS_ERR(mr->mtt))
- return PTR_ERR(mr->mtt);
+ for (i = MTHCA_MTT_SEG_SIZE / 8, mr->order = 0;
+ i < list_len;
+ i <<= 1, ++mr->order)
+ ; /* nothing */
+
+ mr->first_seg = mthca_alloc_mtt(dev, mr->order,
+ &dev->mr_table.mtt_buddy);
+ if (mr->first_seg == -1)
+ goto err_out_table;
+
+ /*
+ * If list_len is odd, we add one more dummy entry for
+ * firmware efficiency.
+ */
+ mailbox = kmalloc(max(sizeof *mpt_entry,
+ (size_t) 8 * (list_len + (list_len & 1) + 2)) +
+ MTHCA_CMD_MAILBOX_EXTRA,
+ GFP_KERNEL);
+ if (!mailbox)
+ goto err_out_free_mtt;
+
+ mtt_entry = MAILBOX_ALIGN(mailbox);
+
+ mtt_entry[0] = cpu_to_be64(dev->mr_table.mtt_base +
+ mr->first_seg * MTHCA_MTT_SEG_SIZE);
+ mtt_entry[1] = 0;
+ for (i = 0; i < list_len; ++i)
+ mtt_entry[i + 2] = cpu_to_be64(buffer_list[i] |
+ MTHCA_MTT_FLAG_PRESENT);
+ if (list_len & 1) {
+ mtt_entry[i + 2] = 0;
+ ++list_len;
+ }
+
+ if (0) {
+ mthca_dbg(dev, "Dumping MPT entry\n");
+ for (i = 0; i < list_len + 2; ++i)
+ printk(KERN_ERR "[%2d] %016llx\n",
+ i, (unsigned long long) be64_to_cpu(mtt_entry[i]));
+ }
- err = mthca_write_mtt(dev, mr->mtt, 0, buffer_list, list_len);
+ err = mthca_WRITE_MTT(dev, mtt_entry, list_len, &status);
if (err) {
- mthca_free_mtt(dev, mr->mtt);
- return err;
+ mthca_warn(dev, "WRITE_MTT failed (%d)\n", err);
+ goto err_out_mailbox_free;
+ }
+ if (status) {
+ mthca_warn(dev, "WRITE_MTT returned status 0x%02x\n",
+ status);
+ err = -EINVAL;
+ goto err_out_mailbox_free;
}
- err = mthca_mr_alloc(dev, pd, buffer_size_shift, iova,
- total_size, access, mr);
+ mpt_entry = MAILBOX_ALIGN(mailbox);
+
+ mpt_entry->flags = cpu_to_be32(MTHCA_MPT_FLAG_SW_OWNS |
+ MTHCA_MPT_FLAG_MIO |
+ MTHCA_MPT_FLAG_REGION |
+ access);
+
+ mpt_entry->page_size = cpu_to_be32(buffer_size_shift - 12);
+ mpt_entry->key = cpu_to_be32(key);
+ mpt_entry->pd = cpu_to_be32(pd);
+ mpt_entry->start = cpu_to_be64(iova);
+ mpt_entry->length = cpu_to_be64(total_size);
+ memset(&mpt_entry->lkey, 0,
+ sizeof *mpt_entry - offsetof(struct mthca_mpt_entry, lkey));
+ mpt_entry->mtt_seg = cpu_to_be64(dev->mr_table.mtt_base +
+ mr->first_seg * MTHCA_MTT_SEG_SIZE);
+
+ if (0) {
+ mthca_dbg(dev, "Dumping MPT entry %08x:\n", mr->ibmr.lkey);
+ for (i = 0; i < sizeof (struct mthca_mpt_entry) / 4; ++i) {
+ if (i % 4 == 0)
+ printk("[%02x] ", i * 4);
+ printk(" %08x", be32_to_cpu(((u32 *) mpt_entry)[i]));
+ if ((i + 1) % 4 == 0)
+ printk("\n");
+ }
+ }
+
+ err = mthca_SW2HW_MPT(dev, mpt_entry,
+ key & (dev->limits.num_mpts - 1),
+ &status);
if (err)
- mthca_free_mtt(dev, mr->mtt);
+ mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err);
+ else if (status) {
+ mthca_warn(dev, "SW2HW_MPT returned status 0x%02x\n",
+ status);
+ err = -EINVAL;
+ }
+
+ kfree(mailbox);
+ return err;
+
+err_out_mailbox_free:
+ kfree(mailbox);
+
+err_out_free_mtt:
+ mthca_free_mtt(dev, mr->first_seg, mr->order, &dev->mr_table.mtt_buddy);
+
+err_out_table:
+ if (mthca_is_memfree(dev))
+ mthca_table_put(dev, dev->mr_table.mpt_table, key);
+err_out_mpt_free:
+ mthca_free(&dev->mr_table.mpt_alloc, key);
return err;
}
/* Free mr or fmr */
-static void mthca_free_region(struct mthca_dev *dev, u32 lkey)
+static void mthca_free_region(struct mthca_dev *dev, u32 lkey, int order,
+ u32 first_seg, struct mthca_buddy *buddy)
{
- mthca_table_put(dev, dev->mr_table.mpt_table,
- arbel_key_to_hw_index(lkey));
+ if (order >= 0)
+ mthca_free_mtt(dev, first_seg, order, buddy);
+
+ if (mthca_is_memfree(dev))
+ mthca_table_put(dev, dev->mr_table.mpt_table,
+ arbel_key_to_hw_index(lkey));
mthca_free(&dev->mr_table.mpt_alloc, key_to_hw_index(dev, lkey));
}
@@ -480,15 +476,15 @@ void mthca_free_mr(struct mthca_dev *dev, struct mthca_mr *mr)
mthca_warn(dev, "HW2SW_MPT returned status 0x%02x\n",
status);
- mthca_free_region(dev, mr->ibmr.lkey);
- mthca_free_mtt(dev, mr->mtt);
+ mthca_free_region(dev, mr->ibmr.lkey, mr->order, mr->first_seg,
+ &dev->mr_table.mtt_buddy);
}
int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd,
u32 access, struct mthca_fmr *mr)
{
struct mthca_mpt_entry *mpt_entry;
- struct mthca_mailbox *mailbox;
+ void *mailbox;
u64 mtt_seg;
u32 key, idx;
u8 status;
@@ -526,24 +522,31 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd,
mr->mem.tavor.mpt = dev->mr_table.tavor_fmr.mpt_base +
sizeof *(mr->mem.tavor.mpt) * idx;
- mr->mtt = __mthca_alloc_mtt(dev, list_len, dev->mr_table.fmr_mtt_buddy);
- if (IS_ERR(mr->mtt))
+ for (i = MTHCA_MTT_SEG_SIZE / 8, mr->order = 0;
+ i < list_len;
+ i <<= 1, ++mr->order)
+ ; /* nothing */
+
+ mr->first_seg = mthca_alloc_mtt(dev, mr->order,
+ dev->mr_table.fmr_mtt_buddy);
+ if (mr->first_seg == -1)
goto err_out_table;
- mtt_seg = mr->mtt->first_seg * MTHCA_MTT_SEG_SIZE;
+ mtt_seg = mr->first_seg * MTHCA_MTT_SEG_SIZE;
if (mthca_is_memfree(dev)) {
mr->mem.arbel.mtts = mthca_table_find(dev->mr_table.mtt_table,
- mr->mtt->first_seg);
+ mr->first_seg);
BUG_ON(!mr->mem.arbel.mtts);
} else
mr->mem.tavor.mtts = dev->mr_table.tavor_fmr.mtt_base + mtt_seg;
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
+ mailbox = kmalloc(sizeof *mpt_entry + MTHCA_CMD_MAILBOX_EXTRA,
+ GFP_KERNEL);
+ if (!mailbox)
goto err_out_free_mtt;
- mpt_entry = mailbox->buf;
+ mpt_entry = MAILBOX_ALIGN(mailbox);
mpt_entry->flags = cpu_to_be32(MTHCA_MPT_FLAG_SW_OWNS |
MTHCA_MPT_FLAG_MIO |
@@ -568,7 +571,7 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd,
}
}
- err = mthca_SW2HW_MPT(dev, mailbox,
+ err = mthca_SW2HW_MPT(dev, mpt_entry,
key & (dev->limits.num_mpts - 1),
&status);
if (err) {
@@ -582,17 +585,19 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd,
goto err_out_mailbox_free;
}
- mthca_free_mailbox(dev, mailbox);
+ kfree(mailbox);
return 0;
err_out_mailbox_free:
- mthca_free_mailbox(dev, mailbox);
+ kfree(mailbox);
err_out_free_mtt:
- mthca_free_mtt(dev, mr->mtt);
+ mthca_free_mtt(dev, mr->first_seg, mr->order,
+ dev->mr_table.fmr_mtt_buddy);
err_out_table:
- mthca_table_put(dev, dev->mr_table.mpt_table, key);
+ if (mthca_is_memfree(dev))
+ mthca_table_put(dev, dev->mr_table.mpt_table, key);
err_out_mpt_free:
mthca_free(&dev->mr_table.mpt_alloc, mr->ibmr.lkey);
@@ -604,9 +609,8 @@ int mthca_free_fmr(struct mthca_dev *dev, struct mthca_fmr *fmr)
if (fmr->maps)
return -EBUSY;
- mthca_free_region(dev, fmr->ibmr.lkey);
- mthca_free_mtt(dev, fmr->mtt);
-
+ mthca_free_region(dev, fmr->ibmr.lkey, fmr->order, fmr->first_seg,
+ dev->mr_table.fmr_mtt_buddy);
return 0;
}
@@ -822,8 +826,7 @@ int __devinit mthca_init_mr_table(struct mthca_dev *dev)
if (dev->limits.reserved_mtts) {
i = fls(dev->limits.reserved_mtts - 1);
- if (mthca_alloc_mtt_range(dev, i,
- dev->mr_table.fmr_mtt_buddy) == -1) {
+ if (mthca_alloc_mtt(dev, i, dev->mr_table.fmr_mtt_buddy) == -1) {
mthca_warn(dev, "MTT table of order %d is too small.\n",
dev->mr_table.fmr_mtt_buddy->max_order);
err = -ENOMEM;
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_provider.c b/trunk/drivers/infiniband/hw/mthca/mthca_provider.c
index 0b5adfd91597..159f4e6c312d 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -53,7 +52,7 @@ static int mthca_query_device(struct ib_device *ibdev,
if (!in_mad || !out_mad)
goto out;
- memset(props, 0, sizeof *props);
+ memset(props, 0, sizeof props);
props->fw_ver = mdev->fw_ver;
@@ -559,7 +558,6 @@ static struct ib_mr *mthca_reg_phys_mr(struct ib_pd *pd,
convert_access(acc), mr);
if (err) {
- kfree(page_list);
kfree(mr);
return ERR_PTR(err);
}
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_provider.h b/trunk/drivers/infiniband/hw/mthca/mthca_provider.h
index 4d976cccb1a8..619710f95a87 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_provider.h
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_provider.h
@@ -54,18 +54,18 @@ struct mthca_uar {
int index;
};
-struct mthca_mtt;
-
struct mthca_mr {
- struct ib_mr ibmr;
- struct mthca_mtt *mtt;
+ struct ib_mr ibmr;
+ int order;
+ u32 first_seg;
};
struct mthca_fmr {
- struct ib_fmr ibmr;
+ struct ib_fmr ibmr;
struct ib_fmr_attr attr;
- struct mthca_mtt *mtt;
- int maps;
+ int order;
+ u32 first_seg;
+ int maps;
union {
struct {
struct mthca_mpt_entry __iomem *mpt;
diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_qp.c b/trunk/drivers/infiniband/hw/mthca/mthca_qp.c
index 163a8ef4186f..ca73bab11a02 100644
--- a/trunk/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/trunk/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -357,9 +357,6 @@ static const struct {
[UD] = (IB_QP_PKEY_INDEX |
IB_QP_PORT |
IB_QP_QKEY),
- [UC] = (IB_QP_PKEY_INDEX |
- IB_QP_PORT |
- IB_QP_ACCESS_FLAGS),
[RC] = (IB_QP_PKEY_INDEX |
IB_QP_PORT |
IB_QP_ACCESS_FLAGS),
@@ -381,9 +378,6 @@ static const struct {
[UD] = (IB_QP_PKEY_INDEX |
IB_QP_PORT |
IB_QP_QKEY),
- [UC] = (IB_QP_PKEY_INDEX |
- IB_QP_PORT |
- IB_QP_ACCESS_FLAGS),
[RC] = (IB_QP_PKEY_INDEX |
IB_QP_PORT |
IB_QP_ACCESS_FLAGS),
@@ -394,11 +388,6 @@ static const struct {
[IB_QPS_RTR] = {
.trans = MTHCA_TRANS_INIT2RTR,
.req_param = {
- [UC] = (IB_QP_AV |
- IB_QP_PATH_MTU |
- IB_QP_DEST_QPN |
- IB_QP_RQ_PSN |
- IB_QP_MAX_DEST_RD_ATOMIC),
[RC] = (IB_QP_AV |
IB_QP_PATH_MTU |
IB_QP_DEST_QPN |
@@ -409,9 +398,6 @@ static const struct {
.opt_param = {
[UD] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY),
- [UC] = (IB_QP_ALT_PATH |
- IB_QP_ACCESS_FLAGS |
- IB_QP_PKEY_INDEX),
[RC] = (IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
IB_QP_PKEY_INDEX),
@@ -427,8 +413,6 @@ static const struct {
.trans = MTHCA_TRANS_RTR2RTS,
.req_param = {
[UD] = IB_QP_SQ_PSN,
- [UC] = (IB_QP_SQ_PSN |
- IB_QP_MAX_QP_RD_ATOMIC),
[RC] = (IB_QP_TIMEOUT |
IB_QP_RETRY_CNT |
IB_QP_RNR_RETRY |
@@ -439,11 +423,6 @@ static const struct {
.opt_param = {
[UD] = (IB_QP_CUR_STATE |
IB_QP_QKEY),
- [UC] = (IB_QP_CUR_STATE |
- IB_QP_ALT_PATH |
- IB_QP_ACCESS_FLAGS |
- IB_QP_PKEY_INDEX |
- IB_QP_PATH_MIG_STATE),
[RC] = (IB_QP_CUR_STATE |
IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
@@ -463,9 +442,6 @@ static const struct {
.opt_param = {
[UD] = (IB_QP_CUR_STATE |
IB_QP_QKEY),
- [UC] = (IB_QP_ACCESS_FLAGS |
- IB_QP_ALT_PATH |
- IB_QP_PATH_MIG_STATE),
[RC] = (IB_QP_ACCESS_FLAGS |
IB_QP_ALT_PATH |
IB_QP_PATH_MIG_STATE |
@@ -486,10 +462,6 @@ static const struct {
.opt_param = {
[UD] = (IB_QP_CUR_STATE |
IB_QP_QKEY),
- [UC] = (IB_QP_CUR_STATE |
- IB_QP_ALT_PATH |
- IB_QP_ACCESS_FLAGS |
- IB_QP_PATH_MIG_STATE),
[RC] = (IB_QP_CUR_STATE |
IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
@@ -504,14 +476,6 @@ static const struct {
.opt_param = {
[UD] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY),
- [UC] = (IB_QP_AV |
- IB_QP_MAX_QP_RD_ATOMIC |
- IB_QP_MAX_DEST_RD_ATOMIC |
- IB_QP_CUR_STATE |
- IB_QP_ALT_PATH |
- IB_QP_ACCESS_FLAGS |
- IB_QP_PKEY_INDEX |
- IB_QP_PATH_MIG_STATE),
[RC] = (IB_QP_AV |
IB_QP_TIMEOUT |
IB_QP_RETRY_CNT |
@@ -537,7 +501,6 @@ static const struct {
.opt_param = {
[UD] = (IB_QP_CUR_STATE |
IB_QP_QKEY),
- [UC] = (IB_QP_CUR_STATE),
[RC] = (IB_QP_CUR_STATE |
IB_QP_MIN_RNR_TIMER),
[MLX] = (IB_QP_CUR_STATE |
@@ -589,7 +552,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
struct mthca_dev *dev = to_mdev(ibqp->device);
struct mthca_qp *qp = to_mqp(ibqp);
enum ib_qp_state cur_state, new_state;
- struct mthca_mailbox *mailbox;
+ void *mailbox = NULL;
struct mthca_qp_param *qp_param;
struct mthca_qp_context *qp_context;
u32 req_param, opt_param;
@@ -646,10 +609,10 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
return -EINVAL;
}
- mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- qp_param = mailbox->buf;
+ mailbox = kmalloc(sizeof (*qp_param) + MTHCA_CMD_MAILBOX_EXTRA, GFP_KERNEL);
+ if (!mailbox)
+ return -ENOMEM;
+ qp_param = MAILBOX_ALIGN(mailbox);
qp_context = &qp_param->context;
memset(qp_param, 0, sizeof *qp_param);
@@ -720,7 +683,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
if (attr_mask & IB_QP_AV) {
qp_context->pri_path.g_mylmc = attr->ah_attr.src_path_bits & 0x7f;
qp_context->pri_path.rlid = cpu_to_be16(attr->ah_attr.dlid);
- qp_context->pri_path.static_rate = !!attr->ah_attr.static_rate;
+ qp_context->pri_path.static_rate = (!!attr->ah_attr.static_rate) << 3;
if (attr->ah_attr.ah_flags & IB_AH_GRH) {
qp_context->pri_path.g_mylmc |= 1 << 7;
qp_context->pri_path.mgid_index = attr->ah_attr.grh.sgid_index;
@@ -761,9 +724,9 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RETRY_COUNT);
}
- if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) {
- qp_context->params1 |= cpu_to_be32(min(attr->max_rd_atomic ?
- ffs(attr->max_rd_atomic) - 1 : 0,
+ if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
+ qp_context->params1 |= cpu_to_be32(min(attr->max_dest_rd_atomic ?
+ ffs(attr->max_dest_rd_atomic) - 1 : 0,
7) << 21);
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_SRA_MAX);
}
@@ -801,10 +764,10 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
qp->atomic_rd_en = attr->qp_access_flags;
}
- if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
+ if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) {
u8 rra_max;
- if (qp->resp_depth && !attr->max_dest_rd_atomic) {
+ if (qp->resp_depth && !attr->max_rd_atomic) {
/*
* Lowering our responder resources to zero.
* Turn off RDMA/atomics as responder.
@@ -815,7 +778,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
MTHCA_QP_OPTPAR_RAE);
}
- if (!qp->resp_depth && attr->max_dest_rd_atomic) {
+ if (!qp->resp_depth && attr->max_rd_atomic) {
/*
* Increasing our responder resources from
* zero. Turn on RDMA/atomics as appropriate.
@@ -836,7 +799,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
}
for (rra_max = 0;
- 1 << rra_max < attr->max_dest_rd_atomic &&
+ 1 << rra_max < attr->max_rd_atomic &&
rra_max < dev->qp_table.rdb_shift;
++rra_max)
; /* nothing */
@@ -844,7 +807,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
qp_context->params2 |= cpu_to_be32(rra_max << 21);
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRA_MAX);
- qp->resp_depth = attr->max_dest_rd_atomic;
+ qp->resp_depth = attr->max_rd_atomic;
}
qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RSC);
@@ -872,7 +835,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
}
err = mthca_MODIFY_QP(dev, state_table[cur_state][new_state].trans,
- qp->qpn, 0, mailbox, 0, &status);
+ qp->qpn, 0, qp_param, 0, &status);
if (status) {
mthca_warn(dev, "modify QP %d returned status %02x.\n",
state_table[cur_state][new_state].trans, status);
@@ -882,7 +845,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
if (!err)
qp->state = new_state;
- mthca_free_mailbox(dev, mailbox);
+ kfree(mailbox);
if (is_sqp(dev, qp))
store_attrs(to_msqp(qp), attr, attr_mask);
@@ -971,8 +934,7 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev,
mthca_dbg(dev, "Creating direct QP of size %d (shift %d)\n",
size, shift);
- qp->queue.direct.buf = dma_alloc_coherent(&dev->pdev->dev, size,
- &t, GFP_KERNEL);
+ qp->queue.direct.buf = pci_alloc_consistent(dev->pdev, size, &t);
if (!qp->queue.direct.buf)
goto err_out;
@@ -1011,8 +973,7 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev,
for (i = 0; i < npages; ++i) {
qp->queue.page_list[i].buf =
- dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE,
- &t, GFP_KERNEL);
+ pci_alloc_consistent(dev->pdev, PAGE_SIZE, &t);
if (!qp->queue.page_list[i].buf)
goto err_out_free;
@@ -1035,15 +996,16 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev,
err_out_free:
if (qp->is_direct) {
- dma_free_coherent(&dev->pdev->dev, size, qp->queue.direct.buf,
- pci_unmap_addr(&qp->queue.direct, mapping));
+ pci_free_consistent(dev->pdev, size,
+ qp->queue.direct.buf,
+ pci_unmap_addr(&qp->queue.direct, mapping));
} else
for (i = 0; i < npages; ++i) {
if (qp->queue.page_list[i].buf)
- dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
- qp->queue.page_list[i].buf,
- pci_unmap_addr(&qp->queue.page_list[i],
- mapping));
+ pci_free_consistent(dev->pdev, PAGE_SIZE,
+ qp->queue.page_list[i].buf,
+ pci_unmap_addr(&qp->queue.page_list[i],
+ mapping));
}
@@ -1111,12 +1073,11 @@ static void mthca_free_memfree(struct mthca_dev *dev,
if (mthca_is_memfree(dev)) {
mthca_free_db(dev, MTHCA_DB_TYPE_SQ, qp->sq.db_index);
mthca_free_db(dev, MTHCA_DB_TYPE_RQ, qp->rq.db_index);
+ mthca_table_put(dev, dev->qp_table.rdb_table,
+ qp->qpn << dev->qp_table.rdb_shift);
+ mthca_table_put(dev, dev->qp_table.eqp_table, qp->qpn);
+ mthca_table_put(dev, dev->qp_table.qp_table, qp->qpn);
}
-
- mthca_table_put(dev, dev->qp_table.rdb_table,
- qp->qpn << dev->qp_table.rdb_shift);
- mthca_table_put(dev, dev->qp_table.eqp_table, qp->qpn);
- mthca_table_put(dev, dev->qp_table.qp_table, qp->qpn);
}
static void mthca_wq_init(struct mthca_wq* wq)
@@ -1568,26 +1529,6 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
break;
- case UC:
- switch (wr->opcode) {
- case IB_WR_RDMA_WRITE:
- case IB_WR_RDMA_WRITE_WITH_IMM:
- ((struct mthca_raddr_seg *) wqe)->raddr =
- cpu_to_be64(wr->wr.rdma.remote_addr);
- ((struct mthca_raddr_seg *) wqe)->rkey =
- cpu_to_be32(wr->wr.rdma.rkey);
- ((struct mthca_raddr_seg *) wqe)->reserved = 0;
- wqe += sizeof (struct mthca_raddr_seg);
- size += sizeof (struct mthca_raddr_seg) / 16;
- break;
-
- default:
- /* No extra segments required for sends */
- break;
- }
-
- break;
-
case UD:
((struct mthca_tavor_ud_seg *) wqe)->lkey =
cpu_to_be32(to_mah(wr->wr.ud.ah)->key);
@@ -1873,29 +1814,9 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
sizeof (struct mthca_atomic_seg);
break;
- case IB_WR_RDMA_READ:
- case IB_WR_RDMA_WRITE:
- case IB_WR_RDMA_WRITE_WITH_IMM:
- ((struct mthca_raddr_seg *) wqe)->raddr =
- cpu_to_be64(wr->wr.rdma.remote_addr);
- ((struct mthca_raddr_seg *) wqe)->rkey =
- cpu_to_be32(wr->wr.rdma.rkey);
- ((struct mthca_raddr_seg *) wqe)->reserved = 0;
- wqe += sizeof (struct mthca_raddr_seg);
- size += sizeof (struct mthca_raddr_seg) / 16;
- break;
-
- default:
- /* No extra segments required for sends */
- break;
- }
-
- break;
-
- case UC:
- switch (wr->opcode) {
case IB_WR_RDMA_WRITE:
case IB_WR_RDMA_WRITE_WITH_IMM:
+ case IB_WR_RDMA_READ:
((struct mthca_raddr_seg *) wqe)->raddr =
cpu_to_be64(wr->wr.rdma.remote_addr);
((struct mthca_raddr_seg *) wqe)->rkey =
diff --git a/trunk/drivers/input/evdev.c b/trunk/drivers/input/evdev.c
index 374f404e81da..556264b43425 100644
--- a/trunk/drivers/input/evdev.c
+++ b/trunk/drivers/input/evdev.c
@@ -21,7 +21,6 @@
#include
#include
#include
-#include
struct evdev {
int exist;
@@ -146,41 +145,6 @@ static int evdev_open(struct inode * inode, struct file * file)
return 0;
}
-#ifdef CONFIG_COMPAT
-struct input_event_compat {
- struct compat_timeval time;
- __u16 type;
- __u16 code;
- __s32 value;
-};
-
-#ifdef CONFIG_X86_64
-# define COMPAT_TEST test_thread_flag(TIF_IA32)
-#elif defined(CONFIG_IA64)
-# define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current))
-#elif defined(CONFIG_ARCH_S390)
-# define COMPAT_TEST test_thread_flag(TIF_31BIT)
-#else
-# define COMPAT_TEST test_thread_flag(TIF_32BIT)
-#endif
-
-static ssize_t evdev_write_compat(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
-{
- struct evdev_list *list = file->private_data;
- struct input_event_compat event;
- int retval = 0;
-
- while (retval < count) {
- if (copy_from_user(&event, buffer + retval, sizeof(struct input_event_compat)))
- return -EFAULT;
- input_event(list->evdev->handle.dev, event.type, event.code, event.value);
- retval += sizeof(struct input_event_compat);
- }
-
- return retval;
-}
-#endif
-
static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
{
struct evdev_list *list = file->private_data;
@@ -189,11 +153,6 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_
if (!list->evdev->exist) return -ENODEV;
-#ifdef CONFIG_COMPAT
- if (COMPAT_TEST)
- return evdev_write_compat(file, buffer, count, ppos);
-#endif
-
while (retval < count) {
if (copy_from_user(&event, buffer + retval, sizeof(struct input_event)))
@@ -205,56 +164,11 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_
return retval;
}
-#ifdef CONFIG_COMPAT
-static ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
-{
- struct evdev_list *list = file->private_data;
- int retval;
-
- if (count < sizeof(struct input_event_compat))
- return -EINVAL;
-
- if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
- return -EAGAIN;
-
- retval = wait_event_interruptible(list->evdev->wait,
- list->head != list->tail || (!list->evdev->exist));
-
- if (retval)
- return retval;
-
- if (!list->evdev->exist)
- return -ENODEV;
-
- while (list->head != list->tail && retval + sizeof(struct input_event_compat) <= count) {
- struct input_event *event = (struct input_event *) list->buffer + list->tail;
- struct input_event_compat event_compat;
- event_compat.time.tv_sec = event->time.tv_sec;
- event_compat.time.tv_usec = event->time.tv_usec;
- event_compat.type = event->type;
- event_compat.code = event->code;
- event_compat.value = event->value;
-
- if (copy_to_user(buffer + retval, &event_compat,
- sizeof(struct input_event_compat))) return -EFAULT;
- list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
- retval += sizeof(struct input_event_compat);
- }
-
- return retval;
-}
-#endif
-
static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
{
struct evdev_list *list = file->private_data;
int retval;
-#ifdef CONFIG_COMPAT
- if (COMPAT_TEST)
- return evdev_read_compat(file, buffer, count, ppos);
-#endif
-
if (count < sizeof(struct input_event))
return -EINVAL;
@@ -272,7 +186,7 @@ static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count
while (list->head != list->tail && retval + sizeof(struct input_event) <= count) {
if (copy_to_user(buffer + retval, list->buffer + list->tail,
- sizeof(struct input_event))) return -EFAULT;
+ sizeof(struct input_event))) return -EFAULT;
list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
retval += sizeof(struct input_event);
}
@@ -289,7 +203,7 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait)
(list->evdev->exist ? 0 : (POLLHUP | POLLERR));
}
-static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
struct evdev_list *list = file->private_data;
struct evdev *evdev = list->evdev;
@@ -371,267 +285,109 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
default:
- if (_IOC_TYPE(cmd) != 'E')
+ if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ)
return -EINVAL;
- if (_IOC_DIR(cmd) == _IOC_READ) {
-
- if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
-
- long *bits;
- int len;
-
- switch (_IOC_NR(cmd) & EV_MAX) {
- case 0: bits = dev->evbit; len = EV_MAX; break;
- case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
- case EV_REL: bits = dev->relbit; len = REL_MAX; break;
- case EV_ABS: bits = dev->absbit; len = ABS_MAX; break;
- case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break;
- case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
- case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
- case EV_FF: bits = dev->ffbit; len = FF_MAX; break;
- default: return -EINVAL;
- }
- len = NBITS(len) * sizeof(long);
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, bits, len) ? -EFAULT : len;
- }
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) {
- int len;
- len = NBITS(KEY_MAX) * sizeof(long);
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->key, len) ? -EFAULT : len;
+ if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
+
+ long *bits;
+ int len;
+
+ switch (_IOC_NR(cmd) & EV_MAX) {
+ case 0: bits = dev->evbit; len = EV_MAX; break;
+ case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
+ case EV_REL: bits = dev->relbit; len = REL_MAX; break;
+ case EV_ABS: bits = dev->absbit; len = ABS_MAX; break;
+ case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break;
+ case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
+ case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
+ case EV_FF: bits = dev->ffbit; len = FF_MAX; break;
+ default: return -EINVAL;
}
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) {
- int len;
- len = NBITS(LED_MAX) * sizeof(long);
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->led, len) ? -EFAULT : len;
- }
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) {
- int len;
- len = NBITS(SND_MAX) * sizeof(long);
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->snd, len) ? -EFAULT : len;
- }
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
- int len;
- if (!dev->name) return -ENOENT;
- len = strlen(dev->name) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->name, len) ? -EFAULT : len;
- }
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
- int len;
- if (!dev->phys) return -ENOENT;
- len = strlen(dev->phys) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->phys, len) ? -EFAULT : len;
- }
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
- int len;
- if (!dev->uniq) return -ENOENT;
- len = strlen(dev->uniq) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->uniq, len) ? -EFAULT : len;
- }
-
- if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
-
- int t = _IOC_NR(cmd) & ABS_MAX;
-
- abs.value = dev->abs[t];
- abs.minimum = dev->absmin[t];
- abs.maximum = dev->absmax[t];
- abs.fuzz = dev->absfuzz[t];
- abs.flat = dev->absflat[t];
-
- if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
- return -EFAULT;
-
- return 0;
- }
-
+ len = NBITS(len) * sizeof(long);
+ if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+ return copy_to_user(p, bits, len) ? -EFAULT : len;
}
- if (_IOC_DIR(cmd) == _IOC_WRITE) {
-
- if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
-
- int t = _IOC_NR(cmd) & ABS_MAX;
-
- if (copy_from_user(&abs, p, sizeof(struct input_absinfo)))
- return -EFAULT;
-
- dev->abs[t] = abs.value;
- dev->absmin[t] = abs.minimum;
- dev->absmax[t] = abs.maximum;
- dev->absfuzz[t] = abs.fuzz;
- dev->absflat[t] = abs.flat;
-
- return 0;
- }
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) {
+ int len;
+ len = NBITS(KEY_MAX) * sizeof(long);
+ if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+ return copy_to_user(p, dev->key, len) ? -EFAULT : len;
}
- }
- return -EINVAL;
-}
-
-#ifdef CONFIG_COMPAT
-
-#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8)
-#define NBITS_COMPAT(x) ((((x)-1)/BITS_PER_LONG_COMPAT)+1)
-#define OFF_COMPAT(x) ((x)%BITS_PER_LONG_COMPAT)
-#define BIT_COMPAT(x) (1UL<> OFF_COMPAT(bit)) & 1)
-
-#ifdef __BIG_ENDIAN
-#define bit_to_user(bit, max) \
-do { \
- int i; \
- int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \
- for (i = 0; i < len / sizeof(compat_long_t); i++) \
- if (copy_to_user((compat_long_t*) p + i, \
- (compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \
- sizeof(compat_long_t))) \
- return -EFAULT; \
- return len; \
-} while (0)
-#else
-#define bit_to_user(bit, max) \
-do { \
- int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \
- return copy_to_user(p, (bit), len) ? -EFAULT : len; \
-} while (0)
-#endif
-
-static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct evdev_list *list = file->private_data;
- struct evdev *evdev = list->evdev;
- struct input_dev *dev = evdev->handle.dev;
- struct input_absinfo abs;
- void __user *p = compat_ptr(arg);
-
- if (!evdev->exist) return -ENODEV;
-
- switch (cmd) {
-
- case EVIOCGVERSION:
- case EVIOCGID:
- case EVIOCGKEYCODE:
- case EVIOCSKEYCODE:
- case EVIOCSFF:
- case EVIOCRMFF:
- case EVIOCGEFFECTS:
- case EVIOCGRAB:
- return evdev_ioctl(file, cmd, (unsigned long) p);
-
- default:
- if (_IOC_TYPE(cmd) != 'E')
- return -EINVAL;
-
- if (_IOC_DIR(cmd) == _IOC_READ) {
-
- if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
- long *bits;
- int max;
-
- switch (_IOC_NR(cmd) & EV_MAX) {
- case 0: bits = dev->evbit; max = EV_MAX; break;
- case EV_KEY: bits = dev->keybit; max = KEY_MAX; break;
- case EV_REL: bits = dev->relbit; max = REL_MAX; break;
- case EV_ABS: bits = dev->absbit; max = ABS_MAX; break;
- case EV_MSC: bits = dev->mscbit; max = MSC_MAX; break;
- case EV_LED: bits = dev->ledbit; max = LED_MAX; break;
- case EV_SND: bits = dev->sndbit; max = SND_MAX; break;
- case EV_FF: bits = dev->ffbit; max = FF_MAX; break;
- default: return -EINVAL;
- }
- bit_to_user(bits, max);
- }
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
- bit_to_user(dev->key, KEY_MAX);
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
- bit_to_user(dev->led, LED_MAX);
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) {
+ int len;
+ len = NBITS(LED_MAX) * sizeof(long);
+ if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+ return copy_to_user(p, dev->led, len) ? -EFAULT : len;
+ }
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
- bit_to_user(dev->snd, SND_MAX);
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) {
+ int len;
+ len = NBITS(SND_MAX) * sizeof(long);
+ if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+ return copy_to_user(p, dev->snd, len) ? -EFAULT : len;
+ }
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
- int len;
- if (!dev->name) return -ENOENT;
- len = strlen(dev->name) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->name, len) ? -EFAULT : len;
- }
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
+ int len;
+ if (!dev->name) return -ENOENT;
+ len = strlen(dev->name) + 1;
+ if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+ return copy_to_user(p, dev->name, len) ? -EFAULT : len;
+ }
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
- int len;
- if (!dev->phys) return -ENOENT;
- len = strlen(dev->phys) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->phys, len) ? -EFAULT : len;
- }
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
+ int len;
+ if (!dev->phys) return -ENOENT;
+ len = strlen(dev->phys) + 1;
+ if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+ return copy_to_user(p, dev->phys, len) ? -EFAULT : len;
+ }
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
- int len;
- if (!dev->uniq) return -ENOENT;
- len = strlen(dev->uniq) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->uniq, len) ? -EFAULT : len;
- }
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
+ int len;
+ if (!dev->uniq) return -ENOENT;
+ len = strlen(dev->uniq) + 1;
+ if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+ return copy_to_user(p, dev->uniq, len) ? -EFAULT : len;
+ }
- if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
+ if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
- int t = _IOC_NR(cmd) & ABS_MAX;
+ int t = _IOC_NR(cmd) & ABS_MAX;
- abs.value = dev->abs[t];
- abs.minimum = dev->absmin[t];
- abs.maximum = dev->absmax[t];
- abs.fuzz = dev->absfuzz[t];
- abs.flat = dev->absflat[t];
+ abs.value = dev->abs[t];
+ abs.minimum = dev->absmin[t];
+ abs.maximum = dev->absmax[t];
+ abs.fuzz = dev->absfuzz[t];
+ abs.flat = dev->absflat[t];
- if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
- return -EFAULT;
+ if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
+ return -EFAULT;
- return 0;
- }
+ return 0;
}
- if (_IOC_DIR(cmd) == _IOC_WRITE) {
-
- if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
+ if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
- int t = _IOC_NR(cmd) & ABS_MAX;
+ int t = _IOC_NR(cmd) & ABS_MAX;
- if (copy_from_user(&abs, p, sizeof(struct input_absinfo)))
- return -EFAULT;
+ if (copy_from_user(&abs, p, sizeof(struct input_absinfo)))
+ return -EFAULT;
- dev->abs[t] = abs.value;
- dev->absmin[t] = abs.minimum;
- dev->absmax[t] = abs.maximum;
- dev->absfuzz[t] = abs.fuzz;
- dev->absflat[t] = abs.flat;
+ dev->abs[t] = abs.value;
+ dev->absmin[t] = abs.minimum;
+ dev->absmax[t] = abs.maximum;
+ dev->absfuzz[t] = abs.fuzz;
+ dev->absflat[t] = abs.flat;
- return 0;
- }
+ return 0;
}
}
return -EINVAL;
}
-#endif
static struct file_operations evdev_fops = {
.owner = THIS_MODULE,
@@ -640,10 +396,7 @@ static struct file_operations evdev_fops = {
.poll = evdev_poll,
.open = evdev_open,
.release = evdev_release,
- .unlocked_ioctl = evdev_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = evdev_ioctl_compat,
-#endif
+ .ioctl = evdev_ioctl,
.fasync = evdev_fasync,
.flush = evdev_flush
};
diff --git a/trunk/drivers/input/gameport/Kconfig b/trunk/drivers/input/gameport/Kconfig
index 7524bd7d8b8f..1d93f5092904 100644
--- a/trunk/drivers/input/gameport/Kconfig
+++ b/trunk/drivers/input/gameport/Kconfig
@@ -49,8 +49,22 @@ config GAMEPORT_EMU10K1
To compile this driver as a module, choose M here: the
module will be called emu10k1-gp.
+config GAMEPORT_VORTEX
+ tristate "Aureal Vortex, Vortex 2 gameport support"
+ depends on PCI
+ help
+ Say Y here if you have an Aureal Vortex 1 or 2 card and want
+ to use its gameport.
+
+ To compile this driver as a module, choose M here: the
+ module will be called vortex.
+
config GAMEPORT_FM801
tristate "ForteMedia FM801 gameport support"
depends on PCI
+config GAMEPORT_CS461X
+ tristate "Crystal SoundFusion gameport support"
+ depends on PCI
+
endif
diff --git a/trunk/drivers/input/gameport/Makefile b/trunk/drivers/input/gameport/Makefile
index b6f6097bd8c4..5367b4267adf 100644
--- a/trunk/drivers/input/gameport/Makefile
+++ b/trunk/drivers/input/gameport/Makefile
@@ -5,7 +5,9 @@
# Each configuration option enables a list of files.
obj-$(CONFIG_GAMEPORT) += gameport.o
+obj-$(CONFIG_GAMEPORT_CS461X) += cs461x.o
obj-$(CONFIG_GAMEPORT_EMU10K1) += emu10k1-gp.o
obj-$(CONFIG_GAMEPORT_FM801) += fm801-gp.o
obj-$(CONFIG_GAMEPORT_L4) += lightning.o
obj-$(CONFIG_GAMEPORT_NS558) += ns558.o
+obj-$(CONFIG_GAMEPORT_VORTEX) += vortex.o
diff --git a/trunk/drivers/input/gameport/cs461x.c b/trunk/drivers/input/gameport/cs461x.c
new file mode 100644
index 000000000000..d4013ff98623
--- /dev/null
+++ b/trunk/drivers/input/gameport/cs461x.c
@@ -0,0 +1,322 @@
+/*
+ The all defines and part of code (such as cs461x_*) are
+ contributed from ALSA 0.5.8 sources.
+ See http://www.alsa-project.org/ for sources
+
+ Tested on Linux 686 2.4.0-test9, ALSA 0.5.8a and CS4610
+*/
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+MODULE_AUTHOR("Victor Krapivin");
+MODULE_LICENSE("GPL");
+
+/*
+ These options are experimental
+
+#define CS461X_FULL_MAP
+*/
+
+
+#ifndef PCI_VENDOR_ID_CIRRUS
+#define PCI_VENDOR_ID_CIRRUS 0x1013
+#endif
+#ifndef PCI_DEVICE_ID_CIRRUS_4610
+#define PCI_DEVICE_ID_CIRRUS_4610 0x6001
+#endif
+#ifndef PCI_DEVICE_ID_CIRRUS_4612
+#define PCI_DEVICE_ID_CIRRUS_4612 0x6003
+#endif
+#ifndef PCI_DEVICE_ID_CIRRUS_4615
+#define PCI_DEVICE_ID_CIRRUS_4615 0x6004
+#endif
+
+/* Registers */
+
+#define BA0_JSPT 0x00000480
+#define BA0_JSCTL 0x00000484
+#define BA0_JSC1 0x00000488
+#define BA0_JSC2 0x0000048C
+#define BA0_JSIO 0x000004A0
+
+/* Bits for JSPT */
+
+#define JSPT_CAX 0x00000001
+#define JSPT_CAY 0x00000002
+#define JSPT_CBX 0x00000004
+#define JSPT_CBY 0x00000008
+#define JSPT_BA1 0x00000010
+#define JSPT_BA2 0x00000020
+#define JSPT_BB1 0x00000040
+#define JSPT_BB2 0x00000080
+
+/* Bits for JSCTL */
+
+#define JSCTL_SP_MASK 0x00000003
+#define JSCTL_SP_SLOW 0x00000000
+#define JSCTL_SP_MEDIUM_SLOW 0x00000001
+#define JSCTL_SP_MEDIUM_FAST 0x00000002
+#define JSCTL_SP_FAST 0x00000003
+#define JSCTL_ARE 0x00000004
+
+/* Data register pairs masks */
+
+#define JSC1_Y1V_MASK 0x0000FFFF
+#define JSC1_X1V_MASK 0xFFFF0000
+#define JSC1_Y1V_SHIFT 0
+#define JSC1_X1V_SHIFT 16
+#define JSC2_Y2V_MASK 0x0000FFFF
+#define JSC2_X2V_MASK 0xFFFF0000
+#define JSC2_Y2V_SHIFT 0
+#define JSC2_X2V_SHIFT 16
+
+/* JS GPIO */
+
+#define JSIO_DAX 0x00000001
+#define JSIO_DAY 0x00000002
+#define JSIO_DBX 0x00000004
+#define JSIO_DBY 0x00000008
+#define JSIO_AXOE 0x00000010
+#define JSIO_AYOE 0x00000020
+#define JSIO_BXOE 0x00000040
+#define JSIO_BYOE 0x00000080
+
+/*
+ The card initialization code is obfuscated; the module cs461x
+ need to be loaded after ALSA modules initialized and something
+ played on the CS 4610 chip (see sources for details of CS4610
+ initialization code from ALSA)
+*/
+
+/* Card specific definitions */
+
+#define CS461X_BA0_SIZE 0x2000
+#define CS461X_BA1_DATA0_SIZE 0x3000
+#define CS461X_BA1_DATA1_SIZE 0x3800
+#define CS461X_BA1_PRG_SIZE 0x7000
+#define CS461X_BA1_REG_SIZE 0x0100
+
+#define BA1_SP_DMEM0 0x00000000
+#define BA1_SP_DMEM1 0x00010000
+#define BA1_SP_PMEM 0x00020000
+#define BA1_SP_REG 0x00030000
+
+#define BA1_DWORD_SIZE (13 * 1024 + 512)
+#define BA1_MEMORY_COUNT 3
+
+/*
+ Only one CS461x card is still suppoted; the code requires
+ redesign to avoid this limitatuion.
+*/
+
+static unsigned long ba0_addr;
+static unsigned int __iomem *ba0;
+
+#ifdef CS461X_FULL_MAP
+static unsigned long ba1_addr;
+static union ba1_t {
+ struct {
+ unsigned int __iomem *data0;
+ unsigned int __iomem *data1;
+ unsigned int __iomem *pmem;
+ unsigned int __iomem *reg;
+ } name;
+ unsigned int __iomem *idx[4];
+} ba1;
+
+static void cs461x_poke(unsigned long reg, unsigned int val)
+{
+ writel(val, &ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]);
+}
+
+static unsigned int cs461x_peek(unsigned long reg)
+{
+ return readl(&ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]);
+}
+
+#endif
+
+static void cs461x_pokeBA0(unsigned long reg, unsigned int val)
+{
+ writel(val, &ba0[reg >> 2]);
+}
+
+static unsigned int cs461x_peekBA0(unsigned long reg)
+{
+ return readl(&ba0[reg >> 2]);
+}
+
+static int cs461x_free(struct pci_dev *pdev)
+{
+ struct gameport *port = pci_get_drvdata(pdev);
+
+ if (port)
+ gameport_unregister_port(port);
+
+ if (ba0) iounmap(ba0);
+#ifdef CS461X_FULL_MAP
+ if (ba1.name.data0) iounmap(ba1.name.data0);
+ if (ba1.name.data1) iounmap(ba1.name.data1);
+ if (ba1.name.pmem) iounmap(ba1.name.pmem);
+ if (ba1.name.reg) iounmap(ba1.name.reg);
+#endif
+ return 0;
+}
+
+static void cs461x_gameport_trigger(struct gameport *gameport)
+{
+ cs461x_pokeBA0(BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF);
+}
+
+static unsigned char cs461x_gameport_read(struct gameport *gameport)
+{
+ return cs461x_peekBA0(BA0_JSPT); //inb(gameport->io);
+}
+
+static int cs461x_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
+{
+ unsigned js1, js2, jst;
+
+ js1 = cs461x_peekBA0(BA0_JSC1);
+ js2 = cs461x_peekBA0(BA0_JSC2);
+ jst = cs461x_peekBA0(BA0_JSPT);
+
+ *buttons = (~jst >> 4) & 0x0F;
+
+ axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF;
+ axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF;
+ axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF;
+ axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF;
+
+ for(jst=0;jst<4;++jst)
+ if(axes[jst]==0xFFFF) axes[jst] = -1;
+ return 0;
+}
+
+static int cs461x_gameport_open(struct gameport *gameport, int mode)
+{
+ switch (mode) {
+ case GAMEPORT_MODE_COOKED:
+ case GAMEPORT_MODE_RAW:
+ return 0;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static struct pci_device_id cs461x_pci_tbl[] = {
+ { PCI_VENDOR_ID_CIRRUS, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4610 */
+ { PCI_VENDOR_ID_CIRRUS, 0x6003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4612 */
+ { PCI_VENDOR_ID_CIRRUS, 0x6005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4615 */
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, cs461x_pci_tbl);
+
+static int __devinit cs461x_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ int rc;
+ struct gameport* port;
+
+ rc = pci_enable_device(pdev);
+ if (rc) {
+ printk(KERN_ERR "cs461x: Cannot enable PCI gameport (bus %d, devfn %d) error=%d\n",
+ pdev->bus->number, pdev->devfn, rc);
+ return rc;
+ }
+
+ ba0_addr = pci_resource_start(pdev, 0);
+#ifdef CS461X_FULL_MAP
+ ba1_addr = pci_resource_start(pdev, 1);
+#endif
+ if (ba0_addr == 0 || ba0_addr == ~0
+#ifdef CS461X_FULL_MAP
+ || ba1_addr == 0 || ba1_addr == ~0
+#endif
+ ) {
+ printk(KERN_ERR "cs461x: wrong address - ba0 = 0x%lx\n", ba0_addr);
+#ifdef CS461X_FULL_MAP
+ printk(KERN_ERR "cs461x: wrong address - ba1 = 0x%lx\n", ba1_addr);
+#endif
+ cs461x_free(pdev);
+ return -ENOMEM;
+ }
+
+ ba0 = ioremap(ba0_addr, CS461X_BA0_SIZE);
+#ifdef CS461X_FULL_MAP
+ ba1.name.data0 = ioremap(ba1_addr + BA1_SP_DMEM0, CS461X_BA1_DATA0_SIZE);
+ ba1.name.data1 = ioremap(ba1_addr + BA1_SP_DMEM1, CS461X_BA1_DATA1_SIZE);
+ ba1.name.pmem = ioremap(ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE);
+ ba1.name.reg = ioremap(ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE);
+
+ if (ba0 == NULL || ba1.name.data0 == NULL ||
+ ba1.name.data1 == NULL || ba1.name.pmem == NULL ||
+ ba1.name.reg == NULL) {
+ cs461x_free(pdev);
+ return -ENOMEM;
+ }
+#else
+ if (ba0 == NULL) {
+ cs461x_free(pdev);
+ return -ENOMEM;
+ }
+#endif
+
+ if (!(port = gameport_allocate_port())) {
+ printk(KERN_ERR "cs461x: Memory allocation failed\n");
+ cs461x_free(pdev);
+ return -ENOMEM;
+ }
+
+ pci_set_drvdata(pdev, port);
+
+ port->open = cs461x_gameport_open;
+ port->trigger = cs461x_gameport_trigger;
+ port->read = cs461x_gameport_read;
+ port->cooked_read = cs461x_gameport_cooked_read;
+
+ gameport_set_name(port, "CS416x");
+ gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev));
+ port->dev.parent = &pdev->dev;
+
+ cs461x_pokeBA0(BA0_JSIO, 0xFF); // ?
+ cs461x_pokeBA0(BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
+
+ gameport_register_port(port);
+
+ return 0;
+}
+
+static void __devexit cs461x_pci_remove(struct pci_dev *pdev)
+{
+ cs461x_free(pdev);
+}
+
+static struct pci_driver cs461x_pci_driver = {
+ .name = "CS461x_gameport",
+ .id_table = cs461x_pci_tbl,
+ .probe = cs461x_pci_probe,
+ .remove = __devexit_p(cs461x_pci_remove),
+};
+
+static int __init cs461x_init(void)
+{
+ return pci_register_driver(&cs461x_pci_driver);
+}
+
+static void __exit cs461x_exit(void)
+{
+ pci_unregister_driver(&cs461x_pci_driver);
+}
+
+module_init(cs461x_init);
+module_exit(cs461x_exit);
+
diff --git a/trunk/drivers/input/gameport/gameport.c b/trunk/drivers/input/gameport/gameport.c
index 3e72c9b1461e..c77a82e46055 100644
--- a/trunk/drivers/input/gameport/gameport.c
+++ b/trunk/drivers/input/gameport/gameport.c
@@ -17,10 +17,11 @@
#include
#include
#include
+#include
#include
+#include
#include
#include
-#include
/*#include */
@@ -237,7 +238,8 @@ struct gameport_event {
static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */
static LIST_HEAD(gameport_event_list);
static DECLARE_WAIT_QUEUE_HEAD(gameport_wait);
-static struct task_struct *gameport_task;
+static DECLARE_COMPLETION(gameport_exited);
+static int gameport_pid;
static void gameport_queue_event(void *object, struct module *owner,
enum gameport_event_type event_type)
@@ -248,12 +250,12 @@ static void gameport_queue_event(void *object, struct module *owner,
spin_lock_irqsave(&gameport_event_lock, flags);
/*
- * Scan event list for the other events for the same gameport port,
+ * Scan event list for the other events for the same gameport port,
* starting with the most recent one. If event is the same we
* do not need add new one. If event is of different type we
* need to add this event and should not look further because
* we need to preseve sequence of distinct events.
- */
+ */
list_for_each_entry_reverse(event, &gameport_event_list, node) {
if (event->object == object) {
if (event->type == event_type)
@@ -430,15 +432,20 @@ static struct gameport *gameport_get_pending_child(struct gameport *parent)
static int gameport_thread(void *nothing)
{
+ lock_kernel();
+ daemonize("kgameportd");
+ allow_signal(SIGTERM);
+
do {
gameport_handle_events();
- wait_event_interruptible(gameport_wait,
- kthread_should_stop() || !list_empty(&gameport_event_list));
+ wait_event_interruptible(gameport_wait, !list_empty(&gameport_event_list));
try_to_freeze();
- } while (!kthread_should_stop());
+ } while (!signal_pending(current));
printk(KERN_DEBUG "gameport: kgameportd exiting\n");
- return 0;
+
+ unlock_kernel();
+ complete_and_exit(&gameport_exited, 0);
}
@@ -766,10 +773,9 @@ void gameport_close(struct gameport *gameport)
static int __init gameport_init(void)
{
- gameport_task = kthread_run(gameport_thread, NULL, "kgameportd");
- if (IS_ERR(gameport_task)) {
+ if (!(gameport_pid = kernel_thread(gameport_thread, NULL, CLONE_KERNEL))) {
printk(KERN_ERR "gameport: Failed to start kgameportd\n");
- return PTR_ERR(gameport_task);
+ return -1;
}
gameport_bus.dev_attrs = gameport_device_attrs;
@@ -783,7 +789,8 @@ static int __init gameport_init(void)
static void __exit gameport_exit(void)
{
bus_unregister(&gameport_bus);
- kthread_stop(gameport_task);
+ kill_proc(gameport_pid, SIGTERM, 1);
+ wait_for_completion(&gameport_exited);
}
module_init(gameport_init);
diff --git a/trunk/drivers/input/gameport/ns558.c b/trunk/drivers/input/gameport/ns558.c
index 1ab5f2dc8a2a..7c5c6318eeb9 100644
--- a/trunk/drivers/input/gameport/ns558.c
+++ b/trunk/drivers/input/gameport/ns558.c
@@ -258,18 +258,18 @@ static int __init ns558_init(void)
{
int i = 0;
- if (pnp_register_driver(&ns558_pnp_driver) >= 0)
- pnp_registered = 1;
-
/*
- * Probe ISA ports after PnP, so that PnP ports that are already
- * enabled get detected as PnP. This may be suboptimal in multi-device
- * configurations, but saves hassle with simple setups.
+ * Probe ISA ports first so that PnP gets to choose free port addresses
+ * not occupied by the ISA ports.
*/
while (ns558_isa_portlist[i])
ns558_isa_probe(ns558_isa_portlist[i++]);
+ if (pnp_register_driver(&ns558_pnp_driver) >= 0)
+ pnp_registered = 1;
+
+
return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0;
}
diff --git a/trunk/drivers/input/gameport/vortex.c b/trunk/drivers/input/gameport/vortex.c
new file mode 100644
index 000000000000..36b0309c8bf6
--- /dev/null
+++ b/trunk/drivers/input/gameport/vortex.c
@@ -0,0 +1,186 @@
+/*
+ * $Id: vortex.c,v 1.5 2002/07/01 15:39:30 vojtech Exp $
+ *
+ * Copyright (c) 2000-2001 Vojtech Pavlik
+ *
+ * Based on the work of:
+ * Raymond Ingles
+ */
+
+/*
+ * Trident 4DWave and Aureal Vortex gameport driver for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to , or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+MODULE_AUTHOR("Vojtech Pavlik ");
+MODULE_DESCRIPTION("Aureal Vortex and Vortex2 gameport driver");
+MODULE_LICENSE("GPL");
+
+#define VORTEX_GCR 0x0c /* Gameport control register */
+#define VORTEX_LEG 0x08 /* Legacy port location */
+#define VORTEX_AXD 0x10 /* Axes start */
+#define VORTEX_DATA_WAIT 20 /* 20 ms */
+
+struct vortex {
+ struct gameport *gameport;
+ struct pci_dev *dev;
+ unsigned char __iomem *base;
+ unsigned char __iomem *io;
+};
+
+static unsigned char vortex_read(struct gameport *gameport)
+{
+ struct vortex *vortex = gameport->port_data;
+ return readb(vortex->io + VORTEX_LEG);
+}
+
+static void vortex_trigger(struct gameport *gameport)
+{
+ struct vortex *vortex = gameport->port_data;
+ writeb(0xff, vortex->io + VORTEX_LEG);
+}
+
+static int vortex_cooked_read(struct gameport *gameport, int *axes, int *buttons)
+{
+ struct vortex *vortex = gameport->port_data;
+ int i;
+
+ *buttons = (~readb(vortex->base + VORTEX_LEG) >> 4) & 0xf;
+
+ for (i = 0; i < 4; i++) {
+ axes[i] = readw(vortex->io + VORTEX_AXD + i * sizeof(u32));
+ if (axes[i] == 0x1fff) axes[i] = -1;
+ }
+
+ return 0;
+}
+
+static int vortex_open(struct gameport *gameport, int mode)
+{
+ struct vortex *vortex = gameport->port_data;
+
+ switch (mode) {
+ case GAMEPORT_MODE_COOKED:
+ writeb(0x40, vortex->io + VORTEX_GCR);
+ msleep(VORTEX_DATA_WAIT);
+ return 0;
+ case GAMEPORT_MODE_RAW:
+ writeb(0x00, vortex->io + VORTEX_GCR);
+ return 0;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int __devinit vortex_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ struct vortex *vortex;
+ struct gameport *port;
+ int i;
+
+ vortex = kcalloc(1, sizeof(struct vortex), GFP_KERNEL);
+ port = gameport_allocate_port();
+ if (!vortex || !port) {
+ printk(KERN_ERR "vortex: Memory allocation failed.\n");
+ kfree(vortex);
+ gameport_free_port(port);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < 6; i++)
+ if (~pci_resource_flags(dev, i) & IORESOURCE_IO)
+ break;
+
+ pci_enable_device(dev);
+
+ vortex->dev = dev;
+ vortex->gameport = port;
+ vortex->base = ioremap(pci_resource_start(vortex->dev, i),
+ pci_resource_len(vortex->dev, i));
+ vortex->io = vortex->base + id->driver_data;
+
+ pci_set_drvdata(dev, vortex);
+
+ port->port_data = vortex;
+ port->fuzz = 64;
+
+ gameport_set_name(port, "AU88x0");
+ gameport_set_phys(port, "pci%s/gameport0", pci_name(dev));
+ port->dev.parent = &dev->dev;
+ port->read = vortex_read;
+ port->trigger = vortex_trigger;
+ port->cooked_read = vortex_cooked_read;
+ port->open = vortex_open;
+
+ gameport_register_port(port);
+
+ return 0;
+}
+
+static void __devexit vortex_remove(struct pci_dev *dev)
+{
+ struct vortex *vortex = pci_get_drvdata(dev);
+
+ gameport_unregister_port(vortex->gameport);
+ iounmap(vortex->base);
+ kfree(vortex);
+}
+
+static struct pci_device_id vortex_id_table[] = {
+ { 0x12eb, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x11000 },
+ { 0x12eb, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x28800 },
+ { 0 }
+};
+
+static struct pci_driver vortex_driver = {
+ .name = "vortex_gameport",
+ .id_table = vortex_id_table,
+ .probe = vortex_probe,
+ .remove = __devexit_p(vortex_remove),
+};
+
+static int __init vortex_init(void)
+{
+ return pci_register_driver(&vortex_driver);
+}
+
+static void __exit vortex_exit(void)
+{
+ pci_unregister_driver(&vortex_driver);
+}
+
+module_init(vortex_init);
+module_exit(vortex_exit);
diff --git a/trunk/drivers/input/input.c b/trunk/drivers/input/input.c
index 7c4b4d37b3e6..83c77c990dda 100644
--- a/trunk/drivers/input/input.c
+++ b/trunk/drivers/input/input.c
@@ -219,24 +219,10 @@ void input_release_device(struct input_handle *handle)
int input_open_device(struct input_handle *handle)
{
- struct input_dev *dev = handle->dev;
- int err;
-
- err = down_interruptible(&dev->sem);
- if (err)
- return err;
-
handle->open++;
-
- if (!dev->users++ && dev->open)
- err = dev->open(dev);
-
- if (err)
- handle->open--;
-
- up(&dev->sem);
-
- return err;
+ if (handle->dev->open)
+ return handle->dev->open(handle->dev);
+ return 0;
}
int input_flush_device(struct input_handle* handle, struct file* file)
@@ -249,17 +235,10 @@ int input_flush_device(struct input_handle* handle, struct file* file)
void input_close_device(struct input_handle *handle)
{
- struct input_dev *dev = handle->dev;
-
input_release_device(handle);
-
- down(&dev->sem);
-
- if (!--dev->users && dev->close)
- dev->close(dev);
+ if (handle->dev->close)
+ handle->dev->close(handle->dev);
handle->open--;
-
- up(&dev->sem);
}
static void input_link_handle(struct input_handle *handle)
@@ -436,8 +415,6 @@ void input_register_device(struct input_dev *dev)
set_bit(EV_SYN, dev->evbit);
- init_MUTEX(&dev->sem);
-
/*
* If delay and period are pre-set by the driver, then autorepeating
* is handled by the driver itself and we don't do it in input.c.
@@ -697,8 +674,6 @@ static int input_handlers_read(char *buf, char **start, off_t pos, int count, in
return (count > cnt) ? cnt : count;
}
-static struct file_operations input_fileops;
-
static int __init input_proc_init(void)
{
struct proc_dir_entry *entry;
@@ -713,8 +688,6 @@ static int __init input_proc_init(void)
return -ENOMEM;
}
entry->owner = THIS_MODULE;
- input_fileops = *entry->proc_fops;
- entry->proc_fops = &input_fileops;
entry->proc_fops->poll = input_devices_poll;
entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);
if (entry == NULL) {
diff --git a/trunk/drivers/input/joydev.c b/trunk/drivers/input/joydev.c
index ff8e1bbd0e13..39775fc380c7 100644
--- a/trunk/drivers/input/joydev.c
+++ b/trunk/drivers/input/joydev.c
@@ -285,33 +285,48 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait)
(POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR));
}
-static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp)
+static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
+ struct joydev_list *list = file->private_data;
+ struct joydev *joydev = list->joydev;
struct input_dev *dev = joydev->handle.dev;
+ void __user *argp = (void __user *)arg;
int i, j;
+ if (!joydev->exist) return -ENODEV;
+
switch (cmd) {
case JS_SET_CAL:
return copy_from_user(&joydev->glue.JS_CORR, argp,
- sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0;
+ sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0;
case JS_GET_CAL:
return copy_to_user(argp, &joydev->glue.JS_CORR,
- sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0;
+ sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0;
case JS_SET_TIMEOUT:
- return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);
+ return get_user(joydev->glue.JS_TIMEOUT, (int __user *) arg);
case JS_GET_TIMEOUT:
- return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);
+ return put_user(joydev->glue.JS_TIMEOUT, (int __user *) arg);
+ case JS_SET_TIMELIMIT:
+ return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
+ case JS_GET_TIMELIMIT:
+ return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
+ case JS_SET_ALL:
+ return copy_from_user(&joydev->glue, argp,
+ sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0;
+ case JS_GET_ALL:
+ return copy_to_user(argp, &joydev->glue,
+ sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0;
case JSIOCGVERSION:
- return put_user(JS_VERSION, (__u32 __user *) argp);
+ return put_user(JS_VERSION, (__u32 __user *) arg);
case JSIOCGAXES:
- return put_user(joydev->nabs, (__u8 __user *) argp);
+ return put_user(joydev->nabs, (__u8 __user *) arg);
case JSIOCGBUTTONS:
- return put_user(joydev->nkey, (__u8 __user *) argp);
+ return put_user(joydev->nkey, (__u8 __user *) arg);
case JSIOCSCORR:
if (copy_from_user(joydev->corr, argp,
- sizeof(joydev->corr[0]) * joydev->nabs))
+ sizeof(struct js_corr) * joydev->nabs))
return -EFAULT;
for (i = 0; i < joydev->nabs; i++) {
j = joydev->abspam[i];
@@ -320,7 +335,7 @@ static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __u
return 0;
case JSIOCGCORR:
return copy_to_user(argp, joydev->corr,
- sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0;
+ sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0;
case JSIOCSAXMAP:
if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1)))
return -EFAULT;
@@ -356,84 +371,6 @@ static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __u
return -EINVAL;
}
-#ifdef CONFIG_COMPAT
-static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct joydev_list *list = file->private_data;
- struct joydev *joydev = list->joydev;
- void __user *argp = (void __user *)arg;
- s32 tmp32;
- struct JS_DATA_SAVE_TYPE_32 ds32;
- int err;
-
- if (!joydev->exist) return -ENODEV;
- switch(cmd) {
- case JS_SET_TIMELIMIT:
- err = get_user(tmp32, (s32 __user *) arg);
- if (err == 0)
- joydev->glue.JS_TIMELIMIT = tmp32;
- break;
- case JS_GET_TIMELIMIT:
- tmp32 = joydev->glue.JS_TIMELIMIT;
- err = put_user(tmp32, (s32 __user *) arg);
- break;
-
- case JS_SET_ALL:
- err = copy_from_user(&ds32, argp,
- sizeof(ds32)) ? -EFAULT : 0;
- if (err == 0) {
- joydev->glue.JS_TIMEOUT = ds32.JS_TIMEOUT;
- joydev->glue.BUSY = ds32.BUSY;
- joydev->glue.JS_EXPIRETIME = ds32.JS_EXPIRETIME;
- joydev->glue.JS_TIMELIMIT = ds32.JS_TIMELIMIT;
- joydev->glue.JS_SAVE = ds32.JS_SAVE;
- joydev->glue.JS_CORR = ds32.JS_CORR;
- }
- break;
-
- case JS_GET_ALL:
- ds32.JS_TIMEOUT = joydev->glue.JS_TIMEOUT;
- ds32.BUSY = joydev->glue.BUSY;
- ds32.JS_EXPIRETIME = joydev->glue.JS_EXPIRETIME;
- ds32.JS_TIMELIMIT = joydev->glue.JS_TIMELIMIT;
- ds32.JS_SAVE = joydev->glue.JS_SAVE;
- ds32.JS_CORR = joydev->glue.JS_CORR;
-
- err = copy_to_user(argp, &ds32,
- sizeof(ds32)) ? -EFAULT : 0;
- break;
-
- default:
- err = joydev_ioctl_common(joydev, cmd, argp);
- }
- return err;
-}
-#endif /* CONFIG_COMPAT */
-
-static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct joydev_list *list = file->private_data;
- struct joydev *joydev = list->joydev;
- void __user *argp = (void __user *)arg;
-
- if (!joydev->exist) return -ENODEV;
-
- switch(cmd) {
- case JS_SET_TIMELIMIT:
- return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
- case JS_GET_TIMELIMIT:
- return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
- case JS_SET_ALL:
- return copy_from_user(&joydev->glue, argp,
- sizeof(joydev->glue)) ? -EFAULT : 0;
- case JS_GET_ALL:
- return copy_to_user(argp, &joydev->glue,
- sizeof(joydev->glue)) ? -EFAULT : 0;
- default:
- return joydev_ioctl_common(joydev, cmd, argp);
- }
-}
-
static struct file_operations joydev_fops = {
.owner = THIS_MODULE,
.read = joydev_read,
@@ -442,9 +379,6 @@ static struct file_operations joydev_fops = {
.open = joydev_open,
.release = joydev_release,
.ioctl = joydev_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = joydev_compat_ioctl,
-#endif
.fasync = joydev_fasync,
};
diff --git a/trunk/drivers/input/joystick/a3d.c b/trunk/drivers/input/joystick/a3d.c
index bf34f75b9467..ad39fe4bf35f 100644
--- a/trunk/drivers/input/joystick/a3d.c
+++ b/trunk/drivers/input/joystick/a3d.c
@@ -185,7 +185,7 @@ static void a3d_poll(struct gameport *gameport)
a3d->reads++;
if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length ||
data[0] != a3d->mode || a3d_csum(data, a3d->length))
- a3d->bads++;
+ a3d->bads++;
else
a3d_read(a3d, data);
}
diff --git a/trunk/drivers/input/joystick/adi.c b/trunk/drivers/input/joystick/adi.c
index 265962956c63..83f6dafc1716 100644
--- a/trunk/drivers/input/joystick/adi.c
+++ b/trunk/drivers/input/joystick/adi.c
@@ -82,7 +82,7 @@ static char adi_cm2_abs[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
static char adi_wmf_abs[] = { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y };
static short adi_wmgpe_key[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT };
-static short adi_wmi_key[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA };
+static short adi_wmi_key[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA };
static short adi_wmed3d_key[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2 };
static short adi_cm2_key[] = { BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 };
@@ -183,7 +183,7 @@ static void adi_move_bits(struct adi_port *port, int length)
int i;
struct adi *adi = port->adi;
- adi[0].idx = adi[1].idx = 0;
+ adi[0].idx = adi[1].idx = 0;
if (adi[0].ret <= 0 || adi[1].ret <= 0) return;
if (adi[0].data[0] & 0x20 || ~adi[1].data[0] & 0x20) return;
diff --git a/trunk/drivers/input/joystick/amijoy.c b/trunk/drivers/input/joystick/amijoy.c
index 033456bb9fe0..cf36ca9b92f3 100644
--- a/trunk/drivers/input/joystick/amijoy.c
+++ b/trunk/drivers/input/joystick/amijoy.c
@@ -51,8 +51,7 @@ MODULE_PARM_DESC(map, "Map of attached joysticks in form of , (default is
__obsolete_setup("amijoy=");
-static int amijoy_used;
-static DECLARE_MUTEX(amijoy_sem);
+static int amijoy_used[2] = { 0, 0 };
static struct input_dev amijoy_dev[2];
static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" };
@@ -85,30 +84,26 @@ static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp)
static int amijoy_open(struct input_dev *dev)
{
- int err;
+ int *used = dev->private;
- err = down_interruptible(&amijoy_sem);
- if (err)
- return err;
+ if ((*used)++)
+ return 0;
- if (!amijoy_used && request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) {
+ if (request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) {
+ (*used)--;
printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB);
- err = -EBUSY;
- goto out;
+ return -EBUSY;
}
- amijoy_used++;
-out:
- up(&amijoy_sem);
- return err;
+ return 0;
}
static void amijoy_close(struct input_dev *dev)
{
- down(&amijoysem);
- if (!--amijoy_used)
+ int *used = dev->private;
+
+ if (!--(*used))
free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
- up(&amijoy_sem);
}
static int __init amijoy_init(void)
@@ -143,6 +138,8 @@ static int __init amijoy_init(void)
amijoy_dev[i].id.product = 0x0003;
amijoy_dev[i].id.version = 0x0100;
+ amijoy_dev[i].private = amijoy_used + i;
+
input_register_device(amijoy_dev + i);
printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i);
}
diff --git a/trunk/drivers/input/joystick/db9.c b/trunk/drivers/input/joystick/db9.c
index fbd3eed07f90..cfdd3acf06a1 100644
--- a/trunk/drivers/input/joystick/db9.c
+++ b/trunk/drivers/input/joystick/db9.c
@@ -87,7 +87,7 @@ __obsolete_setup("db9_3=");
#define DB9_NORMAL 0x0a
#define DB9_NOSELECT 0x08
-#define DB9_MAX_DEVICES 2
+#define DB9_MAX_DEVICES 2
#define DB9_GENESIS6_DELAY 14
#define DB9_REFRESH_TIME HZ/100
@@ -98,7 +98,6 @@ struct db9 {
struct pardevice *pd;
int mode;
int used;
- struct semaphore sem;
char phys[2][32];
};
@@ -504,11 +503,6 @@ static int db9_open(struct input_dev *dev)
{
struct db9 *db9 = dev->private;
struct parport *port = db9->pd->port;
- int err;
-
- err = down_interruptible(&db9->sem);
- if (err)
- return err;
if (!db9->used++) {
parport_claim(db9->pd);
@@ -520,7 +514,6 @@ static int db9_open(struct input_dev *dev)
mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
}
- up(&db9->sem);
return 0;
}
@@ -529,14 +522,12 @@ static void db9_close(struct input_dev *dev)
struct db9 *db9 = dev->private;
struct parport *port = db9->pd->port;
- down(&db9->sem);
if (!--db9->used) {
- del_timer_sync(&db9->timer);
+ del_timer(&db9->timer);
parport_write_control(port, 0x00);
parport_data_forward(port);
parport_release(db9->pd);
}
- up(&db9->sem);
}
static struct db9 __init *db9_probe(int *config, int nargs)
@@ -572,12 +563,12 @@ static struct db9 __init *db9_probe(int *config, int nargs)
}
}
- if (!(db9 = kcalloc(1, sizeof(struct db9), GFP_KERNEL))) {
+ if (!(db9 = kmalloc(sizeof(struct db9), GFP_KERNEL))) {
parport_put_port(pp);
return NULL;
}
+ memset(db9, 0, sizeof(struct db9));
- init_MUTEX(&db9->sem);
db9->mode = config[1];
init_timer(&db9->timer);
db9->timer.data = (long) db9;
diff --git a/trunk/drivers/input/joystick/gamecon.c b/trunk/drivers/input/joystick/gamecon.c
index 95bbdd302aad..8732f52bdd08 100644
--- a/trunk/drivers/input/joystick/gamecon.c
+++ b/trunk/drivers/input/joystick/gamecon.c
@@ -1,12 +1,12 @@
/*
* NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux
*
- * Copyright (c) 1999-2004 Vojtech Pavlik
- * Copyright (c) 2004 Peter Nelson
+ * Copyright (c) 1999-2004 Vojtech Pavlik
+ * Copyright (c) 2004 Peter Nelson
*
* Based on the work of:
- * Andree Borrmann John Dahlstrom
- * David Kuder Nathan Hand
+ * Andree Borrmann John Dahlstrom
+ * David Kuder Nathan Hand
*/
/*
@@ -81,7 +81,6 @@ struct gc {
struct timer_list timer;
unsigned char pads[GC_MAX + 1];
int used;
- struct semaphore sem;
char phys[5][32];
};
@@ -434,7 +433,7 @@ static void gc_timer(unsigned long private)
gc_psx_read_packet(gc, data_psx, data);
for (i = 0; i < 5; i++) {
- switch (data[i]) {
+ switch (data[i]) {
case GC_PSX_RUMBLE:
@@ -504,33 +503,22 @@ static void gc_timer(unsigned long private)
static int gc_open(struct input_dev *dev)
{
struct gc *gc = dev->private;
- int err;
-
- err = down_interruptible(&gc->sem);
- if (err)
- return err;
-
if (!gc->used++) {
parport_claim(gc->pd);
parport_write_control(gc->pd->port, 0x04);
mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
}
-
- up(&gc->sem);
return 0;
}
static void gc_close(struct input_dev *dev)
{
struct gc *gc = dev->private;
-
- down(&gc->sem);
if (!--gc->used) {
- del_timer_sync(&gc->timer);
+ del_timer(&gc->timer);
parport_write_control(gc->pd->port, 0x00);
parport_release(gc->pd);
}
- up(&gc->sem);
}
static struct gc __init *gc_probe(int *config, int nargs)
@@ -554,12 +542,11 @@ static struct gc __init *gc_probe(int *config, int nargs)
return NULL;
}
- if (!(gc = kcalloc(1, sizeof(struct gc), GFP_KERNEL))) {
+ if (!(gc = kmalloc(sizeof(struct gc), GFP_KERNEL))) {
parport_put_port(pp);
return NULL;
}
-
- init_MUTEX(&gc->sem);
+ memset(gc, 0, sizeof(struct gc));
gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
diff --git a/trunk/drivers/input/joystick/gf2k.c b/trunk/drivers/input/joystick/gf2k.c
index 7d969420066c..ad13f09a4e71 100644
--- a/trunk/drivers/input/joystick/gf2k.c
+++ b/trunk/drivers/input/joystick/gf2k.c
@@ -329,7 +329,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
for (i = 0; i < gf2k_axes[gf2k->id]; i++) {
gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 :
- gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32;
+ gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32;
gf2k->dev.absmin[gf2k_abs[i]] = 32;
gf2k->dev.absfuzz[gf2k_abs[i]] = 8;
gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0;
diff --git a/trunk/drivers/input/joystick/grip_mp.c b/trunk/drivers/input/joystick/grip_mp.c
index 0da7bd133ccf..42e5005d621f 100644
--- a/trunk/drivers/input/joystick/grip_mp.c
+++ b/trunk/drivers/input/joystick/grip_mp.c
@@ -171,7 +171,7 @@ static int mp_io(struct gameport* gameport, int sendflags, int sendcode, u32 *pa
*packet = 0;
raw_data = gameport_read(gameport);
if (raw_data & 1)
- return IO_RETRY;
+ return IO_RETRY;
for (i = 0; i < 64; i++) {
raw_data = gameport_read(gameport);
diff --git a/trunk/drivers/input/joystick/iforce/iforce-main.c b/trunk/drivers/input/joystick/iforce/iforce-main.c
index e31b7b93fde2..028f3513629a 100644
--- a/trunk/drivers/input/joystick/iforce/iforce-main.c
+++ b/trunk/drivers/input/joystick/iforce/iforce-main.c
@@ -78,7 +78,6 @@ static struct iforce_device iforce_device[] = {
{ 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //?
- { 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //?
{ 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce }
};
diff --git a/trunk/drivers/input/joystick/iforce/iforce-usb.c b/trunk/drivers/input/joystick/iforce/iforce-usb.c
index 6369a24684fe..617c0b0e5a39 100644
--- a/trunk/drivers/input/joystick/iforce/iforce-usb.c
+++ b/trunk/drivers/input/joystick/iforce/iforce-usb.c
@@ -229,7 +229,6 @@ static struct usb_device_id iforce_usb_ids [] = {
{ USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */
{ USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */
{ USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */
- { USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */
{ } /* Terminating entry */
};
diff --git a/trunk/drivers/input/joystick/spaceball.c b/trunk/drivers/input/joystick/spaceball.c
index a436f2220856..ec0a2a64d49c 100644
--- a/trunk/drivers/input/joystick/spaceball.c
+++ b/trunk/drivers/input/joystick/spaceball.c
@@ -4,8 +4,8 @@
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* Based on the work of:
- * David Thompson
- * Joseph Krahn
+ * David Thompson
+ * Joseph Krahn
*/
/*
diff --git a/trunk/drivers/input/joystick/spaceorb.c b/trunk/drivers/input/joystick/spaceorb.c
index 01fd2e4791ae..874367bfab08 100644
--- a/trunk/drivers/input/joystick/spaceorb.c
+++ b/trunk/drivers/input/joystick/spaceorb.c
@@ -4,7 +4,7 @@
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* Based on the work of:
- * David Thompson
+ * David Thompson
*/
/*
diff --git a/trunk/drivers/input/joystick/tmdc.c b/trunk/drivers/input/joystick/tmdc.c
index 9eb9954cac6e..aaee52ceb920 100644
--- a/trunk/drivers/input/joystick/tmdc.c
+++ b/trunk/drivers/input/joystick/tmdc.c
@@ -79,7 +79,7 @@ static short tmdc_btn_pad[TMDC_BTN] =
{ BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR };
static short tmdc_btn_joy[TMDC_BTN] =
{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE,
- BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z };
+ BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z };
static short tmdc_btn_fm[TMDC_BTN] =
{ BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 };
static short tmdc_btn_at[TMDC_BTN] =
diff --git a/trunk/drivers/input/joystick/turbografx.c b/trunk/drivers/input/joystick/turbografx.c
index 28100d461cb7..dd88b9cb49fa 100644
--- a/trunk/drivers/input/joystick/turbografx.c
+++ b/trunk/drivers/input/joystick/turbografx.c
@@ -84,7 +84,6 @@ static struct tgfx {
char phys[7][32];
int sticks;
int used;
- struct semaphore sem;
} *tgfx_base[3];
/*
@@ -100,7 +99,7 @@ static void tgfx_timer(unsigned long private)
for (i = 0; i < 7; i++)
if (tgfx->sticks & (1 << i)) {
- dev = tgfx->dev + i;
+ dev = tgfx->dev + i;
parport_write_data(tgfx->pd->port, ~(1 << i));
data1 = parport_read_status(tgfx->pd->port) ^ 0x7f;
@@ -123,34 +122,23 @@ static void tgfx_timer(unsigned long private)
static int tgfx_open(struct input_dev *dev)
{
- struct tgfx *tgfx = dev->private;
- int err;
-
- err = down_interruptible(&tgfx->sem);
- if (err)
- return err;
-
- if (!tgfx->used++) {
+ struct tgfx *tgfx = dev->private;
+ if (!tgfx->used++) {
parport_claim(tgfx->pd);
parport_write_control(tgfx->pd->port, 0x04);
- mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
+ mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
}
-
- up(&tgfx->sem);
- return 0;
+ return 0;
}
static void tgfx_close(struct input_dev *dev)
{
- struct tgfx *tgfx = dev->private;
-
- down(&tgfx->sem);
- if (!--tgfx->used) {
- del_timer_sync(&tgfx->timer);
+ struct tgfx *tgfx = dev->private;
+ if (!--tgfx->used) {
+ del_timer(&tgfx->timer);
parport_write_control(tgfx->pd->port, 0x00);
- parport_release(tgfx->pd);
+ parport_release(tgfx->pd);
}
- up(&tgfx->sem);
}
/*
@@ -178,12 +166,11 @@ static struct tgfx __init *tgfx_probe(int *config, int nargs)
return NULL;
}
- if (!(tgfx = kcalloc(1, sizeof(struct tgfx), GFP_KERNEL))) {
+ if (!(tgfx = kmalloc(sizeof(struct tgfx), GFP_KERNEL))) {
parport_put_port(pp);
return NULL;
}
-
- init_MUTEX(&tgfx->sem);
+ memset(tgfx, 0, sizeof(struct tgfx));
tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
diff --git a/trunk/drivers/input/keyboard/atkbd.c b/trunk/drivers/input/keyboard/atkbd.c
index 4d4985b59abf..82fad9a23ace 100644
--- a/trunk/drivers/input/keyboard/atkbd.c
+++ b/trunk/drivers/input/keyboard/atkbd.c
@@ -227,7 +227,7 @@ static ssize_t atkbd_do_set_##_name(struct device *d, struct device_attribute *a
{ \
return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \
} \
-static struct device_attribute atkbd_attr_##_name = \
+static struct device_attribute atkbd_attr_##_name = \
__ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name);
ATKBD_DEFINE_ATTR(extra);
@@ -388,7 +388,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
value = atkbd->release ? 0 :
(1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key)));
- switch (value) { /* Workaround Toshiba laptop multiple keypress */
+ switch (value) { /* Workaround Toshiba laptop multiple keypress */
case 0:
atkbd->last = 0;
break;
@@ -894,7 +894,7 @@ static int atkbd_reconnect(struct serio *serio)
if (atkbd->write) {
param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0)
| (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0)
- | (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0);
+ | (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0);
if (atkbd_probe(atkbd))
return -1;
diff --git a/trunk/drivers/input/keyboard/corgikbd.c b/trunk/drivers/input/keyboard/corgikbd.c
index a8551711e8d6..0f1220a0ceb5 100644
--- a/trunk/drivers/input/keyboard/corgikbd.c
+++ b/trunk/drivers/input/keyboard/corgikbd.c
@@ -39,7 +39,6 @@
#define CORGI_KEY_CALENDER KEY_F1
#define CORGI_KEY_ADDRESS KEY_F2
#define CORGI_KEY_FN KEY_F3
-#define CORGI_KEY_CANCEL KEY_F4
#define CORGI_KEY_OFF KEY_SUSPEND
#define CORGI_KEY_EXOK KEY_F5
#define CORGI_KEY_EXCANCEL KEY_F6
@@ -47,7 +46,6 @@
#define CORGI_KEY_EXJOGUP KEY_F8
#define CORGI_KEY_JAP1 KEY_LEFTCTRL
#define CORGI_KEY_JAP2 KEY_LEFTALT
-#define CORGI_KEY_MAIL KEY_F10
#define CORGI_KEY_OK KEY_F11
#define CORGI_KEY_MENU KEY_F12
#define CORGI_HINGE_0 KEY_KP0
@@ -61,8 +59,8 @@ static unsigned char corgikbd_keycode[NR_SCANCODES] = {
KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */
CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */
CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */
- CORGI_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */
- KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, CORGI_KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */
+ KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */
+ KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */
CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */
CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2 /* 125-127 */
};
diff --git a/trunk/drivers/input/keyboard/lkkbd.c b/trunk/drivers/input/keyboard/lkkbd.c
index 098963c7cdd6..2694ff2b5beb 100644
--- a/trunk/drivers/input/keyboard/lkkbd.c
+++ b/trunk/drivers/input/keyboard/lkkbd.c
@@ -15,10 +15,10 @@
* information given below, I will _not_ be liable!
*
* RJ10 pinout: To DE9: Or DB25:
- * 1 - RxD <----> Pin 3 (TxD) <-> Pin 2 (TxD)
- * 2 - GND <----> Pin 5 (GND) <-> Pin 7 (GND)
- * 4 - TxD <----> Pin 2 (RxD) <-> Pin 3 (RxD)
- * 3 - +12V (from HDD drive connector), DON'T connect to DE9 or DB25!!!
+ * 1 - RxD <----> Pin 3 (TxD) <-> Pin 2 (TxD)
+ * 2 - GND <----> Pin 5 (GND) <-> Pin 7 (GND)
+ * 4 - TxD <----> Pin 2 (RxD) <-> Pin 3 (RxD)
+ * 3 - +12V (from HDD drive connector), DON'T connect to DE9 or DB25!!!
*
* Pin numbers for DE9 and DB25 are noted on the plug (quite small:). For
* RJ10, it's like this:
diff --git a/trunk/drivers/input/keyboard/locomokbd.c b/trunk/drivers/input/keyboard/locomokbd.c
index 8935290256b3..d3e9dd6a13cd 100644
--- a/trunk/drivers/input/keyboard/locomokbd.c
+++ b/trunk/drivers/input/keyboard/locomokbd.c
@@ -42,7 +42,7 @@ MODULE_AUTHOR("John Lenz ");
MODULE_DESCRIPTION("LoCoMo keyboard driver");
MODULE_LICENSE("GPL");
-#define LOCOMOKBD_NUMKEYS 128
+#define LOCOMOKBD_NUMKEYS 128
#define KEY_ACTIVITY KEY_F16
#define KEY_CONTACT KEY_F18
@@ -61,7 +61,7 @@ static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
KEY_G, KEY_F, KEY_X, KEY_S, 0, 0, 0, 0, 0, 0, /* 90 - 99 */
0, 0, KEY_DOT, 0, KEY_COMMA, KEY_N, KEY_B, KEY_C, KEY_Z, KEY_A, /* 100 - 109 */
KEY_LEFTSHIFT, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0, 0, 0, /* 110 - 119 */
- KEY_M, KEY_SPACE, KEY_V, KEY_APOSTROPHE, KEY_SLASH, 0, 0, 0 /* 120 - 128 */
+ KEY_M, KEY_SPACE, KEY_V, KEY_APOSTROPHE, KEY_SLASH, 0, 0, 0 /* 120 - 128 */
};
#define KB_ROWS 16
@@ -82,7 +82,7 @@ struct locomokbd {
struct locomo_dev *ldev;
unsigned long base;
spinlock_t lock;
-
+
struct timer_list timer;
};
@@ -95,7 +95,7 @@ static inline void locomokbd_charge_all(unsigned long membase)
static inline void locomokbd_activate_all(unsigned long membase)
{
unsigned long r;
-
+
locomo_writel(0, membase + LOCOMO_KSC);
r = locomo_readl(membase + LOCOMO_KIC);
r &= 0xFEFF;
@@ -127,7 +127,7 @@ static inline void locomokbd_reset_col(unsigned long membase, int col)
*/
/* Scan the hardware keyboard and push any changes up through the input layer */
-static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *regs)
+static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *regs)
{
unsigned int row, col, rowd, scancode;
unsigned long flags;
@@ -138,7 +138,7 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *
if (regs)
input_regs(&locomokbd->input, regs);
-
+
locomokbd_charge_all(membase);
num_pressed = 0;
@@ -146,9 +146,9 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *
locomokbd_activate_col(membase, col);
udelay(KB_DELAY);
-
+
rowd = ~locomo_readl(membase + LOCOMO_KIB);
- for (row = 0; row < KB_ROWS; row++) {
+ for (row = 0; row < KB_ROWS; row++ ) {
scancode = SCANCODE(col, row);
if (rowd & KB_ROWMASK(row)) {
num_pressed += 1;
@@ -170,7 +170,7 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *
spin_unlock_irqrestore(&locomokbd->lock, flags);
}
-/*
+/*
* LoCoMo keyboard interrupt handler.
*/
static irqreturn_t locomokbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -205,8 +205,8 @@ static int locomokbd_probe(struct locomo_dev *dev)
memset(locomokbd, 0, sizeof(struct locomokbd));
/* try and claim memory region */
- if (!request_mem_region((unsigned long) dev->mapbase,
- dev->length,
+ if (!request_mem_region((unsigned long) dev->mapbase,
+ dev->length,
LOCOMO_DRIVER_NAME(dev))) {
ret = -EBUSY;
printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n");
@@ -225,7 +225,7 @@ static int locomokbd_probe(struct locomo_dev *dev)
locomokbd->timer.data = (unsigned long) locomokbd;
locomokbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
-
+
init_input_dev(&locomokbd->input);
locomokbd->input.keycode = locomokbd->keycode;
locomokbd->input.keycodesize = sizeof(unsigned char);
@@ -271,11 +271,11 @@ static int locomokbd_probe(struct locomo_dev *dev)
static int locomokbd_remove(struct locomo_dev *dev)
{
struct locomokbd *locomokbd = locomo_get_drvdata(dev);
-
+
free_irq(dev->irq[0], locomokbd);
del_timer_sync(&locomokbd->timer);
-
+
input_unregister_device(&locomokbd->input);
locomo_set_drvdata(dev, NULL);
diff --git a/trunk/drivers/input/keyboard/maple_keyb.c b/trunk/drivers/input/keyboard/maple_keyb.c
index eecbde294f1f..859ed771ee0a 100644
--- a/trunk/drivers/input/keyboard/maple_keyb.c
+++ b/trunk/drivers/input/keyboard/maple_keyb.c
@@ -1,6 +1,6 @@
/*
* $Id: maple_keyb.c,v 1.4 2004/03/22 01:18:15 lethal Exp $
- * SEGA Dreamcast keyboard driver
+ * SEGA Dreamcast keyboard driver
* Based on drivers/usb/usbkbd.c
*/
@@ -40,6 +40,7 @@ struct dc_kbd {
struct input_dev dev;
unsigned char new[8];
unsigned char old[8];
+ int open;
};
@@ -94,6 +95,22 @@ static void dc_kbd_callback(struct mapleq *mq)
}
}
+
+static int dc_kbd_open(struct input_dev *dev)
+{
+ struct dc_kbd *kbd = dev->private;
+ kbd->open++;
+ return 0;
+}
+
+
+static void dc_kbd_close(struct input_dev *dev)
+{
+ struct dc_kbd *kbd = dev->private;
+ kbd->open--;
+}
+
+
static int dc_kbd_connect(struct maple_device *dev)
{
int i;
@@ -116,6 +133,9 @@ static int dc_kbd_connect(struct maple_device *dev)
clear_bit(0, kbd->dev.keybit);
kbd->dev.private = kbd;
+ kbd->dev.open = dc_kbd_open;
+ kbd->dev.close = dc_kbd_close;
+ kbd->dev.event = NULL;
kbd->dev.name = dev->product_name;
kbd->dev.id.bustype = BUS_MAPLE;
diff --git a/trunk/drivers/input/misc/uinput.c b/trunk/drivers/input/misc/uinput.c
index 98710997aaaa..158c8e845ff9 100644
--- a/trunk/drivers/input/misc/uinput.c
+++ b/trunk/drivers/input/misc/uinput.c
@@ -298,11 +298,9 @@ static int uinput_alloc_device(struct file *file, const char __user *buffer, siz
/* check if absmin/absmax/absfuzz/absflat are filled as
* told in Documentation/input/input-programming.txt */
if (test_bit(EV_ABS, dev->evbit)) {
- int err = uinput_validate_absbits(dev);
- if (err < 0) {
- retval = err;
+ retval = uinput_validate_absbits(dev);
+ if (retval < 0)
kfree(dev->name);
- }
}
exit:
diff --git a/trunk/drivers/input/mouse/Makefile b/trunk/drivers/input/mouse/Makefile
index c4909b49337d..a7864195806a 100644
--- a/trunk/drivers/input/mouse/Makefile
+++ b/trunk/drivers/input/mouse/Makefile
@@ -15,4 +15,4 @@ obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o
obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
-psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o
+psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o
diff --git a/trunk/drivers/input/mouse/alps.c b/trunk/drivers/input/mouse/alps.c
index a12e98158a75..7bf4be733e9a 100644
--- a/trunk/drivers/input/mouse/alps.c
+++ b/trunk/drivers/input/mouse/alps.c
@@ -30,11 +30,10 @@
#define ALPS_DUALPOINT 0x01
#define ALPS_WHEEL 0x02
-#define ALPS_FW_BK_1 0x04
+#define ALPS_FW_BK 0x04
#define ALPS_4BTN 0x08
#define ALPS_OLDPROTO 0x10
#define ALPS_PASS 0x20
-#define ALPS_FW_BK_2 0x40
static struct alps_model_info alps_model_data[] = {
{ { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */
@@ -44,11 +43,11 @@ static struct alps_model_info alps_model_data[] = {
{ { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
{ { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, 0 },
{ { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */
- { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */
+ { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK }, /* NEC Versa L320 */
{ { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 },
{ { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */
{ { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
- { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */
+ { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
{ { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
{ { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
{ { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
@@ -62,11 +61,11 @@ static struct alps_model_info alps_model_data[] = {
/*
* ALPS abolute Mode - new format
- *
- * byte 0: 1 ? ? ? 1 ? ? ?
+ *
+ * byte 0: 1 ? ? ? 1 ? ? ?
* byte 1: 0 x6 x5 x4 x3 x2 x1 x0
* byte 2: 0 x10 x9 x8 x7 ? fin ges
- * byte 3: 0 y9 y8 y7 1 M R L
+ * byte 3: 0 y9 y8 y7 1 M R L
* byte 4: 0 y6 y5 y4 y3 y2 y1 y0
* byte 5: 0 z6 z5 z4 z3 z2 z1 z0
*
@@ -82,12 +81,11 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
struct input_dev *dev = &psmouse->dev;
struct input_dev *dev2 = &priv->dev2;
int x, y, z, ges, fin, left, right, middle;
- int back = 0, forward = 0;
input_regs(dev, regs);
if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */
- input_report_key(dev2, BTN_LEFT, packet[0] & 1);
+ input_report_key(dev2, BTN_LEFT, packet[0] & 1);
input_report_key(dev2, BTN_RIGHT, packet[0] & 2);
input_report_key(dev2, BTN_MIDDLE, packet[0] & 4);
input_report_rel(dev2, REL_X,
@@ -114,18 +112,6 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
z = packet[5];
}
- if (priv->i->flags & ALPS_FW_BK_1) {
- back = packet[2] & 4;
- forward = packet[0] & 0x10;
- }
-
- if (priv->i->flags & ALPS_FW_BK_2) {
- back = packet[3] & 4;
- forward = packet[2] & 4;
- if ((middle = forward && back))
- forward = back = 0;
- }
-
ges = packet[2] & 1;
fin = packet[2] & 2;
@@ -169,12 +155,13 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
input_report_abs(dev, ABS_PRESSURE, z);
input_report_key(dev, BTN_TOOL_FINGER, z > 0);
+
if (priv->i->flags & ALPS_WHEEL)
input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08));
- if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
- input_report_key(dev, BTN_FORWARD, forward);
- input_report_key(dev, BTN_BACK, back);
+ if (priv->i->flags & ALPS_FW_BK) {
+ input_report_key(dev, BTN_FORWARD, packet[0] & 0x10);
+ input_report_key(dev, BTN_BACK, packet[2] & 0x04);
}
input_sync(dev);
@@ -270,6 +257,7 @@ static struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *vers
static int alps_passthrough_mode(struct psmouse *psmouse, int enable)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
+ unsigned char param[3];
int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11;
if (ps2_command(ps2dev, NULL, cmd) ||
@@ -279,7 +267,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, int enable)
return -1;
/* we may get 3 more bytes, just ignore them */
- ps2_drain(ps2dev, 3, 100);
+ ps2_command(ps2dev, param, 0x0300);
return 0;
}
@@ -437,7 +425,7 @@ int alps_init(struct psmouse *psmouse)
psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL);
}
- if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
+ if (priv->i->flags & ALPS_FW_BK) {
psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD);
psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
}
@@ -448,8 +436,8 @@ int alps_init(struct psmouse *psmouse)
priv->dev2.id.bustype = BUS_I8042;
priv->dev2.id.vendor = 0x0002;
priv->dev2.id.product = PSMOUSE_ALPS;
- priv->dev2.id.version = 0x0000;
-
+ priv->dev2.id.version = 0x0000;
+
priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
@@ -473,15 +461,17 @@ int alps_init(struct psmouse *psmouse)
int alps_detect(struct psmouse *psmouse, int set_properties)
{
int version;
- struct alps_model_info *model;
+ struct alps_model_info *model;
if (!(model = alps_get_model(psmouse, &version)))
return -1;
if (set_properties) {
psmouse->vendor = "ALPS";
- psmouse->name = model->flags & ALPS_DUALPOINT ?
- "DualPoint TouchPad" : "GlidePoint";
+ if (model->flags & ALPS_DUALPOINT)
+ psmouse->name = "DualPoint TouchPad";
+ else
+ psmouse->name = "GlidePoint";
psmouse->model = version;
}
return 0;
diff --git a/trunk/drivers/input/mouse/amimouse.c b/trunk/drivers/input/mouse/amimouse.c
index e994849efb8f..7baa09cca7c5 100644
--- a/trunk/drivers/input/mouse/amimouse.c
+++ b/trunk/drivers/input/mouse/amimouse.c
@@ -33,6 +33,7 @@ MODULE_AUTHOR("Vojtech Pavlik ");
MODULE_DESCRIPTION("Amiga mouse driver");
MODULE_LICENSE("GPL");
+static int amimouse_used = 0;
static int amimouse_lastx, amimouse_lasty;
static struct input_dev amimouse_dev;
@@ -80,12 +81,16 @@ static int amimouse_open(struct input_dev *dev)
{
unsigned short joy0dat;
+ if (amimouse_used++)
+ return 0;
+
joy0dat = custom.joy0dat;
amimouse_lastx = joy0dat & 0xff;
amimouse_lasty = joy0dat >> 8;
if (request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", amimouse_interrupt)) {
+ amimouse_used--;
printk(KERN_ERR "amimouse.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB);
return -EBUSY;
}
@@ -95,7 +100,8 @@ static int amimouse_open(struct input_dev *dev)
static void amimouse_close(struct input_dev *dev)
{
- free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt);
+ if (!--amimouse_used)
+ free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt);
}
static int __init amimouse_init(void)
diff --git a/trunk/drivers/input/mouse/inport.c b/trunk/drivers/input/mouse/inport.c
index 1f62c0134010..ca4e96886627 100644
--- a/trunk/drivers/input/mouse/inport.c
+++ b/trunk/drivers/input/mouse/inport.c
@@ -17,18 +17,18 @@
/*
* 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
+ * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
+ *
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to , or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
@@ -87,23 +87,29 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)");
__obsolete_setup("inport_irq=");
+static int inport_used;
+
static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int inport_open(struct input_dev *dev)
{
- if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL))
- return -EBUSY;
- outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
- outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
+ if (!inport_used++) {
+ if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL))
+ return -EBUSY;
+ outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
+ outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
+ }
return 0;
}
static void inport_close(struct input_dev *dev)
{
- outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
- outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
- free_irq(inport_irq, NULL);
+ if (!--inport_used) {
+ outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
+ outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
+ free_irq(inport_irq, NULL);
+ }
}
static struct input_dev inport_dev = {
@@ -114,11 +120,11 @@ static struct input_dev inport_dev = {
.close = inport_close,
.name = INPORT_NAME,
.phys = "isa023c/input0",
- .id = {
- .bustype = BUS_ISA,
- .vendor = INPORT_VENDOR,
- .product = 0x0001,
- .version = 0x0100,
+ .id = {
+ .bustype = BUS_ISA,
+ .vendor = INPORT_VENDOR,
+ .product = 0x0001,
+ .version = 0x0100,
},
};
diff --git a/trunk/drivers/input/mouse/lifebook.c b/trunk/drivers/input/mouse/lifebook.c
deleted file mode 100644
index bd9df9b28325..000000000000
--- a/trunk/drivers/input/mouse/lifebook.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Fujitsu B-series Lifebook PS/2 TouchScreen driver
- *
- * Copyright (c) 2005 Vojtech Pavlik
- * Copyright (c) 2005 Kenan Esau
- *
- * TouchScreen detection, absolute mode setting and packet layout is taken from
- * Harald Hoyer's description of the device.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#include
-#include
-#include
-#include
-
-#include "psmouse.h"
-#include "lifebook.h"
-
-static struct dmi_system_id lifebook_dmi_table[] = {
- {
- .ident = "Lifebook B",
- .matches = {
- DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"),
- },
- },
- { }
-};
-
-
-static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
-{
- unsigned char *packet = psmouse->packet;
- struct input_dev *dev = &psmouse->dev;
-
- if (psmouse->pktcnt != 3)
- return PSMOUSE_GOOD_DATA;
-
- input_regs(dev, regs);
-
- /* calculate X and Y */
- if ((packet[0] & 0x08) == 0x00) {
- input_report_abs(dev, ABS_X,
- (packet[1] | ((packet[0] & 0x30) << 4)));
- input_report_abs(dev, ABS_Y,
- 1024 - (packet[2] | ((packet[0] & 0xC0) << 2)));
- } else {
- input_report_rel(dev, REL_X,
- ((packet[0] & 0x10) ? packet[1] - 256 : packet[1]));
- input_report_rel(dev, REL_Y,
- -(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2]));
- }
-
- input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
- input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
- input_report_key(dev, BTN_TOUCH, packet[0] & 0x04);
-
- input_sync(dev);
-
- return PSMOUSE_FULL_PACKET;
-}
-
-static int lifebook_absolute_mode(struct psmouse *psmouse)
-{
- struct ps2dev *ps2dev = &psmouse->ps2dev;
- unsigned char param;
-
- if (psmouse_reset(psmouse))
- return -1;
-
- /*
- Enable absolute output -- ps2_command fails always but if
- you leave this call out the touchsreen will never send
- absolute coordinates
- */
- param = 0x07;
- ps2_command(ps2dev, ¶m, PSMOUSE_CMD_SETRES);
-
- return 0;
-}
-
-static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolution)
-{
- unsigned char params[] = { 0, 1, 2, 2, 3 };
-
- if (resolution == 0 || resolution > 400)
- resolution = 400;
-
- ps2_command(&psmouse->ps2dev, ¶ms[resolution / 100], PSMOUSE_CMD_SETRES);
- psmouse->resolution = 50 << params[resolution / 100];
-}
-
-static void lifebook_disconnect(struct psmouse *psmouse)
-{
- psmouse_reset(psmouse);
-}
-
-int lifebook_detect(struct psmouse *psmouse, int set_properties)
-{
- if (!dmi_check_system(lifebook_dmi_table))
- return -1;
-
- if (set_properties) {
- psmouse->vendor = "Fujitsu";
- psmouse->name = "Lifebook TouchScreen";
- }
-
- return 0;
-}
-
-int lifebook_init(struct psmouse *psmouse)
-{
- if (lifebook_absolute_mode(psmouse))
- return -1;
-
- psmouse->dev.evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
- psmouse->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- psmouse->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
- psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
- input_set_abs_params(&psmouse->dev, ABS_X, 0, 1024, 0, 0);
- input_set_abs_params(&psmouse->dev, ABS_Y, 0, 1024, 0, 0);
-
- psmouse->protocol_handler = lifebook_process_byte;
- psmouse->set_resolution = lifebook_set_resolution;
- psmouse->disconnect = lifebook_disconnect;
- psmouse->reconnect = lifebook_absolute_mode;
- psmouse->pktsize = 3;
-
- return 0;
-}
-
diff --git a/trunk/drivers/input/mouse/lifebook.h b/trunk/drivers/input/mouse/lifebook.h
deleted file mode 100644
index be1c0943825d..000000000000
--- a/trunk/drivers/input/mouse/lifebook.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Fujitsu B-series Lifebook PS/2 TouchScreen driver
- *
- * Copyright (c) 2005 Vojtech Pavlik
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#ifndef _LIFEBOOK_H
-#define _LIFEBOOK_H
-
-int lifebook_detect(struct psmouse *psmouse, int set_properties);
-int lifebook_init(struct psmouse *psmouse);
-
-#endif
diff --git a/trunk/drivers/input/mouse/logibm.c b/trunk/drivers/input/mouse/logibm.c
index 8b5243167227..77eb83e87f61 100644
--- a/trunk/drivers/input/mouse/logibm.c
+++ b/trunk/drivers/input/mouse/logibm.c
@@ -18,18 +18,18 @@
/*
* 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
+ * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
+ *
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to , or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
@@ -77,11 +77,16 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)");
__obsolete_setup("logibm_irq=");
+static int logibm_used = 0;
+
static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int logibm_open(struct input_dev *dev)
{
+ if (logibm_used++)
+ return 0;
if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) {
+ logibm_used--;
printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq);
return -EBUSY;
}
@@ -91,6 +96,8 @@ static int logibm_open(struct input_dev *dev)
static void logibm_close(struct input_dev *dev)
{
+ if (--logibm_used)
+ return;
outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
free_irq(logibm_irq, NULL);
}
@@ -160,7 +167,7 @@ static int __init logibm_init(void)
outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
input_register_device(&logibm_dev);
-
+
printk(KERN_INFO "input: Logitech bus mouse at %#x irq %d\n", LOGIBM_BASE, logibm_irq);
return 0;
diff --git a/trunk/drivers/input/mouse/maplemouse.c b/trunk/drivers/input/mouse/maplemouse.c
index e90c60cbbf05..12dc0ef5020f 100644
--- a/trunk/drivers/input/mouse/maplemouse.c
+++ b/trunk/drivers/input/mouse/maplemouse.c
@@ -1,6 +1,6 @@
/*
* $Id: maplemouse.c,v 1.2 2004/03/22 01:18:15 lethal Exp $
- * SEGA Dreamcast mouse driver
+ * SEGA Dreamcast mouse driver
* Based on drivers/usb/usbmouse.c
*/
@@ -15,51 +15,80 @@
MODULE_AUTHOR("YAEGASHI Takeshi ");
MODULE_DESCRIPTION("SEGA Dreamcast mouse driver");
+struct dc_mouse {
+ struct input_dev dev;
+ int open;
+};
+
+
static void dc_mouse_callback(struct mapleq *mq)
{
int buttons, relx, rely, relz;
struct maple_device *mapledev = mq->dev;
- struct input_dev *dev = mapledev->private_data;
+ struct dc_mouse *mouse = mapledev->private_data;
+ struct input_dev *dev = &mouse->dev;
unsigned char *res = mq->recvbuf;
buttons = ~res[8];
- relx = *(unsigned short *)(res + 12) - 512;
- rely = *(unsigned short *)(res + 14) - 512;
- relz = *(unsigned short *)(res + 16) - 512;
+ relx=*(unsigned short *)(res+12)-512;
+ rely=*(unsigned short *)(res+14)-512;
+ relz=*(unsigned short *)(res+16)-512;
- input_report_key(dev, BTN_LEFT, buttons & 4);
- input_report_key(dev, BTN_MIDDLE, buttons & 9);
- input_report_key(dev, BTN_RIGHT, buttons & 2);
+ input_report_key(dev, BTN_LEFT, buttons&4);
+ input_report_key(dev, BTN_MIDDLE, buttons&9);
+ input_report_key(dev, BTN_RIGHT, buttons&2);
input_report_rel(dev, REL_X, relx);
input_report_rel(dev, REL_Y, rely);
input_report_rel(dev, REL_WHEEL, relz);
input_sync(dev);
}
+
+static int dc_mouse_open(struct input_dev *dev)
+{
+ struct dc_mouse *mouse = dev->private;
+ mouse->open++;
+ return 0;
+}
+
+
+static void dc_mouse_close(struct input_dev *dev)
+{
+ struct dc_mouse *mouse = dev->private;
+ mouse->open--;
+}
+
+
static int dc_mouse_connect(struct maple_device *dev)
{
unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
- struct input_dev *input_dev;
+ struct dc_mouse *mouse;
- if (!(input_dev = kmalloc(sizeof(struct input_dev), GFP_KERNEL)))
+ if (!(mouse = kmalloc(sizeof(struct dc_mouse), GFP_KERNEL)))
return -1;
+ memset(mouse, 0, sizeof(struct dc_mouse));
+
+ dev->private_data = mouse;
- dev->private_data = input_dev;
+ mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+ mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
- memset(input_dev, 0, sizeof(struct dc_mouse));
- init_input_dev(input_dev);
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
- input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
+ init_input_dev(&mouse->dev);
- input_dev->name = dev->product_name;
- input_dev->id.bustype = BUS_MAPLE;
+ mouse->dev.private = mouse;
+ mouse->dev.open = dc_mouse_open;
+ mouse->dev.close = dc_mouse_close;
+ mouse->dev.event = NULL;
- input_register_device(input_dev);
+ mouse->dev.name = dev->product_name;
+ mouse->dev.id.bustype = BUS_MAPLE;
+
+ input_register_device(&mouse->dev);
maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE);
- printk(KERN_INFO "input: mouse(0x%lx): %s\n", data, input_dev->name);
+ printk(KERN_INFO "input: mouse(0x%lx): %s\n", data, mouse->dev.name);
return 0;
}
@@ -67,10 +96,10 @@ static int dc_mouse_connect(struct maple_device *dev)
static void dc_mouse_disconnect(struct maple_device *dev)
{
- struct input_dev *input_dev = dev->private_data;
+ struct dc_mouse *mouse = dev->private_data;
- input_unregister_device(input_dev);
- kfree(input_dev);
+ input_unregister_device(&mouse->dev);
+ kfree(mouse);
}
diff --git a/trunk/drivers/input/mouse/pc110pad.c b/trunk/drivers/input/mouse/pc110pad.c
index 93393d5c0078..0c74918fe254 100644
--- a/trunk/drivers/input/mouse/pc110pad.c
+++ b/trunk/drivers/input/mouse/pc110pad.c
@@ -4,7 +4,7 @@
* Copyright (c) 2000-2001 Vojtech Pavlik
*
* Based on the work of:
- * Alan Cox Robin O'Leary
+ * Alan Cox Robin O'Leary
*/
/*
@@ -56,6 +56,7 @@ static int pc110pad_io = 0x15e0;
static struct input_dev pc110pad_dev;
static int pc110pad_data[3];
static int pc110pad_count;
+static int pc110pad_used;
static char *pc110pad_name = "IBM PC110 TouchPad";
static char *pc110pad_phys = "isa15e0/input0";
@@ -73,7 +74,7 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs)
if (pc110pad_count < 3)
return IRQ_HANDLED;
-
+
input_regs(&pc110pad_dev, regs);
input_report_key(&pc110pad_dev, BTN_TOUCH,
pc110pad_data[0] & 0x01);
@@ -89,11 +90,15 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs)
static void pc110pad_close(struct input_dev *dev)
{
- outb(PC110PAD_OFF, pc110pad_io + 2);
+ if (!--pc110pad_used)
+ outb(PC110PAD_OFF, pc110pad_io + 2);
}
static int pc110pad_open(struct input_dev *dev)
{
+ if (pc110pad_used++)
+ return 0;
+
pc110pad_interrupt(0,NULL,NULL);
pc110pad_interrupt(0,NULL,NULL);
pc110pad_interrupt(0,NULL,NULL);
@@ -140,7 +145,7 @@ static int __init pc110pad_init(void)
pc110pad_dev.absmax[ABS_X] = 0x1ff;
pc110pad_dev.absmax[ABS_Y] = 0x0ff;
-
+
pc110pad_dev.open = pc110pad_open;
pc110pad_dev.close = pc110pad_close;
@@ -151,17 +156,17 @@ static int __init pc110pad_init(void)
pc110pad_dev.id.product = 0x0001;
pc110pad_dev.id.version = 0x0100;
- input_register_device(&pc110pad_dev);
+ input_register_device(&pc110pad_dev);
printk(KERN_INFO "input: %s at %#x irq %d\n",
pc110pad_name, pc110pad_io, pc110pad_irq);
-
+
return 0;
}
-
+
static void __exit pc110pad_exit(void)
{
- input_unregister_device(&pc110pad_dev);
+ input_unregister_device(&pc110pad_dev);
outb(PC110PAD_OFF, pc110pad_io + 2);
diff --git a/trunk/drivers/input/mouse/psmouse-base.c b/trunk/drivers/input/mouse/psmouse-base.c
index 19785a6c5abd..019034b21a0b 100644
--- a/trunk/drivers/input/mouse/psmouse-base.c
+++ b/trunk/drivers/input/mouse/psmouse-base.c
@@ -24,7 +24,6 @@
#include "synaptics.h"
#include "logips2pp.h"
#include "alps.h"
-#include "lifebook.h"
#define DRIVER_DESC "PS/2 mouse driver"
@@ -32,9 +31,10 @@ MODULE_AUTHOR("Vojtech Pavlik ");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-static unsigned int psmouse_max_proto = PSMOUSE_AUTO;
+static unsigned int psmouse_max_proto = -1U;
static int psmouse_set_maxproto(const char *val, struct kernel_param *kp);
static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp);
+static char *psmouse_proto_abbrev[] = { NULL, "bare", NULL, NULL, NULL, "imps", "exps", NULL, NULL, NULL };
#define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int)
#define param_set_proto_abbrev psmouse_set_maxproto
#define param_get_proto_abbrev psmouse_get_maxproto
@@ -57,7 +57,6 @@ static unsigned int psmouse_resetafter;
module_param_named(resetafter, psmouse_resetafter, uint, 0644);
MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
-PSMOUSE_DEFINE_ATTR(protocol);
PSMOUSE_DEFINE_ATTR(rate);
PSMOUSE_DEFINE_ATTR(resolution);
PSMOUSE_DEFINE_ATTR(resetafter);
@@ -68,23 +67,7 @@ __obsolete_setup("psmouse_smartscroll=");
__obsolete_setup("psmouse_resetafter=");
__obsolete_setup("psmouse_rate=");
-/*
- * psmouse_sem protects all operations changing state of mouse
- * (connecting, disconnecting, changing rate or resolution via
- * sysfs). We could use a per-device semaphore but since there
- * rarely more than one PS/2 mouse connected and since semaphore
- * is taken in "slow" paths it is not worth it.
- */
-static DECLARE_MUTEX(psmouse_sem);
-
-struct psmouse_protocol {
- enum psmouse_type type;
- char *name;
- char *alias;
- int maxproto;
- int (*detect)(struct psmouse *, int);
- int (*init)(struct psmouse *);
-};
+static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "ThinkPS/2", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2", "AlpsPS/2" };
/*
* psmouse_process_byte() analyzes the PS/2 data stream and reports
@@ -424,15 +407,12 @@ static int thinking_detect(struct psmouse *psmouse, int set_properties)
*/
static int ps2bare_detect(struct psmouse *psmouse, int set_properties)
{
- if (set_properties) {
- if (!psmouse->vendor) psmouse->vendor = "Generic";
- if (!psmouse->name) psmouse->name = "Mouse";
- }
+ if (!psmouse->vendor) psmouse->vendor = "Generic";
+ if (!psmouse->name) psmouse->name = "Mouse";
return 0;
}
-
/*
* psmouse_extensions() probes for any extensions to the basic PS/2 protocol
* the mouse may have.
@@ -443,17 +423,6 @@ static int psmouse_extensions(struct psmouse *psmouse,
{
int synaptics_hardware = 0;
-/*
- * We always check for lifebook because it does not disturb mouse
- * (it only checks DMI information).
- */
- if (lifebook_detect(psmouse, set_properties) == 0) {
- if (max_proto > PSMOUSE_IMEX) {
- if (!set_properties || lifebook_init(psmouse) == 0)
- return PSMOUSE_LIFEBOOK;
- }
- }
-
/*
* Try Kensington ThinkingMouse (we try first, because synaptics probe
* upsets the thinkingmouse).
@@ -537,103 +506,6 @@ static int psmouse_extensions(struct psmouse *psmouse,
return PSMOUSE_PS2;
}
-static struct psmouse_protocol psmouse_protocols[] = {
- {
- .type = PSMOUSE_PS2,
- .name = "PS/2",
- .alias = "bare",
- .maxproto = 1,
- .detect = ps2bare_detect,
- },
- {
- .type = PSMOUSE_PS2PP,
- .name = "PS2++",
- .alias = "logitech",
- .detect = ps2pp_init,
- },
- {
- .type = PSMOUSE_THINKPS,
- .name = "ThinkPS/2",
- .alias = "thinkps",
- .detect = thinking_detect,
- },
- {
- .type = PSMOUSE_GENPS,
- .name = "GenPS/2",
- .alias = "genius",
- .detect = genius_detect,
- },
- {
- .type = PSMOUSE_IMPS,
- .name = "ImPS/2",
- .alias = "imps",
- .maxproto = 1,
- .detect = intellimouse_detect,
- },
- {
- .type = PSMOUSE_IMEX,
- .name = "ImExPS/2",
- .alias = "exps",
- .maxproto = 1,
- .detect = im_explorer_detect,
- },
- {
- .type = PSMOUSE_SYNAPTICS,
- .name = "SynPS/2",
- .alias = "synaptics",
- .detect = synaptics_detect,
- .init = synaptics_init,
- },
- {
- .type = PSMOUSE_ALPS,
- .name = "AlpsPS/2",
- .alias = "alps",
- .detect = alps_detect,
- .init = alps_init,
- },
- {
- .type = PSMOUSE_LIFEBOOK,
- .name = "LBPS/2",
- .alias = "lifebook",
- .init = lifebook_init,
- },
- {
- .type = PSMOUSE_AUTO,
- .name = "auto",
- .alias = "any",
- .maxproto = 1,
- },
-};
-
-static struct psmouse_protocol *psmouse_protocol_by_type(enum psmouse_type type)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++)
- if (psmouse_protocols[i].type == type)
- return &psmouse_protocols[i];
-
- WARN_ON(1);
- return &psmouse_protocols[0];
-}
-
-static struct psmouse_protocol *psmouse_protocol_by_name(const char *name, size_t len)
-{
- struct psmouse_protocol *p;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++) {
- p = &psmouse_protocols[i];
-
- if ((strlen(p->name) == len && !strncmp(p->name, name, len)) ||
- (strlen(p->alias) == len && !strncmp(p->alias, name, len)))
- return &psmouse_protocols[i];
- }
-
- return NULL;
-}
-
-
/*
* psmouse_probe() probes for a PS/2 mouse.
*/
@@ -781,84 +653,30 @@ static void psmouse_cleanup(struct serio *serio)
static void psmouse_disconnect(struct serio *serio)
{
- struct psmouse *psmouse, *parent = NULL;
+ struct psmouse *psmouse, *parent;
- psmouse = serio_get_drvdata(serio);
-
- device_remove_file(&serio->dev, &psmouse_attr_protocol);
device_remove_file(&serio->dev, &psmouse_attr_rate);
device_remove_file(&serio->dev, &psmouse_attr_resolution);
device_remove_file(&serio->dev, &psmouse_attr_resetafter);
- down(&psmouse_sem);
-
+ psmouse = serio_get_drvdata(serio);
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = serio_get_drvdata(serio->parent);
- psmouse_deactivate(parent);
+ if (parent->pt_deactivate)
+ parent->pt_deactivate(parent);
}
if (psmouse->disconnect)
psmouse->disconnect(psmouse);
- if (parent && parent->pt_deactivate)
- parent->pt_deactivate(parent);
-
psmouse_set_state(psmouse, PSMOUSE_IGNORE);
input_unregister_device(&psmouse->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
kfree(psmouse);
-
- if (parent)
- psmouse_activate(parent);
-
- up(&psmouse_sem);
-}
-
-static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_protocol *proto)
-{
- memset(&psmouse->dev, 0, sizeof(struct input_dev));
-
- init_input_dev(&psmouse->dev);
-
- psmouse->dev.private = psmouse;
- psmouse->dev.dev = &psmouse->ps2dev.serio->dev;
-
- psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
- psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
-
- psmouse->set_rate = psmouse_set_rate;
- psmouse->set_resolution = psmouse_set_resolution;
- psmouse->protocol_handler = psmouse_process_byte;
- psmouse->pktsize = 3;
-
- if (proto && (proto->detect || proto->init)) {
- if (proto->detect && proto->detect(psmouse, 1) < 0)
- return -1;
-
- if (proto->init && proto->init(psmouse) < 0)
- return -1;
-
- psmouse->type = proto->type;
- }
- else
- psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);
-
- sprintf(psmouse->devname, "%s %s %s",
- psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name);
-
- psmouse->dev.name = psmouse->devname;
- psmouse->dev.phys = psmouse->phys;
- psmouse->dev.id.bustype = BUS_I8042;
- psmouse->dev.id.vendor = 0x0002;
- psmouse->dev.id.product = psmouse->type;
- psmouse->dev.id.version = psmouse->model;
-
- return 0;
}
/*
@@ -870,8 +688,6 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
struct psmouse *psmouse, *parent = NULL;
int retval;
- down(&psmouse_sem);
-
/*
* If this is a pass-through port deactivate parent so the device
* connected to this port can be successfully identified
@@ -881,14 +697,20 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
psmouse_deactivate(parent);
}
- if (!(psmouse = kcalloc(1, sizeof(struct psmouse), GFP_KERNEL))) {
+ if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL))) {
retval = -ENOMEM;
goto out;
}
+ memset(psmouse, 0, sizeof(struct psmouse));
+
ps2_init(&psmouse->ps2dev, serio);
sprintf(psmouse->phys, "%s/input0", serio->phys);
-
+ psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+ psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ psmouse->dev.private = psmouse;
+ psmouse->dev.dev = &serio->dev;
psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
serio_set_drvdata(serio, psmouse);
@@ -912,10 +734,25 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
psmouse->resolution = psmouse_resolution;
psmouse->resetafter = psmouse_resetafter;
psmouse->smartscroll = psmouse_smartscroll;
+ psmouse->set_rate = psmouse_set_rate;
+ psmouse->set_resolution = psmouse_set_resolution;
+ psmouse->protocol_handler = psmouse_process_byte;
+ psmouse->pktsize = 3;
- psmouse_switch_protocol(psmouse, NULL);
+ psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);
+
+ sprintf(psmouse->devname, "%s %s %s",
+ psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name);
+
+ psmouse->dev.name = psmouse->devname;
+ psmouse->dev.phys = psmouse->phys;
+ psmouse->dev.id.bustype = BUS_I8042;
+ psmouse->dev.id.vendor = 0x0002;
+ psmouse->dev.id.product = psmouse->type;
+ psmouse->dev.id.version = psmouse->model;
input_register_device(&psmouse->dev);
+
printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
@@ -925,7 +762,6 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
if (parent && parent->pt_activate)
parent->pt_activate(parent);
- device_create_file(&serio->dev, &psmouse_attr_protocol);
device_create_file(&serio->dev, &psmouse_attr_rate);
device_create_file(&serio->dev, &psmouse_attr_resolution);
device_create_file(&serio->dev, &psmouse_attr_resetafter);
@@ -935,11 +771,10 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
retval = 0;
out:
- /* If this is a pass-through port the parent needs to be re-activated */
+ /* If this is a pass-through port the parent awaits to be activated */
if (parent)
psmouse_activate(parent);
- up(&psmouse_sem);
return retval;
}
@@ -956,8 +791,6 @@ static int psmouse_reconnect(struct serio *serio)
return -1;
}
- down(&psmouse_sem);
-
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = serio_get_drvdata(serio->parent);
psmouse_deactivate(parent);
@@ -990,7 +823,6 @@ static int psmouse_reconnect(struct serio *serio)
if (parent)
psmouse_activate(parent);
- up(&psmouse_sem);
return rc;
}
@@ -1061,109 +893,26 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
if (serio->drv != &psmouse_drv) {
retval = -ENODEV;
- goto out_unpin;
- }
-
- retval = down_interruptible(&psmouse_sem);
- if (retval)
- goto out_unpin;
-
- if (psmouse->state == PSMOUSE_IGNORE) {
- retval = -ENODEV;
- goto out_up;
+ goto out;
}
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = serio_get_drvdata(serio->parent);
psmouse_deactivate(parent);
}
-
psmouse_deactivate(psmouse);
retval = handler(psmouse, buf, count);
- if (retval != -ENODEV)
- psmouse_activate(psmouse);
-
+ psmouse_activate(psmouse);
if (parent)
psmouse_activate(parent);
- out_up:
- up(&psmouse_sem);
- out_unpin:
+out:
serio_unpin_driver(serio);
return retval;
}
-static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, char *buf)
-{
- return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name);
-}
-
-static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *buf, size_t count)
-{
- struct serio *serio = psmouse->ps2dev.serio;
- struct psmouse *parent = NULL;
- struct psmouse_protocol *proto;
- int retry = 0;
-
- if (!(proto = psmouse_protocol_by_name(buf, count)))
- return -EINVAL;
-
- if (psmouse->type == proto->type)
- return count;
-
- while (serio->child) {
- if (++retry > 3) {
- printk(KERN_WARNING "psmouse: failed to destroy child port, protocol change aborted.\n");
- return -EIO;
- }
-
- up(&psmouse_sem);
- serio_unpin_driver(serio);
- serio_unregister_child_port(serio);
- serio_pin_driver_uninterruptible(serio);
- down(&psmouse_sem);
-
- if (serio->drv != &psmouse_drv)
- return -ENODEV;
-
- if (psmouse->type == proto->type)
- return count; /* switched by other thread */
- }
-
- if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
- parent = serio_get_drvdata(serio->parent);
- if (parent->pt_deactivate)
- parent->pt_deactivate(parent);
- }
-
- if (psmouse->disconnect)
- psmouse->disconnect(psmouse);
-
- psmouse_set_state(psmouse, PSMOUSE_IGNORE);
- input_unregister_device(&psmouse->dev);
-
- psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
-
- if (psmouse_switch_protocol(psmouse, proto) < 0) {
- psmouse_reset(psmouse);
- /* default to PSMOUSE_PS2 */
- psmouse_switch_protocol(psmouse, &psmouse_protocols[0]);
- }
-
- psmouse_initialize(psmouse);
- psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
-
- input_register_device(&psmouse->dev);
- printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
-
- if (parent && parent->pt_activate)
- parent->pt_activate(parent);
-
- return count;
-}
-
static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf)
{
return sprintf(buf, "%d\n", psmouse->rate);
@@ -1220,26 +969,34 @@ static ssize_t psmouse_attr_set_resetafter(struct psmouse *psmouse, const char *
static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
{
- struct psmouse_protocol *proto;
+ int i;
if (!val)
return -EINVAL;
- proto = psmouse_protocol_by_name(val, strlen(val));
+ if (!strncmp(val, "any", 3)) {
+ *((unsigned int *)kp->arg) = -1U;
+ return 0;
+ }
- if (!proto || !proto->maxproto)
- return -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(psmouse_proto_abbrev); i++) {
+ if (!psmouse_proto_abbrev[i])
+ continue;
- *((unsigned int *)kp->arg) = proto->type;
+ if (!strncmp(val, psmouse_proto_abbrev[i], strlen(psmouse_proto_abbrev[i]))) {
+ *((unsigned int *)kp->arg) = i;
+ return 0;
+ }
+ }
- return 0; \
+ return -EINVAL; \
}
static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
{
- int type = *((unsigned int *)kp->arg);
-
- return sprintf(buffer, "%s\n", psmouse_protocol_by_type(type)->name);
+ return sprintf(buffer, "%s\n",
+ psmouse_max_proto < ARRAY_SIZE(psmouse_proto_abbrev) ?
+ psmouse_proto_abbrev[psmouse_max_proto] : "any");
}
static int __init psmouse_init(void)
diff --git a/trunk/drivers/input/mouse/psmouse.h b/trunk/drivers/input/mouse/psmouse.h
index 86691cf43433..79e17a0c4664 100644
--- a/trunk/drivers/input/mouse/psmouse.h
+++ b/trunk/drivers/input/mouse/psmouse.h
@@ -77,8 +77,6 @@ enum psmouse_type {
PSMOUSE_IMEX,
PSMOUSE_SYNAPTICS,
PSMOUSE_ALPS,
- PSMOUSE_LIFEBOOK,
- PSMOUSE_AUTO /* This one should always be last */
};
int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
@@ -101,7 +99,7 @@ static ssize_t psmouse_do_set_##_name(struct device *d, struct device_attribute
{ \
return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name); \
} \
-static struct device_attribute psmouse_attr_##_name = \
+static struct device_attribute psmouse_attr_##_name = \
__ATTR(_name, S_IWUSR | S_IRUGO, \
psmouse_do_show_##_name, psmouse_do_set_##_name);
diff --git a/trunk/drivers/input/mouse/rpcmouse.c b/trunk/drivers/input/mouse/rpcmouse.c
index 8fe1212b8fd7..7280f68afcee 100644
--- a/trunk/drivers/input/mouse/rpcmouse.c
+++ b/trunk/drivers/input/mouse/rpcmouse.c
@@ -59,7 +59,7 @@ static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs)
b = (short) (__raw_readl(0xe0310000) ^ 0x70);
dx = x - rpcmouse_lastx;
- dy = y - rpcmouse_lasty;
+ dy = y - rpcmouse_lasty;
rpcmouse_lastx = x;
rpcmouse_lasty = y;
diff --git a/trunk/drivers/input/mouse/vsxxxaa.c b/trunk/drivers/input/mouse/vsxxxaa.c
index f024be9b44d2..b2cb101c8110 100644
--- a/trunk/drivers/input/mouse/vsxxxaa.c
+++ b/trunk/drivers/input/mouse/vsxxxaa.c
@@ -1,7 +1,7 @@
/*
* Driver for DEC VSXXX-AA mouse (hockey-puck mouse, ball or two rollers)
- * DEC VSXXX-GA mouse (rectangular mouse, with ball)
- * DEC VSXXX-AB tablet (digitizer with hair cross or stylus)
+ * DEC VSXXX-GA mouse (rectangular mouse, with ball)
+ * DEC VSXXX-AB tablet (digitizer with hair cross or stylus)
*
* Copyright (C) 2003-2004 by Jan-Benedict Glaw
*
diff --git a/trunk/drivers/input/mousedev.c b/trunk/drivers/input/mousedev.c
index c6194a9dd174..062848ac7e6b 100644
--- a/trunk/drivers/input/mousedev.c
+++ b/trunk/drivers/input/mousedev.c
@@ -220,7 +220,6 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h
struct mousedev_list *list;
struct mousedev_motion *p;
unsigned long flags;
- int wake_readers = 0;
list_for_each_entry(list, &mousedev->list, node) {
spin_lock_irqsave(&list->packet_lock, flags);
@@ -256,14 +255,11 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h
spin_unlock_irqrestore(&list->packet_lock, flags);
- if (list->ready) {
+ if (list->ready)
kill_fasync(&list->fasync, SIGIO, POLL_IN);
- wake_readers = 1;
- }
}
- if (wake_readers)
- wake_up_interruptible(&mousedev->wait);
+ wake_up_interruptible(&mousedev->wait);
}
static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
diff --git a/trunk/drivers/input/serio/libps2.c b/trunk/drivers/input/serio/libps2.c
index d4c990f7c85e..c978657068c5 100644
--- a/trunk/drivers/input/serio/libps2.c
+++ b/trunk/drivers/input/serio/libps2.c
@@ -29,7 +29,6 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL(ps2_init);
EXPORT_SYMBOL(ps2_sendbyte);
-EXPORT_SYMBOL(ps2_drain);
EXPORT_SYMBOL(ps2_command);
EXPORT_SYMBOL(ps2_schedule_command);
EXPORT_SYMBOL(ps2_handle_ack);
@@ -46,11 +45,11 @@ struct ps2work {
/*
- * ps2_sendbyte() sends a byte to the device and waits for acknowledge.
- * It doesn't handle retransmission, though it could - because if there
- * is a need for retransmissions device has to be replaced anyway.
+ * ps2_sendbyte() sends a byte to the mouse, and waits for acknowledge.
+ * It doesn't handle retransmission, though it could - because when there would
+ * be need for retransmissions, the mouse has to be replaced anyway.
*
- * ps2_sendbyte() can only be called from a process context.
+ * ps2_sendbyte() can only be called from a process context
*/
int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout)
@@ -72,91 +71,6 @@ int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout)
return -ps2dev->nak;
}
-/*
- * ps2_drain() waits for device to transmit requested number of bytes
- * and discards them.
- */
-
-void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout)
-{
- if (maxbytes > sizeof(ps2dev->cmdbuf)) {
- WARN_ON(1);
- maxbytes = sizeof(ps2dev->cmdbuf);
- }
-
- down(&ps2dev->cmd_sem);
-
- serio_pause_rx(ps2dev->serio);
- ps2dev->flags = PS2_FLAG_CMD;
- ps2dev->cmdcnt = maxbytes;
- serio_continue_rx(ps2dev->serio);
-
- wait_event_timeout(ps2dev->wait,
- !(ps2dev->flags & PS2_FLAG_CMD),
- msecs_to_jiffies(timeout));
- up(&ps2dev->cmd_sem);
-}
-
-/*
- * ps2_is_keyboard_id() checks received ID byte against the list of
- * known keyboard IDs.
- */
-
-static inline int ps2_is_keyboard_id(char id_byte)
-{
- static char keyboard_ids[] = {
- 0xab, /* Regular keyboards */
- 0xac, /* NCD Sun keyboard */
- 0x2b, /* Trust keyboard, translated */
- 0x5d, /* Trust keyboard */
- 0x60, /* NMB SGI keyboard, translated */
- 0x47, /* NMB SGI keyboard */
- };
-
- return memchr(keyboard_ids, id_byte, sizeof(keyboard_ids)) != NULL;
-}
-
-/*
- * ps2_adjust_timeout() is called after receiving 1st byte of command
- * response and tries to reduce remaining timeout to speed up command
- * completion.
- */
-
-static int ps2_adjust_timeout(struct ps2dev *ps2dev, int command, int timeout)
-{
- switch (command) {
- case PS2_CMD_RESET_BAT:
- /*
- * Device has sent the first response byte after
- * reset command, reset is thus done, so we can
- * shorten the timeout.
- * The next byte will come soon (keyboard) or not
- * at all (mouse).
- */
- if (timeout > msecs_to_jiffies(100))
- timeout = msecs_to_jiffies(100);
- break;
-
- case PS2_CMD_GETID:
- /*
- * If device behind the port is not a keyboard there
- * won't be 2nd byte of ID response.
- */
- if (!ps2_is_keyboard_id(ps2dev->cmdbuf[1])) {
- serio_pause_rx(ps2dev->serio);
- ps2dev->flags = ps2dev->cmdcnt = 0;
- serio_continue_rx(ps2dev->serio);
- timeout = 0;
- }
- break;
-
- default:
- break;
- }
-
- return timeout;
-}
-
/*
* ps2_command() sends a command and its parameters to the mouse,
* then waits for the response and puts it in the param array.
@@ -172,11 +86,6 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
int rc = -1;
int i;
- if (receive > sizeof(ps2dev->cmdbuf)) {
- WARN_ON(1);
- return -1;
- }
-
down(&ps2dev->cmd_sem);
serio_pause_rx(ps2dev->serio);
@@ -192,9 +101,10 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
* ACKing the reset command, and so it can take a long
* time before the ACK arrrives.
*/
- if (ps2_sendbyte(ps2dev, command & 0xff,
- command == PS2_CMD_RESET_BAT ? 1000 : 200))
- goto out;
+ if (command & 0xff)
+ if (ps2_sendbyte(ps2dev, command & 0xff,
+ command == PS2_CMD_RESET_BAT ? 1000 : 200))
+ goto out;
for (i = 0; i < send; i++)
if (ps2_sendbyte(ps2dev, param[i], 200))
@@ -210,7 +120,33 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
if (ps2dev->cmdcnt && timeout > 0) {
- timeout = ps2_adjust_timeout(ps2dev, command, timeout);
+ if (command == PS2_CMD_RESET_BAT && timeout > msecs_to_jiffies(100)) {
+ /*
+ * Device has sent the first response byte
+ * after a reset command, reset is thus done,
+ * shorten the timeout. The next byte will come
+ * soon (keyboard) or not at all (mouse).
+ */
+ timeout = msecs_to_jiffies(100);
+ }
+
+ if (command == PS2_CMD_GETID &&
+ ps2dev->cmdbuf[receive - 1] != 0xab && /* Regular keyboards */
+ ps2dev->cmdbuf[receive - 1] != 0xac && /* NCD Sun keyboard */
+ ps2dev->cmdbuf[receive - 1] != 0x2b && /* Trust keyboard, translated */
+ ps2dev->cmdbuf[receive - 1] != 0x5d && /* Trust keyboard */
+ ps2dev->cmdbuf[receive - 1] != 0x60 && /* NMB SGI keyboard, translated */
+ ps2dev->cmdbuf[receive - 1] != 0x47) { /* NMB SGI keyboard */
+ /*
+ * Device behind the port is not a keyboard
+ * so we don't need to wait for the 2nd byte
+ * of ID response.
+ */
+ serio_pause_rx(ps2dev->serio);
+ ps2dev->flags = ps2dev->cmdcnt = 0;
+ serio_continue_rx(ps2dev->serio);
+ }
+
wait_event_timeout(ps2dev->wait,
!(ps2dev->flags & PS2_FLAG_CMD), timeout);
}
@@ -224,7 +160,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
rc = 0;
- out:
+out:
serio_pause_rx(ps2dev->serio);
ps2dev->flags = 0;
serio_continue_rx(ps2dev->serio);
diff --git a/trunk/drivers/input/serio/serio.c b/trunk/drivers/input/serio/serio.c
index f367695e69b5..341824c48529 100644
--- a/trunk/drivers/input/serio/serio.c
+++ b/trunk/drivers/input/serio/serio.c
@@ -31,9 +31,10 @@
#include
#include
#include
+#include
#include
+#include
#include
-#include
MODULE_AUTHOR("Vojtech Pavlik ");
MODULE_DESCRIPTION("Serio abstraction core");
@@ -42,7 +43,6 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL(serio_interrupt);
EXPORT_SYMBOL(__serio_register_port);
EXPORT_SYMBOL(serio_unregister_port);
-EXPORT_SYMBOL(serio_unregister_child_port);
EXPORT_SYMBOL(__serio_unregister_port_delayed);
EXPORT_SYMBOL(__serio_register_driver);
EXPORT_SYMBOL(serio_unregister_driver);
@@ -68,37 +68,6 @@ static void serio_destroy_port(struct serio *serio);
static void serio_reconnect_port(struct serio *serio);
static void serio_disconnect_port(struct serio *serio);
-static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
-{
- int retval;
-
- down(&serio->drv_sem);
- retval = drv->connect(serio, drv);
- up(&serio->drv_sem);
-
- return retval;
-}
-
-static int serio_reconnect_driver(struct serio *serio)
-{
- int retval = -1;
-
- down(&serio->drv_sem);
- if (serio->drv && serio->drv->reconnect)
- retval = serio->drv->reconnect(serio);
- up(&serio->drv_sem);
-
- return retval;
-}
-
-static void serio_disconnect_driver(struct serio *serio)
-{
- down(&serio->drv_sem);
- if (serio->drv)
- serio->drv->disconnect(serio);
- up(&serio->drv_sem);
-}
-
static int serio_match_port(const struct serio_device_id *ids, struct serio *serio)
{
while (ids->type || ids->proto) {
@@ -122,7 +91,7 @@ static void serio_bind_driver(struct serio *serio, struct serio_driver *drv)
if (serio_match_port(drv->id_table, serio)) {
serio->dev.driver = &drv->driver;
- if (serio_connect_driver(serio, drv)) {
+ if (drv->connect(serio, drv)) {
serio->dev.driver = NULL;
goto out;
}
@@ -169,7 +138,8 @@ struct serio_event {
static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */
static LIST_HEAD(serio_event_list);
static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
-static struct task_struct *serio_task;
+static DECLARE_COMPLETION(serio_exited);
+static int serio_pid;
static void serio_queue_event(void *object, struct module *owner,
enum serio_event_type event_type)
@@ -180,12 +150,12 @@ static void serio_queue_event(void *object, struct module *owner,
spin_lock_irqsave(&serio_event_lock, flags);
/*
- * Scan event list for the other events for the same serio port,
+ * Scan event list for the other events for the same serio port,
* starting with the most recent one. If event is the same we
* do not need add new one. If event is of different type we
* need to add this event and should not look further because
* we need to preseve sequence of distinct events.
- */
+ */
list_for_each_entry_reverse(event, &serio_event_list, node) {
if (event->object == object) {
if (event->type == event_type)
@@ -367,15 +337,20 @@ static struct serio *serio_get_pending_child(struct serio *parent)
static int serio_thread(void *nothing)
{
+ lock_kernel();
+ daemonize("kseriod");
+ allow_signal(SIGTERM);
+
do {
serio_handle_events();
- wait_event_interruptible(serio_wait,
- kthread_should_stop() || !list_empty(&serio_event_list));
+ wait_event_interruptible(serio_wait, !list_empty(&serio_event_list));
try_to_freeze();
- } while (!kthread_should_stop());
+ } while (!signal_pending(current));
printk(KERN_DEBUG "serio: kseriod exiting\n");
- return 0;
+
+ unlock_kernel();
+ complete_and_exit(&serio_exited, 0);
}
@@ -582,7 +557,7 @@ static void serio_destroy_port(struct serio *serio)
static void serio_reconnect_port(struct serio *serio)
{
do {
- if (serio_reconnect_driver(serio)) {
+ if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) {
serio_disconnect_port(serio);
serio_find_driver(serio);
/* Ok, old children are now gone, we are done */
@@ -654,19 +629,6 @@ void serio_unregister_port(struct serio *serio)
up(&serio_sem);
}
-/*
- * Safely unregisters child port if one is present.
- */
-void serio_unregister_child_port(struct serio *serio)
-{
- down(&serio_sem);
- if (serio->child) {
- serio_disconnect_port(serio->child);
- serio_destroy_port(serio->child);
- }
- up(&serio_sem);
-}
-
/*
* Submits register request to kseriod for subsequent execution.
* Can be used when it is not obvious whether the serio_sem is
@@ -724,14 +686,15 @@ static int serio_driver_probe(struct device *dev)
struct serio *serio = to_serio_port(dev);
struct serio_driver *drv = to_serio_driver(dev->driver);
- return serio_connect_driver(serio, drv);
+ return drv->connect(serio, drv);
}
static int serio_driver_remove(struct device *dev)
{
struct serio *serio = to_serio_port(dev);
+ struct serio_driver *drv = to_serio_driver(dev->driver);
- serio_disconnect_driver(serio);
+ drv->disconnect(serio);
return 0;
}
@@ -767,9 +730,11 @@ void serio_unregister_driver(struct serio_driver *drv)
static void serio_set_drv(struct serio *serio, struct serio_driver *drv)
{
+ down(&serio->drv_sem);
serio_pause_rx(serio);
serio->drv = drv;
serio_continue_rx(serio);
+ up(&serio->drv_sem);
}
static int serio_bus_match(struct device *dev, struct device_driver *drv)
@@ -829,7 +794,7 @@ static int serio_resume(struct device *dev)
{
struct serio *serio = to_serio_port(dev);
- if (serio_reconnect_driver(serio)) {
+ if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) {
/*
* Driver re-probing can take a while, so better let kseriod
* deal with it.
@@ -883,10 +848,9 @@ irqreturn_t serio_interrupt(struct serio *serio,
static int __init serio_init(void)
{
- serio_task = kthread_run(serio_thread, NULL, "kseriod");
- if (IS_ERR(serio_task)) {
+ if (!(serio_pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL))) {
printk(KERN_ERR "serio: Failed to start kseriod\n");
- return PTR_ERR(serio_task);
+ return -1;
}
serio_bus.dev_attrs = serio_device_attrs;
@@ -902,7 +866,8 @@ static int __init serio_init(void)
static void __exit serio_exit(void)
{
bus_unregister(&serio_bus);
- kthread_stop(serio_task);
+ kill_proc(serio_pid, SIGTERM, 1);
+ wait_for_completion(&serio_exited);
}
module_init(serio_init);
diff --git a/trunk/drivers/input/touchscreen/elo.c b/trunk/drivers/input/touchscreen/elo.c
index 3cdc9cab688d..546ce599334e 100644
--- a/trunk/drivers/input/touchscreen/elo.c
+++ b/trunk/drivers/input/touchscreen/elo.c
@@ -226,7 +226,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0);
input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 255, 0, 0);
break;
-
+
case 1: /* 6-byte protocol */
input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 15, 0, 0);
diff --git a/trunk/drivers/input/touchscreen/h3600_ts_input.c b/trunk/drivers/input/touchscreen/h3600_ts_input.c
index bcfa1e36f957..acb9137a0226 100644
--- a/trunk/drivers/input/touchscreen/h3600_ts_input.c
+++ b/trunk/drivers/input/touchscreen/h3600_ts_input.c
@@ -89,9 +89,9 @@ MODULE_LICENSE("GPL");
#define H3600_SCANCODE_Q 4 /* 4 -> Q button */
#define H3600_SCANCODE_START 5 /* 5 -> start menu */
#define H3600_SCANCODE_UP 6 /* 6 -> up */
-#define H3600_SCANCODE_RIGHT 7 /* 7 -> right */
-#define H3600_SCANCODE_LEFT 8 /* 8 -> left */
-#define H3600_SCANCODE_DOWN 9 /* 9 -> down */
+#define H3600_SCANCODE_RIGHT 7 /* 7 -> right */
+#define H3600_SCANCODE_LEFT 8 /* 8 -> left */
+#define H3600_SCANCODE_DOWN 9 /* 9 -> down */
static char *h3600_name = "H3600 TouchScreen";
@@ -113,7 +113,7 @@ struct h3600_dev {
static irqreturn_t action_button_handler(int irq, void *dev_id, struct pt_regs *regs)
{
- int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1;
+ int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1;
struct input_dev *dev = (struct input_dev *) dev_id;
input_regs(dev, regs);
@@ -125,7 +125,7 @@ static irqreturn_t action_button_handler(int irq, void *dev_id, struct pt_regs *
static irqreturn_t npower_button_handler(int irq, void *dev_id, struct pt_regs *regs)
{
- int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1;
+ int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1;
struct input_dev *dev = (struct input_dev *) dev_id;
/*
@@ -145,8 +145,8 @@ static irqreturn_t npower_button_handler(int irq, void *dev_id, struct pt_regs *
static int flite_brightness = 25;
enum flite_pwr {
- FLITE_PWR_OFF = 0,
- FLITE_PWR_ON = 1
+ FLITE_PWR_OFF = 0,
+ FLITE_PWR_ON = 1
};
/*
@@ -157,9 +157,9 @@ unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr)
struct h3600_dev *ts = dev->private;
/* Must be in this order */
- ts->serio->write(ts->serio, 1);
+ ts->serio->write(ts->serio, 1);
ts->serio->write(ts->serio, pwr);
- ts->serio->write(ts->serio, brightness);
+ ts->serio->write(ts->serio, brightness);
return 0;
}
@@ -169,26 +169,26 @@ static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req,
{
struct input_dev *dev = (struct input_dev *) data;
- switch (req) {
- case PM_SUSPEND: /* enter D1-D3 */
- suspended = 1;
- h3600_flite_power(dev, FLITE_PWR_OFF);
- break;
- case PM_BLANK:
- if (!suspended)
- h3600_flite_power(dev, FLITE_PWR_OFF);
- break;
- case PM_RESUME: /* enter D0 */
- /* same as unblank */
- case PM_UNBLANK:
- if (suspended) {
- //initSerial();
- suspended = 0;
- }
- h3600_flite_power(dev, FLITE_PWR_ON);
- break;
- }
- return 0;
+ switch (req) {
+ case PM_SUSPEND: /* enter D1-D3 */
+ suspended = 1;
+ h3600_flite_power(dev, FLITE_PWR_OFF);
+ break;
+ case PM_BLANK:
+ if (!suspended)
+ h3600_flite_power(dev, FLITE_PWR_OFF);
+ break;
+ case PM_RESUME: /* enter D0 */
+ /* same as unblank */
+ case PM_UNBLANK:
+ if (suspended) {
+ //initSerial();
+ suspended = 0;
+ }
+ h3600_flite_power(dev, FLITE_PWR_ON);
+ break;
+ }
+ return 0;
}
#endif
@@ -199,25 +199,25 @@ static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req,
*/
static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs)
{
- struct input_dev *dev = &ts->dev;
+ struct input_dev *dev = &ts->dev;
static int touched = 0;
int key, down = 0;
input_regs(dev, regs);
- switch (ts->event) {
- /*
- Buttons - returned as a single byte
- 7 6 5 4 3 2 1 0
- S x x x N N N N
+ switch (ts->event) {
+ /*
+ Buttons - returned as a single byte
+ 7 6 5 4 3 2 1 0
+ S x x x N N N N
- S switch state ( 0=pressed 1=released)
- x Unused.
- NNNN switch number 0-15
+ S switch state ( 0=pressed 1=released)
+ x Unused.
+ NNNN switch number 0-15
- Note: This is true for non interrupt generated key events.
- */
- case KEYBD_ID:
+ Note: This is true for non interrupt generated key events.
+ */
+ case KEYBD_ID:
down = (ts->buf[0] & 0x80) ? 0 : 1;
switch (ts->buf[0] & 0x7f) {
@@ -229,40 +229,40 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs)
break;
case H3600_SCANCODE_CONTACTS:
key = KEY_PROG2;
- break;
+ break;
case H3600_SCANCODE_Q:
key = KEY_Q;
- break;
+ break;
case H3600_SCANCODE_START:
key = KEY_PROG3;
- break;
+ break;
case H3600_SCANCODE_UP:
key = KEY_UP;
- break;
+ break;
case H3600_SCANCODE_RIGHT:
key = KEY_RIGHT;
- break;
+ break;
case H3600_SCANCODE_LEFT:
key = KEY_LEFT;
- break;
+ break;
case H3600_SCANCODE_DOWN:
key = KEY_DOWN;
- break;
+ break;
default:
key = 0;
}
- if (key)
- input_report_key(dev, key, down);
- break;
- /*
- * Native touchscreen event data is formatted as shown below:-
- *
- * +-------+-------+-------+-------+
- * | Xmsb | Xlsb | Ymsb | Ylsb |
- * +-------+-------+-------+-------+
- * byte 0 1 2 3
- */
- case TOUCHS_ID:
+ if (key)
+ input_report_key(dev, key, down);
+ break;
+ /*
+ * Native touchscreen event data is formatted as shown below:-
+ *
+ * +-------+-------+-------+-------+
+ * | Xmsb | Xlsb | Ymsb | Ylsb |
+ * +-------+-------+-------+-------+
+ * byte 0 1 2 3
+ */
+ case TOUCHS_ID:
if (!touched) {
input_report_key(dev, BTN_TOUCH, 1);
touched = 1;
@@ -272,19 +272,19 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs)
unsigned short x, y;
x = ts->buf[0]; x <<= 8; x += ts->buf[1];
- y = ts->buf[2]; y <<= 8; y += ts->buf[3];
+ y = ts->buf[2]; y <<= 8; y += ts->buf[3];
- input_report_abs(dev, ABS_X, x);
- input_report_abs(dev, ABS_Y, y);
+ input_report_abs(dev, ABS_X, x);
+ input_report_abs(dev, ABS_Y, y);
} else {
- input_report_key(dev, BTN_TOUCH, 0);
+ input_report_key(dev, BTN_TOUCH, 0);
touched = 0;
}
- break;
+ break;
default:
/* Send a non input event elsewhere */
break;
- }
+ }
input_sync(dev);
}
@@ -293,7 +293,7 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs)
* h3600ts_event() handles events from the input module.
*/
static int h3600ts_event(struct input_dev *dev, unsigned int type,
- unsigned int code, int value)
+ unsigned int code, int value)
{
struct h3600_dev *ts = dev->private;
@@ -332,41 +332,41 @@ static int state;
static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data,
unsigned int flags, struct pt_regs *regs)
{
- struct h3600_dev *ts = serio_get_drvdata(serio);
+ struct h3600_dev *ts = serio_get_drvdata(serio);
/*
- * We have a new frame coming in.
- */
+ * We have a new frame coming in.
+ */
switch (state) {
case STATE_SOF:
- if (data == CHAR_SOF)
- state = STATE_ID;
+ if (data == CHAR_SOF)
+ state = STATE_ID;
break;
- case STATE_ID:
+ case STATE_ID:
ts->event = (data & 0xf0) >> 4;
ts->len = (data & 0xf);
ts->idx = 0;
if (ts->event >= MAX_ID) {
state = STATE_SOF;
- break;
+ break;
}
ts->chksum = data;
- state = (ts->len > 0) ? STATE_DATA : STATE_EOF;
+ state = (ts->len > 0) ? STATE_DATA : STATE_EOF;
break;
case STATE_DATA:
ts->chksum += data;
ts->buf[ts->idx]= data;
- if (++ts->idx == ts->len)
- state = STATE_EOF;
+ if(++ts->idx == ts->len)
+ state = STATE_EOF;
break;
case STATE_EOF:
- state = STATE_SOF;
- if (data == CHAR_EOF || data == ts->chksum)
+ state = STATE_SOF;
+ if (data == CHAR_EOF || data == ts->chksum)
h3600ts_process_packet(ts, regs);
- break;
- default:
- printk("Error3\n");
- break;
+ break;
+ default:
+ printk("Error3\n");
+ break;
}
return IRQ_HANDLED;
@@ -390,10 +390,10 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
init_input_dev(&ts->dev);
/* Device specific stuff */
- set_GPIO_IRQ_edge(GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES);
- set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE);
+ set_GPIO_IRQ_edge(GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES);
+ set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE);
- if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler,
+ if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler,
SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM,
"h3600_action", &ts->dev)) {
printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n");
@@ -401,7 +401,7 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
return -EBUSY;
}
- if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
+ if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM,
"h3600_suspend", &ts->dev)) {
free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev);
@@ -433,7 +433,7 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
sprintf(ts->phys, "%s/input0", serio->phys);
- ts->dev.event = h3600ts_event;
+ ts->dev.event = h3600ts_event;
ts->dev.private = ts;
ts->dev.name = h3600_name;
ts->dev.phys = ts->phys;
@@ -446,8 +446,8 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
err = serio_open(serio, drv);
if (err) {
- free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts);
- free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts);
+ free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts);
+ free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts);
serio_set_drvdata(serio, NULL);
kfree(ts);
return err;
diff --git a/trunk/drivers/input/touchscreen/mk712.c b/trunk/drivers/input/touchscreen/mk712.c
index afaaebe5225b..2d14a57a05e5 100644
--- a/trunk/drivers/input/touchscreen/mk712.c
+++ b/trunk/drivers/input/touchscreen/mk712.c
@@ -17,7 +17,7 @@
* found in Gateway AOL Connected Touchpad computers.
*
* Documentation for ICS MK712 can be found at:
- * http://www.icst.com/pdf/mk712.pdf
+ * http://www.icst.com/pdf/mk712.pdf
*/
/*
@@ -77,6 +77,7 @@ MODULE_PARM_DESC(irq, "IRQ of MK712 touchscreen controller");
#define MK712_READ_ONE_POINT 0x20
#define MK712_POWERUP 0x40
+static int mk712_used = 0;
static struct input_dev mk712_dev;
static DEFINE_SPINLOCK(mk712_lock);
@@ -129,14 +130,17 @@ static int mk712_open(struct input_dev *dev)
spin_lock_irqsave(&mk712_lock, flags);
- outb(0, mk712_io + MK712_CONTROL); /* Reset */
+ if (!mk712_used++) {
- outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE |
- MK712_INT_ON_CHANGE_IN_TOUCH_STATUS |
- MK712_ENABLE_PERIODIC_CONVERSIONS |
- MK712_POWERUP, mk712_io + MK712_CONTROL);
+ outb(0, mk712_io + MK712_CONTROL); /* Reset */
- outb(10, mk712_io + MK712_RATE); /* 187 points per second */
+ outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE |
+ MK712_INT_ON_CHANGE_IN_TOUCH_STATUS |
+ MK712_ENABLE_PERIODIC_CONVERSIONS |
+ MK712_POWERUP, mk712_io + MK712_CONTROL);
+
+ outb(10, mk712_io + MK712_RATE); /* 187 points per second */
+ }
spin_unlock_irqrestore(&mk712_lock, flags);
@@ -149,7 +153,8 @@ static void mk712_close(struct input_dev *dev)
spin_lock_irqsave(&mk712_lock, flags);
- outb(0, mk712_io + MK712_CONTROL);
+ if (!--mk712_used)
+ outb(0, mk712_io + MK712_CONTROL);
spin_unlock_irqrestore(&mk712_lock, flags);
}
diff --git a/trunk/drivers/isdn/hardware/avm/avm_cs.c b/trunk/drivers/isdn/hardware/avm/avm_cs.c
index ee750e9456dd..dc00c85e3e35 100644
--- a/trunk/drivers/isdn/hardware/avm/avm_cs.c
+++ b/trunk/drivers/isdn/hardware/avm/avm_cs.c
@@ -486,14 +486,6 @@ static int avmcs_event(event_t event, int priority,
return 0;
} /* avmcs_event */
-static struct pcmcia_device_id avmcs_ids[] = {
- PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335),
- PCMCIA_DEVICE_PROD_ID12("AVM", "Mobile ISDN-Controller M1", 0x95d42008, 0x81e10430),
- PCMCIA_DEVICE_PROD_ID12("AVM", "Mobile ISDN-Controller M2", 0x95d42008, 0x18e8558a),
- PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, avmcs_ids);
-
static struct pcmcia_driver avmcs_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -501,7 +493,6 @@ static struct pcmcia_driver avmcs_driver = {
},
.attach = avmcs_attach,
.detach = avmcs_detach,
- .id_table = avmcs_ids,
};
static int __init avmcs_init(void)
diff --git a/trunk/drivers/isdn/hisax/avma1_cs.c b/trunk/drivers/isdn/hisax/avma1_cs.c
index 67c60e04a37b..663a0bf703b7 100644
--- a/trunk/drivers/isdn/hisax/avma1_cs.c
+++ b/trunk/drivers/isdn/hisax/avma1_cs.c
@@ -501,13 +501,6 @@ static int avma1cs_event(event_t event, int priority,
return 0;
} /* avma1cs_event */
-static struct pcmcia_device_id avma1cs_ids[] = {
- PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb),
- PCMCIA_DEVICE_PROD_ID12("ISDN", "CARD", 0x8d9761c8, 0x01c5aa7b),
- PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, avma1cs_ids);
-
static struct pcmcia_driver avma1cs_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -515,7 +508,6 @@ static struct pcmcia_driver avma1cs_driver = {
},
.attach = avma1cs_attach,
.detach = avma1cs_detach,
- .id_table = avma1cs_ids,
};
/*====================================================================*/
diff --git a/trunk/drivers/isdn/hisax/elsa_cs.c b/trunk/drivers/isdn/hisax/elsa_cs.c
index 9146be547044..bfc013225f46 100644
--- a/trunk/drivers/isdn/hisax/elsa_cs.c
+++ b/trunk/drivers/isdn/hisax/elsa_cs.c
@@ -508,13 +508,6 @@ static int elsa_cs_event(event_t event, int priority,
return 0;
} /* elsa_cs_event */
-static struct pcmcia_device_id elsa_ids[] = {
- PCMCIA_DEVICE_PROD_ID12("ELSA AG (Aachen, Germany)", "MicroLink ISDN/MC ", 0x983de2c4, 0x333ba257),
- PCMCIA_DEVICE_PROD_ID12("ELSA GmbH, Aachen", "MicroLink ISDN/MC ", 0x639e5718, 0x333ba257),
- PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, elsa_ids);
-
static struct pcmcia_driver elsa_cs_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -522,7 +515,6 @@ static struct pcmcia_driver elsa_cs_driver = {
},
.attach = elsa_cs_attach,
.detach = elsa_cs_detach,
- .id_table = elsa_ids,
};
static int __init init_elsa_cs(void)
diff --git a/trunk/drivers/isdn/hisax/sedlbauer_cs.c b/trunk/drivers/isdn/hisax/sedlbauer_cs.c
index 058147a69576..449651241477 100644
--- a/trunk/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/trunk/drivers/isdn/hisax/sedlbauer_cs.c
@@ -616,18 +616,6 @@ static int sedlbauer_event(event_t event, int priority,
return 0;
} /* sedlbauer_event */
-static struct pcmcia_device_id sedlbauer_ids[] = {
- PCMCIA_DEVICE_PROD_ID1234("SEDLBAUER", "speed star II", "V 3.1", "(c) 93 - 98 cb ", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a, 0x50d4149c),
- PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D67", 0x81fb79f5, 0xe4e9bc12, 0x397b7e90),
- PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D98", 0x81fb79f5, 0xe4e9bc12, 0x2e5c7fce),
- PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (C) 93-94 VK", 0x81fb79f5, 0xe4e9bc12, 0x8db143fe),
- PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (c) 93-95 VK", 0x81fb79f5, 0xe4e9bc12, 0xb391ab4c),
- PCMCIA_DEVICE_PROD_ID12("HST High Soft Tech GmbH", "Saphir II B", 0xd79e0b84, 0x21d083ae),
-/* PCMCIA_DEVICE_PROD_ID1234("SEDLBAUER", 0x81fb79f5), */ /* too generic*/
- PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, sedlbauer_ids);
-
static struct pcmcia_driver sedlbauer_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -635,7 +623,6 @@ static struct pcmcia_driver sedlbauer_driver = {
},
.attach = sedlbauer_attach,
.detach = sedlbauer_detach,
- .id_table = sedlbauer_ids,
};
static int __init init_sedlbauer_cs(void)
diff --git a/trunk/drivers/isdn/hisax/teles_cs.c b/trunk/drivers/isdn/hisax/teles_cs.c
index 107376ff5b9b..63e8e20c17a8 100644
--- a/trunk/drivers/isdn/hisax/teles_cs.c
+++ b/trunk/drivers/isdn/hisax/teles_cs.c
@@ -489,12 +489,6 @@ static int teles_cs_event(event_t event, int priority,
return 0;
} /* teles_cs_event */
-static struct pcmcia_device_id teles_ids[] = {
- PCMCIA_DEVICE_PROD_ID12("TELES", "S0/PC", 0x67b50eae, 0xe9e70119),
- PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, teles_ids);
-
static struct pcmcia_driver teles_cs_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -502,7 +496,6 @@ static struct pcmcia_driver teles_cs_driver = {
},
.attach = teles_attach,
.detach = teles_detach,
- .id_table = teles_ids,
};
static int __init init_teles_cs(void)
diff --git a/trunk/drivers/macintosh/Kconfig b/trunk/drivers/macintosh/Kconfig
index 91691a6c004e..8a7117a08cf0 100644
--- a/trunk/drivers/macintosh/Kconfig
+++ b/trunk/drivers/macintosh/Kconfig
@@ -86,18 +86,33 @@ config PMAC_SMU
on the "SMU" system control chip which replaces the old PMU.
If you don't know, say Y.
+config PMAC_PBOOK
+ bool "Power management support for PowerBooks"
+ depends on ADB_PMU
+ ---help---
+ This provides support for putting a PowerBook to sleep; it also
+ enables media bay support. Power management works on the
+ PB2400/3400/3500, Wallstreet, Lombard, and Bronze PowerBook G3 and
+ the Titanium Powerbook G4, as well as the iBooks. You should get
+ the power management daemon, pmud, to make it work and you must have
+ the /dev/pmu device (see the pmud README).
+
+ Get pmud from .
+
+ If you have a PowerBook, you should say Y here.
+
+ You may also want to compile the dma sound driver as a module and
+ have it autoloaded. The act of removing the module shuts down the
+ sound hardware for more power savings.
+
+config PM
+ bool
+ depends on PPC_PMAC && ADB_PMU && PMAC_PBOOK
+ default y
+
config PMAC_APM_EMU
tristate "APM emulation"
- depends on PPC_PMAC && PPC32 && PM
-
-config PMAC_MEDIABAY
- bool "Support PowerBook hotswap media bay"
- depends on PPC_PMAC && PPC32
- help
- This option adds support for older PowerBook's hotswap media bay
- that can contains batteries, floppy drives, or IDE devices. PCI
- devices are not fully supported in the bay as I never had one to
- try with
+ depends on PMAC_PBOOK
# made a separate option since backlight may end up beeing used
# on non-powerbook machines (but only on PMU based ones AFAIK)
@@ -111,6 +126,13 @@ config PMAC_BACKLIGHT
events; also, the PowerBook button device will be enabled so you can
change the screen brightness.
+config MAC_SERIAL
+ tristate "Support for PowerMac serial ports (OBSOLETE DRIVER)"
+ depends on PPC_PMAC && BROKEN
+ help
+ This driver is obsolete. Use CONFIG_SERIAL_PMACZILOG in
+ "Character devices --> Serial drivers --> PowerMac z85c30" option.
+
config ADB_MACIO
bool "Include MacIO (CHRP) ADB driver"
depends on ADB && PPC_CHRP && !PPC_PMAC64
diff --git a/trunk/drivers/macintosh/Makefile b/trunk/drivers/macintosh/Makefile
index f5ae171dbfef..c3a4705a8295 100644
--- a/trunk/drivers/macintosh/Makefile
+++ b/trunk/drivers/macintosh/Makefile
@@ -6,7 +6,8 @@
obj-$(CONFIG_PPC_PMAC) += macio_asic.o
-obj-$(CONFIG_PMAC_MEDIABAY) += mediabay.o
+obj-$(CONFIG_PMAC_PBOOK) += mediabay.o
+obj-$(CONFIG_MAC_SERIAL) += macserial.o
obj-$(CONFIG_MAC_EMUMOUSEBTN) += mac_hid.o
obj-$(CONFIG_INPUT_ADBHID) += adbhid.o
obj-$(CONFIG_ANSLCD) += ans-lcd.o
diff --git a/trunk/drivers/macintosh/adb.c b/trunk/drivers/macintosh/adb.c
index c0dc1e3fa58b..493e2afa191c 100644
--- a/trunk/drivers/macintosh/adb.c
+++ b/trunk/drivers/macintosh/adb.c
@@ -90,7 +90,7 @@ static int sleepy_trackpad;
static int autopoll_devs;
int __adb_probe_sync;
-#ifdef CONFIG_PM
+#ifdef CONFIG_PMAC_PBOOK
static int adb_notify_sleep(struct pmu_sleep_notifier *self, int when);
static struct pmu_sleep_notifier adb_sleep_notifier = {
adb_notify_sleep,
@@ -320,9 +320,9 @@ int __init adb_init(void)
printk(KERN_WARNING "Warning: no ADB interface detected\n");
adb_controller = NULL;
} else {
-#ifdef CONFIG_PM
+#ifdef CONFIG_PMAC_PBOOK
pmu_register_sleep_notifier(&adb_sleep_notifier);
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PMAC_PBOOK */
#ifdef CONFIG_PPC
if (machine_is_compatible("AAPL,PowerBook1998") ||
machine_is_compatible("PowerBook1,1"))
@@ -337,7 +337,7 @@ int __init adb_init(void)
__initcall(adb_init);
-#ifdef CONFIG_PM
+#ifdef CONFIG_PMAC_PBOOK
/*
* notify clients before sleep and reset bus afterwards
*/
@@ -378,7 +378,7 @@ adb_notify_sleep(struct pmu_sleep_notifier *self, int when)
}
return PBOOK_SLEEP_OK;
}
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PMAC_PBOOK */
static int
do_adb_reset_bus(void)
diff --git a/trunk/drivers/macintosh/macserial.c b/trunk/drivers/macintosh/macserial.c
new file mode 100644
index 000000000000..0be3ac6cc169
--- /dev/null
+++ b/trunk/drivers/macintosh/macserial.c
@@ -0,0 +1,3036 @@
+/*
+ * macserial.c: Serial port driver for Power Macintoshes.
+ *
+ * Derived from drivers/sbus/char/sunserial.c by Paul Mackerras.
+ *
+ * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * Receive DMA code by Takashi Oe .
+ *
+ * $Id: macserial.c,v 1.24.2.4 1999/10/19 04:36:42 paulus Exp $
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#ifdef CONFIG_SERIAL_CONSOLE
+#include
+#endif
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#ifdef CONFIG_KGDB
+#include
+#endif
+#include
+
+#include "macserial.h"
+
+#ifdef CONFIG_PMAC_PBOOK
+static int serial_notify_sleep(struct pmu_sleep_notifier *self, int when);
+static struct pmu_sleep_notifier serial_sleep_notifier = {
+ serial_notify_sleep,
+ SLEEP_LEVEL_MISC,
+};
+#endif
+
+#define SUPPORT_SERIAL_DMA
+#define MACSERIAL_VERSION "2.0"
+
+/*
+ * It would be nice to dynamically allocate everything that
+ * depends on NUM_SERIAL, so we could support any number of
+ * Z8530s, but for now...
+ */
+#define NUM_SERIAL 2 /* Max number of ZS chips supported */
+#define NUM_CHANNELS (NUM_SERIAL * 2) /* 2 channels per chip */
+
+/* On PowerMacs, the hardware takes care of the SCC recovery time,
+ but we need the eieio to make sure that the accesses occur
+ in the order we want. */
+#define RECOVERY_DELAY eieio()
+
+static struct tty_driver *serial_driver;
+
+struct mac_zschannel zs_channels[NUM_CHANNELS];
+
+struct mac_serial zs_soft[NUM_CHANNELS];
+int zs_channels_found;
+struct mac_serial *zs_chain; /* list of all channels */
+
+struct tty_struct zs_ttys[NUM_CHANNELS];
+
+static int is_powerbook;
+
+#ifdef CONFIG_SERIAL_CONSOLE
+static struct console sercons;
+#endif
+
+#ifdef CONFIG_KGDB
+struct mac_zschannel *zs_kgdbchan;
+static unsigned char scc_inittab[] = {
+ 9, 0x80, /* reset A side (CHRA) */
+ 13, 0, /* set baud rate divisor */
+ 12, 1,
+ 14, 1, /* baud rate gen enable, src=rtxc (BRENABL) */
+ 11, 0x50, /* clocks = br gen (RCBR | TCBR) */
+ 5, 0x6a, /* tx 8 bits, assert RTS (Tx8 | TxENAB | RTS) */
+ 4, 0x44, /* x16 clock, 1 stop (SB1 | X16CLK)*/
+ 3, 0xc1, /* rx enable, 8 bits (RxENABLE | Rx8)*/
+};
+#endif
+#define ZS_CLOCK 3686400 /* Z8530 RTxC input clock rate */
+
+/* serial subtype definitions */
+#define SERIAL_TYPE_NORMAL 1
+
+/* number of characters left in xmit buffer before we ask for more */
+#define WAKEUP_CHARS 256
+
+/*
+ * Debugging.
+ */
+#undef SERIAL_DEBUG_INTR
+#undef SERIAL_DEBUG_OPEN
+#undef SERIAL_DEBUG_FLOW
+#undef SERIAL_DEBUG_POWER
+#undef SERIAL_DEBUG_THROTTLE
+#undef SERIAL_DEBUG_STOP
+#undef SERIAL_DEBUG_BAUDS
+
+#define RS_STROBE_TIME 10
+#define RS_ISR_PASS_LIMIT 256
+
+#define _INLINE_ inline
+
+#ifdef SERIAL_DEBUG_OPEN
+#define OPNDBG(fmt, arg...) printk(KERN_DEBUG fmt , ## arg)
+#else
+#define OPNDBG(fmt, arg...) do { } while (0)
+#endif
+#ifdef SERIAL_DEBUG_POWER
+#define PWRDBG(fmt, arg...) printk(KERN_DEBUG fmt , ## arg)
+#else
+#define PWRDBG(fmt, arg...) do { } while (0)
+#endif
+#ifdef SERIAL_DEBUG_BAUDS
+#define BAUDBG(fmt, arg...) printk(fmt , ## arg)
+#else
+#define BAUDBG(fmt, arg...) do { } while (0)
+#endif
+
+static void probe_sccs(void);
+static void change_speed(struct mac_serial *info, struct termios *old);
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
+static int set_scc_power(struct mac_serial * info, int state);
+static int setup_scc(struct mac_serial * info);
+static void dbdma_reset(volatile struct dbdma_regs *dma);
+static void dbdma_flush(volatile struct dbdma_regs *dma);
+static irqreturn_t rs_txdma_irq(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t rs_rxdma_irq(int irq, void *dev_id, struct pt_regs *regs);
+static void dma_init(struct mac_serial * info);
+static void rxdma_start(struct mac_serial * info, int curr);
+static void rxdma_to_tty(struct mac_serial * info);
+
+/*
+ * tmp_buf is used as a temporary buffer by serial_write. We need to
+ * lock it in case the copy_from_user blocks while swapping in a page,
+ * and some other program tries to do a serial write at the same time.
+ * Since the lock will only come under contention when the system is
+ * swapping and available memory is low, it makes sense to share one
+ * buffer across all the serial ports, since it significantly saves
+ * memory if large numbers of serial ports are open.
+ */
+static unsigned char *tmp_buf;
+static DECLARE_MUTEX(tmp_buf_sem);
+
+
+static inline int __pmac
+serial_paranoia_check(struct mac_serial *info,
+ char *name, const char *routine)
+{
+#ifdef SERIAL_PARANOIA_CHECK
+ static const char badmagic[] = KERN_WARNING
+ "Warning: bad magic number for serial struct %s in %s\n";
+ static const char badinfo[] = KERN_WARNING
+ "Warning: null mac_serial for %s in %s\n";
+
+ if (!info) {
+ printk(badinfo, name, routine);
+ return 1;
+ }
+ if (info->magic != SERIAL_MAGIC) {
+ printk(badmagic, name, routine);
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+/*
+ * Reading and writing Z8530 registers.
+ */
+static inline unsigned char __pmac read_zsreg(struct mac_zschannel *channel,
+ unsigned char reg)
+{
+ unsigned char retval;
+ unsigned long flags;
+
+ /*
+ * We have to make this atomic.
+ */
+ spin_lock_irqsave(&channel->lock, flags);
+ if (reg != 0) {
+ *channel->control = reg;
+ RECOVERY_DELAY;
+ }
+ retval = *channel->control;
+ RECOVERY_DELAY;
+ spin_unlock_irqrestore(&channel->lock, flags);
+ return retval;
+}
+
+static inline void __pmac write_zsreg(struct mac_zschannel *channel,
+ unsigned char reg, unsigned char value)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&channel->lock, flags);
+ if (reg != 0) {
+ *channel->control = reg;
+ RECOVERY_DELAY;
+ }
+ *channel->control = value;
+ RECOVERY_DELAY;
+ spin_unlock_irqrestore(&channel->lock, flags);
+ return;
+}
+
+static inline unsigned char __pmac read_zsdata(struct mac_zschannel *channel)
+{
+ unsigned char retval;
+
+ retval = *channel->data;
+ RECOVERY_DELAY;
+ return retval;
+}
+
+static inline void write_zsdata(struct mac_zschannel *channel,
+ unsigned char value)
+{
+ *channel->data = value;
+ RECOVERY_DELAY;
+ return;
+}
+
+static inline void load_zsregs(struct mac_zschannel *channel,
+ unsigned char *regs)
+{
+ ZS_CLEARERR(channel);
+ ZS_CLEARFIFO(channel);
+ /* Load 'em up */
+ write_zsreg(channel, R4, regs[R4]);
+ write_zsreg(channel, R10, regs[R10]);
+ write_zsreg(channel, R3, regs[R3] & ~RxENABLE);
+ write_zsreg(channel, R5, regs[R5] & ~TxENAB);
+ write_zsreg(channel, R1, regs[R1]);
+ write_zsreg(channel, R9, regs[R9]);
+ write_zsreg(channel, R11, regs[R11]);
+ write_zsreg(channel, R12, regs[R12]);
+ write_zsreg(channel, R13, regs[R13]);
+ write_zsreg(channel, R14, regs[R14]);
+ write_zsreg(channel, R15, regs[R15]);
+ write_zsreg(channel, R3, regs[R3]);
+ write_zsreg(channel, R5, regs[R5]);
+ return;
+}
+
+/* Sets or clears DTR/RTS on the requested line */
+static inline void zs_rtsdtr(struct mac_serial *ss, int set)
+{
+ if (set)
+ ss->curregs[5] |= (RTS | DTR);
+ else
+ ss->curregs[5] &= ~(RTS | DTR);
+ write_zsreg(ss->zs_channel, 5, ss->curregs[5]);
+ return;
+}
+
+/* Utility routines for the Zilog */
+static inline int get_zsbaud(struct mac_serial *ss)
+{
+ struct mac_zschannel *channel = ss->zs_channel;
+ int brg;
+
+ if ((ss->curregs[R11] & TCBR) == 0) {
+ /* higher rates don't use the baud rate generator */
+ return (ss->curregs[R4] & X32CLK)? ZS_CLOCK/32: ZS_CLOCK/16;
+ }
+ /* The baud rate is split up between two 8-bit registers in
+ * what is termed 'BRG time constant' format in my docs for
+ * the chip, it is a function of the clk rate the chip is
+ * receiving which happens to be constant.
+ */
+ brg = (read_zsreg(channel, 13) << 8);
+ brg |= read_zsreg(channel, 12);
+ return BRG_TO_BPS(brg, (ZS_CLOCK/(ss->clk_divisor)));
+}
+
+/* On receive, this clears errors and the receiver interrupts */
+static inline void rs_recv_clear(struct mac_zschannel *zsc)
+{
+ write_zsreg(zsc, 0, ERR_RES);
+ write_zsreg(zsc, 0, RES_H_IUS); /* XXX this is unnecessary */
+}
+
+/*
+ * Reset a Descriptor-Based DMA channel.
+ */
+static void dbdma_reset(volatile struct dbdma_regs *dma)
+{
+ int i;
+
+ out_le32(&dma->control, (WAKE|FLUSH|PAUSE|RUN) << 16);
+
+ /*
+ * Yes this looks peculiar, but apparently it needs to be this
+ * way on some machines. (We need to make sure the DBDMA
+ * engine has actually got the write above and responded
+ * to it. - paulus)
+ */
+ for (i = 200; i > 0; --i)
+ if (ld_le32(&dma->status) & RUN)
+ udelay(1);
+}
+
+/*
+ * Tells a DBDMA channel to stop and write any buffered data
+ * it might have to memory.
+ */
+static _INLINE_ void dbdma_flush(volatile struct dbdma_regs *dma)
+{
+ int i = 0;
+
+ out_le32(&dma->control, (FLUSH << 16) | FLUSH);
+ while (((in_le32(&dma->status) & FLUSH) != 0) && (i++ < 100))
+ udelay(1);
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Here starts the interrupt handling routines. All of the following
+ * subroutines are declared as inline and are folded into
+ * rs_interrupt(). They were separated out for readability's sake.
+ *
+ * - Ted Ts'o (tytso@mit.edu), 7-Mar-93
+ * -----------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver.
+ */
+static _INLINE_ void rs_sched_event(struct mac_serial *info,
+ int event)
+{
+ info->event |= 1 << event;
+ schedule_work(&info->tqueue);
+}
+
+/* Work out the flag value for a z8530 status value. */
+static _INLINE_ int stat_to_flag(int stat)
+{
+ int flag;
+
+ if (stat & Rx_OVR) {
+ flag = TTY_OVERRUN;
+ } else if (stat & FRM_ERR) {
+ flag = TTY_FRAME;
+ } else if (stat & PAR_ERR) {
+ flag = TTY_PARITY;
+ } else
+ flag = 0;
+ return flag;
+}
+
+static _INLINE_ void receive_chars(struct mac_serial *info,
+ struct pt_regs *regs)
+{
+ struct tty_struct *tty = info->tty;
+ unsigned char ch, stat, flag;
+
+ while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) != 0) {
+
+ stat = read_zsreg(info->zs_channel, R1);
+ ch = read_zsdata(info->zs_channel);
+
+#ifdef CONFIG_KGDB
+ if (info->kgdb_channel) {
+ if (ch == 0x03 || ch == '$')
+ breakpoint();
+ if (stat & (Rx_OVR|FRM_ERR|PAR_ERR))
+ write_zsreg(info->zs_channel, 0, ERR_RES);
+ return;
+ }
+#endif
+ if (!tty)
+ continue;
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+ tty_flip_buffer_push(tty);
+
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ static int flip_buf_ovf;
+ if (++flip_buf_ovf <= 1)
+ printk(KERN_WARNING "FB. overflow: %d\n",
+ flip_buf_ovf);
+ break;
+ }
+ tty->flip.count++;
+ {
+ static int flip_max_cnt;
+ if (flip_max_cnt < tty->flip.count)
+ flip_max_cnt = tty->flip.count;
+ }
+ flag = stat_to_flag(stat);
+ if (flag)
+ /* reset the error indication */
+ write_zsreg(info->zs_channel, 0, ERR_RES);
+ *tty->flip.flag_buf_ptr++ = flag;
+ *tty->flip.char_buf_ptr++ = ch;
+ }
+ if (tty)
+ tty_flip_buffer_push(tty);
+}
+
+static void transmit_chars(struct mac_serial *info)
+{
+ if ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0)
+ return;
+ info->tx_active = 0;
+
+ if (info->x_char && !info->power_wait) {
+ /* Send next char */
+ write_zsdata(info->zs_channel, info->x_char);
+ info->x_char = 0;
+ info->tx_active = 1;
+ return;
+ }
+
+ if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tx_stopped
+ || info->power_wait) {
+ write_zsreg(info->zs_channel, 0, RES_Tx_P);
+ return;
+ }
+
+ /* Send char */
+ write_zsdata(info->zs_channel, info->xmit_buf[info->xmit_tail++]);
+ info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
+ info->xmit_cnt--;
+ info->tx_active = 1;
+
+ if (info->xmit_cnt < WAKEUP_CHARS)
+ rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+}
+
+static void powerup_done(unsigned long data)
+{
+ struct mac_serial *info = (struct mac_serial *) data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock, flags);
+ info->power_wait = 0;
+ transmit_chars(info);
+ spin_unlock_irqrestore(&info->lock, flags);
+}
+
+static _INLINE_ void status_handle(struct mac_serial *info)
+{
+ unsigned char status;
+
+ /* Get status from Read Register 0 */
+ status = read_zsreg(info->zs_channel, 0);
+
+ /* Check for DCD transitions */
+ if (((status ^ info->read_reg_zero) & DCD) != 0
+ && info->tty && !C_CLOCAL(info->tty)) {
+ if (status & DCD) {
+ wake_up_interruptible(&info->open_wait);
+ } else {
+ if (info->tty)
+ tty_hangup(info->tty);
+ }
+ }
+
+ /* Check for CTS transitions */
+ if (info->tty && C_CRTSCTS(info->tty)) {
+ /*
+ * For some reason, on the Power Macintosh,
+ * it seems that the CTS bit is 1 when CTS is
+ * *negated* and 0 when it is asserted.
+ * The DCD bit doesn't seem to be inverted
+ * like this.
+ */
+ if ((status & CTS) == 0) {
+ if (info->tx_stopped) {
+#ifdef SERIAL_DEBUG_FLOW
+ printk(KERN_DEBUG "CTS up\n");
+#endif
+ info->tx_stopped = 0;
+ if (!info->tx_active)
+ transmit_chars(info);
+ }
+ } else {
+#ifdef SERIAL_DEBUG_FLOW
+ printk(KERN_DEBUG "CTS down\n");
+#endif
+ info->tx_stopped = 1;
+ }
+ }
+
+ /* Clear status condition... */
+ write_zsreg(info->zs_channel, 0, RES_EXT_INT);
+ info->read_reg_zero = status;
+}
+
+static _INLINE_ void receive_special_dma(struct mac_serial *info)
+{
+ unsigned char stat, flag;
+ volatile struct dbdma_regs *rd = &info->rx->dma;
+ int where = RX_BUF_SIZE;
+
+ spin_lock(&info->rx_dma_lock);
+ if ((ld_le32(&rd->status) & ACTIVE) != 0)
+ dbdma_flush(rd);
+ if (in_le32(&rd->cmdptr)
+ == virt_to_bus(info->rx_cmds[info->rx_cbuf] + 1))
+ where -= in_le16(&info->rx->res_count);
+ where--;
+
+ stat = read_zsreg(info->zs_channel, R1);
+
+ flag = stat_to_flag(stat);
+ if (flag) {
+ info->rx_flag_buf[info->rx_cbuf][where] = flag;
+ /* reset the error indication */
+ write_zsreg(info->zs_channel, 0, ERR_RES);
+ }
+
+ spin_unlock(&info->rx_dma_lock);
+}
+
+/*
+ * This is the serial driver's generic interrupt routine
+ */
+static irqreturn_t rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+ struct mac_serial *info = (struct mac_serial *) dev_id;
+ unsigned char zs_intreg;
+ int shift;
+ unsigned long flags;
+ int handled = 0;
+
+ if (!(info->flags & ZILOG_INITIALIZED)) {
+ printk(KERN_WARNING "rs_interrupt: irq %d, port not "
+ "initialized\n", irq);
+ disable_irq(irq);
+ return IRQ_NONE;
+ }
+
+ /* NOTE: The read register 3, which holds the irq status,
+ * does so for both channels on each chip. Although
+ * the status value itself must be read from the A
+ * channel and is only valid when read from channel A.
+ * Yes... broken hardware...
+ */
+#define CHAN_IRQMASK (CHBRxIP | CHBTxIP | CHBEXT)
+
+ if (info->zs_chan_a == info->zs_channel)
+ shift = 3; /* Channel A */
+ else
+ shift = 0; /* Channel B */
+
+ spin_lock_irqsave(&info->lock, flags);
+ for (;;) {
+ zs_intreg = read_zsreg(info->zs_chan_a, 3) >> shift;
+#ifdef SERIAL_DEBUG_INTR
+ printk(KERN_DEBUG "rs_interrupt: irq %d, zs_intreg 0x%x\n",
+ irq, (int)zs_intreg);
+#endif
+
+ if ((zs_intreg & CHAN_IRQMASK) == 0)
+ break;
+ handled = 1;
+
+ if (zs_intreg & CHBRxIP) {
+ /* If we are doing DMA, we only ask for interrupts
+ on characters with errors or special conditions. */
+ if (info->dma_initted)
+ receive_special_dma(info);
+ else
+ receive_chars(info, regs);
+ }
+ if (zs_intreg & CHBTxIP)
+ transmit_chars(info);
+ if (zs_intreg & CHBEXT)
+ status_handle(info);
+ }
+ spin_unlock_irqrestore(&info->lock, flags);
+ return IRQ_RETVAL(handled);
+}
+
+/* Transmit DMA interrupt - not used at present */
+static irqreturn_t rs_txdma_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ return IRQ_HANDLED;
+}
+
+/*
+ * Receive DMA interrupt.
+ */
+static irqreturn_t rs_rxdma_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct mac_serial *info = (struct mac_serial *) dev_id;
+ volatile struct dbdma_cmd *cd;
+
+ if (!info->dma_initted)
+ return IRQ_NONE;
+ spin_lock(&info->rx_dma_lock);
+ /* First, confirm that this interrupt is, indeed, coming */
+ /* from Rx DMA */
+ cd = info->rx_cmds[info->rx_cbuf] + 2;
+ if ((in_le16(&cd->xfer_status) & (RUN | ACTIVE)) != (RUN | ACTIVE)) {
+ spin_unlock(&info->rx_dma_lock);
+ return IRQ_NONE;
+ }
+ if (info->rx_fbuf != RX_NO_FBUF) {
+ info->rx_cbuf = info->rx_fbuf;
+ if (++info->rx_fbuf == info->rx_nbuf)
+ info->rx_fbuf = 0;
+ if (info->rx_fbuf == info->rx_ubuf)
+ info->rx_fbuf = RX_NO_FBUF;
+ }
+ spin_unlock(&info->rx_dma_lock);
+ return IRQ_HANDLED;
+}
+
+/*
+ * -------------------------------------------------------------------
+ * Here ends the serial interrupt routines.
+ * -------------------------------------------------------------------
+ */
+
+/*
+ * ------------------------------------------------------------
+ * rs_stop() and rs_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * ------------------------------------------------------------
+ */
+static void rs_stop(struct tty_struct *tty)
+{
+ struct mac_serial *info = (struct mac_serial *)tty->driver_data;
+
+#ifdef SERIAL_DEBUG_STOP
+ printk(KERN_DEBUG "rs_stop %ld....\n",
+ tty->ldisc.chars_in_buffer(tty));
+#endif
+
+ if (serial_paranoia_check(info, tty->name, "rs_stop"))
+ return;
+
+#if 0
+ spin_lock_irqsave(&info->lock, flags);
+ if (info->curregs[5] & TxENAB) {
+ info->curregs[5] &= ~TxENAB;
+ info->pendregs[5] &= ~TxENAB;
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+ }
+ spin_unlock_irqrestore(&info->lock, flags);
+#endif
+}
+
+static void rs_start(struct tty_struct *tty)
+{
+ struct mac_serial *info = (struct mac_serial *)tty->driver_data;
+ unsigned long flags;
+
+#ifdef SERIAL_DEBUG_STOP
+ printk(KERN_DEBUG "rs_start %ld....\n",
+ tty->ldisc.chars_in_buffer(tty));
+#endif
+
+ if (serial_paranoia_check(info, tty->name, "rs_start"))
+ return;
+
+ spin_lock_irqsave(&info->lock, flags);
+#if 0
+ if (info->xmit_cnt && info->xmit_buf && !(info->curregs[5] & TxENAB)) {
+ info->curregs[5] |= TxENAB;
+ info->pendregs[5] = info->curregs[5];
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+ }
+#else
+ if (info->xmit_cnt && info->xmit_buf && !info->tx_active) {
+ transmit_chars(info);
+ }
+#endif
+ spin_unlock_irqrestore(&info->lock, flags);
+}
+
+static void do_softint(void *private_)
+{
+ struct mac_serial *info = (struct mac_serial *) private_;
+ struct tty_struct *tty;
+
+ tty = info->tty;
+ if (!tty)
+ return;
+
+ if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event))
+ tty_wakeup(tty);
+}
+
+static int startup(struct mac_serial * info)
+{
+ int delay;
+
+ OPNDBG("startup() (ttyS%d, irq %d)\n", info->line, info->irq);
+
+ if (info->flags & ZILOG_INITIALIZED) {
+ OPNDBG(" -> already inited\n");
+ return 0;
+ }
+
+ if (!info->xmit_buf) {
+ info->xmit_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL);
+ if (!info->xmit_buf)
+ return -ENOMEM;
+ }
+
+ OPNDBG("starting up ttyS%d (irq %d)...\n", info->line, info->irq);
+
+ delay = set_scc_power(info, 1);
+
+ setup_scc(info);
+
+ if (delay) {
+ unsigned long flags;
+
+ /* delay is in ms */
+ spin_lock_irqsave(&info->lock, flags);
+ info->power_wait = 1;
+ mod_timer(&info->powerup_timer,
+ jiffies + (delay * HZ + 999) / 1000);
+ spin_unlock_irqrestore(&info->lock, flags);
+ }
+
+ OPNDBG("enabling IRQ on ttyS%d (irq %d)...\n", info->line, info->irq);
+
+ info->flags |= ZILOG_INITIALIZED;
+ enable_irq(info->irq);
+ if (info->dma_initted) {
+ enable_irq(info->rx_dma_irq);
+ }
+
+ return 0;
+}
+
+static _INLINE_ void rxdma_start(struct mac_serial * info, int curr)
+{
+ volatile struct dbdma_regs *rd = &info->rx->dma;
+ volatile struct dbdma_cmd *cd = info->rx_cmds[curr];
+
+//printk(KERN_DEBUG "SCC: rxdma_start\n");
+
+ st_le32(&rd->cmdptr, virt_to_bus(cd));
+ out_le32(&rd->control, (RUN << 16) | RUN);
+}
+
+static void rxdma_to_tty(struct mac_serial *info)
+{
+ struct tty_struct *tty = info->tty;
+ volatile struct dbdma_regs *rd = &info->rx->dma;
+ unsigned long flags;
+ int residue, available, space, do_queue;
+
+ if (!tty)
+ return;
+
+ do_queue = 0;
+ spin_lock_irqsave(&info->rx_dma_lock, flags);
+more:
+ space = TTY_FLIPBUF_SIZE - tty->flip.count;
+ if (!space) {
+ do_queue++;
+ goto out;
+ }
+ residue = 0;
+ if (info->rx_ubuf == info->rx_cbuf) {
+ if ((ld_le32(&rd->status) & ACTIVE) != 0) {
+ dbdma_flush(rd);
+ if (in_le32(&rd->cmdptr)
+ == virt_to_bus(info->rx_cmds[info->rx_cbuf]+1))
+ residue = in_le16(&info->rx->res_count);
+ }
+ }
+ available = RX_BUF_SIZE - residue - info->rx_done_bytes;
+ if (available > space)
+ available = space;
+ if (available) {
+ memcpy(tty->flip.char_buf_ptr,
+ info->rx_char_buf[info->rx_ubuf] + info->rx_done_bytes,
+ available);
+ memcpy(tty->flip.flag_buf_ptr,
+ info->rx_flag_buf[info->rx_ubuf] + info->rx_done_bytes,
+ available);
+ tty->flip.char_buf_ptr += available;
+ tty->flip.count += available;
+ tty->flip.flag_buf_ptr += available;
+ memset(info->rx_flag_buf[info->rx_ubuf] + info->rx_done_bytes,
+ 0, available);
+ info->rx_done_bytes += available;
+ do_queue++;
+ }
+ if (info->rx_done_bytes == RX_BUF_SIZE) {
+ volatile struct dbdma_cmd *cd = info->rx_cmds[info->rx_ubuf];
+
+ if (info->rx_ubuf == info->rx_cbuf)
+ goto out;
+ /* mark rx_char_buf[rx_ubuf] free */
+ st_le16(&cd->command, DBDMA_NOP);
+ cd++;
+ st_le32(&cd->cmd_dep, 0);
+ st_le32((unsigned int *)&cd->res_count, 0);
+ cd++;
+ st_le16(&cd->xfer_status, 0);
+
+ if (info->rx_fbuf == RX_NO_FBUF) {
+ info->rx_fbuf = info->rx_ubuf;
+ if (!(ld_le32(&rd->status) & ACTIVE)) {
+ dbdma_reset(&info->rx->dma);
+ rxdma_start(info, info->rx_ubuf);
+ info->rx_cbuf = info->rx_ubuf;
+ }
+ }
+ info->rx_done_bytes = 0;
+ if (++info->rx_ubuf == info->rx_nbuf)
+ info->rx_ubuf = 0;
+ if (info->rx_fbuf == info->rx_ubuf)
+ info->rx_fbuf = RX_NO_FBUF;
+ goto more;
+ }
+out:
+ spin_unlock_irqrestore(&info->rx_dma_lock, flags);
+ if (do_queue)
+ tty_flip_buffer_push(tty);
+}
+
+static void poll_rxdma(unsigned long private_)
+{
+ struct mac_serial *info = (struct mac_serial *) private_;
+ unsigned long flags;
+
+ rxdma_to_tty(info);
+ spin_lock_irqsave(&info->rx_dma_lock, flags);
+ mod_timer(&info->poll_dma_timer, RX_DMA_TIMER);
+ spin_unlock_irqrestore(&info->rx_dma_lock, flags);
+}
+
+static void dma_init(struct mac_serial * info)
+{
+ int i, size;
+ volatile struct dbdma_cmd *cd;
+ unsigned char *p;
+
+ info->rx_nbuf = 8;
+
+ /* various mem set up */
+ size = sizeof(struct dbdma_cmd) * (3 * info->rx_nbuf + 2)
+ + (RX_BUF_SIZE * 2 + sizeof(*info->rx_cmds)
+ + sizeof(*info->rx_char_buf) + sizeof(*info->rx_flag_buf))
+ * info->rx_nbuf;
+ info->dma_priv = kmalloc(size, GFP_KERNEL | GFP_DMA);
+ if (info->dma_priv == NULL)
+ return;
+ memset(info->dma_priv, 0, size);
+
+ info->rx_cmds = (volatile struct dbdma_cmd **)info->dma_priv;
+ info->rx_char_buf = (unsigned char **) (info->rx_cmds + info->rx_nbuf);
+ info->rx_flag_buf = info->rx_char_buf + info->rx_nbuf;
+ p = (unsigned char *) (info->rx_flag_buf + info->rx_nbuf);
+ for (i = 0; i < info->rx_nbuf; i++, p += RX_BUF_SIZE)
+ info->rx_char_buf[i] = p;
+ for (i = 0; i < info->rx_nbuf; i++, p += RX_BUF_SIZE)
+ info->rx_flag_buf[i] = p;
+
+ /* a bit of DMA programming */
+ cd = info->rx_cmds[0] = (volatile struct dbdma_cmd *) DBDMA_ALIGN(p);
+ st_le16(&cd->command, DBDMA_NOP);
+ cd++;
+ st_le16(&cd->req_count, RX_BUF_SIZE);
+ st_le16(&cd->command, INPUT_MORE);
+ st_le32(&cd->phy_addr, virt_to_bus(info->rx_char_buf[0]));
+ cd++;
+ st_le16(&cd->req_count, 4);
+ st_le16(&cd->command, STORE_WORD | INTR_ALWAYS);
+ st_le32(&cd->phy_addr, virt_to_bus(cd-2));
+ st_le32(&cd->cmd_dep, DBDMA_STOP);
+ for (i = 1; i < info->rx_nbuf; i++) {
+ info->rx_cmds[i] = ++cd;
+ st_le16(&cd->command, DBDMA_NOP);
+ cd++;
+ st_le16(&cd->req_count, RX_BUF_SIZE);
+ st_le16(&cd->command, INPUT_MORE);
+ st_le32(&cd->phy_addr, virt_to_bus(info->rx_char_buf[i]));
+ cd++;
+ st_le16(&cd->req_count, 4);
+ st_le16(&cd->command, STORE_WORD | INTR_ALWAYS);
+ st_le32(&cd->phy_addr, virt_to_bus(cd-2));
+ st_le32(&cd->cmd_dep, DBDMA_STOP);
+ }
+ cd++;
+ st_le16(&cd->command, DBDMA_NOP | BR_ALWAYS);
+ st_le32(&cd->cmd_dep, virt_to_bus(info->rx_cmds[0]));
+
+ /* setup DMA to our liking */
+ dbdma_reset(&info->rx->dma);
+ st_le32(&info->rx->dma.intr_sel, 0x10001);
+ st_le32(&info->rx->dma.br_sel, 0x10001);
+ out_le32(&info->rx->dma.wait_sel, 0x10001);
+
+ /* set various flags */
+ info->rx_ubuf = 0;
+ info->rx_cbuf = 0;
+ info->rx_fbuf = info->rx_ubuf + 1;
+ if (info->rx_fbuf == info->rx_nbuf)
+ info->rx_fbuf = RX_NO_FBUF;
+ info->rx_done_bytes = 0;
+
+ /* setup polling */
+ init_timer(&info->poll_dma_timer);
+ info->poll_dma_timer.function = (void *)&poll_rxdma;
+ info->poll_dma_timer.data = (unsigned long)info;
+
+ info->dma_initted = 1;
+}
+
+/*
+ * FixZeroBug....Works around a bug in the SCC receving channel.
+ * Taken from Darwin code, 15 Sept. 2000 -DanM
+ *
+ * The following sequence prevents a problem that is seen with O'Hare ASICs
+ * (most versions -- also with some Heathrow and Hydra ASICs) where a zero
+ * at the input to the receiver becomes 'stuck' and locks up the receiver.
+ * This problem can occur as a result of a zero bit at the receiver input
+ * coincident with any of the following events:
+ *
+ * The SCC is initialized (hardware or software).
+ * A framing error is detected.
+ * The clocking option changes from synchronous or X1 asynchronous
+ * clocking to X16, X32, or X64 asynchronous clocking.
+ * The decoding mode is changed among NRZ, NRZI, FM0, or FM1.
+ *
+ * This workaround attempts to recover from the lockup condition by placing
+ * the SCC in synchronous loopback mode with a fast clock before programming
+ * any of the asynchronous modes.
+ */
+static void fix_zero_bug_scc(struct mac_serial * info)
+{
+ write_zsreg(info->zs_channel, 9,
+ (info->zs_channel == info->zs_chan_a? CHRA: CHRB));
+ udelay(10);
+ write_zsreg(info->zs_channel, 9,
+ ((info->zs_channel == info->zs_chan_a? CHRA: CHRB) | NV));
+
+ write_zsreg(info->zs_channel, 4, (X1CLK | EXTSYNC));
+
+ /* I think this is wrong....but, I just copying code....
+ */
+ write_zsreg(info->zs_channel, 3, (8 & ~RxENABLE));
+
+ write_zsreg(info->zs_channel, 5, (8 & ~TxENAB));
+ write_zsreg(info->zs_channel, 9, NV); /* Didn't we already do this? */
+ write_zsreg(info->zs_channel, 11, (RCBR | TCBR));
+ write_zsreg(info->zs_channel, 12, 0);
+ write_zsreg(info->zs_channel, 13, 0);
+ write_zsreg(info->zs_channel, 14, (LOOPBAK | SSBR));
+ write_zsreg(info->zs_channel, 14, (LOOPBAK | SSBR | BRENABL));
+ write_zsreg(info->zs_channel, 3, (8 | RxENABLE));
+ write_zsreg(info->zs_channel, 0, RES_EXT_INT);
+ write_zsreg(info->zs_channel, 0, RES_EXT_INT); /* to kill some time */
+
+ /* The channel should be OK now, but it is probably receiving
+ * loopback garbage.
+ * Switch to asynchronous mode, disable the receiver,
+ * and discard everything in the receive buffer.
+ */
+ write_zsreg(info->zs_channel, 9, NV);
+ write_zsreg(info->zs_channel, 4, PAR_ENA);
+ write_zsreg(info->zs_channel, 3, (8 & ~RxENABLE));
+
+ while (read_zsreg(info->zs_channel, 0) & Rx_CH_AV) {
+ (void)read_zsreg(info->zs_channel, 8);
+ write_zsreg(info->zs_channel, 0, RES_EXT_INT);
+ write_zsreg(info->zs_channel, 0, ERR_RES);
+ }
+}
+
+static int setup_scc(struct mac_serial * info)
+{
+ unsigned long flags;
+
+ OPNDBG("setting up ttyS%d SCC...\n", info->line);
+
+ spin_lock_irqsave(&info->lock, flags);
+
+ /* Nice buggy HW ... */
+ fix_zero_bug_scc(info);
+
+ /*
+ * Reset the chip.
+ */
+ write_zsreg(info->zs_channel, 9,
+ (info->zs_channel == info->zs_chan_a? CHRA: CHRB));
+ udelay(10);
+ write_zsreg(info->zs_channel, 9, 0);
+
+ /*
+ * Clear the receive FIFO.
+ */
+ ZS_CLEARFIFO(info->zs_channel);
+ info->xmit_fifo_size = 1;
+
+ /*
+ * Reset DMAs
+ */
+ if (info->has_dma)
+ dma_init(info);
+
+ /*
+ * Clear the interrupt registers.
+ */
+ write_zsreg(info->zs_channel, 0, ERR_RES);
+ write_zsreg(info->zs_channel, 0, RES_H_IUS);
+
+ /*
+ * Turn on RTS and DTR.
+ */
+ if (!info->is_irda)
+ zs_rtsdtr(info, 1);
+
+ /*
+ * Finally, enable sequencing and interrupts
+ */
+ if (!info->dma_initted) {
+ /* interrupt on ext/status changes, all received chars,
+ transmit ready */
+ info->curregs[1] = (info->curregs[1] & ~0x18)
+ | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB);
+ } else {
+ /* interrupt on ext/status changes, W/Req pin is
+ receive DMA request */
+ info->curregs[1] = (info->curregs[1] & ~(0x18 | TxINT_ENAB))
+ | (EXT_INT_ENAB | WT_RDY_RT | WT_FN_RDYFN);
+ write_zsreg(info->zs_channel, 1, info->curregs[1]);
+ /* enable W/Req pin */
+ info->curregs[1] |= WT_RDY_ENAB;
+ write_zsreg(info->zs_channel, 1, info->curregs[1]);
+ /* enable interrupts on transmit ready and receive errors */
+ info->curregs[1] |= INT_ERR_Rx | TxINT_ENAB;
+ }
+ info->pendregs[1] = info->curregs[1];
+ info->curregs[3] |= (RxENABLE | Rx8);
+ info->pendregs[3] = info->curregs[3];
+ info->curregs[5] |= (TxENAB | Tx8);
+ info->pendregs[5] = info->curregs[5];
+ info->curregs[9] |= (NV | MIE);
+ info->pendregs[9] = info->curregs[9];
+ write_zsreg(info->zs_channel, 3, info->curregs[3]);
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+ write_zsreg(info->zs_channel, 9, info->curregs[9]);
+
+ if (info->tty)
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+ spin_unlock_irqrestore(&info->lock, flags);
+
+ /*
+ * Set the speed of the serial port
+ */
+ change_speed(info, 0);
+
+ /* Save the current value of RR0 */
+ info->read_reg_zero = read_zsreg(info->zs_channel, 0);
+
+ if (info->dma_initted) {
+ spin_lock_irqsave(&info->rx_dma_lock, flags);
+ rxdma_start(info, 0);
+ info->poll_dma_timer.expires = RX_DMA_TIMER;
+ add_timer(&info->poll_dma_timer);
+ spin_unlock_irqrestore(&info->rx_dma_lock, flags);
+ }
+
+ return 0;
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void shutdown(struct mac_serial * info)
+{
+ OPNDBG("Shutting down serial port %d (irq %d)....\n", info->line,
+ info->irq);
+
+ if (!(info->flags & ZILOG_INITIALIZED)) {
+ OPNDBG("(already shutdown)\n");
+ return;
+ }
+
+ if (info->has_dma) {
+ del_timer(&info->poll_dma_timer);
+ dbdma_reset(info->tx_dma);
+ dbdma_reset(&info->rx->dma);
+ disable_irq(info->tx_dma_irq);
+ disable_irq(info->rx_dma_irq);
+ }
+ disable_irq(info->irq);
+
+ info->pendregs[1] = info->curregs[1] = 0;
+ write_zsreg(info->zs_channel, 1, 0); /* no interrupts */
+
+ info->curregs[3] &= ~RxENABLE;
+ info->pendregs[3] = info->curregs[3];
+ write_zsreg(info->zs_channel, 3, info->curregs[3]);
+
+ info->curregs[5] &= ~TxENAB;
+ if (!info->tty || C_HUPCL(info->tty))
+ info->curregs[5] &= ~DTR;
+ info->pendregs[5] = info->curregs[5];
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+ set_scc_power(info, 0);
+
+ if (info->xmit_buf) {
+ free_page((unsigned long) info->xmit_buf);
+ info->xmit_buf = 0;
+ }
+
+ if (info->has_dma && info->dma_priv) {
+ kfree(info->dma_priv);
+ info->dma_priv = NULL;
+ info->dma_initted = 0;
+ }
+
+ memset(info->curregs, 0, sizeof(info->curregs));
+ memset(info->pendregs, 0, sizeof(info->pendregs));
+
+ info->flags &= ~ZILOG_INITIALIZED;
+}
+
+/*
+ * Turn power on or off to the SCC and associated stuff
+ * (port drivers, modem, IR port, etc.)
+ * Returns the number of milliseconds we should wait before
+ * trying to use the port.
+ */
+static int set_scc_power(struct mac_serial * info, int state)
+{
+ int delay = 0;
+
+ if (state) {
+ PWRDBG("ttyS%d: powering up hardware\n", info->line);
+ pmac_call_feature(
+ PMAC_FTR_SCC_ENABLE,
+ info->dev_node, info->port_type, 1);
+ if (info->is_internal_modem) {
+ pmac_call_feature(
+ PMAC_FTR_MODEM_ENABLE,
+ info->dev_node, 0, 1);
+ delay = 2500; /* wait for 2.5s before using */
+ } else if (info->is_irda)
+ mdelay(50); /* Do better here once the problems
+ * with blocking have been ironed out
+ */
+ } else {
+ /* TODO: Make that depend on a timer, don't power down
+ * immediately
+ */
+ PWRDBG("ttyS%d: shutting down hardware\n", info->line);
+ if (info->is_internal_modem) {
+ PWRDBG("ttyS%d: shutting down modem\n", info->line);
+ pmac_call_feature(
+ PMAC_FTR_MODEM_ENABLE,
+ info->dev_node, 0, 0);
+ }
+ pmac_call_feature(
+ PMAC_FTR_SCC_ENABLE,
+ info->dev_node, info->port_type, 0);
+ }
+ return delay;
+}
+
+static void irda_rts_pulses(struct mac_serial *info, int w)
+{
+ udelay(w);
+ write_zsreg(info->zs_channel, 5, Tx8 | TxENAB);
+ udelay(2);
+ write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS);
+ udelay(8);
+ write_zsreg(info->zs_channel, 5, Tx8 | TxENAB);
+ udelay(4);
+ write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS);
+}
+
+/*
+ * Set the irda codec on the imac to the specified baud rate.
+ */
+static void irda_setup(struct mac_serial *info)
+{
+ int code, speed, t;
+
+ speed = info->tty->termios->c_cflag & CBAUD;
+ if (speed < B2400 || speed > B115200)
+ return;
+ code = 0x4d + B115200 - speed;
+
+ /* disable serial interrupts and receive DMA */
+ write_zsreg(info->zs_channel, 1, info->curregs[1] & ~0x9f);
+
+ /* wait for transmitter to drain */
+ t = 10000;
+ while ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0
+ || (read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) {
+ if (--t <= 0) {
+ printk(KERN_ERR "transmitter didn't drain\n");
+ return;
+ }
+ udelay(10);
+ }
+ udelay(100);
+
+ /* set to 8 bits, no parity, 19200 baud, RTS on, DTR off */
+ write_zsreg(info->zs_channel, 4, X16CLK | SB1);
+ write_zsreg(info->zs_channel, 11, TCBR | RCBR);
+ t = BPS_TO_BRG(19200, ZS_CLOCK/16);
+ write_zsreg(info->zs_channel, 12, t);
+ write_zsreg(info->zs_channel, 13, t >> 8);
+ write_zsreg(info->zs_channel, 14, BRENABL);
+ write_zsreg(info->zs_channel, 3, Rx8 | RxENABLE);
+ write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS);
+
+ /* set TxD low for ~104us and pulse RTS */
+ udelay(1000);
+ write_zsdata(info->zs_channel, 0xfe);
+ irda_rts_pulses(info, 150);
+ irda_rts_pulses(info, 180);
+ irda_rts_pulses(info, 50);
+ udelay(100);
+
+ /* assert DTR, wait 30ms, talk to the chip */
+ write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS | DTR);
+ mdelay(30);
+ while (read_zsreg(info->zs_channel, 0) & Rx_CH_AV)
+ read_zsdata(info->zs_channel);
+
+ write_zsdata(info->zs_channel, 1);
+ t = 1000;
+ while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) == 0) {
+ if (--t <= 0) {
+ printk(KERN_ERR "irda_setup timed out on 1st byte\n");
+ goto out;
+ }
+ udelay(10);
+ }
+ t = read_zsdata(info->zs_channel);
+ if (t != 4)
+ printk(KERN_ERR "irda_setup 1st byte = %x\n", t);
+
+ write_zsdata(info->zs_channel, code);
+ t = 1000;
+ while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) == 0) {
+ if (--t <= 0) {
+ printk(KERN_ERR "irda_setup timed out on 2nd byte\n");
+ goto out;
+ }
+ udelay(10);
+ }
+ t = read_zsdata(info->zs_channel);
+ if (t != code)
+ printk(KERN_ERR "irda_setup 2nd byte = %x (%x)\n", t, code);
+
+ /* Drop DTR again and do some more RTS pulses */
+ out:
+ udelay(100);
+ write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS);
+ irda_rts_pulses(info, 80);
+
+ /* We should be right to go now. We assume that load_zsregs
+ will get called soon to load up the correct baud rate etc. */
+ info->curregs[5] = (info->curregs[5] | RTS) & ~DTR;
+ info->pendregs[5] = info->curregs[5];
+}
+
+/*
+ * This routine is called to set the UART divisor registers to match
+ * the specified baud rate for a serial port.
+ */
+static void change_speed(struct mac_serial *info, struct termios *old_termios)
+{
+ unsigned cflag;
+ int bits;
+ int brg, baud;
+ unsigned long flags;
+
+ if (!info->tty || !info->tty->termios)
+ return;
+
+ cflag = info->tty->termios->c_cflag;
+ baud = tty_get_baud_rate(info->tty);
+ if (baud == 0) {
+ if (old_termios) {
+ info->tty->termios->c_cflag &= ~CBAUD;
+ info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
+ cflag = info->tty->termios->c_cflag;
+ baud = tty_get_baud_rate(info->tty);
+ }
+ else
+ baud = info->zs_baud;
+ }
+ if (baud > 230400)
+ baud = 230400;
+ else if (baud == 0)
+ baud = 38400;
+
+ spin_lock_irqsave(&info->lock, flags);
+ info->zs_baud = baud;
+ info->clk_divisor = 16;
+
+ BAUDBG(KERN_DEBUG "set speed to %d bds, ", baud);
+
+ switch (baud) {
+ case ZS_CLOCK/16: /* 230400 */
+ info->curregs[4] = X16CLK;
+ info->curregs[11] = 0;
+ break;
+ case ZS_CLOCK/32: /* 115200 */
+ info->curregs[4] = X32CLK;
+ info->curregs[11] = 0;
+ break;
+ default:
+ info->curregs[4] = X16CLK;
+ info->curregs[11] = TCBR | RCBR;
+ brg = BPS_TO_BRG(baud, ZS_CLOCK/info->clk_divisor);
+ info->curregs[12] = (brg & 255);
+ info->curregs[13] = ((brg >> 8) & 255);
+ info->curregs[14] = BRENABL;
+ }
+
+ /* byte size and parity */
+ info->curregs[3] &= ~RxNBITS_MASK;
+ info->curregs[5] &= ~TxNBITS_MASK;
+ switch (cflag & CSIZE) {
+ case CS5:
+ info->curregs[3] |= Rx5;
+ info->curregs[5] |= Tx5;
+ BAUDBG("5 bits, ");
+ bits = 7;
+ break;
+ case CS6:
+ info->curregs[3] |= Rx6;
+ info->curregs[5] |= Tx6;
+ BAUDBG("6 bits, ");
+ bits = 8;
+ break;
+ case CS7:
+ info->curregs[3] |= Rx7;
+ info->curregs[5] |= Tx7;
+ BAUDBG("7 bits, ");
+ bits = 9;
+ break;
+ case CS8:
+ default: /* defaults to 8 bits */
+ info->curregs[3] |= Rx8;
+ info->curregs[5] |= Tx8;
+ BAUDBG("8 bits, ");
+ bits = 10;
+ break;
+ }
+ info->pendregs[3] = info->curregs[3];
+ info->pendregs[5] = info->curregs[5];
+
+ info->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN);
+ if (cflag & CSTOPB) {
+ info->curregs[4] |= SB2;
+ bits++;
+ BAUDBG("2 stop, ");
+ } else {
+ info->curregs[4] |= SB1;
+ BAUDBG("1 stop, ");
+ }
+ if (cflag & PARENB) {
+ bits++;
+ info->curregs[4] |= PAR_ENA;
+ BAUDBG("parity, ");
+ }
+ if (!(cflag & PARODD)) {
+ info->curregs[4] |= PAR_EVEN;
+ }
+ info->pendregs[4] = info->curregs[4];
+
+ if (!(cflag & CLOCAL)) {
+ if (!(info->curregs[15] & DCDIE))
+ info->read_reg_zero = read_zsreg(info->zs_channel, 0);
+ info->curregs[15] |= DCDIE;
+ } else
+ info->curregs[15] &= ~DCDIE;
+ if (cflag & CRTSCTS) {
+ info->curregs[15] |= CTSIE;
+ if ((read_zsreg(info->zs_channel, 0) & CTS) != 0)
+ info->tx_stopped = 1;
+ } else {
+ info->curregs[15] &= ~CTSIE;
+ info->tx_stopped = 0;
+ }
+ info->pendregs[15] = info->curregs[15];
+
+ /* Calc timeout value. This is pretty broken with high baud rates with HZ=100.
+ This code would love a larger HZ and a >1 fifo size, but this is not
+ a priority. The resulting value must be >HZ/2
+ */
+ info->timeout = ((info->xmit_fifo_size*HZ*bits) / baud);
+ info->timeout += HZ/50+1; /* Add .02 seconds of slop */
+
+ BAUDBG("timeout=%d/%ds, base:%d\n", (int)info->timeout, (int)HZ,
+ (int)info->baud_base);
+
+ /* set the irda codec to the right rate */
+ if (info->is_irda)
+ irda_setup(info);
+
+ /* Load up the new values */
+ load_zsregs(info->zs_channel, info->curregs);
+
+ spin_unlock_irqrestore(&info->lock, flags);
+}
+
+static void rs_flush_chars(struct tty_struct *tty)
+{
+ struct mac_serial *info = (struct mac_serial *)tty->driver_data;
+ unsigned long flags;
+
+ if (serial_paranoia_check(info, tty->name, "rs_flush_chars"))
+ return;
+
+ spin_lock_irqsave(&info->lock, flags);
+ if (!(info->xmit_cnt <= 0 || tty->stopped || info->tx_stopped ||
+ !info->xmit_buf))
+ /* Enable transmitter */
+ transmit_chars(info);
+ spin_unlock_irqrestore(&info->lock, flags);
+}
+
+static int rs_write(struct tty_struct * tty,
+ const unsigned char *buf, int count)
+{
+ int c, ret = 0;
+ struct mac_serial *info = (struct mac_serial *)tty->driver_data;
+ unsigned long flags;
+
+ if (serial_paranoia_check(info, tty->name, "rs_write"))
+ return 0;
+
+ if (!tty || !info->xmit_buf || !tmp_buf)
+ return 0;
+
+ while (1) {
+ spin_lock_irqsave(&info->lock, flags);
+ c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+ SERIAL_XMIT_SIZE - info->xmit_head));
+ if (c <= 0) {
+ spin_unlock_irqrestore(&info->lock, flags);
+ break;
+ }
+ memcpy(info->xmit_buf + info->xmit_head, buf, c);
+ info->xmit_head = ((info->xmit_head + c) &
+ (SERIAL_XMIT_SIZE-1));
+ info->xmit_cnt += c;
+ spin_unlock_irqrestore(&info->lock, flags);
+ buf += c;
+ count -= c;
+ ret += c;
+ }
+ spin_lock_irqsave(&info->lock, flags);
+ if (info->xmit_cnt && !tty->stopped && !info->tx_stopped
+ && !info->tx_active)
+ transmit_chars(info);
+ spin_unlock_irqrestore(&info->lock, flags);
+ return ret;
+}
+
+static int rs_write_room(struct tty_struct *tty)
+{
+ struct mac_serial *info = (struct mac_serial *)tty->driver_data;
+ int ret;
+
+ if (serial_paranoia_check(info, tty->name, "rs_write_room"))
+ return 0;
+ ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
+ if (ret < 0)
+ ret = 0;
+ return ret;
+}
+
+static int rs_chars_in_buffer(struct tty_struct *tty)
+{
+ struct mac_serial *info = (struct mac_serial *)tty->driver_data;
+
+ if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer"))
+ return 0;
+ return info->xmit_cnt;
+}
+
+static void rs_flush_buffer(struct tty_struct *tty)
+{
+ struct mac_serial *info = (struct mac_serial *)tty->driver_data;
+ unsigned long flags;
+
+ if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
+ return;
+ spin_lock_irqsave(&info->lock, flags);
+ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+ spin_unlock_irqrestore(&info->lock, flags);
+ tty_wakeup(tty);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_throttle()
+ *
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ * ------------------------------------------------------------
+ */
+static void rs_throttle(struct tty_struct * tty)
+{
+ struct mac_serial *info = (struct mac_serial *)tty->driver_data;
+ unsigned long flags;
+#ifdef SERIAL_DEBUG_THROTTLE
+ printk(KERN_DEBUG "throttle %ld....\n",tty->ldisc.chars_in_buffer(tty));
+#endif
+
+ if (serial_paranoia_check(info, tty->name, "rs_throttle"))
+ return;
+
+ if (I_IXOFF(tty)) {
+ spin_lock_irqsave(&info->lock, flags);
+ info->x_char = STOP_CHAR(tty);
+ if (!info->tx_active)
+ transmit_chars(info);
+ spin_unlock_irqrestore(&info->lock, flags);
+ }
+
+ if (C_CRTSCTS(tty)) {
+ /*
+ * Here we want to turn off the RTS line. On Macintoshes,
+ * the external serial ports using a DIN-8 or DIN-9
+ * connector only have the DTR line (which is usually
+ * wired to both RTS and DTR on an external modem in
+ * the cable). RTS doesn't go out to the serial port
+ * socket, it acts as an output enable for the transmit
+ * data line. So in this case we don't drop RTS.
+ *
+ * Macs with internal modems generally do have both RTS
+ * and DTR wired to the modem, so in that case we do
+ * drop RTS.
+ */
+ if (info->is_internal_modem) {
+ spin_lock_irqsave(&info->lock, flags);
+ info->curregs[5] &= ~RTS;
+ info->pendregs[5] &= ~RTS;
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+ spin_unlock_irqrestore(&info->lock, flags);
+ }
+ }
+
+#ifdef CDTRCTS
+ if (tty->termios->c_cflag & CDTRCTS) {
+ spin_lock_irqsave(&info->lock, flags);
+ info->curregs[5] &= ~DTR;
+ info->pendregs[5] &= ~DTR;
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+ spin_unlock_irqrestore(&info->lock, flags);
+ }
+#endif /* CDTRCTS */
+}
+
+static void rs_unthrottle(struct tty_struct * tty)
+{
+ struct mac_serial *info = (struct mac_serial *)tty->driver_data;
+ unsigned long flags;
+#ifdef SERIAL_DEBUG_THROTTLE
+ printk(KERN_DEBUG "unthrottle %s: %d....\n",
+ tty->ldisc.chars_in_buffer(tty));
+#endif
+
+ if (serial_paranoia_check(info, tty->name, "rs_unthrottle"))
+ return;
+
+ if (I_IXOFF(tty)) {
+ spin_lock_irqsave(&info->lock, flags);
+ if (info->x_char)
+ info->x_char = 0;
+ else {
+ info->x_char = START_CHAR(tty);
+ if (!info->tx_active)
+ transmit_chars(info);
+ }
+ spin_unlock_irqrestore(&info->lock, flags);
+ }
+
+ if (C_CRTSCTS(tty) && info->is_internal_modem) {
+ /* Assert RTS line */
+ spin_lock_irqsave(&info->lock, flags);
+ info->curregs[5] |= RTS;
+ info->pendregs[5] |= RTS;
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+ spin_unlock_irqrestore(&info->lock, flags);
+ }
+
+#ifdef CDTRCTS
+ if (tty->termios->c_cflag & CDTRCTS) {
+ /* Assert DTR line */
+ spin_lock_irqsave(&info->lock, flags);
+ info->curregs[5] |= DTR;
+ info->pendregs[5] |= DTR;
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+ spin_unlock_irqrestore(&info->lock, flags);
+ }
+#endif
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_ioctl() and friends
+ * ------------------------------------------------------------
+ */
+
+static int get_serial_info(struct mac_serial * info,
+ struct serial_struct __user * retinfo)
+{
+ struct serial_struct tmp;
+
+ if (!retinfo)
+ return -EFAULT;
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.type = info->type;
+ tmp.line = info->line;
+ tmp.port = info->port;
+ tmp.irq = info->irq;
+ tmp.flags = info->flags;
+ tmp.baud_base = info->baud_base;
+ tmp.close_delay = info->close_delay;
+ tmp.closing_wait = info->closing_wait;
+ tmp.custom_divisor = info->custom_divisor;
+ if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
+ return -EFAULT;
+ return 0;
+}
+
+static int set_serial_info(struct mac_serial * info,
+ struct serial_struct __user * new_info)
+{
+ struct serial_struct new_serial;
+ struct mac_serial old_info;
+ int retval = 0;
+
+ if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
+ return -EFAULT;
+ old_info = *info;
+
+ if (!capable(CAP_SYS_ADMIN)) {
+ if ((new_serial.baud_base != info->baud_base) ||
+ (new_serial.type != info->type) ||
+ (new_serial.close_delay != info->close_delay) ||
+ ((new_serial.flags & ~ZILOG_USR_MASK) !=
+ (info->flags & ~ZILOG_USR_MASK)))
+ return -EPERM;
+ info->flags = ((info->flags & ~ZILOG_USR_MASK) |
+ (new_serial.flags & ZILOG_USR_MASK));
+ info->custom_divisor = new_serial.custom_divisor;
+ goto check_and_exit;
+ }
+
+ if (info->count > 1)
+ return -EBUSY;
+
+ /*
+ * OK, past this point, all the error checking has been done.
+ * At this point, we start making changes.....
+ */
+
+ info->baud_base = new_serial.baud_base;
+ info->flags = ((info->flags & ~ZILOG_FLAGS) |
+ (new_serial.flags & ZILOG_FLAGS));
+ info->type = new_serial.type;
+ info->close_delay = new_serial.close_delay;
+ info->closing_wait = new_serial.closing_wait;
+
+check_and_exit:
+ if (info->flags & ZILOG_INITIALIZED)
+ retval = setup_scc(info);
+ return retval;
+}
+
+/*
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ * is emptied. On bus types like RS485, the transmitter must
+ * release the bus after transmitting. This must be done when
+ * the transmit shift register is empty, not be done when the
+ * transmit holding register is empty. This functionality
+ * allows an RS485 driver to be written in user space.
+ */
+static int get_lsr_info(struct mac_serial * info, unsigned int *value)
+{
+ unsigned char status;
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock, flags);
+ status = read_zsreg(info->zs_channel, 0);
+ spin_unlock_irqrestore(&info->lock, flags);
+ status = (status & Tx_BUF_EMP)? TIOCSER_TEMT: 0;
+ return put_user(status,value);
+}
+
+static int rs_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ struct mac_serial * info = (struct mac_serial *)tty->driver_data;
+ unsigned char control, status;
+ unsigned long flags;
+
+#ifdef CONFIG_KGDB
+ if (info->kgdb_channel)
+ return -ENODEV;
+#endif
+ if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+ return -ENODEV;
+
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+
+ spin_lock_irqsave(&info->lock, flags);
+ control = info->curregs[5];
+ status = read_zsreg(info->zs_channel, 0);
+ spin_unlock_irqrestore(&info->lock, flags);
+ return ((control & RTS) ? TIOCM_RTS: 0)
+ | ((control & DTR) ? TIOCM_DTR: 0)
+ | ((status & DCD) ? TIOCM_CAR: 0)
+ | ((status & CTS) ? 0: TIOCM_CTS);
+}
+
+static int rs_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct mac_serial * info = (struct mac_serial *)tty->driver_data;
+ unsigned int arg, bits;
+ unsigned long flags;
+
+#ifdef CONFIG_KGDB
+ if (info->kgdb_channel)
+ return -ENODEV;
+#endif
+ if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+ return -ENODEV;
+
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+
+ spin_lock_irqsave(&info->lock, flags);
+ if (set & TIOCM_RTS)
+ info->curregs[5] |= RTS;
+ if (set & TIOCM_DTR)
+ info->curregs[5] |= DTR;
+ if (clear & TIOCM_RTS)
+ info->curregs[5] &= ~RTS;
+ if (clear & TIOCM_DTR)
+ info->curregs[5] &= ~DTR;
+
+ info->pendregs[5] = info->curregs[5];
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+ spin_unlock_irqrestore(&info->lock, flags);
+ return 0;
+}
+
+/*
+ * rs_break - turn transmit break condition on/off
+ */
+static void rs_break(struct tty_struct *tty, int break_state)
+{
+ struct mac_serial *info = (struct mac_serial *) tty->driver_data;
+ unsigned long flags;
+
+ if (serial_paranoia_check(info, tty->name, "rs_break"))
+ return;
+
+ spin_lock_irqsave(&info->lock, flags);
+ if (break_state == -1)
+ info->curregs[5] |= SND_BRK;
+ else
+ info->curregs[5] &= ~SND_BRK;
+ write_zsreg(info->zs_channel, 5, info->curregs[5]);
+ spin_unlock_irqrestore(&info->lock, flags);
+}
+
+static int rs_ioctl(struct tty_struct *tty, struct file * file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct mac_serial * info = (struct mac_serial *)tty->driver_data;
+
+#ifdef CONFIG_KGDB
+ if (info->kgdb_channel)
+ return -ENODEV;
+#endif
+ if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
+ return -ENODEV;
+
+ if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+ (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT)) {
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+ }
+
+ switch (cmd) {
+ case TIOCGSERIAL:
+ return get_serial_info(info,
+ (struct serial_struct __user *) arg);
+ case TIOCSSERIAL:
+ return set_serial_info(info,
+ (struct serial_struct __user *) arg);
+ case TIOCSERGETLSR: /* Get line status register */
+ return get_lsr_info(info, (unsigned int *) arg);
+
+ case TIOCSERGSTRUCT:
+ if (copy_to_user((struct mac_serial __user *) arg,
+ info, sizeof(struct mac_serial)))
+ return -EFAULT;
+ return 0;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+
+static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+{
+ struct mac_serial *info = (struct mac_serial *)tty->driver_data;
+ int was_stopped;
+
+ if (tty->termios->c_cflag == old_termios->c_cflag)
+ return;
+ was_stopped = info->tx_stopped;
+
+ change_speed(info, old_termios);
+
+ if (was_stopped && !info->tx_stopped) {
+ tty->hw_stopped = 0;
+ rs_start(tty);
+ }
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_close()
+ *
+ * This routine is called when the serial port gets closed.
+ * Wait for the last remaining data to be sent.
+ * ------------------------------------------------------------
+ */
+static void rs_close(struct tty_struct *tty, struct file * filp)
+{
+ struct mac_serial * info = (struct mac_serial *)tty->driver_data;
+ unsigned long flags;
+
+ if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
+ return;
+
+ spin_lock_irqsave(&info->lock, flags);
+
+ if (tty_hung_up_p(filp)) {
+ spin_unlock_irqrestore(&info->lock, flags);
+ return;
+ }
+
+ OPNDBG("rs_close ttyS%d, count = %d\n", info->line, info->count);
+ if ((tty->count == 1) && (info->count != 1)) {
+ /*
+ * Uh, oh. tty->count is 1, which means that the tty
+ * structure will be freed. Info->count should always
+ * be one in these conditions. If it's greater than
+ * one, we've got real problems, since it means the
+ * serial port won't be shutdown.
+ */
+ printk(KERN_ERR "rs_close: bad serial port count; tty->count "
+ "is 1, info->count is %d\n", info->count);
+ info->count = 1;
+ }
+ if (--info->count < 0) {
+ printk(KERN_ERR "rs_close: bad serial port count for "
+ "ttyS%d: %d\n", info->line, info->count);
+ info->count = 0;
+ }
+ if (info->count) {
+ spin_unlock_irqrestore(&info->lock, flags);
+ return;
+ }
+ info->flags |= ZILOG_CLOSING;
+ /*
+ * Now we wait for the transmit buffer to clear; and we notify
+ * the line discipline to only process XON/XOFF characters.
+ */
+ OPNDBG("waiting end of Tx... (timeout:%d)\n", info->closing_wait);
+ tty->closing = 1;
+ if (info->closing_wait != ZILOG_CLOSING_WAIT_NONE) {
+ spin_unlock_irqrestore(&info->lock, flags);
+ tty_wait_until_sent(tty, info->closing_wait);
+ spin_lock_irqsave(&info->lock, flags);
+ }
+
+ /*
+ * At this point we stop accepting input. To do this, we
+ * disable the receiver and receive interrupts.
+ */
+ info->curregs[3] &= ~RxENABLE;
+ info->pendregs[3] = info->curregs[3];
+ write_zsreg(info->zs_channel, 3, info->curregs[3]);
+ info->curregs[1] &= ~(0x18); /* disable any rx ints */
+ info->pendregs[1] = info->curregs[1];
+ write_zsreg(info->zs_channel, 1, info->curregs[1]);
+ ZS_CLEARFIFO(info->zs_channel);
+ if (info->flags & ZILOG_INITIALIZED) {
+ /*
+ * Before we drop DTR, make sure the SCC transmitter
+ * has completely drained.
+ */
+ OPNDBG("waiting end of Rx...\n");
+ spin_unlock_irqrestore(&info->lock, flags);
+ rs_wait_until_sent(tty, info->timeout);
+ spin_lock_irqsave(&info->lock, flags);
+ }
+
+ shutdown(info);
+ /* restore flags now since shutdown() will have disabled this port's
+ specific irqs */
+ spin_unlock_irqrestore(&info->lock, flags);
+
+ if (tty->driver->flush_buffer)
+ tty->driver->flush_buffer(tty);
+ tty_ldisc_flush(tty);
+ tty->closing = 0;
+ info->event = 0;
+ info->tty = 0;
+
+ if (info->blocked_open) {
+ if (info->close_delay) {
+ msleep_interruptible(jiffies_to_msecs(info->close_delay));
+ }
+ wake_up_interruptible(&info->open_wait);
+ }
+ info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CLOSING);
+ wake_up_interruptible(&info->close_wait);
+}
+
+/*
+ * rs_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+ struct mac_serial *info = (struct mac_serial *) tty->driver_data;
+ unsigned long orig_jiffies, char_time;
+
+ if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent"))
+ return;
+
+/* printk("rs_wait_until_sent, timeout:%d, tty_stopped:%d, tx_stopped:%d\n",
+ timeout, tty->stopped, info->tx_stopped);
+*/
+ orig_jiffies = jiffies;
+ /*
+ * Set the check interval to be 1/5 of the estimated time to
+ * send a single character, and make it at least 1. The check
+ * interval should also be less than the timeout.
+ */
+ if (info->timeout <= HZ/50) {
+ printk(KERN_INFO "macserial: invalid info->timeout=%d\n",
+ info->timeout);
+ info->timeout = HZ/50+1;
+ }
+
+ char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
+ char_time = char_time / 5;
+ if (char_time > HZ) {
+ printk(KERN_WARNING "macserial: char_time %ld >HZ !!!\n",
+ char_time);
+ char_time = 1;
+ } else if (char_time == 0)
+ char_time = 1;
+ if (timeout)
+ char_time = min_t(unsigned long, char_time, timeout);
+ while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) {
+ msleep_interruptible(jiffies_to_msecs(char_time));
+ if (signal_pending(current))
+ break;
+ if (timeout && time_after(jiffies, orig_jiffies + timeout))
+ break;
+ }
+ current->state = TASK_RUNNING;
+}
+
+/*
+ * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
+ */
+static void rs_hangup(struct tty_struct *tty)
+{
+ struct mac_serial * info = (struct mac_serial *)tty->driver_data;
+
+ if (serial_paranoia_check(info, tty->name, "rs_hangup"))
+ return;
+
+ rs_flush_buffer(tty);
+ shutdown(info);
+ info->event = 0;
+ info->count = 0;
+ info->flags &= ~ZILOG_NORMAL_ACTIVE;
+ info->tty = 0;
+ wake_up_interruptible(&info->open_wait);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_open() and friends
+ * ------------------------------------------------------------
+ */
+static int block_til_ready(struct tty_struct *tty, struct file * filp,
+ struct mac_serial *info)
+{
+ DECLARE_WAITQUEUE(wait,current);
+ int retval;
+ int do_clocal = 0;
+
+ /*
+ * If the device is in the middle of being closed, then block
+ * until it's done, and then try again.
+ */
+ if (info->flags & ZILOG_CLOSING) {
+ interruptible_sleep_on(&info->close_wait);
+ return -EAGAIN;
+ }
+
+ /*
+ * If non-blocking mode is set, or the port is not enabled,
+ * then make the check up front and then exit.
+ */
+ if ((filp->f_flags & O_NONBLOCK) ||
+ (tty->flags & (1 << TTY_IO_ERROR))) {
+ info->flags |= ZILOG_NORMAL_ACTIVE;
+ return 0;
+ }
+
+ if (tty->termios->c_cflag & CLOCAL)
+ do_clocal = 1;
+
+ /*
+ * Block waiting for the carrier detect and the line to become
+ * free (i.e., not in use by the callout). While we are in
+ * this loop, info->count is dropped by one, so that
+ * rs_close() knows when to free things. We restore it upon
+ * exit, either normal or abnormal.
+ */
+ retval = 0;
+ add_wait_queue(&info->open_wait, &wait);
+ OPNDBG("block_til_ready before block: ttyS%d, count = %d\n",
+ info->line, info->count);
+ spin_lock_irq(&info->lock);
+ if (!tty_hung_up_p(filp))
+ info->count--;
+ spin_unlock_irq(&info->lock);
+ info->blocked_open++;
+ while (1) {
+ spin_lock_irq(&info->lock);
+ if ((tty->termios->c_cflag & CBAUD) &&
+ !info->is_irda)
+ zs_rtsdtr(info, 1);
+ spin_unlock_irq(&info->lock);
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (tty_hung_up_p(filp) ||
+ !(info->flags & ZILOG_INITIALIZED)) {
+ retval = -EAGAIN;
+ break;
+ }
+ if (!(info->flags & ZILOG_CLOSING) &&
+ (do_clocal || (read_zsreg(info->zs_channel, 0) & DCD)))
+ break;
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+ OPNDBG("block_til_ready blocking: ttyS%d, count = %d\n",
+ info->line, info->count);
+ schedule();
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&info->open_wait, &wait);
+ if (!tty_hung_up_p(filp))
+ info->count++;
+ info->blocked_open--;
+ OPNDBG("block_til_ready after blocking: ttyS%d, count = %d\n",
+ info->line, info->count);
+ if (retval)
+ return retval;
+ info->flags |= ZILOG_NORMAL_ACTIVE;
+ return 0;
+}
+
+/*
+ * This routine is called whenever a serial port is opened. It
+ * enables interrupts for a serial port, linking in its ZILOG structure into
+ * the IRQ chain. It also performs the serial-specific
+ * initialization for the tty structure.
+ */
+static int rs_open(struct tty_struct *tty, struct file * filp)
+{
+ struct mac_serial *info;
+ int retval, line;
+ unsigned long page;
+
+ line = tty->index;
+ if ((line < 0) || (line >= zs_channels_found)) {
+ return -ENODEV;
+ }
+ info = zs_soft + line;
+
+#ifdef CONFIG_KGDB
+ if (info->kgdb_channel) {
+ return -ENODEV;
+ }
+#endif
+ if (serial_paranoia_check(info, tty->name, "rs_open"))
+ return -ENODEV;
+ OPNDBG("rs_open %s, count = %d, tty=%p\n", tty->name,
+ info->count, tty);
+
+ info->count++;
+ tty->driver_data = info;
+ info->tty = tty;
+
+ if (!tmp_buf) {
+ page = get_zeroed_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+ if (tmp_buf)
+ free_page(page);
+ else
+ tmp_buf = (unsigned char *) page;
+ }
+
+ /*
+ * If the port is the middle of closing, bail out now
+ */
+ if (tty_hung_up_p(filp) ||
+ (info->flags & ZILOG_CLOSING)) {
+ if (info->flags & ZILOG_CLOSING)
+ interruptible_sleep_on(&info->close_wait);
+ return -EAGAIN;
+ }
+
+ /*
+ * Start up serial port
+ */
+
+ retval = startup(info);
+ if (retval)
+ return retval;
+
+ retval = block_til_ready(tty, filp, info);
+ if (retval) {
+ OPNDBG("rs_open returning after block_til_ready with %d\n",
+ retval);
+ return retval;
+ }
+
+#ifdef CONFIG_SERIAL_CONSOLE
+ if (sercons.cflag && sercons.index == line) {
+ tty->termios->c_cflag = sercons.cflag;
+ sercons.cflag = 0;
+ change_speed(info, 0);
+ }
+#endif
+
+ OPNDBG("rs_open %s successful...\n", tty->name);
+ return 0;
+}
+
+/* Finally, routines used to initialize the serial driver. */
+
+static void show_serial_version(void)
+{
+ printk(KERN_INFO "PowerMac Z8530 serial driver version " MACSERIAL_VERSION "\n");
+}
+
+/*
+ * Initialize one channel, both the mac_serial and mac_zschannel
+ * structs. We use the dev_node field of the mac_serial struct.
+ */
+static int
+chan_init(struct mac_serial *zss, struct mac_zschannel *zs_chan,
+ struct mac_zschannel *zs_chan_a)
+{
+ struct device_node *ch = zss->dev_node;
+ char *conn;
+ int len;
+ struct slot_names_prop {
+ int count;
+ char name[1];
+ } *slots;
+
+ zss->irq = ch->intrs[0].line;
+ zss->has_dma = 0;
+#if !defined(CONFIG_KGDB) && defined(SUPPORT_SERIAL_DMA)
+ if (ch->n_addrs >= 3 && ch->n_intrs == 3)
+ zss->has_dma = 1;
+#endif
+ zss->dma_initted = 0;
+
+ zs_chan->control = (volatile unsigned char *)
+ ioremap(ch->addrs[0].address, 0x1000);
+ zs_chan->data = zs_chan->control + 0x10;
+ spin_lock_init(&zs_chan->lock);
+ zs_chan->parent = zss;
+ zss->zs_channel = zs_chan;
+ zss->zs_chan_a = zs_chan_a;
+
+ /* setup misc varariables */
+ zss->kgdb_channel = 0;
+
+ /* For now, we assume you either have a slot-names property
+ * with "Modem" in it, or your channel is compatible with
+ * "cobalt". Might need additional fixups
+ */
+ zss->is_internal_modem = device_is_compatible(ch, "cobalt");
+ conn = get_property(ch, "AAPL,connector", &len);
+ zss->is_irda = conn && (strcmp(conn, "infrared") == 0);
+ zss->port_type = PMAC_SCC_ASYNC;
+ /* 1999 Powerbook G3 has slot-names property instead */
+ slots = (struct slot_names_prop *)get_property(ch, "slot-names", &len);
+ if (slots && slots->count > 0) {
+ if (strcmp(slots->name, "IrDA") == 0)
+ zss->is_irda = 1;
+ else if (strcmp(slots->name, "Modem") == 0)
+ zss->is_internal_modem = 1;
+ }
+ if (zss->is_irda)
+ zss->port_type = PMAC_SCC_IRDA;
+ if (zss->is_internal_modem) {
+ struct device_node* i2c_modem = find_devices("i2c-modem");
+ if (i2c_modem) {
+ char* mid = get_property(i2c_modem, "modem-id", NULL);
+ if (mid) switch(*mid) {
+ case 0x04 :
+ case 0x05 :
+ case 0x07 :
+ case 0x08 :
+ case 0x0b :
+ case 0x0c :
+ zss->port_type = PMAC_SCC_I2S1;
+ }
+ printk(KERN_INFO "macserial: i2c-modem detected, id: %d\n",
+ mid ? (*mid) : 0);
+ } else {
+ printk(KERN_INFO "macserial: serial modem detected\n");
+ }
+ }
+
+ while (zss->has_dma) {
+ zss->dma_priv = NULL;
+ /* it seems that the last two addresses are the
+ DMA controllers */
+ zss->tx_dma = (volatile struct dbdma_regs *)
+ ioremap(ch->addrs[ch->n_addrs - 2].address, 0x100);
+ zss->rx = (volatile struct mac_dma *)
+ ioremap(ch->addrs[ch->n_addrs - 1].address, 0x100);
+ zss->tx_dma_irq = ch->intrs[1].line;
+ zss->rx_dma_irq = ch->intrs[2].line;
+ spin_lock_init(&zss->rx_dma_lock);
+ break;
+ }
+
+ init_timer(&zss->powerup_timer);
+ zss->powerup_timer.function = powerup_done;
+ zss->powerup_timer.data = (unsigned long) zss;
+ return 0;
+}
+
+/*
+ * /proc fs routines. TODO: Add status lines & error stats
+ */
+static inline int
+line_info(char *buf, struct mac_serial *info)
+{
+ int ret=0;
+ unsigned char* connector;
+ int lenp;
+
+ ret += sprintf(buf, "%d: port:0x%X irq:%d", info->line, info->port, info->irq);
+
+ connector = get_property(info->dev_node, "AAPL,connector", &lenp);
+ if (connector)
+ ret+=sprintf(buf+ret," con:%s ", connector);
+ if (info->is_internal_modem) {
+ if (!connector)
+ ret+=sprintf(buf+ret," con:");
+ ret+=sprintf(buf+ret,"%s", " (internal modem)");
+ }
+ if (info->is_irda) {
+ if (!connector)
+ ret+=sprintf(buf+ret," con:");
+ ret+=sprintf(buf+ret,"%s", " (IrDA)");
+ }
+ ret+=sprintf(buf+ret,"\n");
+
+ return ret;
+}
+
+int macserial_read_proc(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+{
+ int l, len = 0;
+ off_t begin = 0;
+ struct mac_serial *info;
+
+ len += sprintf(page, "serinfo:1.0 driver:" MACSERIAL_VERSION "\n");
+ for (info = zs_chain; info && len < 4000; info = info->zs_next) {
+ l = line_info(page + len, info);
+ len += l;
+ if (len+begin > off+count)
+ goto done;
+ if (len+begin < off) {
+ begin += len;
+ len = 0;
+ }
+ }
+ *eof = 1;
+done:
+ if (off >= len+begin)
+ return 0;
+ *start = page + (off-begin);
+ return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/* Ask the PROM how many Z8530s we have and initialize their zs_channels */
+static void
+probe_sccs(void)
+{
+ struct device_node *dev, *ch;
+ struct mac_serial **pp;
+ int n, chip, nchan;
+ struct mac_zschannel *zs_chan;
+ int chan_a_index;
+
+ n = 0;
+ pp = &zs_chain;
+ zs_chan = zs_channels;
+ for (dev = find_devices("escc"); dev != 0; dev = dev->next) {
+ nchan = 0;
+ chip = n;
+ if (n >= NUM_CHANNELS) {
+ printk(KERN_WARNING "Sorry, can't use %s: no more "
+ "channels\n", dev->full_name);
+ continue;
+ }
+ chan_a_index = 0;
+ for (ch = dev->child; ch != 0; ch = ch->sibling) {
+ if (nchan >= 2) {
+ printk(KERN_WARNING "SCC: Only 2 channels per "
+ "chip are supported\n");
+ break;
+ }
+ if (ch->n_addrs < 1 || (ch ->n_intrs < 1)) {
+ printk("Can't use %s: %d addrs %d intrs\n",
+ ch->full_name, ch->n_addrs, ch->n_intrs);
+ continue;
+ }
+
+ /* The channel with the higher address
+ will be the A side. */
+ if (nchan > 0 &&
+ ch->addrs[0].address
+ > zs_soft[n-1].dev_node->addrs[0].address)
+ chan_a_index = 1;
+
+ /* minimal initialization for now */
+ zs_soft[n].dev_node = ch;
+ *pp = &zs_soft[n];
+ pp = &zs_soft[n].zs_next;
+ ++nchan;
+ ++n;
+ }
+ if (nchan == 0)
+ continue;
+
+ /* set up A side */
+ if (chan_init(&zs_soft[chip + chan_a_index], zs_chan, zs_chan))
+ continue;
+ ++zs_chan;
+
+ /* set up B side, if it exists */
+ if (nchan > 1)
+ if (chan_init(&zs_soft[chip + 1 - chan_a_index],
+ zs_chan, zs_chan - 1))
+ continue;
+ ++zs_chan;
+ }
+ *pp = 0;
+
+ zs_channels_found = n;
+#ifdef CONFIG_PMAC_PBOOK
+ if (n)
+ pmu_register_sleep_notifier(&serial_sleep_notifier);
+#endif /* CONFIG_PMAC_PBOOK */
+}
+
+static struct tty_operations serial_ops = {
+ .open = rs_open,
+ .close = rs_close,
+ .write = rs_write,
+ .flush_chars = rs_flush_chars,
+ .write_room = rs_write_room,
+ .chars_in_buffer = rs_chars_in_buffer,
+ .flush_buffer = rs_flush_buffer,
+ .ioctl = rs_ioctl,
+ .throttle = rs_throttle,
+ .unthrottle = rs_unthrottle,
+ .set_termios = rs_set_termios,
+ .stop = rs_stop,
+ .start = rs_start,
+ .hangup = rs_hangup,
+ .break_ctl = rs_break,
+ .wait_until_sent = rs_wait_until_sent,
+ .read_proc = macserial_read_proc,
+ .tiocmget = rs_tiocmget,
+ .tiocmset = rs_tiocmset,
+};
+
+static int macserial_init(void)
+{
+ int channel, i;
+ struct mac_serial *info;
+
+ /* Find out how many Z8530 SCCs we have */
+ if (zs_chain == 0)
+ probe_sccs();
+
+ serial_driver = alloc_tty_driver(zs_channels_found);
+ if (!serial_driver)
+ return -ENOMEM;
+
+ /* XXX assume it's a powerbook if we have a via-pmu
+ *
+ * This is OK for core99 machines as well.
+ */
+ is_powerbook = find_devices("via-pmu") != 0;
+
+ /* Register the interrupt handler for each one
+ * We also request the OF resources here as probe_sccs()
+ * might be called too early for that
+ */
+ for (i = 0; i < zs_channels_found; ++i) {
+ struct device_node* ch = zs_soft[i].dev_node;
+ if (!request_OF_resource(ch, 0, NULL)) {
+ printk(KERN_ERR "macserial: can't request IO resource !\n");
+ put_tty_driver(serial_driver);
+ return -ENODEV;
+ }
+ if (zs_soft[i].has_dma) {
+ if (!request_OF_resource(ch, ch->n_addrs - 2, " (tx dma)")) {
+ printk(KERN_ERR "macserial: can't request TX DMA resource !\n");
+ zs_soft[i].has_dma = 0;
+ goto no_dma;
+ }
+ if (!request_OF_resource(ch, ch->n_addrs - 1, " (rx dma)")) {
+ release_OF_resource(ch, ch->n_addrs - 2);
+ printk(KERN_ERR "macserial: can't request RX DMA resource !\n");
+ zs_soft[i].has_dma = 0;
+ goto no_dma;
+ }
+ if (request_irq(zs_soft[i].tx_dma_irq, rs_txdma_irq, 0,
+ "SCC-txdma", &zs_soft[i]))
+ printk(KERN_ERR "macserial: can't get irq %d\n",
+ zs_soft[i].tx_dma_irq);
+ disable_irq(zs_soft[i].tx_dma_irq);
+ if (request_irq(zs_soft[i].rx_dma_irq, rs_rxdma_irq, 0,
+ "SCC-rxdma", &zs_soft[i]))
+ printk(KERN_ERR "macserial: can't get irq %d\n",
+ zs_soft[i].rx_dma_irq);
+ disable_irq(zs_soft[i].rx_dma_irq);
+ }
+no_dma:
+ if (request_irq(zs_soft[i].irq, rs_interrupt, 0,
+ "SCC", &zs_soft[i]))
+ printk(KERN_ERR "macserial: can't get irq %d\n",
+ zs_soft[i].irq);
+ disable_irq(zs_soft[i].irq);
+ }
+
+ show_serial_version();
+
+ /* Initialize the tty_driver structure */
+ /* Not all of this is exactly right for us. */
+
+ serial_driver->owner = THIS_MODULE;
+ serial_driver->driver_name = "macserial";
+ serial_driver->devfs_name = "tts/";
+ serial_driver->name = "ttyS";
+ serial_driver->major = TTY_MAJOR;
+ serial_driver->minor_start = 64;
+ serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+ serial_driver->subtype = SERIAL_TYPE_NORMAL;
+ serial_driver->init_termios = tty_std_termios;
+ serial_driver->init_termios.c_cflag =
+ B38400 | CS8 | CREAD | HUPCL | CLOCAL;
+ serial_driver->flags = TTY_DRIVER_REAL_RAW;
+ tty_set_operations(serial_driver, &serial_ops);
+
+ if (tty_register_driver(serial_driver))
+ printk(KERN_ERR "Error: couldn't register serial driver\n");
+
+ for (channel = 0; channel < zs_channels_found; ++channel) {
+#ifdef CONFIG_KGDB
+ if (zs_soft[channel].kgdb_channel) {
+ kgdb_interruptible(1);
+ continue;
+ }
+#endif
+ zs_soft[channel].clk_divisor = 16;
+/* -- we are not sure the SCC is powered ON at this point
+ zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]);
+*/
+ zs_soft[channel].zs_baud = 38400;
+
+ /* If console serial line, then enable interrupts. */
+ if (zs_soft[channel].is_cons) {
+ printk(KERN_INFO "macserial: console line, enabling "
+ "interrupt %d\n", zs_soft[channel].irq);
+ panic("macserial: console not supported yet !");
+ write_zsreg(zs_soft[channel].zs_channel, R1,
+ (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB));
+ write_zsreg(zs_soft[channel].zs_channel, R9,
+ (NV | MIE));
+ }
+ }
+
+ for (info = zs_chain, i = 0; info; info = info->zs_next, i++)
+ {
+ unsigned char* connector;
+ int lenp;
+
+#ifdef CONFIG_KGDB
+ if (info->kgdb_channel) {
+ continue;
+ }
+#endif
+ info->magic = SERIAL_MAGIC;
+ info->port = (int) info->zs_channel->control;
+ info->line = i;
+ info->tty = 0;
+ info->custom_divisor = 16;
+ info->timeout = 0;
+ info->close_delay = 50;
+ info->closing_wait = 3000;
+ info->x_char = 0;
+ info->event = 0;
+ info->count = 0;
+ info->blocked_open = 0;
+ INIT_WORK(&info->tqueue, do_softint, info);
+ spin_lock_init(&info->lock);
+ init_waitqueue_head(&info->open_wait);
+ init_waitqueue_head(&info->close_wait);
+ info->timeout = HZ;
+ printk(KERN_INFO "tty%02d at 0x%08x (irq = %d)", info->line,
+ info->port, info->irq);
+ printk(" is a Z8530 ESCC");
+ connector = get_property(info->dev_node, "AAPL,connector", &lenp);
+ if (connector)
+ printk(", port = %s", connector);
+ if (info->is_internal_modem)
+ printk(" (internal modem)");
+ if (info->is_irda)
+ printk(" (IrDA)");
+ printk("\n");
+ }
+ tmp_buf = 0;
+
+ return 0;
+}
+
+void macserial_cleanup(void)
+{
+ int i;
+ unsigned long flags;
+ struct mac_serial *info;
+
+ for (info = zs_chain, i = 0; info; info = info->zs_next, i++)
+ set_scc_power(info, 0);
+ spin_lock_irqsave(&info->lock, flags);
+ for (i = 0; i < zs_channels_found; ++i) {
+ free_irq(zs_soft[i].irq, &zs_soft[i]);
+ if (zs_soft[i].has_dma) {
+ free_irq(zs_soft[i].tx_dma_irq, &zs_soft[i]);
+ free_irq(zs_soft[i].rx_dma_irq, &zs_soft[i]);
+ }
+ release_OF_resource(zs_soft[i].dev_node, 0);
+ if (zs_soft[i].has_dma) {
+ struct device_node* ch = zs_soft[i].dev_node;
+ release_OF_resource(ch, ch->n_addrs - 2);
+ release_OF_resource(ch, ch->n_addrs - 1);
+ }
+ }
+ spin_unlock_irqrestore(&info->lock, flags);
+ tty_unregister_driver(serial_driver);
+ put_tty_driver(serial_driver);
+
+ if (tmp_buf) {
+ free_page((unsigned long) tmp_buf);
+ tmp_buf = 0;
+ }
+
+#ifdef CONFIG_PMAC_PBOOK
+ if (zs_channels_found)
+ pmu_unregister_sleep_notifier(&serial_sleep_notifier);
+#endif /* CONFIG_PMAC_PBOOK */
+}
+
+module_init(macserial_init);
+module_exit(macserial_cleanup);
+MODULE_LICENSE("GPL");
+
+#if 0
+/*
+ * register_serial and unregister_serial allows for serial ports to be
+ * configured at run-time, to support PCMCIA modems.
+ */
+/* PowerMac: Unused at this time, just here to make things link. */
+int register_serial(struct serial_struct *req)
+{
+ return -1;
+}
+
+void unregister_serial(int line)
+{
+ return;
+}
+#endif
+
+/*
+ * ------------------------------------------------------------
+ * Serial console driver
+ * ------------------------------------------------------------
+ */
+#ifdef CONFIG_SERIAL_CONSOLE
+
+/*
+ * Print a string to the serial port trying not to disturb
+ * any possible real use of the port...
+ */
+static void serial_console_write(struct console *co, const char *s,
+ unsigned count)
+{
+ struct mac_serial *info = zs_soft + co->index;
+ int i;
+
+ /* Turn of interrupts and enable the transmitter. */
+ write_zsreg(info->zs_channel, R1, info->curregs[1] & ~TxINT_ENAB);
+ write_zsreg(info->zs_channel, R5, info->curregs[5] | TxENAB | RTS | DTR);
+
+ for (i=0; izs_channel, 0) & Tx_BUF_EMP) == 0) {
+ eieio();
+ }
+
+ write_zsdata(info->zs_channel, s[i]);
+ if (s[i] == 10) {
+ while ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP)
+ == 0)
+ eieio();
+
+ write_zsdata(info->zs_channel, 13);
+ }
+ }
+
+ /* Restore the values in the registers. */
+ write_zsreg(info->zs_channel, R1, info->curregs[1]);
+ /* Don't disable the transmitter. */
+}
+
+static struct tty_driver *serial_driver;
+
+static struct tty_driver *serial_console_device(struct console *c, int *index)
+{
+ *index = c->index;
+ return serial_driver;
+}
+
+/*
+ * Setup initial baud/bits/parity. We do two things here:
+ * - construct a cflag setting for the first rs_open()
+ * - initialize the serial port
+ * Return non-zero if we didn't find a serial port.
+ */
+static int __init serial_console_setup(struct console *co, char *options)
+{
+ struct mac_serial *info;
+ int baud = 38400;
+ int bits = 8;
+ int parity = 'n';
+ int cflag = CREAD | HUPCL | CLOCAL;
+ int brg;
+ char *s;
+ long flags;
+
+ /* Find out how many Z8530 SCCs we have */
+ if (zs_chain == 0)
+ probe_sccs();
+
+ if (zs_chain == 0)
+ return -1;
+
+ /* Do we have the device asked for? */
+ if (co->index >= zs_channels_found)
+ return -1;
+ info = zs_soft + co->index;
+
+ set_scc_power(info, 1);
+
+ /* Reset the channel */
+ write_zsreg(info->zs_channel, R9, CHRA);
+
+ if (options) {
+ baud = simple_strtoul(options, NULL, 10);
+ s = options;
+ while(*s >= '0' && *s <= '9')
+ s++;
+ if (*s)
+ parity = *s++;
+ if (*s)
+ bits = *s - '0';
+ }
+
+ /*
+ * Now construct a cflag setting.
+ */
+ switch(baud) {
+ case 1200:
+ cflag |= B1200;
+ break;
+ case 2400:
+ cflag |= B2400;
+ break;
+ case 4800:
+ cflag |= B4800;
+ break;
+ case 9600:
+ cflag |= B9600;
+ break;
+ case 19200:
+ cflag |= B19200;
+ break;
+ case 57600:
+ cflag |= B57600;
+ break;
+ case 115200:
+ cflag |= B115200;
+ break;
+ case 38400:
+ default:
+ cflag |= B38400;
+ break;
+ }
+ switch(bits) {
+ case 7:
+ cflag |= CS7;
+ break;
+ default:
+ case 8:
+ cflag |= CS8;
+ break;
+ }
+ switch(parity) {
+ case 'o': case 'O':
+ cflag |= PARENB | PARODD;
+ break;
+ case 'e': case 'E':
+ cflag |= PARENB;
+ break;
+ }
+ co->cflag = cflag;
+
+ spin_lock_irqsave(&info->lock, flags);
+ memset(info->curregs, 0, sizeof(info->curregs));
+
+ info->zs_baud = baud;
+ info->clk_divisor = 16;
+ switch (info->zs_baud) {
+ case ZS_CLOCK/16: /* 230400 */
+ info->curregs[4] = X16CLK;
+ info->curregs[11] = 0;
+ break;
+ case ZS_CLOCK/32: /* 115200 */
+ info->curregs[4] = X32CLK;
+ info->curregs[11] = 0;
+ break;
+ default:
+ info->curregs[4] = X16CLK;
+ info->curregs[11] = TCBR | RCBR;
+ brg = BPS_TO_BRG(info->zs_baud, ZS_CLOCK/info->clk_divisor);
+ info->curregs[12] = (brg & 255);
+ info->curregs[13] = ((brg >> 8) & 255);
+ info->curregs[14] = BRENABL;
+ }
+
+ /* byte size and parity */
+ info->curregs[3] &= ~RxNBITS_MASK;
+ info->curregs[5] &= ~TxNBITS_MASK;
+ switch (cflag & CSIZE) {
+ case CS5:
+ info->curregs[3] |= Rx5;
+ info->curregs[5] |= Tx5;
+ break;
+ case CS6:
+ info->curregs[3] |= Rx6;
+ info->curregs[5] |= Tx6;
+ break;
+ case CS7:
+ info->curregs[3] |= Rx7;
+ info->curregs[5] |= Tx7;
+ break;
+ case CS8:
+ default: /* defaults to 8 bits */
+ info->curregs[3] |= Rx8;
+ info->curregs[5] |= Tx8;
+ break;
+ }
+ info->curregs[5] |= TxENAB | RTS | DTR;
+ info->pendregs[3] = info->curregs[3];
+ info->pendregs[5] = info->curregs[5];
+
+ info->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN);
+ if (cflag & CSTOPB) {
+ info->curregs[4] |= SB2;
+ } else {
+ info->curregs[4] |= SB1;
+ }
+ if (cflag & PARENB) {
+ info->curregs[4] |= PAR_ENA;
+ if (!(cflag & PARODD)) {
+ info->curregs[4] |= PAR_EVEN;
+ }
+ }
+ info->pendregs[4] = info->curregs[4];
+
+ if (!(cflag & CLOCAL)) {
+ if (!(info->curregs[15] & DCDIE))
+ info->read_reg_zero = read_zsreg(info->zs_channel, 0);
+ info->curregs[15] |= DCDIE;
+ } else
+ info->curregs[15] &= ~DCDIE;
+ if (cflag & CRTSCTS) {
+ info->curregs[15] |= CTSIE;
+ if ((read_zsreg(info->zs_channel, 0) & CTS) != 0)
+ info->tx_stopped = 1;
+ } else {
+ info->curregs[15] &= ~CTSIE;
+ info->tx_stopped = 0;
+ }
+ info->pendregs[15] = info->curregs[15];
+
+ /* Load up the new values */
+ load_zsregs(info->zs_channel, info->curregs);
+
+ spin_unlock_irqrestore(&info->lock, flags);
+
+ return 0;
+}
+
+static struct console sercons = {
+ .name = "ttyS",
+ .write = serial_console_write,
+ .device = serial_console_device,
+ .setup = serial_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+
+/*
+ * Register console.
+ */
+static void __init mac_scc_console_init(void)
+{
+ register_console(&sercons);
+}
+console_initcall(mac_scc_console_init);
+
+#endif /* ifdef CONFIG_SERIAL_CONSOLE */
+
+#ifdef CONFIG_KGDB
+/* These are for receiving and sending characters under the kgdb
+ * source level kernel debugger.
+ */
+void putDebugChar(char kgdb_char)
+{
+ struct mac_zschannel *chan = zs_kgdbchan;
+ while ((read_zsreg(chan, 0) & Tx_BUF_EMP) == 0)
+ udelay(5);
+ write_zsdata(chan, kgdb_char);
+}
+
+char getDebugChar(void)
+{
+ struct mac_zschannel *chan = zs_kgdbchan;
+ while((read_zsreg(chan, 0) & Rx_CH_AV) == 0)
+ eieio(); /*barrier();*/
+ return read_zsdata(chan);
+}
+
+void kgdb_interruptible(int yes)
+{
+ struct mac_zschannel *chan = zs_kgdbchan;
+ int one, nine;
+ nine = read_zsreg(chan, 9);
+ if (yes == 1) {
+ one = EXT_INT_ENAB|INT_ALL_Rx;
+ nine |= MIE;
+ printk("turning serial ints on\n");
+ } else {
+ one = RxINT_DISAB;
+ nine &= ~MIE;
+ printk("turning serial ints off\n");
+ }
+ write_zsreg(chan, 1, one);
+ write_zsreg(chan, 9, nine);
+}
+
+/* This sets up the serial port we're using, and turns on
+ * interrupts for that channel, so kgdb is usable once we're done.
+ */
+static inline void kgdb_chaninit(struct mac_zschannel *ms, int intson, int bps)
+{
+ int brg;
+ int i, x;
+ volatile char *sccc = ms->control;
+ brg = BPS_TO_BRG(bps, ZS_CLOCK/16);
+ printk("setting bps on kgdb line to %d [brg=%x]\n", bps, brg);
+ for (i = 20000; i != 0; --i) {
+ x = *sccc; eieio();
+ }
+ for (i = 0; i < sizeof(scc_inittab); ++i) {
+ write_zsreg(ms, scc_inittab[i], scc_inittab[i+1]);
+ i++;
+ }
+}
+
+/* This is called at boot time to prime the kgdb serial debugging
+ * serial line. The 'tty_num' argument is 0 for /dev/ttya and 1
+ * for /dev/ttyb which is determined in setup_arch() from the
+ * boot command line flags.
+ * XXX at the moment probably only channel A will work
+ */
+void __init zs_kgdb_hook(int tty_num)
+{
+ /* Find out how many Z8530 SCCs we have */
+ if (zs_chain == 0)
+ probe_sccs();
+
+ set_scc_power(&zs_soft[tty_num], 1);
+
+ zs_kgdbchan = zs_soft[tty_num].zs_channel;
+ zs_soft[tty_num].change_needed = 0;
+ zs_soft[tty_num].clk_divisor = 16;
+ zs_soft[tty_num].zs_baud = 38400;
+ zs_soft[tty_num].kgdb_channel = 1; /* This runs kgdb */
+
+ /* Turn on transmitter/receiver at 8-bits/char */
+ kgdb_chaninit(zs_soft[tty_num].zs_channel, 1, 38400);
+ printk("KGDB: on channel %d initialized\n", tty_num);
+ set_debug_traps(); /* init stub */
+}
+#endif /* ifdef CONFIG_KGDB */
+
+#ifdef CONFIG_PMAC_PBOOK
+/*
+ * notify clients before sleep and reset bus afterwards
+ */
+int
+serial_notify_sleep(struct pmu_sleep_notifier *self, int when)
+{
+ int i;
+
+ switch (when) {
+ case PBOOK_SLEEP_REQUEST:
+ case PBOOK_SLEEP_REJECT:
+ break;
+
+ case PBOOK_SLEEP_NOW:
+ for (i=0; iflags & ZILOG_INITIALIZED) {
+ shutdown(info);
+ info->flags |= ZILOG_SLEEPING;
+ }
+ }
+ break;
+ case PBOOK_WAKE:
+ for (i=0; iflags & ZILOG_SLEEPING) {
+ info->flags &= ~ZILOG_SLEEPING;
+ startup(info);
+ }
+ }
+ break;
+ }
+ return PBOOK_SLEEP_OK;
+}
+#endif /* CONFIG_PMAC_PBOOK */
diff --git a/trunk/drivers/macintosh/macserial.h b/trunk/drivers/macintosh/macserial.h
new file mode 100644
index 000000000000..bade11a7a5c3
--- /dev/null
+++ b/trunk/drivers/macintosh/macserial.h
@@ -0,0 +1,461 @@
+/*
+ * macserial.h: Definitions for the Macintosh Z8530 serial driver.
+ *
+ * Adapted from drivers/sbus/char/sunserial.h by Paul Mackerras.
+ *
+ * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _MACSERIAL_H
+#define _MACSERIAL_H
+
+#include
+
+#define NUM_ZSREGS 16
+
+struct serial_struct {
+ int type;
+ int line;
+ int port;
+ int irq;
+ int flags;
+ int xmit_fifo_size;
+ int custom_divisor;
+ int baud_base;
+ unsigned short close_delay;
+ char reserved_char[2];
+ int hub6;
+ unsigned short closing_wait; /* time to wait before closing */
+ unsigned short closing_wait2; /* no longer used... */
+ int reserved[4];
+};
+
+/*
+ * For the close wait times, 0 means wait forever for serial port to
+ * flush its output. 65535 means don't wait at all.
+ */
+#define ZILOG_CLOSING_WAIT_INF 0
+#define ZILOG_CLOSING_WAIT_NONE 65535
+
+/*
+ * Definitions for ZILOG_struct (and serial_struct) flags field
+ */
+#define ZILOG_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes
+ * on the callout port */
+#define ZILOG_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */
+#define ZILOG_SAK 0x0004 /* Secure Attention Key (Orange book) */
+#define ZILOG_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */
+
+#define ZILOG_SPD_MASK 0x0030
+#define ZILOG_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */
+
+#define ZILOG_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */
+#define ZILOG_SPD_CUST 0x0030 /* Use user-specified divisor */
+
+#define ZILOG_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */
+#define ZILOG_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */
+#define ZILOG_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */
+#define ZILOG_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */
+#define ZILOG_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */
+
+#define ZILOG_FLAGS 0x0FFF /* Possible legal ZILOG flags */
+#define ZILOG_USR_MASK 0x0430 /* Legal flags that non-privileged
+ * users can set or reset */
+
+/* Internal flags used only by kernel/chr_drv/serial.c */
+#define ZILOG_INITIALIZED 0x80000000 /* Serial port was initialized */
+#define ZILOG_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */
+#define ZILOG_NORMAL_ACTIVE 0x20000000 /* Normal device is active */
+#define ZILOG_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */
+#define ZILOG_CLOSING 0x08000000 /* Serial port is closing */
+#define ZILOG_CTS_FLOW 0x04000000 /* Do CTS flow control */
+#define ZILOG_CHECK_CD 0x02000000 /* i.e., CLOCAL */
+#define ZILOG_SLEEPING 0x01000000 /* have shut it down for sleep */
+
+/* Software state per channel */
+
+#ifdef __KERNEL__
+/*
+ * This is our internal structure for each serial port's state.
+ *
+ * Many fields are paralleled by the structure used by the serial_struct
+ * structure.
+ *
+ * For definitions of the flags field, see tty.h
+ */
+
+struct mac_serial;
+
+struct mac_zschannel {
+ volatile unsigned char* control;
+ volatile unsigned char* data;
+ spinlock_t lock;
+ /* Used for debugging */
+ struct mac_serial* parent;
+};
+
+struct mac_dma {
+ volatile struct dbdma_regs dma;
+ volatile unsigned short res_count;
+ volatile unsigned short command;
+ volatile unsigned int buf_addr;
+};
+
+struct mac_serial {
+ struct mac_serial *zs_next; /* For IRQ servicing chain */
+ struct mac_zschannel *zs_channel; /* Channel registers */
+ struct mac_zschannel *zs_chan_a; /* A side registers */
+ unsigned char read_reg_zero;
+ struct device_node* dev_node;
+ spinlock_t lock;
+
+ char soft_carrier; /* Use soft carrier on this channel */
+ char break_abort; /* Is serial console in, so process brk/abrt */
+ char kgdb_channel; /* Kgdb is running on this channel */
+ char is_cons; /* Is this our console. */
+ char is_internal_modem; /* is connected to an internal modem */
+ char is_irda; /* is connected to an IrDA codec */
+ int port_type; /* Port type for pmac_feature */
+ unsigned char tx_active; /* character is being xmitted */
+ unsigned char tx_stopped; /* output is suspended */
+ unsigned char power_wait; /* waiting for power-up delay to expire */
+
+ /* We need to know the current clock divisor
+ * to read the bps rate the chip has currently
+ * loaded.
+ */
+ unsigned char clk_divisor; /* May be 1, 16, 32, or 64 */
+ int zs_baud;
+
+ /* Current write register values */
+ unsigned char curregs[NUM_ZSREGS];
+
+ /* Values we need to set next opportunity */
+ unsigned char pendregs[NUM_ZSREGS];
+
+ char change_needed;
+
+ int magic;
+ int baud_base;
+ int port;
+ int irq;
+ int flags; /* defined in tty.h */
+ int type; /* UART type */
+ struct tty_struct *tty;
+ int read_status_mask;
+ int ignore_status_mask;
+ int timeout;
+ int xmit_fifo_size;
+ int custom_divisor;
+ int x_char; /* xon/xoff character */
+ int close_delay;
+ unsigned short closing_wait;
+ unsigned short closing_wait2;
+ unsigned long event;
+ unsigned long last_active;
+ int line;
+ int count; /* # of fd on device */
+ int blocked_open; /* # of blocked opens */
+ unsigned char *xmit_buf;
+ int xmit_head;
+ int xmit_tail;
+ int xmit_cnt;
+ struct work_struct tqueue;
+ wait_queue_head_t open_wait;
+ wait_queue_head_t close_wait;
+
+ volatile struct dbdma_regs *tx_dma;
+ int tx_dma_irq;
+ volatile struct dbdma_cmd *tx_cmds;
+ volatile struct mac_dma *rx;
+ int rx_dma_irq;
+ volatile struct dbdma_cmd **rx_cmds;
+ unsigned char **rx_char_buf;
+ unsigned char **rx_flag_buf;
+#define RX_BUF_SIZE 256
+ int rx_nbuf;
+ int rx_done_bytes;
+ int rx_ubuf;
+ int rx_fbuf;
+#define RX_NO_FBUF (-1)
+ int rx_cbuf;
+ spinlock_t rx_dma_lock;
+ int has_dma;
+ int dma_initted;
+ void *dma_priv;
+ struct timer_list poll_dma_timer;
+#define RX_DMA_TIMER (jiffies + 10*HZ/1000)
+
+ struct timer_list powerup_timer;
+};
+
+
+#define SERIAL_MAGIC 0x5301
+
+/*
+ * The size of the serial xmit buffer is 1 page, or 4096 bytes
+ */
+#define SERIAL_XMIT_SIZE 4096
+
+/*
+ * Events are used to schedule things to happen at timer-interrupt
+ * time, instead of at rs interrupt time.
+ */
+#define RS_EVENT_WRITE_WAKEUP 0
+
+#endif /* __KERNEL__ */
+
+/* Conversion routines to/from brg time constants from/to bits
+ * per second.
+ */
+#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2))
+#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2)
+
+/* The Zilog register set */
+
+#define FLAG 0x7e
+
+/* Write Register 0 */
+#define R0 0 /* Register selects */
+#define R1 1
+#define R2 2
+#define R3 3
+#define R4 4
+#define R5 5
+#define R6 6
+#define R7 7
+#define R8 8
+#define R9 9
+#define R10 10
+#define R11 11
+#define R12 12
+#define R13 13
+#define R14 14
+#define R15 15
+
+#define NULLCODE 0 /* Null Code */
+#define POINT_HIGH 0x8 /* Select upper half of registers */
+#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */
+#define SEND_ABORT 0x18 /* HDLC Abort */
+#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */
+#define RES_Tx_P 0x28 /* Reset TxINT Pending */
+#define ERR_RES 0x30 /* Error Reset */
+#define RES_H_IUS 0x38 /* Reset highest IUS */
+
+#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */
+#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */
+#define RES_EOM_L 0xC0 /* Reset EOM latch */
+
+/* Write Register 1 */
+
+#define EXT_INT_ENAB 0x1 /* Ext Int Enable */
+#define TxINT_ENAB 0x2 /* Tx Int Enable */
+#define PAR_SPEC 0x4 /* Parity is special condition */
+
+#define RxINT_DISAB 0 /* Rx Int Disable */
+#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */
+#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */
+#define INT_ERR_Rx 0x18 /* Int on error only */
+
+#define WT_RDY_RT 0x20 /* W/Req reflects recv if 1, xmit if 0 */
+#define WT_FN_RDYFN 0x40 /* W/Req pin is DMA request if 1, wait if 0 */
+#define WT_RDY_ENAB 0x80 /* Enable W/Req pin */
+
+/* Write Register #2 (Interrupt Vector) */
+
+/* Write Register 3 */
+
+#define RxENABLE 0x1 /* Rx Enable */
+#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */
+#define ADD_SM 0x4 /* Address Search Mode (SDLC) */
+#define RxCRC_ENAB 0x8 /* Rx CRC Enable */
+#define ENT_HM 0x10 /* Enter Hunt Mode */
+#define AUTO_ENAB 0x20 /* Auto Enables */
+#define Rx5 0x0 /* Rx 5 Bits/Character */
+#define Rx7 0x40 /* Rx 7 Bits/Character */
+#define Rx6 0x80 /* Rx 6 Bits/Character */
+#define Rx8 0xc0 /* Rx 8 Bits/Character */
+#define RxNBITS_MASK 0xc0
+
+/* Write Register 4 */
+
+#define PAR_ENA 0x1 /* Parity Enable */
+#define PAR_EVEN 0x2 /* Parity Even/Odd* */
+
+#define SYNC_ENAB 0 /* Sync Modes Enable */
+#define SB1 0x4 /* 1 stop bit/char */
+#define SB15 0x8 /* 1.5 stop bits/char */
+#define SB2 0xc /* 2 stop bits/char */
+#define SB_MASK 0xc
+
+#define MONSYNC 0 /* 8 Bit Sync character */
+#define BISYNC 0x10 /* 16 bit sync character */
+#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */
+#define EXTSYNC 0x30 /* External Sync Mode */
+
+#define X1CLK 0x0 /* x1 clock mode */
+#define X16CLK 0x40 /* x16 clock mode */
+#define X32CLK 0x80 /* x32 clock mode */
+#define X64CLK 0xC0 /* x64 clock mode */
+#define XCLK_MASK 0xC0
+
+/* Write Register 5 */
+
+#define TxCRC_ENAB 0x1 /* Tx CRC Enable */
+#define RTS 0x2 /* RTS */
+#define SDLC_CRC 0x4 /* SDLC/CRC-16 */
+#define TxENAB 0x8 /* Tx Enable */
+#define SND_BRK 0x10 /* Send Break */
+#define Tx5 0x0 /* Tx 5 bits (or less)/character */
+#define Tx7 0x20 /* Tx 7 bits/character */
+#define Tx6 0x40 /* Tx 6 bits/character */
+#define Tx8 0x60 /* Tx 8 bits/character */
+#define TxNBITS_MASK 0x60
+#define DTR 0x80 /* DTR */
+
+/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
+
+/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
+
+/* Write Register 7' (Some enhanced feature control) */
+#define ENEXREAD 0x40 /* Enable read of some write registers */
+
+/* Write Register 8 (transmit buffer) */
+
+/* Write Register 9 (Master interrupt control) */
+#define VIS 1 /* Vector Includes Status */
+#define NV 2 /* No Vector */
+#define DLC 4 /* Disable Lower Chain */
+#define MIE 8 /* Master Interrupt Enable */
+#define STATHI 0x10 /* Status high */
+#define NORESET 0 /* No reset on write to R9 */
+#define CHRB 0x40 /* Reset channel B */
+#define CHRA 0x80 /* Reset channel A */
+#define FHWRES 0xc0 /* Force hardware reset */
+
+/* Write Register 10 (misc control bits) */
+#define BIT6 1 /* 6 bit/8bit sync */
+#define LOOPMODE 2 /* SDLC Loop mode */
+#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */
+#define MARKIDLE 8 /* Mark/flag on idle */
+#define GAOP 0x10 /* Go active on poll */
+#define NRZ 0 /* NRZ mode */
+#define NRZI 0x20 /* NRZI mode */
+#define FM1 0x40 /* FM1 (transition = 1) */
+#define FM0 0x60 /* FM0 (transition = 0) */
+#define CRCPS 0x80 /* CRC Preset I/O */
+
+/* Write Register 11 (Clock Mode control) */
+#define TRxCXT 0 /* TRxC = Xtal output */
+#define TRxCTC 1 /* TRxC = Transmit clock */
+#define TRxCBR 2 /* TRxC = BR Generator Output */
+#define TRxCDP 3 /* TRxC = DPLL output */
+#define TRxCOI 4 /* TRxC O/I */
+#define TCRTxCP 0 /* Transmit clock = RTxC pin */
+#define TCTRxCP 8 /* Transmit clock = TRxC pin */
+#define TCBR 0x10 /* Transmit clock = BR Generator output */
+#define TCDPLL 0x18 /* Transmit clock = DPLL output */
+#define RCRTxCP 0 /* Receive clock = RTxC pin */
+#define RCTRxCP 0x20 /* Receive clock = TRxC pin */
+#define RCBR 0x40 /* Receive clock = BR Generator output */
+#define RCDPLL 0x60 /* Receive clock = DPLL output */
+#define RTxCX 0x80 /* RTxC Xtal/No Xtal */
+
+/* Write Register 12 (lower byte of baud rate generator time constant) */
+
+/* Write Register 13 (upper byte of baud rate generator time constant) */
+
+/* Write Register 14 (Misc control bits) */
+#define BRENABL 1 /* Baud rate generator enable */
+#define BRSRC 2 /* Baud rate generator source */
+#define DTRREQ 4 /* DTR/Request function */
+#define AUTOECHO 8 /* Auto Echo */
+#define LOOPBAK 0x10 /* Local loopback */
+#define SEARCH 0x20 /* Enter search mode */
+#define RMC 0x40 /* Reset missing clock */
+#define DISDPLL 0x60 /* Disable DPLL */
+#define SSBR 0x80 /* Set DPLL source = BR generator */
+#define SSRTxC 0xa0 /* Set DPLL source = RTxC */
+#define SFMM 0xc0 /* Set FM mode */
+#define SNRZI 0xe0 /* Set NRZI mode */
+
+/* Write Register 15 (external/status interrupt control) */
+#define EN85C30 1 /* Enable some 85c30-enhanced registers */
+#define ZCIE 2 /* Zero count IE */
+#define ENSTFIFO 4 /* Enable status FIFO (SDLC) */
+#define DCDIE 8 /* DCD IE */
+#define SYNCIE 0x10 /* Sync/hunt IE */
+#define CTSIE 0x20 /* CTS IE */
+#define TxUIE 0x40 /* Tx Underrun/EOM IE */
+#define BRKIE 0x80 /* Break/Abort IE */
+
+
+/* Read Register 0 */
+#define Rx_CH_AV 0x1 /* Rx Character Available */
+#define ZCOUNT 0x2 /* Zero count */
+#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */
+#define DCD 0x8 /* DCD */
+#define SYNC_HUNT 0x10 /* Sync/hunt */
+#define CTS 0x20 /* CTS */
+#define TxEOM 0x40 /* Tx underrun */
+#define BRK_ABRT 0x80 /* Break/Abort */
+
+/* Read Register 1 */
+#define ALL_SNT 0x1 /* All sent */
+/* Residue Data for 8 Rx bits/char programmed */
+#define RES3 0x8 /* 0/3 */
+#define RES4 0x4 /* 0/4 */
+#define RES5 0xc /* 0/5 */
+#define RES6 0x2 /* 0/6 */
+#define RES7 0xa /* 0/7 */
+#define RES8 0x6 /* 0/8 */
+#define RES18 0xe /* 1/8 */
+#define RES28 0x0 /* 2/8 */
+/* Special Rx Condition Interrupts */
+#define PAR_ERR 0x10 /* Parity error */
+#define Rx_OVR 0x20 /* Rx Overrun Error */
+#define FRM_ERR 0x40 /* CRC/Framing Error */
+#define END_FR 0x80 /* End of Frame (SDLC) */
+
+/* Read Register 2 (channel b only) - Interrupt vector */
+#define CHB_Tx_EMPTY 0x00
+#define CHB_EXT_STAT 0x02
+#define CHB_Rx_AVAIL 0x04
+#define CHB_SPECIAL 0x06
+#define CHA_Tx_EMPTY 0x08
+#define CHA_EXT_STAT 0x0a
+#define CHA_Rx_AVAIL 0x0c
+#define CHA_SPECIAL 0x0e
+#define STATUS_MASK 0x06
+
+/* Read Register 3 (interrupt pending register) ch a only */
+#define CHBEXT 0x1 /* Channel B Ext/Stat IP */
+#define CHBTxIP 0x2 /* Channel B Tx IP */
+#define CHBRxIP 0x4 /* Channel B Rx IP */
+#define CHAEXT 0x8 /* Channel A Ext/Stat IP */
+#define CHATxIP 0x10 /* Channel A Tx IP */
+#define CHARxIP 0x20 /* Channel A Rx IP */
+
+/* Read Register 8 (receive data register) */
+
+/* Read Register 10 (misc status bits) */
+#define ONLOOP 2 /* On loop */
+#define LOOPSEND 0x10 /* Loop sending */
+#define CLK2MIS 0x40 /* Two clocks missing */
+#define CLK1MIS 0x80 /* One clock missing */
+
+/* Read Register 12 (lower byte of baud rate generator constant) */
+
+/* Read Register 13 (upper byte of baud rate generator constant) */
+
+/* Read Register 15 (value of WR 15) */
+
+/* Misc macros */
+#define ZS_CLEARERR(channel) (write_zsreg(channel, 0, ERR_RES))
+#define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \
+ garbage = read_zsdata(channel); \
+ garbage = read_zsdata(channel); \
+ garbage = read_zsdata(channel); \
+ } while(0)
+
+#endif /* !(_MACSERIAL_H) */
diff --git a/trunk/drivers/macintosh/via-pmu.c b/trunk/drivers/macintosh/via-pmu.c
index 4a0a0ad2d03c..b941ee220997 100644
--- a/trunk/drivers/macintosh/via-pmu.c
+++ b/trunk/drivers/macintosh/via-pmu.c
@@ -63,10 +63,6 @@
#include
#endif
-#ifdef CONFIG_PPC32
-#include
-#endif
-
/* Some compile options */
#undef SUSPEND_USES_PMU
#define DEBUG_SLEEP
@@ -155,10 +151,10 @@ static spinlock_t pmu_lock;
static u8 pmu_intr_mask;
static int pmu_version;
static int drop_interrupts;
-#ifdef CONFIG_PM
+#ifdef CONFIG_PMAC_PBOOK
static int option_lid_wakeup = 1;
static int sleep_in_progress;
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PMAC_PBOOK */
static unsigned long async_req_locks;
static unsigned int pmu_irq_stats[11];
@@ -168,6 +164,7 @@ static struct proc_dir_entry *proc_pmu_irqstats;
static struct proc_dir_entry *proc_pmu_options;
static int option_server_mode;
+#ifdef CONFIG_PMAC_PBOOK
int pmu_battery_count;
int pmu_cur_battery;
unsigned int pmu_power_flags;
@@ -175,6 +172,7 @@ struct pmu_battery_info pmu_batteries[PMU_MAX_BATTERIES];
static int query_batt_timer = BATTERY_POLLING_COUNT;
static struct adb_request batt_req;
static struct proc_dir_entry *proc_pmu_batt[PMU_MAX_BATTERIES];
+#endif /* CONFIG_PMAC_PBOOK */
#if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
extern int disable_kernel_backlight;
@@ -208,9 +206,11 @@ static int proc_get_irqstats(char *page, char **start, off_t off,
static int pmu_set_backlight_level(int level, void* data);
static int pmu_set_backlight_enable(int on, int level, void* data);
#endif /* CONFIG_PMAC_BACKLIGHT */
+#ifdef CONFIG_PMAC_PBOOK
static void pmu_pass_intr(unsigned char *data, int len);
static int proc_get_batt(char *page, char **start, off_t off,
int count, int *eof, void *data);
+#endif /* CONFIG_PMAC_PBOOK */
static int proc_read_options(char *page, char **start, off_t off,
int count, int *eof, void *data);
static int proc_write_options(struct file *file, const char __user *buffer,
@@ -403,12 +403,8 @@ static int __init via_pmu_start(void)
bright_req_1.complete = 1;
bright_req_2.complete = 1;
+#ifdef CONFIG_PMAC_PBOOK
batt_req.complete = 1;
-
-#ifdef CONFIG_PPC32
- if (pmu_kind == PMU_KEYLARGO_BASED)
- openpic_set_irq_priority(vias->intrs[0].line,
- OPENPIC_PRIORITY_DEFAULT + 1);
#endif
if (request_irq(vias->intrs[0].line, via_pmu_interrupt, 0, "VIA-PMU",
@@ -462,7 +458,7 @@ static int __init via_pmu_dev_init(void)
register_backlight_controller(&pmu_backlight_controller, NULL, "pmu");
#endif /* CONFIG_PMAC_BACKLIGHT */
-#ifdef CONFIG_PPC32
+#ifdef CONFIG_PMAC_PBOOK
if (machine_is_compatible("AAPL,3400/2400") ||
machine_is_compatible("AAPL,3500")) {
int mb = pmac_call_feature(PMAC_FTR_GET_MB_INFO,
@@ -490,19 +486,20 @@ static int __init via_pmu_dev_init(void)
pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART;
}
}
-#endif /* CONFIG_PPC32 */
-
+#endif /* CONFIG_PMAC_PBOOK */
/* Create /proc/pmu */
proc_pmu_root = proc_mkdir("pmu", NULL);
if (proc_pmu_root) {
- long i;
+#ifdef CONFIG_PMAC_PBOOK
+ int i;
for (i=0; i= 0)
p += sprintf(p, "lid_wakeup=%d\n", option_lid_wakeup);
-#endif
+#endif /* CONFIG_PMAC_PBOOK */
if (pmu_kind == PMU_KEYLARGO_BASED)
p += sprintf(p, "server_mode=%d\n", option_server_mode);
@@ -917,12 +922,12 @@ proc_write_options(struct file *file, const char __user *buffer,
*(val++) = 0;
while(*val == ' ')
val++;
-#ifdef CONFIG_PM
+#ifdef CONFIG_PMAC_PBOOK
if (pmu_kind == PMU_KEYLARGO_BASED &&
pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
if (!strcmp(label, "lid_wakeup"))
option_lid_wakeup = ((*val) == '1');
-#endif
+#endif /* CONFIG_PMAC_PBOOK */
if (pmu_kind == PMU_KEYLARGO_BASED && !strcmp(label, "server_mode")) {
int new_value;
new_value = ((*val) == '1');
@@ -1417,6 +1422,7 @@ pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
}
/* Tick interrupt */
else if ((1 << pirq) & PMU_INT_TICK) {
+#ifdef CONFIG_PMAC_PBOOK
/* Environement or tick interrupt, query batteries */
if (pmu_battery_count) {
if ((--query_batt_timer) == 0) {
@@ -1431,6 +1437,7 @@ pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
pmu_pass_intr(data, len);
} else {
pmu_pass_intr(data, len);
+#endif /* CONFIG_PMAC_PBOOK */
}
goto next;
}
@@ -2045,7 +2052,7 @@ pmu_i2c_simple_write(int bus, int addr, u8* data, int len)
return -1;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PMAC_PBOOK
static LIST_HEAD(sleep_notifiers);
@@ -2698,8 +2705,6 @@ powerbook_sleep_3400(void)
return 0;
}
-#endif /* CONFIG_PM */
-
/*
* Support for /dev/pmu device
*/
@@ -2879,11 +2884,11 @@ static int __pmac
pmu_ioctl(struct inode * inode, struct file *filp,
u_int cmd, u_long arg)
{
+ struct pmu_private *pp = filp->private_data;
__u32 __user *argp = (__u32 __user *)arg;
- int error = -EINVAL;
+ int error;
switch (cmd) {
-#ifdef CONFIG_PM
case PMU_IOC_SLEEP:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
@@ -2905,13 +2910,12 @@ pmu_ioctl(struct inode * inode, struct file *filp,
error = -ENOSYS;
}
sleep_in_progress = 0;
- break;
+ return error;
case PMU_IOC_CAN_SLEEP:
if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0)
return put_user(0, argp);
else
return put_user(1, argp);
-#endif /* CONFIG_PM */
#ifdef CONFIG_PMAC_BACKLIGHT
/* Backlight should have its own device or go via
@@ -2932,13 +2936,11 @@ pmu_ioctl(struct inode * inode, struct file *filp,
error = get_user(value, argp);
if (!error)
error = set_backlight_level(value);
- break;
+ return error;
}
#ifdef CONFIG_INPUT_ADBHID
case PMU_IOC_GRAB_BACKLIGHT: {
- struct pmu_private *pp = filp->private_data;
unsigned long flags;
-
if (pp->backlight_locker)
return 0;
pp->backlight_locker = 1;
@@ -2954,7 +2956,7 @@ pmu_ioctl(struct inode * inode, struct file *filp,
case PMU_IOC_HAS_ADB:
return put_user(pmu_has_adb, argp);
}
- return error;
+ return -EINVAL;
}
static struct file_operations pmu_device_fops __pmacdata = {
@@ -2970,16 +2972,14 @@ static struct miscdevice pmu_device __pmacdata = {
PMU_MINOR, "pmu", &pmu_device_fops
};
-static int pmu_device_init(void)
+void pmu_device_init(void)
{
if (!via)
- return 0;
+ return;
if (misc_register(&pmu_device) < 0)
printk(KERN_ERR "via-pmu: cannot register misc device.\n");
- return 0;
}
-device_initcall(pmu_device_init);
-
+#endif /* CONFIG_PMAC_PBOOK */
#ifdef DEBUG_SLEEP
static inline void __pmac
@@ -3147,12 +3147,12 @@ EXPORT_SYMBOL(pmu_i2c_combined_read);
EXPORT_SYMBOL(pmu_i2c_stdsub_write);
EXPORT_SYMBOL(pmu_i2c_simple_read);
EXPORT_SYMBOL(pmu_i2c_simple_write);
-#ifdef CONFIG_PM
+#ifdef CONFIG_PMAC_PBOOK
EXPORT_SYMBOL(pmu_register_sleep_notifier);
EXPORT_SYMBOL(pmu_unregister_sleep_notifier);
EXPORT_SYMBOL(pmu_enable_irled);
EXPORT_SYMBOL(pmu_battery_count);
EXPORT_SYMBOL(pmu_batteries);
EXPORT_SYMBOL(pmu_power_flags);
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PMAC_PBOOK */
diff --git a/trunk/drivers/media/video/Kconfig b/trunk/drivers/media/video/Kconfig
index 1b70f8b0feb9..f9383e7f34ff 100644
--- a/trunk/drivers/media/video/Kconfig
+++ b/trunk/drivers/media/video/Kconfig
@@ -7,7 +7,7 @@ menu "Video For Linux"
comment "Video Adapters"
-config TUNER_MULTI_I2C
+config CONFIG_TUNER_MULTI_I2C
bool "Enable support for multiple I2C devices on Video Adapters (EXPERIMENTAL)"
depends on VIDEO_DEV && EXPERIMENTAL
---help---
diff --git a/trunk/drivers/mtd/maps/Kconfig b/trunk/drivers/mtd/maps/Kconfig
index 2bea2e0b06f2..8480057eadb4 100644
--- a/trunk/drivers/mtd/maps/Kconfig
+++ b/trunk/drivers/mtd/maps/Kconfig
@@ -607,16 +607,6 @@ config MTD_PCMCIA
cards are usually around 4-16MiB in size. This does not include
Compact Flash cards which are treated as IDE devices.
-config MTD_PCMCIA_ANONYMOUS
- bool "Use PCMCIA MTD drivers for anonymous PCMCIA cards"
- depends on MTD_PCMCIA
- default N
- help
- If this option is enabled, PCMCIA cards which do not report
- anything about themselves are assumed to be MTD cards.
-
- If unsure, say N.
-
config MTD_UCLINUX
tristate "Generic uClinux RAM/ROM filesystem support"
depends on MTD_PARTITIONS && !MMU
diff --git a/trunk/drivers/mtd/maps/pcmciamtd.c b/trunk/drivers/mtd/maps/pcmciamtd.c
index c2655a817e3d..e37b4c1976e5 100644
--- a/trunk/drivers/mtd/maps/pcmciamtd.c
+++ b/trunk/drivers/mtd/maps/pcmciamtd.c
@@ -818,32 +818,6 @@ static dev_link_t *pcmciamtd_attach(void)
return link;
}
-static struct pcmcia_device_id pcmciamtd_ids[] = {
- PCMCIA_DEVICE_FUNC_ID(1),
- PCMCIA_DEVICE_PROD_ID123("IO DATA", "PCS-2M", "2MB SRAM", 0x547e66dc, 0x1fed36cd, 0x36eadd21),
- PCMCIA_DEVICE_PROD_ID12("IBM", "2MB SRAM", 0xb569a6e5, 0x36eadd21),
- PCMCIA_DEVICE_PROD_ID12("IBM", "4MB FLASH", 0xb569a6e5, 0x8bc54d2a),
- PCMCIA_DEVICE_PROD_ID12("IBM", "8MB FLASH", 0xb569a6e5, 0x6df1be3e),
- PCMCIA_DEVICE_PROD_ID12("Intel", "S2E20SW", 0x816cc815, 0xd14c9dcf),
- PCMCIA_DEVICE_PROD_ID12("Intel", "S2E8 SW", 0x816cc815, 0xa2d7dedb),
- PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-02 ", 0x40ade711, 0x145cea5c),
- PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-04 ", 0x40ade711, 0x42064dda),
- PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-20 ", 0x40ade711, 0x25ee5cb0),
- PCMCIA_DEVICE_PROD_ID12("intel", "VALUE SERIES 100 ", 0x40ade711, 0xdf8506d8),
- PCMCIA_DEVICE_PROD_ID12("KINGMAX TECHNOLOGY INC.", "SRAM 256K Bytes", 0x54d0c69c, 0xad12c29c),
- PCMCIA_DEVICE_PROD_ID12("Maxtor", "MAXFL MobileMax Flash Memory Card", 0xb68968c8, 0x2dfb47b0),
- PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB101EN20", 0xf9876baf, 0xad0b207b),
- PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB513EN20", 0xf9876baf, 0xe8d884ad),
- PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-3000", 0x05ddca47, 0xe7d67bca),
- PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-4100", 0x05ddca47, 0x7bc32944),
- /* the following was commented out in pcmcia-cs-3.2.7 */
- /* PCMCIA_DEVICE_PROD_ID12("RATOC Systems,Inc.", "SmartMedia ADAPTER PC Card", 0xf4a2fefe, 0x5885b2ae), */
-#ifdef CONFIG_MTD_PCMCIA_ANONYMOUS
- { .match_flags = PCMCIA_DEV_ID_MATCH_ANONYMOUS, },
-#endif
- PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, pcmciamtd_ids);
static struct pcmcia_driver pcmciamtd_driver = {
.drv = {
@@ -851,8 +825,7 @@ static struct pcmcia_driver pcmciamtd_driver = {
},
.attach = pcmciamtd_attach,
.detach = pcmciamtd_detach,
- .owner = THIS_MODULE,
- .id_table = pcmciamtd_ids,
+ .owner = THIS_MODULE
};
diff --git a/trunk/drivers/net/3c523.c b/trunk/drivers/net/3c523.c
index 9e1fe2e0478c..1247a25f1093 100644
--- a/trunk/drivers/net/3c523.c
+++ b/trunk/drivers/net/3c523.c
@@ -1274,7 +1274,6 @@ module_param_array(irq, int, NULL, 0);
module_param_array(io, int, NULL, 0);
MODULE_PARM_DESC(io, "EtherLink/MC I/O base address(es)");
MODULE_PARM_DESC(irq, "EtherLink/MC IRQ number(s)");
-MODULE_LICENSE("GPL");
int init_module(void)
{
diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig
index 2b55687f6ee9..47e158fa5aac 100644
--- a/trunk/drivers/net/Kconfig
+++ b/trunk/drivers/net/Kconfig
@@ -1320,7 +1320,7 @@ config FORCEDETH
config CS89x0
tristate "CS89x0 support"
- depends on (NET_PCI && (ISA || ARCH_IXDP2X01)) || ARCH_PNX0105
+ depends on NET_PCI && (ISA || ARCH_IXDP2X01)
---help---
Support for CS89x0 chipset based Ethernet cards. If you have a
network (Ethernet) card of this type, say Y and read the
diff --git a/trunk/drivers/net/b44.c b/trunk/drivers/net/b44.c
index f1bd45e3da31..3fe8ba992c38 100644
--- a/trunk/drivers/net/b44.c
+++ b/trunk/drivers/net/b44.c
@@ -1285,9 +1285,6 @@ static int b44_open(struct net_device *dev)
b44_init_hw(bp);
bp->flags |= B44_FLAG_INIT_COMPLETE;
- netif_carrier_off(dev);
- b44_check_phy(bp);
-
spin_unlock_irq(&bp->lock);
init_timer(&bp->timer);
diff --git a/trunk/drivers/net/cs89x0.c b/trunk/drivers/net/cs89x0.c
index b96d6fb1929e..25e4495de79e 100644
--- a/trunk/drivers/net/cs89x0.c
+++ b/trunk/drivers/net/cs89x0.c
@@ -174,13 +174,6 @@ static unsigned int cs8900_irq_map[] = {1,0,0,0};
#include
static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0};
static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
-#elif defined(CONFIG_ARCH_PNX0105)
-#include
-#include
-#define CIRRUS_DEFAULT_BASE IO_ADDRESS(EXT_STATIC2_s0_BASE + 0x200000) /* = Physical address 0x48200000 */
-#define CIRRUS_DEFAULT_IRQ VH_INTC_INT_NUM_CASCADED_INTERRUPT_1 /* Event inputs bank 1 - ID 35/bit 3 */
-static unsigned int netcard_portlist[] __initdata = {CIRRUS_DEFAULT_BASE, 0};
-static unsigned int cs8900_irq_map[] = {CIRRUS_DEFAULT_IRQ, 0, 0, 0};
#else
static unsigned int netcard_portlist[] __initdata =
{ 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
@@ -438,30 +431,6 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
#endif
}
-#ifdef CONFIG_ARCH_PNX0105
- initialize_ebi();
-
- /* Map GPIO registers for the pins connected to the CS8900a. */
- if (map_cirrus_gpio() < 0)
- return -ENODEV;
-
- reset_cirrus();
-
- /* Map event-router registers. */
- if (map_event_router() < 0)
- return -ENODEV;
-
- enable_cirrus_irq();
-
- unmap_cirrus_gpio();
- unmap_event_router();
-
- dev->base_addr = ioaddr;
-
- for (i = 0 ; i < 3 ; i++)
- readreg(dev, 0);
-#endif
-
/* Grab the region so we can find another board if autoIRQ fails. */
/* WTF is going on here? */
if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) {
@@ -703,7 +672,7 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
} else {
i = lp->isa_config & INT_NO_MASK;
if (lp->chip_type == CS8900) {
-#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105)
+#ifdef CONFIG_ARCH_IXDP2X01
i = cs8900_irq_map[0];
#else
/* Translate the IRQ using the IRQ mapping table. */
@@ -1176,7 +1145,7 @@ net_open(struct net_device *dev)
int i;
int ret;
-#if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX0105) /* uses irq#1, so this won't work */
+#ifndef CONFIG_SH_HICOSH4 /* uses irq#1, so this won't work */
if (dev->irq < 2) {
/* Allow interrupts to be generated by the chip */
/* Cirrus' release had this: */
@@ -1207,7 +1176,7 @@ net_open(struct net_device *dev)
else
#endif
{
-#if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX0105)
+#ifndef CONFIG_ARCH_IXDP2X01
if (((1 << dev->irq) & lp->irq_map) == 0) {
printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
dev->name, dev->irq, lp->irq_map);
@@ -1292,9 +1261,6 @@ net_open(struct net_device *dev)
case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break;
default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2);
}
-#ifdef CONFIG_ARCH_PNX0105
- result = A_CNF_10B_T;
-#endif
if (!result) {
printk(KERN_ERR "%s: EEPROM is configured for unavailable media\n", dev->name);
release_irq:
diff --git a/trunk/drivers/net/cs89x0.h b/trunk/drivers/net/cs89x0.h
index bd3ad8e6cce9..b0ef7ad2baad 100644
--- a/trunk/drivers/net/cs89x0.h
+++ b/trunk/drivers/net/cs89x0.h
@@ -16,7 +16,7 @@
#include
-#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105)
+#ifdef CONFIG_ARCH_IXDP2X01
/* IXDP2401/IXDP2801 uses dword-aligned register addressing */
#define CS89x0_PORT(reg) ((reg) * 2)
#else
diff --git a/trunk/drivers/net/e100.c b/trunk/drivers/net/e100.c
index 1e56c8eea35f..cfaa6b2bf345 100644
--- a/trunk/drivers/net/e100.c
+++ b/trunk/drivers/net/e100.c
@@ -1093,16 +1093,11 @@ static int e100_phy_init(struct nic *nic)
}
if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
- (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000))) {
- /* enable/disable MDI/MDI-X auto-switching.
- MDI/MDI-X auto-switching is disabled for 82551ER/QM chips */
- if((nic->mac == mac_82551_E) || (nic->mac == mac_82551_F) ||
- (nic->mac == mac_82551_10) || (nic->mii.force_media) ||
- !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))
- mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, 0);
- else
- mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, NCONFIG_AUTO_SWITCH);
- }
+ (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) &&
+ (nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled)))
+ /* enable/disable MDI/MDI-X auto-switching */
+ mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG,
+ nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH);
return 0;
}
@@ -1671,10 +1666,8 @@ static irqreturn_t e100_intr(int irq, void *dev_id, struct pt_regs *regs)
if(stat_ack & stat_ack_rnr)
nic->ru_running = RU_SUSPENDED;
- if(likely(netif_rx_schedule_prep(netdev))) {
- e100_disable_irq(nic);
- __netif_rx_schedule(netdev);
- }
+ e100_disable_irq(nic);
+ netif_rx_schedule(netdev);
return IRQ_HANDLED;
}
@@ -2342,11 +2335,11 @@ static int __devinit e100_probe(struct pci_dev *pdev,
goto err_out_iounmap;
}
+ e100_phy_init(nic);
+
if((err = e100_eeprom_load(nic)))
goto err_out_free;
- e100_phy_init(nic);
-
memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN);
if(!is_valid_ether_addr(netdev->dev_addr)) {
DPRINTK(PROBE, ERR, "Invalid MAC address from "
diff --git a/trunk/drivers/net/e1000/e1000.h b/trunk/drivers/net/e1000/e1000.h
index 092757bc721f..af1e82c5b808 100644
--- a/trunk/drivers/net/e1000/e1000.h
+++ b/trunk/drivers/net/e1000/e1000.h
@@ -140,7 +140,7 @@ struct e1000_adapter;
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
#define AUTO_ALL_MODES 0
-#define E1000_EEPROM_82544_APM 0x0004
+#define E1000_EEPROM_82544_APM 0x0400
#define E1000_EEPROM_APME 0x0400
#ifndef E1000_MASTER_SLAVE
@@ -159,7 +159,7 @@ struct e1000_adapter;
* so a DMA handle can be stored along with the buffer */
struct e1000_buffer {
struct sk_buff *skb;
- dma_addr_t dma;
+ uint64_t dma;
unsigned long time_stamp;
uint16_t length;
uint16_t next_to_watch;
diff --git a/trunk/drivers/net/e1000/e1000_ethtool.c b/trunk/drivers/net/e1000/e1000_ethtool.c
index f133ff0b0b94..237247f74df4 100644
--- a/trunk/drivers/net/e1000/e1000_ethtool.c
+++ b/trunk/drivers/net/e1000/e1000_ethtool.c
@@ -105,7 +105,7 @@ static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
static int
e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
struct e1000_hw *hw = &adapter->hw;
if(hw->media_type == e1000_media_type_copper) {
@@ -141,9 +141,9 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
SUPPORTED_FIBRE |
SUPPORTED_Autoneg);
- ecmd->advertising = (ADVERTISED_1000baseT_Full |
- ADVERTISED_FIBRE |
- ADVERTISED_Autoneg);
+ ecmd->advertising = (SUPPORTED_1000baseT_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Autoneg);
ecmd->port = PORT_FIBRE;
@@ -179,24 +179,13 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
static int
e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
struct e1000_hw *hw = &adapter->hw;
if(ecmd->autoneg == AUTONEG_ENABLE) {
hw->autoneg = 1;
- if(hw->media_type == e1000_media_type_fiber)
- hw->autoneg_advertised = ADVERTISED_1000baseT_Full |
- ADVERTISED_FIBRE |
- ADVERTISED_Autoneg;
- else
- hw->autoneg_advertised = ADVERTISED_10baseT_Half |
- ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Half |
- ADVERTISED_100baseT_Full |
- ADVERTISED_1000baseT_Full|
- ADVERTISED_Autoneg |
- ADVERTISED_TP;
- ecmd->advertising = hw->autoneg_advertised;
+ hw->autoneg_advertised = 0x002F;
+ ecmd->advertising = 0x002F;
} else
if(e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex))
return -EINVAL;
@@ -217,7 +206,7 @@ static void
e1000_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
struct e1000_hw *hw = &adapter->hw;
pause->autoneg =
@@ -237,7 +226,7 @@ static int
e1000_set_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
struct e1000_hw *hw = &adapter->hw;
adapter->fc_autoneg = pause->autoneg;
@@ -270,14 +259,14 @@ e1000_set_pauseparam(struct net_device *netdev,
static uint32_t
e1000_get_rx_csum(struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
return adapter->rx_csum;
}
static int
e1000_set_rx_csum(struct net_device *netdev, uint32_t data)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
adapter->rx_csum = data;
if(netif_running(netdev)) {
@@ -297,7 +286,7 @@ e1000_get_tx_csum(struct net_device *netdev)
static int
e1000_set_tx_csum(struct net_device *netdev, uint32_t data)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
if(adapter->hw.mac_type < e1000_82543) {
if (!data)
@@ -317,8 +306,8 @@ e1000_set_tx_csum(struct net_device *netdev, uint32_t data)
static int
e1000_set_tso(struct net_device *netdev, uint32_t data)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
- if((adapter->hw.mac_type < e1000_82544) ||
+ struct e1000_adapter *adapter = netdev->priv;
+ if ((adapter->hw.mac_type < e1000_82544) ||
(adapter->hw.mac_type == e1000_82547))
return data ? -EINVAL : 0;
@@ -333,14 +322,14 @@ e1000_set_tso(struct net_device *netdev, uint32_t data)
static uint32_t
e1000_get_msglevel(struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
return adapter->msg_enable;
}
static void
e1000_set_msglevel(struct net_device *netdev, uint32_t data)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
adapter->msg_enable = data;
}
@@ -355,7 +344,7 @@ static void
e1000_get_regs(struct net_device *netdev,
struct ethtool_regs *regs, void *p)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
struct e1000_hw *hw = &adapter->hw;
uint32_t *regs_buff = p;
uint16_t phy_data;
@@ -443,7 +432,7 @@ e1000_get_regs(struct net_device *netdev,
static int
e1000_get_eeprom_len(struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
return adapter->hw.eeprom.word_size * 2;
}
@@ -451,7 +440,7 @@ static int
e1000_get_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, uint8_t *bytes)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
struct e1000_hw *hw = &adapter->hw;
uint16_t *eeprom_buff;
int first_word, last_word;
@@ -497,7 +486,7 @@ static int
e1000_set_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, uint8_t *bytes)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
struct e1000_hw *hw = &adapter->hw;
uint16_t *eeprom_buff;
void *ptr;
@@ -558,7 +547,7 @@ static void
e1000_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
strncpy(drvinfo->driver, e1000_driver_name, 32);
strncpy(drvinfo->version, e1000_driver_version, 32);
@@ -574,7 +563,7 @@ static void
e1000_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
e1000_mac_type mac_type = adapter->hw.mac_type;
struct e1000_desc_ring *txdr = &adapter->tx_ring;
struct e1000_desc_ring *rxdr = &adapter->rx_ring;
@@ -595,7 +584,7 @@ static int
e1000_set_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
e1000_mac_type mac_type = adapter->hw.mac_type;
struct e1000_desc_ring *txdr = &adapter->tx_ring;
struct e1000_desc_ring *rxdr = &adapter->rx_ring;
@@ -662,9 +651,6 @@ e1000_set_ringparam(struct net_device *netdev,
E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \
value = E1000_READ_REG(&adapter->hw, R); \
if(value != (test[pat] & W & M)) { \
- DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " \
- "0x%08X expected 0x%08X\n", \
- E1000_##R, value, (test[pat] & W & M)); \
*data = (adapter->hw.mac_type < e1000_82543) ? \
E1000_82542_##R : E1000_##R; \
return 1; \
@@ -677,9 +663,7 @@ e1000_set_ringparam(struct net_device *netdev,
uint32_t value; \
E1000_WRITE_REG(&adapter->hw, R, W & M); \
value = E1000_READ_REG(&adapter->hw, R); \
- if((W & M) != (value & M)) { \
- DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\
- "expected 0x%08X\n", E1000_##R, (value & M), (W & M)); \
+ if ((W & M) != (value & M)) { \
*data = (adapter->hw.mac_type < e1000_82543) ? \
E1000_82542_##R : E1000_##R; \
return 1; \
@@ -689,33 +673,18 @@ e1000_set_ringparam(struct net_device *netdev,
static int
e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
{
- uint32_t value, before, after;
- uint32_t i, toggle;
+ uint32_t value;
+ uint32_t i;
/* The status register is Read Only, so a write should fail.
* Some bits that get toggled are ignored.
*/
- switch (adapter->hw.mac_type) {
- case e1000_82573:
- toggle = 0x7FFFF033;
- break;
- default:
- toggle = 0xFFFFF833;
- break;
- }
-
- before = E1000_READ_REG(&adapter->hw, STATUS);
- value = (E1000_READ_REG(&adapter->hw, STATUS) & toggle);
- E1000_WRITE_REG(&adapter->hw, STATUS, toggle);
- after = E1000_READ_REG(&adapter->hw, STATUS) & toggle;
- if(value != after) {
- DPRINTK(DRV, ERR, "failed STATUS register test got: "
- "0x%08X expected: 0x%08X\n", after, value);
+ value = (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833));
+ E1000_WRITE_REG(&adapter->hw, STATUS, (0xFFFFFFFF));
+ if(value != (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833))) {
*data = 1;
return 1;
}
- /* restore previous status */
- E1000_WRITE_REG(&adapter->hw, STATUS, before);
REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);
@@ -797,7 +766,7 @@ e1000_test_intr(int irq,
struct pt_regs *regs)
{
struct net_device *netdev = (struct net_device *) data;
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
adapter->test_icr |= E1000_READ_REG(&adapter->hw, ICR);
@@ -1245,7 +1214,6 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
case e1000_82541_rev_2:
case e1000_82547:
case e1000_82547_rev_2:
- case e1000_82573:
return e1000_integrated_phy_loopback(adapter);
break;
@@ -1454,7 +1422,7 @@ static void
e1000_diag_test(struct net_device *netdev,
struct ethtool_test *eth_test, uint64_t *data)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
boolean_t if_running = netif_running(netdev);
if(eth_test->flags == ETH_TEST_FL_OFFLINE) {
@@ -1514,7 +1482,7 @@ e1000_diag_test(struct net_device *netdev,
static void
e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
struct e1000_hw *hw = &adapter->hw;
switch(adapter->hw.device_id) {
@@ -1559,7 +1527,7 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
static int
e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
struct e1000_hw *hw = &adapter->hw;
switch(adapter->hw.device_id) {
@@ -1620,31 +1588,22 @@ e1000_led_blink_callback(unsigned long data)
static int
e1000_phys_id(struct net_device *netdev, uint32_t data)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
- if(adapter->hw.mac_type < e1000_82573) {
- if(!adapter->blink_timer.function) {
- init_timer(&adapter->blink_timer);
- adapter->blink_timer.function = e1000_led_blink_callback;
- adapter->blink_timer.data = (unsigned long) adapter;
- }
- e1000_setup_led(&adapter->hw);
- mod_timer(&adapter->blink_timer, jiffies);
- msleep_interruptible(data * 1000);
- del_timer_sync(&adapter->blink_timer);
- }
- else {
- E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
- E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK |
- (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
- (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED1_MODE_SHIFT) |
- (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT)));
- msleep_interruptible(data * 1000);
+ if(!adapter->blink_timer.function) {
+ init_timer(&adapter->blink_timer);
+ adapter->blink_timer.function = e1000_led_blink_callback;
+ adapter->blink_timer.data = (unsigned long) adapter;
}
+ e1000_setup_led(&adapter->hw);
+ mod_timer(&adapter->blink_timer, jiffies);
+
+ msleep_interruptible(data * 1000);
+ del_timer_sync(&adapter->blink_timer);
e1000_led_off(&adapter->hw);
clear_bit(E1000_LED_ON, &adapter->led_status);
e1000_cleanup_led(&adapter->hw);
@@ -1655,7 +1614,7 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
static int
e1000_nway_reset(struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
if(netif_running(netdev)) {
e1000_down(adapter);
e1000_up(adapter);
@@ -1673,7 +1632,7 @@ static void
e1000_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, uint64_t *data)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
int i;
e1000_update_stats(adapter);
diff --git a/trunk/drivers/net/e1000/e1000_hw.c b/trunk/drivers/net/e1000/e1000_hw.c
index 045f5426ab9a..723589b28be5 100644
--- a/trunk/drivers/net/e1000/e1000_hw.c
+++ b/trunk/drivers/net/e1000/e1000_hw.c
@@ -354,27 +354,18 @@ e1000_set_media_type(struct e1000_hw *hw)
hw->media_type = e1000_media_type_internal_serdes;
break;
default:
- switch (hw->mac_type) {
- case e1000_82542_rev2_0:
- case e1000_82542_rev2_1:
- hw->media_type = e1000_media_type_fiber;
- break;
- case e1000_82573:
- /* The STATUS_TBIMODE bit is reserved or reused for the this
- * device.
- */
- hw->media_type = e1000_media_type_copper;
- break;
- default:
+ if(hw->mac_type >= e1000_82543) {
status = E1000_READ_REG(hw, STATUS);
- if (status & E1000_STATUS_TBIMODE) {
+ if(status & E1000_STATUS_TBIMODE) {
hw->media_type = e1000_media_type_fiber;
/* tbi_compatibility not valid on fiber */
hw->tbi_compatibility_en = FALSE;
} else {
hw->media_type = e1000_media_type_copper;
}
- break;
+ } else {
+ /* This is an 82542 (fiber only) */
+ hw->media_type = e1000_media_type_fiber;
}
}
}
@@ -1198,9 +1189,9 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw)
ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
if(ret_val)
return ret_val;
- }
+ }
- return E1000_SUCCESS;
+ return E1000_SUCCESS;
}
diff --git a/trunk/drivers/net/e1000/e1000_hw.h b/trunk/drivers/net/e1000/e1000_hw.h
index 93e9f8788751..a0263ee96c6b 100644
--- a/trunk/drivers/net/e1000/e1000_hw.h
+++ b/trunk/drivers/net/e1000/e1000_hw.h
@@ -66,7 +66,6 @@ typedef enum {
e1000_eeprom_spi,
e1000_eeprom_microwire,
e1000_eeprom_flash,
- e1000_eeprom_none, /* No NVM support */
e1000_num_eeprom_types
} e1000_eeprom_type;
diff --git a/trunk/drivers/net/e1000/e1000_main.c b/trunk/drivers/net/e1000/e1000_main.c
index cb7f051a60ad..137226d98d47 100644
--- a/trunk/drivers/net/e1000/e1000_main.c
+++ b/trunk/drivers/net/e1000/e1000_main.c
@@ -29,8 +29,6 @@
#include "e1000.h"
/* Change Log
- * 6.0.58 4/20/05
- * o Accepted ethtool cleanup patch from Stephen Hemminger
* 6.0.44+ 2/15/05
* o applied Anton's patch to resolve tx hang in hardware
* o Applied Andrew Mortons patch - e1000 stops working after resume
@@ -43,9 +41,9 @@ char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-#define DRV_VERSION "6.0.60-k2"DRIVERNAPI
+#define DRV_VERSION "6.0.54-k2"DRIVERNAPI
char e1000_driver_version[] = DRV_VERSION;
-char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
+char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation.";
/* e1000_pci_tbl - PCI Device ID Table
*
@@ -519,7 +517,7 @@ e1000_probe(struct pci_dev *pdev,
SET_NETDEV_DEV(netdev, &pdev->dev);
pci_set_drvdata(pdev, netdev);
- adapter = netdev_priv(netdev);
+ adapter = netdev->priv;
adapter->netdev = netdev;
adapter->pdev = pdev;
adapter->hw.back = adapter;
@@ -740,7 +738,7 @@ static void __devexit
e1000_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
uint32_t manc, swsm;
flush_scheduled_work();
@@ -873,7 +871,7 @@ e1000_sw_init(struct e1000_adapter *adapter)
static int
e1000_open(struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
int err;
/* allocate transmit descriptors */
@@ -921,7 +919,7 @@ e1000_open(struct net_device *netdev)
static int
e1000_close(struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
e1000_down(adapter);
@@ -1601,7 +1599,7 @@ e1000_leave_82542_rst(struct e1000_adapter *adapter)
static int
e1000_set_mac(struct net_device *netdev, void *p)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
struct sockaddr *addr = p;
if(!is_valid_ether_addr(addr->sa_data))
@@ -1636,7 +1634,7 @@ e1000_set_mac(struct net_device *netdev, void *p)
static void
e1000_set_multi(struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
struct e1000_hw *hw = &adapter->hw;
struct dev_mc_list *mc_ptr;
unsigned long flags;
@@ -2215,7 +2213,7 @@ e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
static int
e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
unsigned int tx_flags = 0;
@@ -2346,7 +2344,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
static void
e1000_tx_timeout(struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
/* Do the reset outside of interrupt context */
schedule_work(&adapter->tx_timeout_task);
@@ -2355,7 +2353,7 @@ e1000_tx_timeout(struct net_device *netdev)
static void
e1000_tx_timeout_task(struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
e1000_down(adapter);
e1000_up(adapter);
@@ -2372,7 +2370,7 @@ e1000_tx_timeout_task(struct net_device *netdev)
static struct net_device_stats *
e1000_get_stats(struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
e1000_update_stats(adapter);
return &adapter->net_stats;
@@ -2389,7 +2387,7 @@ e1000_get_stats(struct net_device *netdev)
static int
e1000_change_mtu(struct net_device *netdev, int new_mtu)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
@@ -2600,7 +2598,7 @@ static irqreturn_t
e1000_intr(int irq, void *data, struct pt_regs *regs)
{
struct net_device *netdev = data;
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
struct e1000_hw *hw = &adapter->hw;
uint32_t icr = E1000_READ_REG(hw, ICR);
#ifndef CONFIG_E1000_NAPI
@@ -2663,7 +2661,7 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
static int
e1000_clean(struct net_device *netdev, int *budget)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
int work_to_do = min(*budget, netdev->quota);
int tx_cleaned;
int work_done = 0;
@@ -2674,8 +2672,8 @@ e1000_clean(struct net_device *netdev, int *budget)
*budget -= work_done;
netdev->quota -= work_done;
+ /* If no Tx and no Rx work done, exit the polling mode */
if ((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
- /* If no Tx and not enough Rx work done, exit the polling mode */
netif_rx_complete(netdev);
e1000_irq_enable(adapter);
return 0;
@@ -2771,13 +2769,13 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
i = tx_ring->next_to_clean;
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = E1000_TX_DESC(*tx_ring, eop);
- DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n"
+ DPRINTK(TX_ERR, ERR, "Detected Tx Unit Hang\n"
" TDH <%x>\n"
" TDT <%x>\n"
" next_to_use <%x>\n"
" next_to_clean <%x>\n"
"buffer_info[next_to_clean]\n"
- " dma <%zx>\n"
+ " dma <%llx>\n"
" time_stamp <%lx>\n"
" next_to_watch <%x>\n"
" jiffies <%lx>\n"
@@ -2996,7 +2994,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
i = rx_ring->next_to_clean;
rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
- staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
+ staterr = rx_desc->wb.middle.status_error;
while(staterr & E1000_RXD_STAT_DD) {
buffer_info = &rx_ring->buffer_info[i];
@@ -3067,16 +3065,16 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
#ifdef CONFIG_E1000_NAPI
if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
- le16_to_cpu(rx_desc->wb.middle.vlan) &
- E1000_RXD_SPC_VLAN_MASK);
+ le16_to_cpu(rx_desc->wb.middle.vlan &
+ E1000_RXD_SPC_VLAN_MASK));
} else {
netif_receive_skb(skb);
}
#else /* CONFIG_E1000_NAPI */
if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
vlan_hwaccel_rx(skb, adapter->vlgrp,
- le16_to_cpu(rx_desc->wb.middle.vlan) &
- E1000_RXD_SPC_VLAN_MASK);
+ le16_to_cpu(rx_desc->wb.middle.vlan &
+ E1000_RXD_SPC_VLAN_MASK));
} else {
netif_rx(skb);
}
@@ -3089,7 +3087,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
if(unlikely(++i == rx_ring->count)) i = 0;
rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
- staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
+ staterr = rx_desc->wb.middle.status_error;
}
rx_ring->next_to_clean = i;
adapter->alloc_rx_buf(adapter);
@@ -3373,12 +3371,11 @@ e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
static int
e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
struct mii_ioctl_data *data = if_mii(ifr);
int retval;
uint16_t mii_reg;
uint16_t spddplx;
- unsigned long flags;
if(adapter->hw.media_type != e1000_media_type_copper)
return -EOPNOTSUPP;
@@ -3388,29 +3385,22 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
data->phy_id = adapter->hw.phy_addr;
break;
case SIOCGMIIREG:
- if(!capable(CAP_NET_ADMIN))
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
- spin_lock_irqsave(&adapter->stats_lock, flags);
- if(e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
- &data->val_out)) {
- spin_unlock_irqrestore(&adapter->stats_lock, flags);
+ if (e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
+ &data->val_out))
return -EIO;
- }
- spin_unlock_irqrestore(&adapter->stats_lock, flags);
break;
case SIOCSMIIREG:
- if(!capable(CAP_NET_ADMIN))
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
- if(data->reg_num & ~(0x1F))
+ if (data->reg_num & ~(0x1F))
return -EFAULT;
mii_reg = data->val_in;
- spin_lock_irqsave(&adapter->stats_lock, flags);
- if(e1000_write_phy_reg(&adapter->hw, data->reg_num,
- mii_reg)) {
- spin_unlock_irqrestore(&adapter->stats_lock, flags);
+ if (e1000_write_phy_reg(&adapter->hw, data->reg_num,
+ mii_reg))
return -EIO;
- }
- if(adapter->hw.phy_type == e1000_phy_m88) {
+ if (adapter->hw.phy_type == e1000_phy_m88) {
switch (data->reg_num) {
case PHY_CTRL:
if(mii_reg & MII_CR_POWER_DOWN)
@@ -3430,12 +3420,8 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
HALF_DUPLEX;
retval = e1000_set_spd_dplx(adapter,
spddplx);
- if(retval) {
- spin_unlock_irqrestore(
- &adapter->stats_lock,
- flags);
+ if(retval)
return retval;
- }
}
if(netif_running(adapter->netdev)) {
e1000_down(adapter);
@@ -3445,11 +3431,8 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
break;
case M88E1000_PHY_SPEC_CTRL:
case M88E1000_EXT_PHY_SPEC_CTRL:
- if(e1000_phy_reset(&adapter->hw)) {
- spin_unlock_irqrestore(
- &adapter->stats_lock, flags);
+ if (e1000_phy_reset(&adapter->hw))
return -EIO;
- }
break;
}
} else {
@@ -3465,7 +3448,6 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
break;
}
}
- spin_unlock_irqrestore(&adapter->stats_lock, flags);
break;
default:
return -EOPNOTSUPP;
@@ -3522,7 +3504,7 @@ e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value)
static void
e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
uint32_t ctrl, rctl;
e1000_irq_disable(adapter);
@@ -3562,7 +3544,7 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
static void
e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
uint32_t vfta, index;
if((adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
@@ -3578,7 +3560,7 @@ e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
static void
e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
uint32_t vfta, index;
e1000_irq_disable(adapter);
@@ -3619,13 +3601,6 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
{
adapter->hw.autoneg = 0;
- /* Fiber NICs only allow 1000 gbps Full duplex */
- if((adapter->hw.media_type == e1000_media_type_fiber) &&
- spddplx != (SPEED_1000 + DUPLEX_FULL)) {
- DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n");
- return -EINVAL;
- }
-
switch(spddplx) {
case SPEED_10 + DUPLEX_HALF:
adapter->hw.forced_speed_duplex = e1000_10_half;
@@ -3672,7 +3647,7 @@ static int
e1000_suspend(struct pci_dev *pdev, uint32_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm;
uint32_t wufc = adapter->wol;
@@ -3765,12 +3740,12 @@ static int
e1000_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct e1000_adapter *adapter = netdev_priv(netdev);
- uint32_t manc, ret_val, swsm;
+ struct e1000_adapter *adapter = netdev->priv;
+ uint32_t manc, ret, swsm;
pci_set_power_state(pdev, 0);
pci_restore_state(pdev);
- ret_val = pci_enable_device(pdev);
+ ret = pci_enable_device(pdev);
pci_set_master(pdev);
pci_enable_wake(pdev, 3, 0);
@@ -3813,7 +3788,7 @@ e1000_resume(struct pci_dev *pdev)
static void
e1000_netpoll(struct net_device *netdev)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = netdev->priv;
disable_irq(adapter->pdev->irq);
e1000_intr(adapter->pdev->irq, netdev, NULL);
enable_irq(adapter->pdev->irq);
diff --git a/trunk/drivers/net/forcedeth.c b/trunk/drivers/net/forcedeth.c
index 64f0f697c958..4ebcd052e150 100644
--- a/trunk/drivers/net/forcedeth.c
+++ b/trunk/drivers/net/forcedeth.c
@@ -82,9 +82,6 @@
* 0.31: 14 Nov 2004: ethtool support for getting/setting link
* capabilities.
* 0.32: 16 Apr 2005: RX_ERROR4 handling added.
- * 0.33: 16 May 2005: Support for MCP51 added.
- * 0.34: 18 Jun 2005: Add DEV_NEED_LINKTIMER to all nForce nics.
- * 0.35: 26 Jun 2005: Support for MCP55 added.
*
* Known bugs:
* We suspect that on some hardware no TX done interrupts are generated.
@@ -96,7 +93,7 @@
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
* superfluous timer interrupts from the nic.
*/
-#define FORCEDETH_VERSION "0.35"
+#define FORCEDETH_VERSION "0.32"
#define DRV_NAME "forcedeth"
#include
@@ -2008,9 +2005,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
/* handle different descriptor versions */
if (pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_1 ||
pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_2 ||
- pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_3 ||
- pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 ||
- pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_13)
+ pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_3)
np->desc_ver = DESC_VER_1;
else
np->desc_ver = DESC_VER_2;
@@ -2220,84 +2215,56 @@ static struct pci_device_id pci_tbl[] = {
.device = PCI_DEVICE_ID_NVIDIA_NVENET_4,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,
},
{ /* nForce3 Ethernet Controller */
.vendor = PCI_VENDOR_ID_NVIDIA,
.device = PCI_DEVICE_ID_NVIDIA_NVENET_5,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,
},
{ /* nForce3 Ethernet Controller */
.vendor = PCI_VENDOR_ID_NVIDIA,
.device = PCI_DEVICE_ID_NVIDIA_NVENET_6,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,
},
{ /* nForce3 Ethernet Controller */
.vendor = PCI_VENDOR_ID_NVIDIA,
.device = PCI_DEVICE_ID_NVIDIA_NVENET_7,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,
},
{ /* CK804 Ethernet Controller */
.vendor = PCI_VENDOR_ID_NVIDIA,
.device = PCI_DEVICE_ID_NVIDIA_NVENET_8,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,
},
{ /* CK804 Ethernet Controller */
.vendor = PCI_VENDOR_ID_NVIDIA,
.device = PCI_DEVICE_ID_NVIDIA_NVENET_9,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,
},
{ /* MCP04 Ethernet Controller */
.vendor = PCI_VENDOR_ID_NVIDIA,
.device = PCI_DEVICE_ID_NVIDIA_NVENET_10,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,
},
{ /* MCP04 Ethernet Controller */
.vendor = PCI_VENDOR_ID_NVIDIA,
.device = PCI_DEVICE_ID_NVIDIA_NVENET_11,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
- },
- { /* MCP51 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_12,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
- },
- { /* MCP51 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_13,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
- },
- { /* MCP55 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_14,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
- },
- { /* MCP55 Ethernet Controller */
- .vendor = PCI_VENDOR_ID_NVIDIA,
- .device = PCI_DEVICE_ID_NVIDIA_NVENET_15,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,
},
{0,},
};
diff --git a/trunk/drivers/net/gianfar.c b/trunk/drivers/net/gianfar.c
index 6518334b9280..b43b2b11aacd 100644
--- a/trunk/drivers/net/gianfar.c
+++ b/trunk/drivers/net/gianfar.c
@@ -1,4 +1,4 @@
-/*
+/*
* drivers/net/gianfar.c
*
* Gianfar Ethernet Driver
@@ -22,9 +22,10 @@
* B-V +1.62
*
* Theory of operation
- * This driver is designed for the non-CPM ethernet controllers
- * on the 85xx and 83xx family of integrated processors
- *
+ * This driver is designed for the Triple-speed Ethernet
+ * controllers on the Freescale 8540/8560 integrated processors,
+ * as well as the Fast Ethernet Controller on the 8540.
+ *
* The driver is initialized through platform_device. Structures which
* define the configuration needed by the board are defined in a
* board structure in arch/ppc/platforms (though I do not
@@ -38,12 +39,12 @@
*
* The Gianfar Ethernet Controller uses a ring of buffer
* descriptors. The beginning is indicated by a register
- * pointing to the physical address of the start of the ring.
- * The end is determined by a "wrap" bit being set in the
+ * pointing to the physical address of the start of the ring.
+ * The end is determined by a "wrap" bit being set in the
* last descriptor of the ring.
*
* When a packet is received, the RXF bit in the
- * IEVENT register is set, triggering an interrupt when the
+ * IEVENT register is set, triggering an interrupt when the
* corresponding bit in the IMASK register is also set (if
* interrupt coalescing is active, then the interrupt may not
* happen immediately, but will wait until either a set number
@@ -51,7 +52,7 @@
* interrupt handler will signal there is work to be done, and
* exit. Without NAPI, the packet(s) will be handled
* immediately. Both methods will start at the last known empty
- * descriptor, and process every subsequent descriptor until there
+ * descriptor, and process every subsequent descriptor until there
* are none left with data (NAPI will stop after a set number of
* packets to give time to other tasks, but will eventually
* process all the packets). The data arrives inside a
@@ -82,13 +83,9 @@
#include
#include
#include
-#include
#include
#include
#include
-#include
-#include
-#include
#include
#include
@@ -126,7 +123,7 @@ static int gfar_set_mac_address(struct net_device *dev);
static int gfar_change_mtu(struct net_device *dev, int new_mtu);
static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs);
static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void gfar_phy_change(void *data);
@@ -142,12 +139,9 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
#ifdef CONFIG_GFAR_NAPI
static int gfar_poll(struct net_device *dev, int *budget);
#endif
-int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
+static int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
static void gfar_phy_startup_timer(unsigned long data);
-static void gfar_vlan_rx_register(struct net_device *netdev,
- struct vlan_group *grp);
-static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
extern struct ethtool_ops gfar_ethtool_ops;
@@ -155,13 +149,6 @@ MODULE_AUTHOR("Freescale Semiconductor, Inc");
MODULE_DESCRIPTION("Gianfar Ethernet Driver");
MODULE_LICENSE("GPL");
-int gfar_uses_fcb(struct gfar_private *priv)
-{
- if (priv->vlan_enable || priv->rx_csum_enable)
- return 1;
- else
- return 0;
-}
static int gfar_probe(struct device *device)
{
u32 tempval;
@@ -172,6 +159,7 @@ static int gfar_probe(struct device *device)
struct resource *r;
int idx;
int err = 0;
+ int dev_ethtool_ops = 0;
einfo = (struct gianfar_platform_data *) pdev->dev.platform_data;
@@ -277,69 +265,15 @@ static int gfar_probe(struct device *device)
dev->mtu = 1500;
dev->set_multicast_list = gfar_set_multi;
- dev->ethtool_ops = &gfar_ethtool_ops;
-
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) {
- priv->rx_csum_enable = 1;
- dev->features |= NETIF_F_IP_CSUM;
- } else
- priv->rx_csum_enable = 0;
-
- priv->vlgrp = NULL;
+ /* Index into the array of possible ethtool
+ * ops to catch all 4 possibilities */
+ if((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) == 0)
+ dev_ethtool_ops += 1;
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
- dev->vlan_rx_register = gfar_vlan_rx_register;
- dev->vlan_rx_kill_vid = gfar_vlan_rx_kill_vid;
+ if((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE) == 0)
+ dev_ethtool_ops += 2;
- dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-
- priv->vlan_enable = 1;
- }
-
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) {
- priv->extended_hash = 1;
- priv->hash_width = 9;
-
- priv->hash_regs[0] = &priv->regs->igaddr0;
- priv->hash_regs[1] = &priv->regs->igaddr1;
- priv->hash_regs[2] = &priv->regs->igaddr2;
- priv->hash_regs[3] = &priv->regs->igaddr3;
- priv->hash_regs[4] = &priv->regs->igaddr4;
- priv->hash_regs[5] = &priv->regs->igaddr5;
- priv->hash_regs[6] = &priv->regs->igaddr6;
- priv->hash_regs[7] = &priv->regs->igaddr7;
- priv->hash_regs[8] = &priv->regs->gaddr0;
- priv->hash_regs[9] = &priv->regs->gaddr1;
- priv->hash_regs[10] = &priv->regs->gaddr2;
- priv->hash_regs[11] = &priv->regs->gaddr3;
- priv->hash_regs[12] = &priv->regs->gaddr4;
- priv->hash_regs[13] = &priv->regs->gaddr5;
- priv->hash_regs[14] = &priv->regs->gaddr6;
- priv->hash_regs[15] = &priv->regs->gaddr7;
-
- } else {
- priv->extended_hash = 0;
- priv->hash_width = 8;
-
- priv->hash_regs[0] = &priv->regs->gaddr0;
- priv->hash_regs[1] = &priv->regs->gaddr1;
- priv->hash_regs[2] = &priv->regs->gaddr2;
- priv->hash_regs[3] = &priv->regs->gaddr3;
- priv->hash_regs[4] = &priv->regs->gaddr4;
- priv->hash_regs[5] = &priv->regs->gaddr5;
- priv->hash_regs[6] = &priv->regs->gaddr6;
- priv->hash_regs[7] = &priv->regs->gaddr7;
- }
-
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_PADDING)
- priv->padding = DEFAULT_PADDING;
- else
- priv->padding = 0;
-
- dev->hard_header_len += priv->padding;
-
- if (dev->features & NETIF_F_IP_CSUM)
- dev->hard_header_len += GMAC_FCB_LEN;
+ dev->ethtool_ops = gfar_op_array[dev_ethtool_ops];
priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE;
#ifdef CONFIG_GFAR_BUFSTASH
@@ -355,9 +289,6 @@ static int gfar_probe(struct device *device)
priv->rxcount = DEFAULT_RXCOUNT;
priv->rxtime = DEFAULT_RXTIME;
- /* Enable most messages by default */
- priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1;
-
err = register_netdev(dev);
if (err) {
@@ -429,9 +360,8 @@ static int init_phy(struct net_device *dev)
GFP_KERNEL);
if(NULL == mii_info) {
- if (netif_msg_ifup(priv))
- printk(KERN_ERR "%s: Could not allocate mii_info\n",
- dev->name);
+ printk(KERN_ERR "%s: Could not allocate mii_info\n",
+ dev->name);
return -ENOMEM;
}
@@ -480,8 +410,7 @@ static int init_phy(struct net_device *dev)
curphy = get_phy_info(priv->mii_info);
if (curphy == NULL) {
- if (netif_msg_ifup(priv))
- printk(KERN_ERR "%s: No PHY found\n", dev->name);
+ printk(KERN_ERR "%s: No PHY found\n", dev->name);
err = -1;
goto no_phy;
}
@@ -492,7 +421,7 @@ static int init_phy(struct net_device *dev)
if(curphy->init) {
err = curphy->init(priv->mii_info);
- if (err)
+ if (err)
goto phy_init_fail;
}
@@ -517,14 +446,14 @@ static void init_registers(struct net_device *dev)
gfar_write(&priv->regs->imask, IMASK_INIT_CLEAR);
/* Init hash registers to zero */
- gfar_write(&priv->regs->igaddr0, 0);
- gfar_write(&priv->regs->igaddr1, 0);
- gfar_write(&priv->regs->igaddr2, 0);
- gfar_write(&priv->regs->igaddr3, 0);
- gfar_write(&priv->regs->igaddr4, 0);
- gfar_write(&priv->regs->igaddr5, 0);
- gfar_write(&priv->regs->igaddr6, 0);
- gfar_write(&priv->regs->igaddr7, 0);
+ gfar_write(&priv->regs->iaddr0, 0);
+ gfar_write(&priv->regs->iaddr1, 0);
+ gfar_write(&priv->regs->iaddr2, 0);
+ gfar_write(&priv->regs->iaddr3, 0);
+ gfar_write(&priv->regs->iaddr4, 0);
+ gfar_write(&priv->regs->iaddr5, 0);
+ gfar_write(&priv->regs->iaddr6, 0);
+ gfar_write(&priv->regs->iaddr7, 0);
gfar_write(&priv->regs->gaddr0, 0);
gfar_write(&priv->regs->gaddr1, 0);
@@ -535,6 +464,9 @@ static void init_registers(struct net_device *dev)
gfar_write(&priv->regs->gaddr6, 0);
gfar_write(&priv->regs->gaddr7, 0);
+ /* Zero out rctrl */
+ gfar_write(&priv->regs->rctrl, 0x00000000);
+
/* Zero out the rmon mib registers if it has them */
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
memset((void *) &(priv->regs->rmon), 0,
@@ -565,14 +497,20 @@ static void init_registers(struct net_device *dev)
gfar_write(&priv->regs->tbipa, TBIPA_VALUE);
}
-
-/* Halt the receive and transmit queues */
-void gfar_halt(struct net_device *dev)
+void stop_gfar(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
struct gfar *regs = priv->regs;
+ unsigned long flags;
u32 tempval;
+ /* Lock it down */
+ spin_lock_irqsave(&priv->lock, flags);
+
+ /* Tell the kernel the link is down */
+ priv->mii_info->link = 0;
+ adjust_link(dev);
+
/* Mask all interrupts */
gfar_write(®s->imask, IMASK_INIT_CLEAR);
@@ -595,29 +533,13 @@ void gfar_halt(struct net_device *dev)
tempval = gfar_read(®s->maccfg1);
tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN);
gfar_write(®s->maccfg1, tempval);
-}
-
-void stop_gfar(struct net_device *dev)
-{
- struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regs = priv->regs;
- unsigned long flags;
-
- /* Lock it down */
- spin_lock_irqsave(&priv->lock, flags);
-
- /* Tell the kernel the link is down */
- priv->mii_info->link = 0;
- adjust_link(dev);
-
- gfar_halt(dev);
if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
/* Clear any pending interrupts */
mii_clear_phy_interrupt(priv->mii_info);
/* Disable PHY Interrupts */
- mii_configure_phy_interrupt(priv->mii_info,
+ mii_configure_phy_interrupt(priv->mii_info,
MII_INTERRUPT_DISABLED);
}
@@ -644,7 +566,7 @@ void stop_gfar(struct net_device *dev)
sizeof(struct txbd8)*priv->tx_ring_size
+ sizeof(struct rxbd8)*priv->rx_ring_size,
priv->tx_bd_base,
- gfar_read(®s->tbase0));
+ gfar_read(®s->tbase));
}
/* If there are any tx skbs or rx skbs still around, free them.
@@ -698,34 +620,6 @@ void free_skb_resources(struct gfar_private *priv)
}
}
-void gfar_start(struct net_device *dev)
-{
- struct gfar_private *priv = netdev_priv(dev);
- struct gfar *regs = priv->regs;
- u32 tempval;
-
- /* Enable Rx and Tx in MACCFG1 */
- tempval = gfar_read(®s->maccfg1);
- tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
- gfar_write(®s->maccfg1, tempval);
-
- /* Initialize DMACTRL to have WWR and WOP */
- tempval = gfar_read(&priv->regs->dmactrl);
- tempval |= DMACTRL_INIT_SETTINGS;
- gfar_write(&priv->regs->dmactrl, tempval);
-
- /* Clear THLT, so that the DMA starts polling now */
- gfar_write(®s->tstat, TSTAT_CLEAR_THALT);
-
- /* Make sure we aren't stopped */
- tempval = gfar_read(&priv->regs->dmactrl);
- tempval &= ~(DMACTRL_GRS | DMACTRL_GTS);
- gfar_write(&priv->regs->dmactrl, tempval);
-
- /* Unmask the interrupts we look for */
- gfar_write(®s->imask, IMASK_DEFAULT);
-}
-
/* Bring the controller up and running */
int startup_gfar(struct net_device *dev)
{
@@ -736,34 +630,33 @@ int startup_gfar(struct net_device *dev)
int i;
struct gfar_private *priv = netdev_priv(dev);
struct gfar *regs = priv->regs;
+ u32 tempval;
int err = 0;
- u32 rctrl = 0;
gfar_write(®s->imask, IMASK_INIT_CLEAR);
/* Allocate memory for the buffer descriptors */
- vaddr = (unsigned long) dma_alloc_coherent(NULL,
+ vaddr = (unsigned long) dma_alloc_coherent(NULL,
sizeof (struct txbd8) * priv->tx_ring_size +
sizeof (struct rxbd8) * priv->rx_ring_size,
&addr, GFP_KERNEL);
if (vaddr == 0) {
- if (netif_msg_ifup(priv))
- printk(KERN_ERR "%s: Could not allocate buffer descriptors!\n",
- dev->name);
+ printk(KERN_ERR "%s: Could not allocate buffer descriptors!\n",
+ dev->name);
return -ENOMEM;
}
priv->tx_bd_base = (struct txbd8 *) vaddr;
/* enet DMA only understands physical addresses */
- gfar_write(®s->tbase0, addr);
+ gfar_write(®s->tbase, addr);
/* Start the rx descriptor ring where the tx ring leaves off */
addr = addr + sizeof (struct txbd8) * priv->tx_ring_size;
vaddr = vaddr + sizeof (struct txbd8) * priv->tx_ring_size;
priv->rx_bd_base = (struct rxbd8 *) vaddr;
- gfar_write(®s->rbase0, addr);
+ gfar_write(®s->rbase, addr);
/* Setup the skbuff rings */
priv->tx_skbuff =
@@ -771,9 +664,8 @@ int startup_gfar(struct net_device *dev)
priv->tx_ring_size, GFP_KERNEL);
if (priv->tx_skbuff == NULL) {
- if (netif_msg_ifup(priv))
- printk(KERN_ERR "%s: Could not allocate tx_skbuff\n",
- dev->name);
+ printk(KERN_ERR "%s: Could not allocate tx_skbuff\n",
+ dev->name);
err = -ENOMEM;
goto tx_skb_fail;
}
@@ -786,9 +678,8 @@ int startup_gfar(struct net_device *dev)
priv->rx_ring_size, GFP_KERNEL);
if (priv->rx_skbuff == NULL) {
- if (netif_msg_ifup(priv))
- printk(KERN_ERR "%s: Could not allocate rx_skbuff\n",
- dev->name);
+ printk(KERN_ERR "%s: Could not allocate rx_skbuff\n",
+ dev->name);
err = -ENOMEM;
goto rx_skb_fail;
}
@@ -835,13 +726,12 @@ int startup_gfar(struct net_device *dev)
/* If the device has multiple interrupts, register for
* them. Otherwise, only register for the one */
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
- /* Install our interrupt handlers for Error,
+ /* Install our interrupt handlers for Error,
* Transmit, and Receive */
if (request_irq(priv->interruptError, gfar_error,
0, "enet_error", dev) < 0) {
- if (netif_msg_intr(priv))
- printk(KERN_ERR "%s: Can't get IRQ %d\n",
- dev->name, priv->interruptError);
+ printk(KERN_ERR "%s: Can't get IRQ %d\n",
+ dev->name, priv->interruptError);
err = -1;
goto err_irq_fail;
@@ -849,9 +739,8 @@ int startup_gfar(struct net_device *dev)
if (request_irq(priv->interruptTransmit, gfar_transmit,
0, "enet_tx", dev) < 0) {
- if (netif_msg_intr(priv))
- printk(KERN_ERR "%s: Can't get IRQ %d\n",
- dev->name, priv->interruptTransmit);
+ printk(KERN_ERR "%s: Can't get IRQ %d\n",
+ dev->name, priv->interruptTransmit);
err = -1;
@@ -860,9 +749,8 @@ int startup_gfar(struct net_device *dev)
if (request_irq(priv->interruptReceive, gfar_receive,
0, "enet_rx", dev) < 0) {
- if (netif_msg_intr(priv))
- printk(KERN_ERR "%s: Can't get IRQ %d (receive0)\n",
- dev->name, priv->interruptReceive);
+ printk(KERN_ERR "%s: Can't get IRQ %d (receive0)\n",
+ dev->name, priv->interruptReceive);
err = -1;
goto rx_irq_fail;
@@ -870,9 +758,8 @@ int startup_gfar(struct net_device *dev)
} else {
if (request_irq(priv->interruptTransmit, gfar_interrupt,
0, "gfar_interrupt", dev) < 0) {
- if (netif_msg_intr(priv))
- printk(KERN_ERR "%s: Can't get IRQ %d\n",
- dev->name, priv->interruptError);
+ printk(KERN_ERR "%s: Can't get IRQ %d\n",
+ dev->name, priv->interruptError);
err = -1;
goto err_irq_fail;
@@ -900,22 +787,28 @@ int startup_gfar(struct net_device *dev)
else
gfar_write(®s->rxic, 0);
- if (priv->rx_csum_enable)
- rctrl |= RCTRL_CHECKSUMMING;
+ init_waitqueue_head(&priv->rxcleanupq);
- if (priv->extended_hash)
- rctrl |= RCTRL_EXTHASH;
+ /* Enable Rx and Tx in MACCFG1 */
+ tempval = gfar_read(®s->maccfg1);
+ tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
+ gfar_write(®s->maccfg1, tempval);
- if (priv->vlan_enable)
- rctrl |= RCTRL_VLAN;
+ /* Initialize DMACTRL to have WWR and WOP */
+ tempval = gfar_read(&priv->regs->dmactrl);
+ tempval |= DMACTRL_INIT_SETTINGS;
+ gfar_write(&priv->regs->dmactrl, tempval);
- /* Init rctrl based on our settings */
- gfar_write(&priv->regs->rctrl, rctrl);
+ /* Clear THLT, so that the DMA starts polling now */
+ gfar_write(®s->tstat, TSTAT_CLEAR_THALT);
- if (dev->features & NETIF_F_IP_CSUM)
- gfar_write(&priv->regs->tctrl, TCTRL_INIT_CSUM);
+ /* Make sure we aren't stopped */
+ tempval = gfar_read(&priv->regs->dmactrl);
+ tempval &= ~(DMACTRL_GRS | DMACTRL_GTS);
+ gfar_write(&priv->regs->dmactrl, tempval);
- gfar_start(dev);
+ /* Unmask the interrupts we look for */
+ gfar_write(®s->imask, IMASK_DEFAULT);
return 0;
@@ -931,7 +824,7 @@ int startup_gfar(struct net_device *dev)
sizeof(struct txbd8)*priv->tx_ring_size
+ sizeof(struct rxbd8)*priv->rx_ring_size,
priv->tx_bd_base,
- gfar_read(®s->tbase0));
+ gfar_read(®s->tbase));
if (priv->mii_info->phyinfo->close)
priv->mii_info->phyinfo->close(priv->mii_info);
@@ -964,62 +857,11 @@ static int gfar_enet_open(struct net_device *dev)
return err;
}
-static struct txfcb *gfar_add_fcb(struct sk_buff *skb, struct txbd8 *bdp)
-{
- struct txfcb *fcb = (struct txfcb *)skb_push (skb, GMAC_FCB_LEN);
-
- memset(fcb, 0, GMAC_FCB_LEN);
-
- /* Flag the bd so the controller looks for the FCB */
- bdp->status |= TXBD_TOE;
-
- return fcb;
-}
-
-static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb)
-{
- int len;
-
- /* If we're here, it's a IP packet with a TCP or UDP
- * payload. We set it to checksum, using a pseudo-header
- * we provide
- */
- fcb->ip = 1;
- fcb->tup = 1;
- fcb->ctu = 1;
- fcb->nph = 1;
-
- /* Notify the controller what the protocol is */
- if (skb->nh.iph->protocol == IPPROTO_UDP)
- fcb->udp = 1;
-
- /* l3os is the distance between the start of the
- * frame (skb->data) and the start of the IP hdr.
- * l4os is the distance between the start of the
- * l3 hdr and the l4 hdr */
- fcb->l3os = (u16)(skb->nh.raw - skb->data - GMAC_FCB_LEN);
- fcb->l4os = (u16)(skb->h.raw - skb->nh.raw);
-
- len = skb->nh.iph->tot_len - fcb->l4os;
-
- /* Provide the pseudoheader csum */
- fcb->phcs = ~csum_tcpudp_magic(skb->nh.iph->saddr,
- skb->nh.iph->daddr, len,
- skb->nh.iph->protocol, 0);
-}
-
-void gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb)
-{
- fcb->vln = 1;
- fcb->vlctl = vlan_tx_tag_get(skb);
-}
-
/* This is called by the kernel when a frame is ready for transmission. */
/* It is pointed to by the dev->hard_start_xmit function pointer */
static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
- struct txfcb *fcb = NULL;
struct txbd8 *txbdp;
/* Update transmit stats */
@@ -1034,24 +876,9 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Clear all but the WRAP status flags */
txbdp->status &= TXBD_WRAP;
- /* Set up checksumming */
- if ((dev->features & NETIF_F_IP_CSUM)
- && (CHECKSUM_HW == skb->ip_summed)) {
- fcb = gfar_add_fcb(skb, txbdp);
- gfar_tx_checksum(skb, fcb);
- }
-
- if (priv->vlan_enable &&
- unlikely(priv->vlgrp && vlan_tx_tag_present(skb))) {
- if (NULL == fcb)
- fcb = gfar_add_fcb(skb, txbdp);
-
- gfar_tx_vlan(skb, fcb);
- }
-
/* Set buffer length and pointer */
txbdp->length = skb->len;
- txbdp->bufPtr = dma_map_single(NULL, skb->data,
+ txbdp->bufPtr = dma_map_single(NULL, skb->data,
skb->len, DMA_TO_DEVICE);
/* Save the skb pointer so we can free it later */
@@ -1145,78 +972,15 @@ int gfar_set_mac_address(struct net_device *dev)
}
-/* Enables and disables VLAN insertion/extraction */
-static void gfar_vlan_rx_register(struct net_device *dev,
- struct vlan_group *grp)
-{
- struct gfar_private *priv = netdev_priv(dev);
- unsigned long flags;
- u32 tempval;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- priv->vlgrp = grp;
-
- if (grp) {
- /* Enable VLAN tag insertion */
- tempval = gfar_read(&priv->regs->tctrl);
- tempval |= TCTRL_VLINS;
-
- gfar_write(&priv->regs->tctrl, tempval);
-
- /* Enable VLAN tag extraction */
- tempval = gfar_read(&priv->regs->rctrl);
- tempval |= RCTRL_VLEX;
- gfar_write(&priv->regs->rctrl, tempval);
- } else {
- /* Disable VLAN tag insertion */
- tempval = gfar_read(&priv->regs->tctrl);
- tempval &= ~TCTRL_VLINS;
- gfar_write(&priv->regs->tctrl, tempval);
-
- /* Disable VLAN tag extraction */
- tempval = gfar_read(&priv->regs->rctrl);
- tempval &= ~RCTRL_VLEX;
- gfar_write(&priv->regs->rctrl, tempval);
- }
-
- spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-
-static void gfar_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
-{
- struct gfar_private *priv = netdev_priv(dev);
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- if (priv->vlgrp)
- priv->vlgrp->vlan_devices[vid] = NULL;
-
- spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-
static int gfar_change_mtu(struct net_device *dev, int new_mtu)
{
int tempsize, tempval;
struct gfar_private *priv = netdev_priv(dev);
int oldsize = priv->rx_buffer_size;
- int frame_size = new_mtu + ETH_HLEN;
-
- if (priv->vlan_enable)
- frame_size += VLAN_ETH_HLEN;
-
- if (gfar_uses_fcb(priv))
- frame_size += GMAC_FCB_LEN;
-
- frame_size += priv->padding;
+ int frame_size = new_mtu + 18;
if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) {
- if (netif_msg_drv(priv))
- printk(KERN_ERR "%s: Invalid MTU setting\n",
- dev->name);
+ printk(KERN_ERR "%s: Invalid MTU setting\n", dev->name);
return -EINVAL;
}
@@ -1356,7 +1120,7 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
skb->dev = dev;
bdp->bufPtr = dma_map_single(NULL, skb->data,
- priv->rx_buffer_size + RXBUF_ALIGNMENT,
+ priv->rx_buffer_size + RXBUF_ALIGNMENT,
DMA_FROM_DEVICE);
bdp->length = 0;
@@ -1426,10 +1190,11 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs)
__netif_rx_schedule(dev);
} else {
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: receive called twice (%x)[%x]\n",
- dev->name, gfar_read(&priv->regs->ievent),
- gfar_read(&priv->regs->imask));
+#ifdef VERBOSE_GFAR_ERRORS
+ printk(KERN_DEBUG "%s: receive called twice (%x)[%x]\n",
+ dev->name, gfar_read(&priv->regs->ievent),
+ gfar_read(&priv->regs->imask));
+#endif
}
#else
@@ -1444,43 +1209,15 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs)
else
gfar_write(&priv->regs->rxic, 0);
+ /* Just in case we need to wake the ring param changer */
+ priv->rxclean = 1;
+
spin_unlock(&priv->lock);
#endif
return IRQ_HANDLED;
}
-static inline int gfar_rx_vlan(struct sk_buff *skb,
- struct vlan_group *vlgrp, unsigned short vlctl)
-{
-#ifdef CONFIG_GFAR_NAPI
- return vlan_hwaccel_receive_skb(skb, vlgrp, vlctl);
-#else
- return vlan_hwaccel_rx(skb, vlgrp, vlctl);
-#endif
-}
-
-static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb)
-{
- /* If valid headers were found, and valid sums
- * were verified, then we tell the kernel that no
- * checksumming is necessary. Otherwise, it is */
- if (fcb->cip && !fcb->eip && fcb->ctu && !fcb->etu)
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- else
- skb->ip_summed = CHECKSUM_NONE;
-}
-
-
-static inline struct rxfcb *gfar_get_fcb(struct sk_buff *skb)
-{
- struct rxfcb *fcb = (struct rxfcb *)skb->data;
-
- /* Remove the FCB from the skb */
- skb_pull(skb, GMAC_FCB_LEN);
-
- return fcb;
-}
/* gfar_process_frame() -- handle one incoming packet if skb
* isn't NULL. */
@@ -1488,51 +1225,35 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
int length)
{
struct gfar_private *priv = netdev_priv(dev);
- struct rxfcb *fcb = NULL;
if (skb == NULL) {
- if (netif_msg_rx_err(priv))
- printk(KERN_WARNING "%s: Missing skb!!.\n", dev->name);
+#ifdef BRIEF_GFAR_ERRORS
+ printk(KERN_WARNING "%s: Missing skb!!.\n",
+ dev->name);
+#endif
priv->stats.rx_dropped++;
priv->extra_stats.rx_skbmissing++;
} else {
- int ret;
-
/* Prep the skb for the packet */
skb_put(skb, length);
- /* Grab the FCB if there is one */
- if (gfar_uses_fcb(priv))
- fcb = gfar_get_fcb(skb);
-
- /* Remove the padded bytes, if there are any */
- if (priv->padding)
- skb_pull(skb, priv->padding);
-
- if (priv->rx_csum_enable)
- gfar_rx_checksum(skb, fcb);
-
/* Tell the skb what kind of packet this is */
skb->protocol = eth_type_trans(skb, dev);
/* Send the packet up the stack */
- if (unlikely(priv->vlgrp && fcb->vln))
- ret = gfar_rx_vlan(skb, priv->vlgrp, fcb->vlctl);
- else
- ret = RECEIVE(skb);
-
- if (NET_RX_DROP == ret)
+ if (RECEIVE(skb) == NET_RX_DROP) {
priv->extra_stats.kernel_dropped++;
+ }
}
return 0;
}
/* gfar_clean_rx_ring() -- Processes each frame in the rx ring
- * until the budget/quota has been reached. Returns the number
+ * until the budget/quota has been reached. Returns the number
* of frames handled
*/
-int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
+static int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
{
struct rxbd8 *bdp;
struct sk_buff *skb;
@@ -1634,6 +1355,9 @@ static int gfar_poll(struct net_device *dev, int *budget)
mk_ic_value(priv->rxcount, priv->rxtime));
else
gfar_write(&priv->regs->rxic, 0);
+
+ /* Signal to the ring size changer that it's safe to go */
+ priv->rxclean = 1;
}
return (rx_work_limit < 0) ? 1 : 0;
@@ -1669,8 +1393,10 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (events & IEVENT_CRL)
priv->stats.tx_aborted_errors++;
if (events & IEVENT_XFUN) {
- if (netif_msg_tx_err(priv))
- printk(KERN_WARNING "%s: tx underrun. dropped packet\n", dev->name);
+#ifdef VERBOSE_GFAR_ERRORS
+ printk(KERN_WARNING "%s: tx underrun. dropped packet\n",
+ dev->name);
+#endif
priv->stats.tx_dropped++;
priv->extra_stats.tx_underrun++;
@@ -1689,30 +1415,36 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs)
gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT);
#endif
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n",
- dev->name,
- gfar_read(&priv->regs->rstat));
+#ifdef VERBOSE_GFAR_ERRORS
+ printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n", dev->name,
+ gfar_read(&priv->regs->rstat));
+#endif
}
if (events & IEVENT_BABR) {
priv->stats.rx_errors++;
priv->extra_stats.rx_babr++;
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: babbling error\n", dev->name);
+#ifdef VERBOSE_GFAR_ERRORS
+ printk(KERN_DEBUG "%s: babbling error\n", dev->name);
+#endif
}
if (events & IEVENT_EBERR) {
priv->extra_stats.eberr++;
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: EBERR\n", dev->name);
+#ifdef VERBOSE_GFAR_ERRORS
+ printk(KERN_DEBUG "%s: EBERR\n", dev->name);
+#endif
+ }
+ if (events & IEVENT_RXC) {
+#ifdef VERBOSE_GFAR_ERRORS
+ printk(KERN_DEBUG "%s: control frame\n", dev->name);
+#endif
}
- if ((events & IEVENT_RXC) && (netif_msg_rx_err(priv)))
- printk(KERN_DEBUG "%s: control frame\n", dev->name);
if (events & IEVENT_BABT) {
priv->extra_stats.tx_babt++;
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: babt error\n", dev->name);
+#ifdef VERBOSE_GFAR_ERRORS
+ printk(KERN_DEBUG "%s: babt error\n", dev->name);
+#endif
}
return IRQ_HANDLED;
@@ -1778,7 +1510,7 @@ static void gfar_phy_timer(unsigned long data)
* If, after GFAR_AN_TIMEOUT seconds, it has not
* finished, we switch to forced.
* Either way, once the process has completed, we either
- * request the interrupt, or switch the timer over to
+ * request the interrupt, or switch the timer over to
* using gfar_phy_timer to check status */
static void gfar_phy_startup_timer(unsigned long data)
{
@@ -1803,9 +1535,8 @@ static void gfar_phy_startup_timer(unsigned long data)
/* Forcing failed! Give up */
if(result) {
- if (netif_msg_link(priv))
- printk(KERN_ERR "%s: Forcing failed!\n",
- mii_info->dev->name);
+ printk(KERN_ERR "%s: Forcing failed!\n",
+ mii_info->dev->name);
return;
}
}
@@ -1815,17 +1546,16 @@ static void gfar_phy_startup_timer(unsigned long data)
/* Grab the PHY interrupt, if necessary/possible */
if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
- if (request_irq(priv->einfo->interruptPHY,
+ if (request_irq(priv->einfo->interruptPHY,
phy_interrupt,
- SA_SHIRQ,
- "phy_interrupt",
+ SA_SHIRQ,
+ "phy_interrupt",
mii_info->dev) < 0) {
- if (netif_msg_intr(priv))
- printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n",
- mii_info->dev->name,
+ printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n",
+ mii_info->dev->name,
priv->einfo->interruptPHY);
} else {
- mii_configure_phy_interrupt(priv->mii_info,
+ mii_configure_phy_interrupt(priv->mii_info,
MII_INTERRUPT_ENABLED);
return;
}
@@ -1862,17 +1592,15 @@ static void adjust_link(struct net_device *dev)
tempval &= ~(MACCFG2_FULL_DUPLEX);
gfar_write(®s->maccfg2, tempval);
- if (netif_msg_link(priv))
- printk(KERN_INFO "%s: Half Duplex\n",
- dev->name);
+ printk(KERN_INFO "%s: Half Duplex\n",
+ dev->name);
} else {
tempval = gfar_read(®s->maccfg2);
tempval |= MACCFG2_FULL_DUPLEX;
gfar_write(®s->maccfg2, tempval);
- if (netif_msg_link(priv))
- printk(KERN_INFO "%s: Full Duplex\n",
- dev->name);
+ printk(KERN_INFO "%s: Full Duplex\n",
+ dev->name);
}
priv->oldduplex = mii_info->duplex;
@@ -1894,32 +1622,27 @@ static void adjust_link(struct net_device *dev)
gfar_write(®s->maccfg2, tempval);
break;
default:
- if (netif_msg_link(priv))
- printk(KERN_WARNING
- "%s: Ack! Speed (%d) is not 10/100/1000!\n",
- dev->name, mii_info->speed);
+ printk(KERN_WARNING
+ "%s: Ack! Speed (%d) is not 10/100/1000!\n",
+ dev->name, mii_info->speed);
break;
}
- if (netif_msg_link(priv))
- printk(KERN_INFO "%s: Speed %dBT\n", dev->name,
- mii_info->speed);
+ printk(KERN_INFO "%s: Speed %dBT\n", dev->name,
+ mii_info->speed);
priv->oldspeed = mii_info->speed;
}
if (!priv->oldlink) {
- if (netif_msg_link(priv))
- printk(KERN_INFO "%s: Link is up\n", dev->name);
+ printk(KERN_INFO "%s: Link is up\n", dev->name);
priv->oldlink = 1;
netif_carrier_on(dev);
netif_schedule(dev);
}
} else {
if (priv->oldlink) {
- if (netif_msg_link(priv))
- printk(KERN_INFO "%s: Link is down\n",
- dev->name);
+ printk(KERN_INFO "%s: Link is down\n", dev->name);
priv->oldlink = 0;
priv->oldspeed = 0;
priv->oldduplex = -1;
@@ -1941,9 +1664,8 @@ static void gfar_set_multi(struct net_device *dev)
u32 tempval;
if(dev->flags & IFF_PROMISC) {
- if (netif_msg_drv(priv))
- printk(KERN_INFO "%s: Entering promiscuous mode.\n",
- dev->name);
+ printk(KERN_INFO "%s: Entering promiscuous mode.\n",
+ dev->name);
/* Set RCTRL to PROM */
tempval = gfar_read(®s->rctrl);
tempval |= RCTRL_PROM;
@@ -1957,14 +1679,6 @@ static void gfar_set_multi(struct net_device *dev)
if(dev->flags & IFF_ALLMULTI) {
/* Set the hash to rx all multicast frames */
- gfar_write(®s->igaddr0, 0xffffffff);
- gfar_write(®s->igaddr1, 0xffffffff);
- gfar_write(®s->igaddr2, 0xffffffff);
- gfar_write(®s->igaddr3, 0xffffffff);
- gfar_write(®s->igaddr4, 0xffffffff);
- gfar_write(®s->igaddr5, 0xffffffff);
- gfar_write(®s->igaddr6, 0xffffffff);
- gfar_write(®s->igaddr7, 0xffffffff);
gfar_write(®s->gaddr0, 0xffffffff);
gfar_write(®s->gaddr1, 0xffffffff);
gfar_write(®s->gaddr2, 0xffffffff);
@@ -1975,14 +1689,6 @@ static void gfar_set_multi(struct net_device *dev)
gfar_write(®s->gaddr7, 0xffffffff);
} else {
/* zero out the hash */
- gfar_write(®s->igaddr0, 0x0);
- gfar_write(®s->igaddr1, 0x0);
- gfar_write(®s->igaddr2, 0x0);
- gfar_write(®s->igaddr3, 0x0);
- gfar_write(®s->igaddr4, 0x0);
- gfar_write(®s->igaddr5, 0x0);
- gfar_write(®s->igaddr6, 0x0);
- gfar_write(®s->igaddr7, 0x0);
gfar_write(®s->gaddr0, 0x0);
gfar_write(®s->gaddr1, 0x0);
gfar_write(®s->gaddr2, 0x0);
@@ -2021,15 +1727,16 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr)
{
u32 tempval;
struct gfar_private *priv = netdev_priv(dev);
+ struct gfar *regs = priv->regs;
+ u32 *hash = ®s->gaddr0;
u32 result = ether_crc(MAC_ADDR_LEN, addr);
- int width = priv->hash_width;
- u8 whichbit = (result >> (32 - width)) & 0x1f;
- u8 whichreg = result >> (32 - width + 5);
+ u8 whichreg = ((result >> 29) & 0x7);
+ u8 whichbit = ((result >> 24) & 0x1f);
u32 value = (1 << (31-whichbit));
- tempval = gfar_read(priv->hash_regs[whichreg]);
+ tempval = gfar_read(&hash[whichreg]);
tempval |= value;
- gfar_write(priv->hash_regs[whichreg], tempval);
+ gfar_write(&hash[whichreg], tempval);
return;
}
@@ -2047,9 +1754,10 @@ static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs)
gfar_write(&priv->regs->ievent, IEVENT_ERR_MASK);
/* Hmm... */
- if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv))
- printk(KERN_DEBUG "%s: error interrupt (ievent=0x%08x imask=0x%08x)\n",
- dev->name, events, gfar_read(&priv->regs->imask));
+#if defined (BRIEF_GFAR_ERRORS) || defined (VERBOSE_GFAR_ERRORS)
+ printk(KERN_DEBUG "%s: error interrupt (ievent=0x%08x imask=0x%08x)\n",
+ dev->name, events, gfar_read(&priv->regs->imask));
+#endif
/* Update the error counters */
if (events & IEVENT_TXE) {
@@ -2060,17 +1768,19 @@ static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs)
if (events & IEVENT_CRL)
priv->stats.tx_aborted_errors++;
if (events & IEVENT_XFUN) {
- if (netif_msg_tx_err(priv))
- printk(KERN_DEBUG "%s: underrun. packet dropped.\n",
- dev->name);
+#ifdef VERBOSE_GFAR_ERRORS
+ printk(KERN_DEBUG "%s: underrun. packet dropped.\n",
+ dev->name);
+#endif
priv->stats.tx_dropped++;
priv->extra_stats.tx_underrun++;
/* Reactivate the Tx Queues */
gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT);
}
- if (netif_msg_tx_err(priv))
- printk(KERN_DEBUG "%s: Transmit Error\n", dev->name);
+#ifdef VERBOSE_GFAR_ERRORS
+ printk(KERN_DEBUG "%s: Transmit Error\n", dev->name);
+#endif
}
if (events & IEVENT_BSY) {
priv->stats.rx_errors++;
@@ -2083,31 +1793,35 @@ static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs)
gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT);
#endif
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n",
- dev->name,
- gfar_read(&priv->regs->rstat));
+#ifdef VERBOSE_GFAR_ERRORS
+ printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n", dev->name,
+ gfar_read(&priv->regs->rstat));
+#endif
}
if (events & IEVENT_BABR) {
priv->stats.rx_errors++;
priv->extra_stats.rx_babr++;
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: babbling error\n", dev->name);
+#ifdef VERBOSE_GFAR_ERRORS
+ printk(KERN_DEBUG "%s: babbling error\n", dev->name);
+#endif
}
if (events & IEVENT_EBERR) {
priv->extra_stats.eberr++;
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: EBERR\n", dev->name);
+#ifdef VERBOSE_GFAR_ERRORS
+ printk(KERN_DEBUG "%s: EBERR\n", dev->name);
+#endif
}
- if ((events & IEVENT_RXC) && netif_msg_rx_status(priv))
- if (netif_msg_rx_status(priv))
- printk(KERN_DEBUG "%s: control frame\n", dev->name);
+ if (events & IEVENT_RXC)
+#ifdef VERBOSE_GFAR_ERRORS
+ printk(KERN_DEBUG "%s: control frame\n", dev->name);
+#endif
if (events & IEVENT_BABT) {
priv->extra_stats.tx_babt++;
- if (netif_msg_tx_err(priv))
- printk(KERN_DEBUG "%s: babt error\n", dev->name);
+#ifdef VERBOSE_GFAR_ERRORS
+ printk(KERN_DEBUG "%s: babt error\n", dev->name);
+#endif
}
return IRQ_HANDLED;
}
diff --git a/trunk/drivers/net/gianfar.h b/trunk/drivers/net/gianfar.h
index 28af087d9fbb..c2f783a6a9fa 100644
--- a/trunk/drivers/net/gianfar.h
+++ b/trunk/drivers/net/gianfar.h
@@ -1,4 +1,4 @@
-/*
+/*
* drivers/net/gianfar.h
*
* Gianfar Ethernet Driver
@@ -53,12 +53,6 @@
/* The maximum number of packets to be handled in one call of gfar_poll */
#define GFAR_DEV_WEIGHT 64
-/* Length for FCB */
-#define GMAC_FCB_LEN 8
-
-/* Default padding amount */
-#define DEFAULT_PADDING 2
-
/* Number of bytes to align the rx bufs to */
#define RXBUF_ALIGNMENT 64
@@ -97,7 +91,7 @@ extern const char gfar_driver_version[];
#define JUMBO_FRAME_SIZE 9600
/* Latency of interface clock in nanoseconds */
-/* Interface clock latency , in this case, means the
+/* Interface clock latency , in this case, means the
* time described by a value of 1 in the interrupt
* coalescing registers' time fields. Since those fields
* refer to the time it takes for 64 clocks to pass, the
@@ -172,28 +166,9 @@ extern const char gfar_driver_version[];
mk_ic_icft(count) | \
mk_ic_ictt(time))
-#define RCTRL_PAL_MASK 0x001f0000
-#define RCTRL_VLEX 0x00002000
-#define RCTRL_FILREN 0x00001000
-#define RCTRL_GHTX 0x00000400
-#define RCTRL_IPCSEN 0x00000200
-#define RCTRL_TUCSEN 0x00000100
-#define RCTRL_PRSDEP_MASK 0x000000c0
-#define RCTRL_PRSDEP_INIT 0x000000c0
#define RCTRL_PROM 0x00000008
-#define RCTRL_CHECKSUMMING (RCTRL_IPCSEN \
- | RCTRL_TUCSEN | RCTRL_PRSDEP_INIT)
-#define RCTRL_EXTHASH (RCTRL_GHTX)
-#define RCTRL_VLAN (RCTRL_PRSDEP_INIT)
-
-
#define RSTAT_CLEAR_RHALT 0x00800000
-#define TCTRL_IPCSEN 0x00004000
-#define TCTRL_TUCSEN 0x00002000
-#define TCTRL_VLINS 0x00001000
-#define TCTRL_INIT_CSUM (TCTRL_TUCSEN | TCTRL_IPCSEN)
-
#define IEVENT_INIT_CLEAR 0xffffffff
#define IEVENT_BABR 0x80000000
#define IEVENT_RXC 0x40000000
@@ -212,16 +187,12 @@ extern const char gfar_driver_version[];
#define IEVENT_RXB0 0x00008000
#define IEVENT_GRSC 0x00000100
#define IEVENT_RXF0 0x00000080
-#define IEVENT_FIR 0x00000008
-#define IEVENT_FIQ 0x00000004
-#define IEVENT_DPE 0x00000002
-#define IEVENT_PERR 0x00000001
#define IEVENT_RX_MASK (IEVENT_RXB0 | IEVENT_RXF0)
#define IEVENT_TX_MASK (IEVENT_TXB | IEVENT_TXF)
#define IEVENT_ERR_MASK \
(IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \
IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \
- | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR)
+ | IEVENT_CRL | IEVENT_XFUN)
#define IMASK_INIT_CLEAR 0x00000000
#define IMASK_BABR 0x80000000
@@ -241,15 +212,10 @@ extern const char gfar_driver_version[];
#define IMASK_RXB0 0x00008000
#define IMASK_GTSC 0x00000100
#define IMASK_RXFEN0 0x00000080
-#define IMASK_FIR 0x00000008
-#define IMASK_FIQ 0x00000004
-#define IMASK_DPE 0x00000002
-#define IMASK_PERR 0x00000001
#define IMASK_RX_DISABLED ~(IMASK_RXFEN0 | IMASK_BSY)
#define IMASK_DEFAULT (IMASK_TXEEN | IMASK_TXFEN | IMASK_TXBEN | \
IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \
- IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \
- | IMASK_PERR)
+ IMASK_XFUN | IMASK_RXC | IMASK_BABT)
/* Attribute fields */
@@ -288,18 +254,6 @@ extern const char gfar_driver_version[];
#define TXBD_RETRYLIMIT 0x0040
#define TXBD_RETRYCOUNTMASK 0x003c
#define TXBD_UNDERRUN 0x0002
-#define TXBD_TOE 0x0002
-
-/* Tx FCB param bits */
-#define TXFCB_VLN 0x80
-#define TXFCB_IP 0x40
-#define TXFCB_IP6 0x20
-#define TXFCB_TUP 0x10
-#define TXFCB_UDP 0x08
-#define TXFCB_CIP 0x04
-#define TXFCB_CTU 0x02
-#define TXFCB_NPH 0x01
-#define TXFCB_DEFAULT (TXFCB_IP|TXFCB_TUP|TXFCB_CTU|TXFCB_NPH)
/* RxBD status field bits */
#define RXBD_EMPTY 0x8000
@@ -319,18 +273,6 @@ extern const char gfar_driver_version[];
#define RXBD_TRUNCATED 0x0001
#define RXBD_STATS 0x01ff
-/* Rx FCB status field bits */
-#define RXFCB_VLN 0x8000
-#define RXFCB_IP 0x4000
-#define RXFCB_IP6 0x2000
-#define RXFCB_TUP 0x1000
-#define RXFCB_CIP 0x0800
-#define RXFCB_CTU 0x0400
-#define RXFCB_EIP 0x0200
-#define RXFCB_ETU 0x0100
-#define RXFCB_PERR_MASK 0x000c
-#define RXFCB_PERR_BADL3 0x0008
-
struct txbd8
{
u16 status; /* Status Fields */
@@ -338,22 +280,6 @@ struct txbd8
u32 bufPtr; /* Buffer Pointer */
};
-struct txfcb {
- u8 vln:1,
- ip:1,
- ip6:1,
- tup:1,
- udp:1,
- cip:1,
- ctu:1,
- nph:1;
- u8 reserved;
- u8 l4os; /* Level 4 Header Offset */
- u8 l3os; /* Level 3 Header Offset */
- u16 phcs; /* Pseudo-header Checksum */
- u16 vlctl; /* VLAN control word */
-};
-
struct rxbd8
{
u16 status; /* Status Fields */
@@ -361,21 +287,6 @@ struct rxbd8
u32 bufPtr; /* Buffer Pointer */
};
-struct rxfcb {
- u16 vln:1,
- ip:1,
- ip6:1,
- tup:1,
- cip:1,
- ctu:1,
- eip:1,
- etu:1;
- u8 rq; /* Receive Queue index */
- u8 pro; /* Layer 4 Protocol */
- u16 reserved;
- u16 vlctl; /* VLAN control word */
-};
-
struct rmon_mib
{
u32 tr64; /* 0x.680 - Transmit and Receive 64-byte Frame Counter */
@@ -460,191 +371,90 @@ struct gfar_stats {
struct gfar {
- u32 tsec_id; /* 0x.000 - Controller ID register */
- u8 res1[12];
- u32 ievent; /* 0x.010 - Interrupt Event Register */
- u32 imask; /* 0x.014 - Interrupt Mask Register */
- u32 edis; /* 0x.018 - Error Disabled Register */
+ u8 res1[16];
+ u32 ievent; /* 0x.010 - Interrupt Event Register */
+ u32 imask; /* 0x.014 - Interrupt Mask Register */
+ u32 edis; /* 0x.018 - Error Disabled Register */
u8 res2[4];
- u32 ecntrl; /* 0x.020 - Ethernet Control Register */
- u32 minflr; /* 0x.024 - Minimum Frame Length Register */
- u32 ptv; /* 0x.028 - Pause Time Value Register */
- u32 dmactrl; /* 0x.02c - DMA Control Register */
- u32 tbipa; /* 0x.030 - TBI PHY Address Register */
+ u32 ecntrl; /* 0x.020 - Ethernet Control Register */
+ u32 minflr; /* 0x.024 - Minimum Frame Length Register */
+ u32 ptv; /* 0x.028 - Pause Time Value Register */
+ u32 dmactrl; /* 0x.02c - DMA Control Register */
+ u32 tbipa; /* 0x.030 - TBI PHY Address Register */
u8 res3[88];
- u32 fifo_tx_thr; /* 0x.08c - FIFO transmit threshold register */
+ u32 fifo_tx_thr; /* 0x.08c - FIFO transmit threshold register */
u8 res4[8];
- u32 fifo_tx_starve; /* 0x.098 - FIFO transmit starve register */
+ u32 fifo_tx_starve; /* 0x.098 - FIFO transmit starve register */
u32 fifo_tx_starve_shutoff; /* 0x.09c - FIFO transmit starve shutoff register */
- u8 res5[4];
- u32 fifo_rx_pause; /* 0x.0a4 - FIFO receive pause threshold register */
- u32 fifo_rx_alarm; /* 0x.0a8 - FIFO receive alarm threshold register */
- u8 res6[84];
- u32 tctrl; /* 0x.100 - Transmit Control Register */
- u32 tstat; /* 0x.104 - Transmit Status Register */
- u32 dfvlan; /* 0x.108 - Default VLAN Control word */
- u32 tbdlen; /* 0x.10c - Transmit Buffer Descriptor Data Length Register */
- u32 txic; /* 0x.110 - Transmit Interrupt Coalescing Configuration Register */
- u32 tqueue; /* 0x.114 - Transmit queue control register */
- u8 res7[40];
- u32 tr03wt; /* 0x.140 - TxBD Rings 0-3 round-robin weightings */
- u32 tr47wt; /* 0x.144 - TxBD Rings 4-7 round-robin weightings */
- u8 res8[52];
- u32 tbdbph; /* 0x.17c - Tx data buffer pointer high */
- u8 res9a[4];
- u32 tbptr0; /* 0x.184 - TxBD Pointer for ring 0 */
- u8 res9b[4];
- u32 tbptr1; /* 0x.18c - TxBD Pointer for ring 1 */
- u8 res9c[4];
- u32 tbptr2; /* 0x.194 - TxBD Pointer for ring 2 */
- u8 res9d[4];
- u32 tbptr3; /* 0x.19c - TxBD Pointer for ring 3 */
- u8 res9e[4];
- u32 tbptr4; /* 0x.1a4 - TxBD Pointer for ring 4 */
- u8 res9f[4];
- u32 tbptr5; /* 0x.1ac - TxBD Pointer for ring 5 */
- u8 res9g[4];
- u32 tbptr6; /* 0x.1b4 - TxBD Pointer for ring 6 */
- u8 res9h[4];
- u32 tbptr7; /* 0x.1bc - TxBD Pointer for ring 7 */
- u8 res9[64];
- u32 tbaseh; /* 0x.200 - TxBD base address high */
- u32 tbase0; /* 0x.204 - TxBD Base Address of ring 0 */
- u8 res10a[4];
- u32 tbase1; /* 0x.20c - TxBD Base Address of ring 1 */
- u8 res10b[4];
- u32 tbase2; /* 0x.214 - TxBD Base Address of ring 2 */
- u8 res10c[4];
- u32 tbase3; /* 0x.21c - TxBD Base Address of ring 3 */
- u8 res10d[4];
- u32 tbase4; /* 0x.224 - TxBD Base Address of ring 4 */
- u8 res10e[4];
- u32 tbase5; /* 0x.22c - TxBD Base Address of ring 5 */
- u8 res10f[4];
- u32 tbase6; /* 0x.234 - TxBD Base Address of ring 6 */
- u8 res10g[4];
- u32 tbase7; /* 0x.23c - TxBD Base Address of ring 7 */
- u8 res10[192];
- u32 rctrl; /* 0x.300 - Receive Control Register */
- u32 rstat; /* 0x.304 - Receive Status Register */
- u8 res12[8];
- u32 rxic; /* 0x.310 - Receive Interrupt Coalescing Configuration Register */
- u32 rqueue; /* 0x.314 - Receive queue control register */
- u8 res13[24];
- u32 rbifx; /* 0x.330 - Receive bit field extract control register */
- u32 rqfar; /* 0x.334 - Receive queue filing table address register */
- u32 rqfcr; /* 0x.338 - Receive queue filing table control register */
- u32 rqfpr; /* 0x.33c - Receive queue filing table property register */
- u32 mrblr; /* 0x.340 - Maximum Receive Buffer Length Register */
- u8 res14[56];
- u32 rbdbph; /* 0x.37c - Rx data buffer pointer high */
- u8 res15a[4];
- u32 rbptr0; /* 0x.384 - RxBD pointer for ring 0 */
- u8 res15b[4];
- u32 rbptr1; /* 0x.38c - RxBD pointer for ring 1 */
- u8 res15c[4];
- u32 rbptr2; /* 0x.394 - RxBD pointer for ring 2 */
- u8 res15d[4];
- u32 rbptr3; /* 0x.39c - RxBD pointer for ring 3 */
- u8 res15e[4];
- u32 rbptr4; /* 0x.3a4 - RxBD pointer for ring 4 */
- u8 res15f[4];
- u32 rbptr5; /* 0x.3ac - RxBD pointer for ring 5 */
- u8 res15g[4];
- u32 rbptr6; /* 0x.3b4 - RxBD pointer for ring 6 */
- u8 res15h[4];
- u32 rbptr7; /* 0x.3bc - RxBD pointer for ring 7 */
- u8 res16[64];
- u32 rbaseh; /* 0x.400 - RxBD base address high */
- u32 rbase0; /* 0x.404 - RxBD base address of ring 0 */
- u8 res17a[4];
- u32 rbase1; /* 0x.40c - RxBD base address of ring 1 */
- u8 res17b[4];
- u32 rbase2; /* 0x.414 - RxBD base address of ring 2 */
- u8 res17c[4];
- u32 rbase3; /* 0x.41c - RxBD base address of ring 3 */
- u8 res17d[4];
- u32 rbase4; /* 0x.424 - RxBD base address of ring 4 */
- u8 res17e[4];
- u32 rbase5; /* 0x.42c - RxBD base address of ring 5 */
- u8 res17f[4];
- u32 rbase6; /* 0x.434 - RxBD base address of ring 6 */
- u8 res17g[4];
- u32 rbase7; /* 0x.43c - RxBD base address of ring 7 */
- u8 res17[192];
- u32 maccfg1; /* 0x.500 - MAC Configuration 1 Register */
- u32 maccfg2; /* 0x.504 - MAC Configuration 2 Register */
- u32 ipgifg; /* 0x.508 - Inter Packet Gap/Inter Frame Gap Register */
- u32 hafdup; /* 0x.50c - Half Duplex Register */
- u32 maxfrm; /* 0x.510 - Maximum Frame Length Register */
+ u8 res5[96];
+ u32 tctrl; /* 0x.100 - Transmit Control Register */
+ u32 tstat; /* 0x.104 - Transmit Status Register */
+ u8 res6[4];
+ u32 tbdlen; /* 0x.10c - Transmit Buffer Descriptor Data Length Register */
+ u32 txic; /* 0x.110 - Transmit Interrupt Coalescing Configuration Register */
+ u8 res7[16];
+ u32 ctbptr; /* 0x.124 - Current Transmit Buffer Descriptor Pointer Register */
+ u8 res8[92];
+ u32 tbptr; /* 0x.184 - Transmit Buffer Descriptor Pointer Low Register */
+ u8 res9[124];
+ u32 tbase; /* 0x.204 - Transmit Descriptor Base Address Register */
+ u8 res10[168];
+ u32 ostbd; /* 0x.2b0 - Out-of-Sequence Transmit Buffer Descriptor Register */
+ u32 ostbdp; /* 0x.2b4 - Out-of-Sequence Transmit Data Buffer Pointer Register */
+ u8 res11[72];
+ u32 rctrl; /* 0x.300 - Receive Control Register */
+ u32 rstat; /* 0x.304 - Receive Status Register */
+ u8 res12[4];
+ u32 rbdlen; /* 0x.30c - RxBD Data Length Register */
+ u32 rxic; /* 0x.310 - Receive Interrupt Coalescing Configuration Register */
+ u8 res13[16];
+ u32 crbptr; /* 0x.324 - Current Receive Buffer Descriptor Pointer */
+ u8 res14[24];
+ u32 mrblr; /* 0x.340 - Maximum Receive Buffer Length Register */
+ u8 res15[64];
+ u32 rbptr; /* 0x.384 - Receive Buffer Descriptor Pointer */
+ u8 res16[124];
+ u32 rbase; /* 0x.404 - Receive Descriptor Base Address */
+ u8 res17[248];
+ u32 maccfg1; /* 0x.500 - MAC Configuration 1 Register */
+ u32 maccfg2; /* 0x.504 - MAC Configuration 2 Register */
+ u32 ipgifg; /* 0x.508 - Inter Packet Gap/Inter Frame Gap Register */
+ u32 hafdup; /* 0x.50c - Half Duplex Register */
+ u32 maxfrm; /* 0x.510 - Maximum Frame Length Register */
u8 res18[12];
- u32 miimcfg; /* 0x.520 - MII Management Configuration Register */
- u32 miimcom; /* 0x.524 - MII Management Command Register */
- u32 miimadd; /* 0x.528 - MII Management Address Register */
- u32 miimcon; /* 0x.52c - MII Management Control Register */
- u32 miimstat; /* 0x.530 - MII Management Status Register */
- u32 miimind; /* 0x.534 - MII Management Indicator Register */
+ u32 miimcfg; /* 0x.520 - MII Management Configuration Register */
+ u32 miimcom; /* 0x.524 - MII Management Command Register */
+ u32 miimadd; /* 0x.528 - MII Management Address Register */
+ u32 miimcon; /* 0x.52c - MII Management Control Register */
+ u32 miimstat; /* 0x.530 - MII Management Status Register */
+ u32 miimind; /* 0x.534 - MII Management Indicator Register */
u8 res19[4];
- u32 ifstat; /* 0x.53c - Interface Status Register */
- u32 macstnaddr1; /* 0x.540 - Station Address Part 1 Register */
- u32 macstnaddr2; /* 0x.544 - Station Address Part 2 Register */
- u32 mac01addr1; /* 0x.548 - MAC exact match address 1, part 1 */
- u32 mac01addr2; /* 0x.54c - MAC exact match address 1, part 2 */
- u32 mac02addr1; /* 0x.550 - MAC exact match address 2, part 1 */
- u32 mac02addr2; /* 0x.554 - MAC exact match address 2, part 2 */
- u32 mac03addr1; /* 0x.558 - MAC exact match address 3, part 1 */
- u32 mac03addr2; /* 0x.55c - MAC exact match address 3, part 2 */
- u32 mac04addr1; /* 0x.560 - MAC exact match address 4, part 1 */
- u32 mac04addr2; /* 0x.564 - MAC exact match address 4, part 2 */
- u32 mac05addr1; /* 0x.568 - MAC exact match address 5, part 1 */
- u32 mac05addr2; /* 0x.56c - MAC exact match address 5, part 2 */
- u32 mac06addr1; /* 0x.570 - MAC exact match address 6, part 1 */
- u32 mac06addr2; /* 0x.574 - MAC exact match address 6, part 2 */
- u32 mac07addr1; /* 0x.578 - MAC exact match address 7, part 1 */
- u32 mac07addr2; /* 0x.57c - MAC exact match address 7, part 2 */
- u32 mac08addr1; /* 0x.580 - MAC exact match address 8, part 1 */
- u32 mac08addr2; /* 0x.584 - MAC exact match address 8, part 2 */
- u32 mac09addr1; /* 0x.588 - MAC exact match address 9, part 1 */
- u32 mac09addr2; /* 0x.58c - MAC exact match address 9, part 2 */
- u32 mac10addr1; /* 0x.590 - MAC exact match address 10, part 1*/
- u32 mac10addr2; /* 0x.594 - MAC exact match address 10, part 2*/
- u32 mac11addr1; /* 0x.598 - MAC exact match address 11, part 1*/
- u32 mac11addr2; /* 0x.59c - MAC exact match address 11, part 2*/
- u32 mac12addr1; /* 0x.5a0 - MAC exact match address 12, part 1*/
- u32 mac12addr2; /* 0x.5a4 - MAC exact match address 12, part 2*/
- u32 mac13addr1; /* 0x.5a8 - MAC exact match address 13, part 1*/
- u32 mac13addr2; /* 0x.5ac - MAC exact match address 13, part 2*/
- u32 mac14addr1; /* 0x.5b0 - MAC exact match address 14, part 1*/
- u32 mac14addr2; /* 0x.5b4 - MAC exact match address 14, part 2*/
- u32 mac15addr1; /* 0x.5b8 - MAC exact match address 15, part 1*/
- u32 mac15addr2; /* 0x.5bc - MAC exact match address 15, part 2*/
- u8 res20[192];
- struct rmon_mib rmon; /* 0x.680-0x.73c */
- u32 rrej; /* 0x.740 - Receive filer rejected packet counter */
- u8 res21[188];
- u32 igaddr0; /* 0x.800 - Indivdual/Group address register 0*/
- u32 igaddr1; /* 0x.804 - Indivdual/Group address register 1*/
- u32 igaddr2; /* 0x.808 - Indivdual/Group address register 2*/
- u32 igaddr3; /* 0x.80c - Indivdual/Group address register 3*/
- u32 igaddr4; /* 0x.810 - Indivdual/Group address register 4*/
- u32 igaddr5; /* 0x.814 - Indivdual/Group address register 5*/
- u32 igaddr6; /* 0x.818 - Indivdual/Group address register 6*/
- u32 igaddr7; /* 0x.81c - Indivdual/Group address register 7*/
+ u32 ifstat; /* 0x.53c - Interface Status Register */
+ u32 macstnaddr1; /* 0x.540 - Station Address Part 1 Register */
+ u32 macstnaddr2; /* 0x.544 - Station Address Part 2 Register */
+ u8 res20[312];
+ struct rmon_mib rmon;
+ u8 res21[192];
+ u32 iaddr0; /* 0x.800 - Indivdual address register 0 */
+ u32 iaddr1; /* 0x.804 - Indivdual address register 1 */
+ u32 iaddr2; /* 0x.808 - Indivdual address register 2 */
+ u32 iaddr3; /* 0x.80c - Indivdual address register 3 */
+ u32 iaddr4; /* 0x.810 - Indivdual address register 4 */
+ u32 iaddr5; /* 0x.814 - Indivdual address register 5 */
+ u32 iaddr6; /* 0x.818 - Indivdual address register 6 */
+ u32 iaddr7; /* 0x.81c - Indivdual address register 7 */
u8 res22[96];
- u32 gaddr0; /* 0x.880 - Group address register 0 */
- u32 gaddr1; /* 0x.884 - Group address register 1 */
- u32 gaddr2; /* 0x.888 - Group address register 2 */
- u32 gaddr3; /* 0x.88c - Group address register 3 */
- u32 gaddr4; /* 0x.890 - Group address register 4 */
- u32 gaddr5; /* 0x.894 - Group address register 5 */
- u32 gaddr6; /* 0x.898 - Group address register 6 */
- u32 gaddr7; /* 0x.89c - Group address register 7 */
- u8 res23a[352];
- u32 fifocfg; /* 0x.a00 - FIFO interface config register */
- u8 res23b[252];
- u8 res23c[248];
- u32 attr; /* 0x.bf8 - Attributes Register */
- u32 attreli; /* 0x.bfc - Attributes Extract Length and Extract Index Register */
+ u32 gaddr0; /* 0x.880 - Global address register 0 */
+ u32 gaddr1; /* 0x.884 - Global address register 1 */
+ u32 gaddr2; /* 0x.888 - Global address register 2 */
+ u32 gaddr3; /* 0x.88c - Global address register 3 */
+ u32 gaddr4; /* 0x.890 - Global address register 4 */
+ u32 gaddr5; /* 0x.894 - Global address register 5 */
+ u32 gaddr6; /* 0x.898 - Global address register 6 */
+ u32 gaddr7; /* 0x.89c - Global address register 7 */
+ u8 res23[856];
+ u32 attr; /* 0x.bf8 - Attributes Register */
+ u32 attreli; /* 0x.bfc - Attributes Extract Length and Extract Index Register */
u8 res24[1024];
};
@@ -686,8 +496,6 @@ struct gfar_private {
struct txbd8 *cur_tx; /* Next free ring entry */
struct txbd8 *dirty_tx; /* The Ring entry to be freed. */
struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */
- u32 *hash_regs[16];
- int hash_width;
struct gfar *phyregs;
struct work_struct tq;
struct timer_list phy_info_timer;
@@ -698,12 +506,9 @@ struct gfar_private {
unsigned int rx_stash_size;
unsigned int tx_ring_size;
unsigned int rx_ring_size;
+ wait_queue_head_t rxcleanupq;
+ unsigned int rxclean;
- unsigned char vlan_enable:1,
- rx_csum_enable:1,
- extended_hash:1;
- unsigned short padding;
- struct vlan_group *vlgrp;
/* Info structure initialized by board setup code */
unsigned int interruptTransmit;
unsigned int interruptReceive;
@@ -714,8 +519,6 @@ struct gfar_private {
int oldspeed;
int oldduplex;
int oldlink;
-
- uint32_t msg_enable;
};
extern inline u32 gfar_read(volatile unsigned *addr)
diff --git a/trunk/drivers/net/gianfar_ethtool.c b/trunk/drivers/net/gianfar_ethtool.c
index a451de629197..28046e9e88ba 100644
--- a/trunk/drivers/net/gianfar_ethtool.c
+++ b/trunk/drivers/net/gianfar_ethtool.c
@@ -46,18 +46,16 @@
extern int startup_gfar(struct net_device *dev);
extern void stop_gfar(struct net_device *dev);
-extern void gfar_halt(struct net_device *dev);
-extern void gfar_start(struct net_device *dev);
-extern int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
+extern void gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
-static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
+void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
u64 * buf);
-static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf);
-static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals);
-static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals);
-static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals);
-static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals);
-static void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo);
+void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf);
+int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals);
+int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals);
+void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals);
+int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals);
+void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo);
static char stat_gstrings[][ETH_GSTRING_LEN] = {
"rx-dropped-by-kernel",
@@ -120,56 +118,57 @@ static char stat_gstrings[][ETH_GSTRING_LEN] = {
"tx-fragmented-frames",
};
-/* Fill in a buffer with the strings which correspond to the
- * stats */
-static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf)
-{
- struct gfar_private *priv = netdev_priv(dev);
-
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON)
- memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN);
- else
- memcpy(buf, stat_gstrings,
- GFAR_EXTRA_STATS_LEN * ETH_GSTRING_LEN);
-}
-
/* Fill in an array of 64-bit statistics from various sources.
* This array will be appended to the end of the ethtool_stats
* structure, and returned to user space
*/
-static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf)
+void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf)
{
int i;
struct gfar_private *priv = netdev_priv(dev);
+ u32 *rmon = (u32 *) & priv->regs->rmon;
u64 *extra = (u64 *) & priv->extra_stats;
+ struct gfar_stats *stats = (struct gfar_stats *) buf;
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
- u32 *rmon = (u32 *) & priv->regs->rmon;
- struct gfar_stats *stats = (struct gfar_stats *) buf;
-
- for (i = 0; i < GFAR_RMON_LEN; i++)
- stats->rmon[i] = (u64) (rmon[i]);
+ for (i = 0; i < GFAR_RMON_LEN; i++) {
+ stats->rmon[i] = (u64) (rmon[i]);
+ }
- for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++)
- stats->extra[i] = extra[i];
- } else
- for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++)
- buf[i] = extra[i];
+ for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) {
+ stats->extra[i] = extra[i];
+ }
}
/* Returns the number of stats (and their corresponding strings) */
-static int gfar_stats_count(struct net_device *dev)
+int gfar_stats_count(struct net_device *dev)
+{
+ return GFAR_STATS_LEN;
+}
+
+void gfar_gstrings_normon(struct net_device *dev, u32 stringset, u8 * buf)
+{
+ memcpy(buf, stat_gstrings, GFAR_EXTRA_STATS_LEN * ETH_GSTRING_LEN);
+}
+
+void gfar_fill_stats_normon(struct net_device *dev,
+ struct ethtool_stats *dummy, u64 * buf)
{
+ int i;
struct gfar_private *priv = netdev_priv(dev);
+ u64 *extra = (u64 *) & priv->extra_stats;
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON)
- return GFAR_STATS_LEN;
- else
- return GFAR_EXTRA_STATS_LEN;
+ for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) {
+ buf[i] = extra[i];
+ }
}
+
+int gfar_stats_count_normon(struct net_device *dev)
+{
+ return GFAR_EXTRA_STATS_LEN;
+}
/* Fills in the drvinfo structure with some basic info */
-static void gfar_gdrvinfo(struct net_device *dev, struct
+void gfar_gdrvinfo(struct net_device *dev, struct
ethtool_drvinfo *drvinfo)
{
strncpy(drvinfo->driver, DRV_NAME, GFAR_INFOSTR_LEN);
@@ -183,7 +182,7 @@ static void gfar_gdrvinfo(struct net_device *dev, struct
}
/* Return the current settings in the ethtool_cmd structure */
-static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct gfar_private *priv = netdev_priv(dev);
uint gigabit_support =
@@ -217,13 +216,13 @@ static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd)
}
/* Return the length of the register structure */
-static int gfar_reglen(struct net_device *dev)
+int gfar_reglen(struct net_device *dev)
{
return sizeof (struct gfar);
}
/* Return a dump of the GFAR register space */
-static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf)
+void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf)
{
int i;
struct gfar_private *priv = netdev_priv(dev);
@@ -234,6 +233,13 @@ static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, voi
buf[i] = theregs[i];
}
+/* Fill in a buffer with the strings which correspond to the
+ * stats */
+void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf)
+{
+ memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN);
+}
+
/* Convert microseconds to ethernet clock ticks, which changes
* depending on what speed the controller is running at */
static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int usecs)
@@ -285,12 +291,9 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic
/* Get the coalescing parameters, and put them in the cvals
* structure. */
-static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals)
+int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals)
{
struct gfar_private *priv = netdev_priv(dev);
-
- if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
- return -EOPNOTSUPP;
cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime);
cvals->rx_max_coalesced_frames = priv->rxcount;
@@ -334,13 +337,10 @@ static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
* Both cvals->*_usecs and cvals->*_frames have to be > 0
* in order for coalescing to be active
*/
-static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals)
+int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals)
{
struct gfar_private *priv = netdev_priv(dev);
- if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
- return -EOPNOTSUPP;
-
/* Set up rx coalescing */
if ((cvals->rx_coalesce_usecs == 0) ||
(cvals->rx_max_coalesced_frames == 0))
@@ -379,7 +379,7 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
/* Fills in rvals with the current ring parameters. Currently,
* rx, rx_mini, and rx_jumbo rings are the same size, as mini and
* jumbo are ignored by the driver */
-static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals)
+void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals)
{
struct gfar_private *priv = netdev_priv(dev);
@@ -401,8 +401,9 @@ static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rv
* necessary so that we don't mess things up while we're in
* motion. We wait for the ring to be clean before reallocating
* the rings. */
-static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals)
+int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals)
{
+ u32 tempval;
struct gfar_private *priv = netdev_priv(dev);
int err = 0;
@@ -424,54 +425,37 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva
return -EINVAL;
}
- if (dev->flags & IFF_UP) {
- unsigned long flags;
-
- /* Halt TX and RX, and process the frames which
- * have already been received */
- spin_lock_irqsave(&priv->lock, flags);
- gfar_halt(dev);
- gfar_clean_rx_ring(dev, priv->rx_ring_size);
- spin_unlock_irqrestore(&priv->lock, flags);
+ /* Stop the controller so we don't rx any more frames */
+ /* But first, make sure we clear the bits */
+ tempval = gfar_read(&priv->regs->dmactrl);
+ tempval &= ~(DMACTRL_GRS | DMACTRL_GTS);
+ gfar_write(&priv->regs->dmactrl, tempval);
- /* Now we take down the rings to rebuild them */
- stop_gfar(dev);
- }
-
- /* Change the size */
- priv->rx_ring_size = rvals->rx_pending;
- priv->tx_ring_size = rvals->tx_pending;
+ tempval = gfar_read(&priv->regs->dmactrl);
+ tempval |= (DMACTRL_GRS | DMACTRL_GTS);
+ gfar_write(&priv->regs->dmactrl, tempval);
- /* Rebuild the rings with the new size */
- if (dev->flags & IFF_UP)
- err = startup_gfar(dev);
+ while (!(gfar_read(&priv->regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC)))
+ cpu_relax();
- return err;
-}
-
-static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
-{
- struct gfar_private *priv = netdev_priv(dev);
- int err = 0;
-
- if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
- return -EOPNOTSUPP;
+ /* Note that rx is not clean right now */
+ priv->rxclean = 0;
if (dev->flags & IFF_UP) {
- unsigned long flags;
+ /* Tell the driver to process the rest of the frames */
+ gfar_receive(0, (void *) dev, NULL);
+
+ /* Now wait for it to be done */
+ wait_event_interruptible(priv->rxcleanupq, priv->rxclean);
- /* Halt TX and RX, and process the frames which
- * have already been received */
- spin_lock_irqsave(&priv->lock, flags);
- gfar_halt(dev);
- gfar_clean_rx_ring(dev, priv->rx_ring_size);
- spin_unlock_irqrestore(&priv->lock, flags);
+ /* Ok, all packets have been handled. Now we bring it down,
+ * change the ring size, and bring it up */
- /* Now we take down the rings to rebuild them */
stop_gfar(dev);
}
- priv->rx_csum_enable = data;
+ priv->rx_ring_size = rvals->rx_pending;
+ priv->tx_ring_size = rvals->tx_pending;
if (dev->flags & IFF_UP)
err = startup_gfar(dev);
@@ -479,61 +463,6 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
return err;
}
-static uint32_t gfar_get_rx_csum(struct net_device *dev)
-{
- struct gfar_private *priv = netdev_priv(dev);
-
- if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
- return 0;
-
- return priv->rx_csum_enable;
-}
-
-static int gfar_set_tx_csum(struct net_device *dev, uint32_t data)
-{
- unsigned long flags;
- struct gfar_private *priv = netdev_priv(dev);
-
- if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
- return -EOPNOTSUPP;
-
- spin_lock_irqsave(&priv->lock, flags);
- gfar_halt(dev);
-
- if (data)
- dev->features |= NETIF_F_IP_CSUM;
- else
- dev->features &= ~NETIF_F_IP_CSUM;
-
- gfar_start(dev);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
-}
-
-static uint32_t gfar_get_tx_csum(struct net_device *dev)
-{
- struct gfar_private *priv = netdev_priv(dev);
-
- if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
- return 0;
-
- return (dev->features & NETIF_F_IP_CSUM) != 0;
-}
-
-static uint32_t gfar_get_msglevel(struct net_device *dev)
-{
- struct gfar_private *priv = netdev_priv(dev);
- return priv->msg_enable;
-}
-
-static void gfar_set_msglevel(struct net_device *dev, uint32_t data)
-{
- struct gfar_private *priv = netdev_priv(dev);
- priv->msg_enable = data;
-}
-
-
struct ethtool_ops gfar_ethtool_ops = {
.get_settings = gfar_gsettings,
.get_drvinfo = gfar_gdrvinfo,
@@ -547,10 +476,52 @@ struct ethtool_ops gfar_ethtool_ops = {
.get_strings = gfar_gstrings,
.get_stats_count = gfar_stats_count,
.get_ethtool_stats = gfar_fill_stats,
- .get_rx_csum = gfar_get_rx_csum,
- .get_tx_csum = gfar_get_tx_csum,
- .set_rx_csum = gfar_set_rx_csum,
- .set_tx_csum = gfar_set_tx_csum,
- .get_msglevel = gfar_get_msglevel,
- .set_msglevel = gfar_set_msglevel,
+};
+
+struct ethtool_ops gfar_normon_nocoalesce_ethtool_ops = {
+ .get_settings = gfar_gsettings,
+ .get_drvinfo = gfar_gdrvinfo,
+ .get_regs_len = gfar_reglen,
+ .get_regs = gfar_get_regs,
+ .get_link = ethtool_op_get_link,
+ .get_ringparam = gfar_gringparam,
+ .set_ringparam = gfar_sringparam,
+ .get_strings = gfar_gstrings_normon,
+ .get_stats_count = gfar_stats_count_normon,
+ .get_ethtool_stats = gfar_fill_stats_normon,
+};
+
+struct ethtool_ops gfar_nocoalesce_ethtool_ops = {
+ .get_settings = gfar_gsettings,
+ .get_drvinfo = gfar_gdrvinfo,
+ .get_regs_len = gfar_reglen,
+ .get_regs = gfar_get_regs,
+ .get_link = ethtool_op_get_link,
+ .get_ringparam = gfar_gringparam,
+ .set_ringparam = gfar_sringparam,
+ .get_strings = gfar_gstrings,
+ .get_stats_count = gfar_stats_count,
+ .get_ethtool_stats = gfar_fill_stats,
+};
+
+struct ethtool_ops gfar_normon_ethtool_ops = {
+ .get_settings = gfar_gsettings,
+ .get_drvinfo = gfar_gdrvinfo,
+ .get_regs_len = gfar_reglen,
+ .get_regs = gfar_get_regs,
+ .get_link = ethtool_op_get_link,
+ .get_coalesce = gfar_gcoalesce,
+ .set_coalesce = gfar_scoalesce,
+ .get_ringparam = gfar_gringparam,
+ .set_ringparam = gfar_sringparam,
+ .get_strings = gfar_gstrings_normon,
+ .get_stats_count = gfar_stats_count_normon,
+ .get_ethtool_stats = gfar_fill_stats_normon,
+};
+
+struct ethtool_ops *gfar_op_array[] = {
+ &gfar_ethtool_ops,
+ &gfar_normon_ethtool_ops,
+ &gfar_nocoalesce_ethtool_ops,
+ &gfar_normon_nocoalesce_ethtool_ops
};
diff --git a/trunk/drivers/net/pcmcia/3c574_cs.c b/trunk/drivers/net/pcmcia/3c574_cs.c
index f0fc04bd37c4..c6e8b25f9685 100644
--- a/trunk/drivers/net/pcmcia/3c574_cs.c
+++ b/trunk/drivers/net/pcmcia/3c574_cs.c
@@ -1286,13 +1286,6 @@ static int el3_close(struct net_device *dev)
return 0;
}
-static struct pcmcia_device_id tc574_ids[] = {
- PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0574),
- PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0556, "3CCFEM556.cis"),
- PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, tc574_ids);
-
static struct pcmcia_driver tc574_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -1300,7 +1293,6 @@ static struct pcmcia_driver tc574_driver = {
},
.attach = tc574_attach,
.detach = tc574_detach,
- .id_table = tc574_ids,
};
static int __init init_tc574(void)
diff --git a/trunk/drivers/net/pcmcia/3c589_cs.c b/trunk/drivers/net/pcmcia/3c589_cs.c
index 8fa1b5f0fb68..89abdda1d343 100644
--- a/trunk/drivers/net/pcmcia/3c589_cs.c
+++ b/trunk/drivers/net/pcmcia/3c589_cs.c
@@ -1057,17 +1057,6 @@ static int el3_close(struct net_device *dev)
return 0;
}
-static struct pcmcia_device_id tc589_ids[] = {
- PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0101, 0x0562),
- PCMCIA_MFC_DEVICE_PROD_ID1(0, "Motorola MARQUIS", 0xf03e4e77),
- PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0589),
- PCMCIA_DEVICE_PROD_ID12("Farallon", "ENet", 0x58d93fc4, 0x992c2202),
- PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0035, "3CXEM556.cis"),
- PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x003d, "3CXEM556.cis"),
- PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, tc589_ids);
-
static struct pcmcia_driver tc589_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -1075,7 +1064,6 @@ static struct pcmcia_driver tc589_driver = {
},
.attach = tc589_attach,
.detach = tc589_detach,
- .id_table = tc589_ids,
};
static int __init init_tc589(void)
diff --git a/trunk/drivers/net/pcmcia/axnet_cs.c b/trunk/drivers/net/pcmcia/axnet_cs.c
index 23ce77b1d5b0..853b586e481a 100644
--- a/trunk/drivers/net/pcmcia/axnet_cs.c
+++ b/trunk/drivers/net/pcmcia/axnet_cs.c
@@ -850,34 +850,6 @@ static void block_output(struct net_device *dev, int count,
outsw(nic_base + AXNET_DATAPORT, buf, count>>1);
}
-static struct pcmcia_device_id axnet_ids[] = {
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x016c, 0x0081),
- PCMCIA_DEVICE_MANF_CARD(0x018a, 0x0301),
- PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0301),
- PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0303),
- PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0309),
- PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1106),
- PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab),
- PCMCIA_DEVICE_PROD_ID124("Fast Ethernet", "16-bit PC Card", "AX88190", 0xb4be14e3, 0x9a12eb6a, 0xab9be5ef),
- PCMCIA_DEVICE_PROD_ID12("ASIX", "AX88190", 0x0959823b, 0xab9be5ef),
- PCMCIA_DEVICE_PROD_ID12("Billionton", "LNA-100B", 0x552ab682, 0xbc3b87e1),
- PCMCIA_DEVICE_PROD_ID12("CHEETAH ETHERCARD", "EN2228", 0x00fa7bc8, 0x00e990cc),
- PCMCIA_DEVICE_PROD_ID12("CNet", "CNF301", 0xbc477dde, 0x78c5f40b),
- PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXD", 0x5261440f, 0x436768c5),
- PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEtherII PCC-TXD", 0x5261440f, 0x730df72e),
- PCMCIA_DEVICE_PROD_ID12("Dynalink", "L100C16", 0x55632fd5, 0x66bc2a90),
- PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V3)", 0x0733cc81, 0x232019a8),
- PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC3-TX", 0x481e0094, 0xf91af609),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "100BASE", 0x281f1c5d, 0x7c2add04),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEtherCard", 0x281f1c5d, 0x7ef26116),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FEP501", 0x281f1c5d, 0x2e272058),
- PCMCIA_DEVICE_PROD_ID14("Network Everywhere", "AX88190", 0x820a67b6, 0xab9be5ef),
- /* this is not specific enough */
- /* PCMCIA_DEVICE_MANF_CARD(0x021b, 0x0202), */
- PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, axnet_ids);
-
static struct pcmcia_driver axnet_cs_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -885,7 +857,6 @@ static struct pcmcia_driver axnet_cs_driver = {
},
.attach = axnet_attach,
.detach = axnet_detach,
- .id_table = axnet_ids,
};
static int __init init_axnet_cs(void)
diff --git a/trunk/drivers/net/pcmcia/com20020_cs.c b/trunk/drivers/net/pcmcia/com20020_cs.c
index 68d58cc58d31..4294e1e3f156 100644
--- a/trunk/drivers/net/pcmcia/com20020_cs.c
+++ b/trunk/drivers/net/pcmcia/com20020_cs.c
@@ -483,11 +483,7 @@ static int com20020_event(event_t event, int priority,
return 0;
} /* com20020_event */
-static struct pcmcia_device_id com20020_ids[] = {
- PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
- PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, com20020_ids);
+
static struct pcmcia_driver com20020_cs_driver = {
.owner = THIS_MODULE,
@@ -496,7 +492,6 @@ static struct pcmcia_driver com20020_cs_driver = {
},
.attach = com20020_attach,
.detach = com20020_detach,
- .id_table = com20020_ids,
};
static int __init init_com20020_cs(void)
diff --git a/trunk/drivers/net/pcmcia/fmvj18x_cs.c b/trunk/drivers/net/pcmcia/fmvj18x_cs.c
index 917adbbf0b5b..0424865e8094 100644
--- a/trunk/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/trunk/drivers/net/pcmcia/fmvj18x_cs.c
@@ -435,9 +435,7 @@ static void fmvj18x_config(dev_link_t *link)
pcmcia_get_status(handle, &status);
if (status.CardState & CS_EVENT_3VCARD)
link->conf.Vcc = 33; /* inserted in 3.3V slot */
- } else if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410
- || le16_to_cpu(buf[1]) == PRODID_TDK_NP9610
- || le16_to_cpu(buf[1]) == PRODID_TDK_MN3200) {
+ } else if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410) {
/* MultiFunction Card */
link->conf.ConfigBase = 0x800;
link->conf.ConfigIndex = 0x47;
@@ -766,31 +764,6 @@ static int fmvj18x_event(event_t event, int priority,
return 0;
} /* fmvj18x_event */
-static struct pcmcia_device_id fmvj18x_ids[] = {
- PCMCIA_DEVICE_MANF_CARD(0x0004, 0x0004),
- PCMCIA_DEVICE_PROD_ID12("EAGLE Technology", "NE200 ETHERNET LAN MBH10302 04", 0x528c88c4, 0x74f91e59),
- PCMCIA_DEVICE_PROD_ID12("Eiger Labs,Inc", "EPX-10BT PC Card Ethernet 10BT", 0x53af556e, 0x877f9922),
- PCMCIA_DEVICE_PROD_ID12("Eiger labs,Inc.", "EPX-10BT PC Card Ethernet 10BT", 0xf47e6c66, 0x877f9922),
- PCMCIA_DEVICE_PROD_ID12("FUJITSU", "LAN Card(FMV-J182)", 0x6ee5a3d8, 0x5baf31db),
- PCMCIA_DEVICE_PROD_ID12("FUJITSU", "MBH10308", 0x6ee5a3d8, 0x3f04875e),
- PCMCIA_DEVICE_PROD_ID12("FUJITSU TOWA", "LA501", 0xb8451188, 0x12939ba2),
- PCMCIA_DEVICE_PROD_ID12("HITACHI", "HT-4840-11", 0xf4f43949, 0x773910f4),
- PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310B Ver1.0 ", 0x8cef4d3a, 0x075fc7b6),
- PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310 Ver1.0 ", 0x8cef4d3a, 0xbccf43e6),
- PCMCIA_DEVICE_PROD_ID12("RATOC System Inc.", "10BASE_T CARD R280", 0x85c10e17, 0xd9413666),
- PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CD02x", 0x1eae9475, 0x8fa0ee70),
- PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CF010", 0x1eae9475, 0x7683bc9a),
- PCMCIA_DEVICE_PROD_ID1("CONTEC Co.,Ltd.", 0x58d8fee2),
- PCMCIA_DEVICE_PROD_ID1("PCMCIA LAN MBH10304 ES", 0x2599f454),
- PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da),
- PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a),
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a),
- PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids);
-
static struct pcmcia_driver fmvj18x_cs_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -798,7 +771,6 @@ static struct pcmcia_driver fmvj18x_cs_driver = {
},
.attach = fmvj18x_attach,
.detach = fmvj18x_detach,
- .id_table = fmvj18x_ids,
};
static int __init init_fmvj18x_cs(void)
diff --git a/trunk/drivers/net/pcmcia/ibmtr_cs.c b/trunk/drivers/net/pcmcia/ibmtr_cs.c
index cf6d073ea558..f0ff06e20410 100644
--- a/trunk/drivers/net/pcmcia/ibmtr_cs.c
+++ b/trunk/drivers/net/pcmcia/ibmtr_cs.c
@@ -508,13 +508,6 @@ static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase)
return;
}
-static struct pcmcia_device_id ibmtr_ids[] = {
- PCMCIA_DEVICE_PROD_ID12("3Com", "TokenLink Velocity PC Card", 0x41240e5b, 0x82c3734e),
- PCMCIA_DEVICE_PROD_ID12("IBM", "TOKEN RING", 0xb569a6e5, 0xbf8eed47),
- PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, ibmtr_ids);
-
static struct pcmcia_driver ibmtr_cs_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -522,7 +515,6 @@ static struct pcmcia_driver ibmtr_cs_driver = {
},
.attach = ibmtr_attach,
.detach = ibmtr_detach,
- .id_table = ibmtr_ids,
};
static int __init init_ibmtr_cs(void)
diff --git a/trunk/drivers/net/pcmcia/nmclan_cs.c b/trunk/drivers/net/pcmcia/nmclan_cs.c
index b86e7253fbfc..4603807fcafb 100644
--- a/trunk/drivers/net/pcmcia/nmclan_cs.c
+++ b/trunk/drivers/net/pcmcia/nmclan_cs.c
@@ -1675,13 +1675,6 @@ static void set_multicast_list(struct net_device *dev)
} /* set_multicast_list */
-static struct pcmcia_device_id nmclan_ids[] = {
- PCMCIA_DEVICE_PROD_ID12("New Media Corporation", "Ethernet", 0x085a850b, 0x00b2e941),
- PCMCIA_DEVICE_PROD_ID12("Portable Add-ons", "Ethernet", 0x0ebf1d60, 0x00b2e941),
- PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, nmclan_ids);
-
static struct pcmcia_driver nmclan_cs_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -1689,7 +1682,6 @@ static struct pcmcia_driver nmclan_cs_driver = {
},
.attach = nmclan_attach,
.detach = nmclan_detach,
- .id_table = nmclan_ids,
};
static int __init init_nmclan_cs(void)
diff --git a/trunk/drivers/net/pcmcia/pcnet_cs.c b/trunk/drivers/net/pcmcia/pcnet_cs.c
index 855a45d062b1..f3ea4a9f2bf1 100644
--- a/trunk/drivers/net/pcmcia/pcnet_cs.c
+++ b/trunk/drivers/net/pcmcia/pcnet_cs.c
@@ -1637,208 +1637,6 @@ static int setup_shmem_window(dev_link_t *link, int start_pg,
/*====================================================================*/
-static struct pcmcia_device_id pcnet_ids[] = {
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0057, 0x0021),
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0104, 0x000a),
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0xea15),
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0x3341),
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0xc0ab),
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x021b, 0x0101),
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x08a1, 0xc0ab),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "AnyCom", "Fast Ethernet ", 0x578ba6e7, 0x02d92d1e),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
- PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c),
- PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3),
- PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15),
- PCMCIA_MFC_DEVICE_PROD_ID123(0, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f),
- PCMCIA_MFC_DEVICE_PROD_ID2(0, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
- PCMCIA_DEVICE_MANF_CARD(0x0057, 0x1004),
- PCMCIA_DEVICE_MANF_CARD(0x0104, 0x000d),
- PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0075),
- PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0145),
- PCMCIA_DEVICE_MANF_CARD(0x0149, 0x0230),
- PCMCIA_DEVICE_MANF_CARD(0x0149, 0x4530),
-/* PCMCIA_DEVICE_MANF_CARD(0x0149, 0xc1ab), conflict with axnet_cs */
- PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0110),
- PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x2328),
- PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x8041),
- PCMCIA_DEVICE_MANF_CARD(0x0213, 0x2452),
-/* PCMCIA_DEVICE_MANF_CARD(0x021b, 0x0202), conflict with axnet_cs */
- PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0300),
- PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0307),
- PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030a),
- PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1103),
- PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1121),
- PCMCIA_DEVICE_PROD_ID12("2408LAN", "Ethernet", 0x352fff7f, 0x00b2e941),
- PCMCIA_DEVICE_PROD_ID123("Cardwell", "PCMCIA", "ETHERNET", 0x9533672e, 0x281f1c5d, 0x3ff7175b),
- PCMCIA_DEVICE_PROD_ID123("CNet ", "CN30BC", "ETHERNET", 0x9fe55d3d, 0x85601198, 0x3ff7175b),
- PCMCIA_DEVICE_PROD_ID123("Digital", "Ethernet", "Adapter", 0x9999ab35, 0x00b2e941, 0x4b0d829e),
- PCMCIA_DEVICE_PROD_ID123("Edimax Technology Inc.", "PCMCIA", "Ethernet Card", 0x738a0019, 0x281f1c5d, 0x5e9d92c0),
- PCMCIA_DEVICE_PROD_ID123("EFA ", "EFA207", "ETHERNET", 0x3d294be4, 0xeb9aab6c, 0x3ff7175b),
- PCMCIA_DEVICE_PROD_ID123("I-O DATA", "PCLA", "ETHERNET", 0x1d55d7ec, 0xe4c64d34, 0x3ff7175b),
- PCMCIA_DEVICE_PROD_ID123("IO DATA", "PCLATE", "ETHERNET", 0x547e66dc, 0x6b260753, 0x3ff7175b),
- PCMCIA_DEVICE_PROD_ID123("KingMax Technology Inc.", "EN10-T2", "PCMCIA Ethernet Card", 0x932b7189, 0x699e4436, 0x6f6652e0),
- PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2216", 0x281f1c5d, 0xd4cd2f20, 0xb87add82),
- PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2620", 0x281f1c5d, 0xd4cd2f20, 0x7d3d83a8),
- PCMCIA_DEVICE_PROD_ID1("2412LAN", 0x67f236ab),
- PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2212", 0xdfc6b5b2, 0xcb112a11),
- PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2216-PCMCIA-ETHERNET", 0xdfc6b5b2, 0x5542bfff),
- PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA100-PCM-T V2 100/10M LAN PC Card", 0xbb7fbdd7, 0xcd91cc68),
- PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA-PCM", 0xbb7fbdd7, 0x5ba10d49),
- PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA100-PCM V2", 0x36634a66, 0xc6d05997),
- PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA-PCM_V2", 0xbb7fBdd7, 0x28e299f8),
- PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA-PCM V3", 0x36634a66, 0x62241d96),
- PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8010", 0x5070a7f9, 0x82f96e96),
- PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8610", 0x5070a7f9, 0x86741224),
- PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002", 0x93b15570, 0x75ec3efb),
- PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002T", 0x93b15570, 0x461c5247),
- PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8010", 0x93b15570, 0x82f96e96),
- PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet", 0x578ba6e7, 0x0a9888c1),
- PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet 10/100", 0x578ba6e7, 0x939fedbd),
- PCMCIA_DEVICE_PROD_ID12("AROWANA", "PCMCIA Ethernet LAN Card", 0x313adbc8, 0x08d9f190),
- PCMCIA_DEVICE_PROD_ID12("ASANTE", "FriendlyNet PC Card", 0x3a7ade0f, 0x41c64504),
- PCMCIA_DEVICE_PROD_ID12("Billionton", "LNT-10TB", 0x552ab682, 0xeeb1ba6a),
- PCMCIA_DEVICE_PROD_ID12("CF", "10Base-Ethernet", 0x44ebf863, 0x93ae4d79),
- PCMCIA_DEVICE_PROD_ID12("CNet", "CN40BC Ethernet", 0xbc477dde, 0xfba775a7),
- PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "BASEline PCMCIA 10 MBit Ethernetadapter", 0xfa2e424d, 0xe9190d8a),
- PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "FASTline PCMCIA 10/100 Fast-Ethernet", 0xfa2e424d, 0x3953d9b9),
- PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722),
- PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2),
- PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd),
- PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d),
- PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa),
- PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9),
- PCMCIA_DEVICE_PROD_ID12("Corega,K.K.", "Ethernet LAN Card", 0x110d26d9, 0x9fd2f0a2),
- PCMCIA_DEVICE_PROD_ID12("corega,K.K.", "Ethernet LAN Card", 0x9791a90e, 0x9fd2f0a2),
- PCMCIA_DEVICE_PROD_ID12("CouplerlessPCMCIA", "100BASE", 0xee5af0ad, 0x7c2add04),
- PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-010", 0x77008979, 0x9d8d445d),
- PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-110E 10/100M LAN Card", 0x77008979, 0xfd184814),
- PCMCIA_DEVICE_PROD_ID12("DataTrek.", "NetCard ", 0x5cd66d9d, 0x84697ce0),
- PCMCIA_DEVICE_PROD_ID12("Dayna Communications, Inc.", "CommuniCard E", 0x0c629325, 0xb4e7dbaf),
- PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100", 0x697403d8, 0xe160b995),
- PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100 Dongless", 0x697403d8, 0xa6d3b233),
- PCMCIA_DEVICE_PROD_ID12("DIGITAL", "DEPCM-XX", 0x69616cb3, 0xe600e76e),
- PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-650", 0x1a424a1c, 0xf28c8398),
- PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-660", 0x1a424a1c, 0xd9a1d05b),
- PCMCIA_DEVICE_PROD_ID12("D-Link", "DFE-650", 0x1a424a1c, 0x0f0073f9),
- PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 PC Card", 0x725b842d, 0xf1efee84),
- PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 Port Attached PC Card", 0x725b842d, 0x2db1f8e9),
- PCMCIA_DEVICE_PROD_ID12("Dynalink", "L10BC", 0x55632fd5, 0xdc65f2b1),
- PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10BC", 0x6a26d1cf, 0xdc65f2b1),
- PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10C", 0x6a26d1cf, 0xc4f84efb),
- PCMCIA_DEVICE_PROD_ID12("E-CARD", "E-CARD", 0x6701da11, 0x6701da11),
- PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet 10BaseT card", 0x53c864c6, 0xedd059f6),
- PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet Combo card", 0x53c864c6, 0x929c486c),
- PCMCIA_DEVICE_PROD_ID12("Ethernet", "Adapter", 0x00b2e941, 0x4b0d829e),
- PCMCIA_DEVICE_PROD_ID12("Ethernet Adapter", "E2000 PCMCIA Ethernet", 0x96767301, 0x71fbbc61),
- PCMCIA_DEVICE_PROD_ID12("Ethernet PCMCIA adapter", "EP-210", 0x8dd86181, 0xf2b52517),
- PCMCIA_DEVICE_PROD_ID12("Fast Ethernet", "Adapter", 0xb4be14e3, 0x4b0d829e),
- PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2000", 0x2a151fac, 0xf00555cb),
- PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2220", 0x2a151fac, 0xc1b7e327),
- PCMCIA_DEVICE_PROD_ID12("GVC", "NIC-2000p", 0x76e171bd, 0x6eb1c947),
- PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "Ethernet", 0xe3736c88, 0x00b2e941),
- PCMCIA_DEVICE_PROD_ID12("IC-CARD", "IC-CARD", 0x60cb09a6, 0x60cb09a6),
- PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCETTX", 0x547e66dc, 0x6fc5459b),
- PCMCIA_DEVICE_PROD_ID12("iPort", "10/100 Ethernet Card", 0x56c538d2, 0x11b0ffc0),
- PCMCIA_DEVICE_PROD_ID12("KANSAI ELECTRIC CO.,LTD", "KLA-PCM/T", 0xb18dc3b4, 0xcc51a956),
- PCMCIA_DEVICE_PROD_ID12("KCI", "PE520 PCMCIA Ethernet Adapter", 0xa89b87d3, 0x1eb88e64),
- PCMCIA_DEVICE_PROD_ID12("KINGMAX", "EN10T2T", 0x7bcb459a, 0xa5c81fa5),
- PCMCIA_DEVICE_PROD_ID12("Kingston", "KNE-PC2", 0x1128e633, 0xce2a89b3),
- PCMCIA_DEVICE_PROD_ID12("Kingston Technology Corp.", "EtheRx PC Card Ethernet Adapter", 0x313c7be3, 0x0afb54a2),
- PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-10/100CD", 0x1b7827b2, 0xcda71d1c),
- PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDF", 0x1b7827b2, 0xfec71e40),
- PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDL/T", 0x1b7827b2, 0x79fba4f7),
- PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDS", 0x1b7827b2, 0x931afaab),
- PCMCIA_DEVICE_PROD_ID12("Linksys", "Combo PCMCIA EthernetCard (EC2T)", 0x0733cc81, 0x32ee8c78),
- PCMCIA_DEVICE_PROD_ID12("LINKSYS", "E-CARD", 0xf7cb0b07, 0x6701da11),
- PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 Integrated PC Card (PCM100)", 0x0733cc81, 0x453c3f9d),
- PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100)", 0x0733cc81, 0x66c5a389),
- PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V2)", 0x0733cc81, 0x3a3b28e9),
- PCMCIA_DEVICE_PROD_ID12("Linksys", "HomeLink Phoneline ", 0x0733cc81, 0x5e07cfa0),
- PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TX", 0x88fcdeda, 0x6d772737),
- PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN20T", 0x88fcdeda, 0x81090922),
- PCMCIA_DEVICE_PROD_ID12("LONGSHINE", "PCMCIA Ethernet Card", 0xf866b0b0, 0x6f6652e0),
- PCMCIA_DEVICE_PROD_ID12("MACNICA", "ME1-JEIDA", 0x20841b68, 0xaf8a3578),
- PCMCIA_DEVICE_PROD_ID12("Macsense", "MPC-10", 0xd830297f, 0xd265c307),
- PCMCIA_DEVICE_PROD_ID12("Matsushita Electric Industrial Co.,LTD.", "CF-VEL211", 0x44445376, 0x8ded41d4),
- PCMCIA_DEVICE_PROD_ID12("MAXTECH", "PCN2000", 0x78d64bc0, 0xca0ca4b8),
- PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-T", 0x481e0094, 0xa2eb0cf3),
- PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-TX", 0x481e0094, 0x41a6916c),
- PCMCIA_DEVICE_PROD_ID12("Microcom C.E.", "Travel Card LAN 10/100", 0x4b91cec7, 0xe70220d6),
- PCMCIA_DEVICE_PROD_ID12("Microdyne", "NE4200", 0x2e6da59b, 0x0478e472),
- PCMCIA_DEVICE_PROD_ID12("MIDORI ELEC.", "LT-PCMT", 0x648d55c1, 0xbde526c7),
- PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover 4100", 0x36e1191f, 0x60c229b9),
- PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover NE4100", 0x36e1191f, 0xa6617ec8),
- PCMCIA_DEVICE_PROD_ID12("NEC", "PC-9801N-J12", 0x18df0ba0, 0xbc912d76),
- PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA410TX", 0x9aa79dc3, 0x60e5bc0e),
- PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA411", 0x9aa79dc3, 0x40fad875),
- PCMCIA_DEVICE_PROD_ID12("Network Everywhere", "Fast Ethernet 10/100 PC Card", 0x820a67b6, 0x31ed1a5f),
- PCMCIA_DEVICE_PROD_ID12("NextCom K.K.", "Next Hawk", 0xaedaec74, 0xad050ef1),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100Mbps Ethernet Card", 0x281f1c5d, 0x6e41773b),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet", 0x281f1c5d, 0x00b2e941),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET", 0x281f1c5d, 0x3ff7175b),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet 10BaseT Card", 0x281f1c5d, 0x4de2f6c8),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Card", 0x281f1c5d, 0x5e9d92c0),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Combo card", 0x281f1c5d, 0x929c486c),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET V1.0", 0x281f1c5d, 0x4d8817c8),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEthernet", 0x281f1c5d, 0xfe871eeb),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Fast-Ethernet", 0x281f1c5d, 0x45f1f3b4),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FAST ETHERNET CARD", 0x281f1c5d, 0xec5dbca7),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA LAN", "Ethernet", 0x7500e246, 0x00b2e941),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "LNT-10TN", 0x281f1c5d, 0xe707f641),
- PCMCIA_DEVICE_PROD_ID12("PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "UE2212", 0x281f1c5d, 0xbf17199b),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", " Ethernet NE2000 Compatible", 0x281f1c5d, 0x42d5d7e1),
- PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10baseT 3.3V", 0xebf91155, 0x30074c80),
- PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10BaseT 3.3V", 0xebf91155, 0x7f5a4f50),
- PCMCIA_DEVICE_PROD_ID12("Psion Dacom", "Gold Card Ethernet", 0xf5f025c2, 0x3a30e110),
- PCMCIA_DEVICE_PROD_ID12("=RELIA==", "Ethernet", 0xcdd0644a, 0x00b2e941),
- PCMCIA_DEVICE_PROD_ID12("RP", "1625B Ethernet NE2000 Compatible", 0xe3e66e22, 0xb96150df),
- PCMCIA_DEVICE_PROD_ID12("RPTI", "EP400 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4a7e2ae0),
- PCMCIA_DEVICE_PROD_ID12("RPTI", "EP401 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4bcbd7fd),
- PCMCIA_DEVICE_PROD_ID12("RPTI LTD.", "EP400", 0xc53ac515, 0x81e39388),
- PCMCIA_DEVICE_PROD_ID12("SCM", "Ethernet Combo card", 0xbdc3b102, 0x929c486c),
- PCMCIA_DEVICE_PROD_ID12("Seiko Epson Corp.", "Ethernet", 0x09928730, 0x00b2e941),
- PCMCIA_DEVICE_PROD_ID12("SMC", "EZCard-10-PCMCIA", 0xc4f8b18b, 0xfb21d265),
- PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision D", 0xc70a4760, 0x2ade483e),
- PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision E", 0xc70a4760, 0x5dd978a8),
- PCMCIA_DEVICE_PROD_ID12("TDK", "LAK-CD031 for PCMCIA", 0x1eae9475, 0x0ed386fa),
- PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE450T", 0x466b05f0, 0x8b74bc4f),
- PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE550T", 0x466b05f0, 0x33c8db2a),
- PCMCIA_DEVICE_PROD_ID13("Hypertec", "EP401", 0x8787bec7, 0xf6e4a31e),
- PCMCIA_DEVICE_PROD_ID13("KingMax Technology Inc.", "Ethernet Card", 0x932b7189, 0x5e9d92c0),
- PCMCIA_DEVICE_PROD_ID13("LONGSHINE", "EP401", 0xf866b0b0, 0xf6e4a31e),
- PCMCIA_DEVICE_PROD_ID13("Xircom", "CFE-10", 0x2e3ee845, 0x22a49f89),
- PCMCIA_DEVICE_PROD_ID1("CyQ've 10 Base-T LAN CARD", 0x94faf360),
- PCMCIA_DEVICE_PROD_ID1("EP-210 PCMCIA LAN CARD.", 0x8850b4de),
- PCMCIA_DEVICE_PROD_ID1("ETHER-C16", 0x06a8514f),
- PCMCIA_DEVICE_PROD_ID1("IC-CARD", 0x60cb09a6),
- PCMCIA_DEVICE_PROD_ID1("NE2000 Compatible", 0x75b8ad5a),
- PCMCIA_DEVICE_PROD_ID2("EN-6200P2", 0xa996d078),
- /* too generic! */
- /* PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100 Ethernet Card", 0x281f1c5d, 0x11b0ffc0), */
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "PCMLM28.cis"),
- PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"),
- PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"),
- PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "DP83903.cis"),
- PCMCIA_DEVICE_CIS_MANF_CARD(0xc00f, 0x0002, "LA-PCM.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("KTI", "PE520 PLUS", 0xad180345, 0x9d58d392, "PE520.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "NE2K.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "PE-200.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "tamarack.cis"),
- PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, pcnet_ids);
-
static struct pcmcia_driver pcnet_driver = {
.drv = {
.name = "pcnet_cs",
@@ -1846,7 +1644,6 @@ static struct pcmcia_driver pcnet_driver = {
.attach = pcnet_attach,
.detach = pcnet_detach,
.owner = THIS_MODULE,
- .id_table = pcnet_ids,
};
static int __init init_pcnet_cs(void)
diff --git a/trunk/drivers/net/pcmcia/smc91c92_cs.c b/trunk/drivers/net/pcmcia/smc91c92_cs.c
index bc01c88c6709..8a5e52c40e46 100644
--- a/trunk/drivers/net/pcmcia/smc91c92_cs.c
+++ b/trunk/drivers/net/pcmcia/smc91c92_cs.c
@@ -2327,38 +2327,6 @@ static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
return rc;
}
-static struct pcmcia_device_id smc91c92_ids[] = {
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0109, 0x0501),
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0140, 0x000a),
- PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63),
- PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63),
- PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef),
- PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "XJEM1144/CCEM1144", "PCMCIA MODEM", 0xf510db04, 0x52d21e1e, 0xbd6c43ef),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "Ositech", "Trumpcard", 0x0c2f80cd, 0x0573c29f),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "Ositech", "Trumpcard", 0x0c2f80cd, 0x0573c29f),
- PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x016c, 0x0020),
- PCMCIA_DEVICE_MANF_CARD(0x016c, 0x0023),
- PCMCIA_DEVICE_PROD_ID123("BASICS by New Media Corporation", "Ethernet", "SMC91C94", 0x23c78a9d, 0x00b2e941, 0xcef397fb),
- PCMCIA_DEVICE_PROD_ID12("ARGOSY", "Fast Ethernet PCCard", 0x78f308dc, 0xdcea68bc),
- PCMCIA_DEVICE_PROD_ID12("dit Co., Ltd.", "PC Card-10/100BTX", 0xe59365c8, 0x6a2161d1),
- PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L100C", 0x6a26d1cf, 0xc16ce9c5),
- PCMCIA_DEVICE_PROD_ID12("Farallon", "Farallon Enet", 0x58d93fc4, 0x244734e9),
- PCMCIA_DEVICE_PROD_ID12("Megahertz", "CC10BT/2", 0x33234748, 0x3c95b953),
- PCMCIA_DEVICE_PROD_ID12("MELCO/SMC", "LPC-TX", 0xa2cd8e6d, 0x42da662a),
- PCMCIA_DEVICE_PROD_ID12("Ositech", "Trumpcard", 0x0c2f80cd, 0x0573c29f),
- PCMCIA_DEVICE_PROD_ID12("Ositech", "Trumpcard", 0x0c2f80cd, 0x0573c29f),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Fast Ethernet PCCard", 0x281f1c5d, 0xdcea68bc),
- PCMCIA_DEVICE_PROD_ID12("Psion", "10Mb Ethernet", 0x4ef00b21, 0x844be9e9),
- PCMCIA_DEVICE_PROD_ID12("SMC", "EtherEZ Ethernet 8020", 0xc4f8b18b, 0x4a0eeb2d),
- /* These conflict with other cards! */
- /* PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0100), */
- /* PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab), */
- PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, smc91c92_ids);
-
static struct pcmcia_driver smc91c92_cs_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -2366,7 +2334,6 @@ static struct pcmcia_driver smc91c92_cs_driver = {
},
.attach = smc91c92_attach,
.detach = smc91c92_detach,
- .id_table = smc91c92_ids,
};
static int __init init_smc91c92_cs(void)
diff --git a/trunk/drivers/net/pcmcia/xirc2ps_cs.c b/trunk/drivers/net/pcmcia/xirc2ps_cs.c
index 0cd225e1595c..58177d67ea12 100644
--- a/trunk/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/trunk/drivers/net/pcmcia/xirc2ps_cs.c
@@ -1983,33 +1983,6 @@ do_stop(struct net_device *dev)
return 0;
}
-static struct pcmcia_device_id xirc2ps_ids[] = {
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0089, 0x110a),
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0138, 0x110a),
- PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea),
- PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM33", 0x2e3ee845, 0x80609023),
- PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM56", 0x2e3ee845, 0xa650c32a),
- PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29),
- PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "Xircom", "CreditCard Ethernet", 0x2e3ee845, 0xc0e778c2),
- PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x010a),
- PCMCIA_DEVICE_PROD_ID13("Toshiba Information Systems", "TPCENET", 0x1b3b94fe, 0xf381c1a2),
- PCMCIA_DEVICE_PROD_ID13("Xircom", "CE3-10/100", 0x2e3ee845, 0x0ec0ac37),
- PCMCIA_DEVICE_PROD_ID13("Xircom", "PS-CE2-10", 0x2e3ee845, 0x947d9073),
- PCMCIA_DEVICE_PROD_ID13("Xircom", "R2E-100BTX", 0x2e3ee845, 0x2464a6e3),
- PCMCIA_DEVICE_PROD_ID13("Xircom", "RE-10", 0x2e3ee845, 0x3e08d609),
- PCMCIA_DEVICE_PROD_ID13("Xircom", "XE2000", 0x2e3ee845, 0xf7188e46),
- PCMCIA_DEVICE_PROD_ID12("Compaq", "Ethernet LAN Card", 0x54f7c49c, 0x9fd2f0a2),
- PCMCIA_DEVICE_PROD_ID12("Compaq", "Netelligent 10/100 PC Card", 0x54f7c49c, 0xefe96769),
- PCMCIA_DEVICE_PROD_ID12("Intel", "EtherExpress(TM) PRO/100 PC Card Mobile Adapter16", 0x816cc815, 0x174397db),
- PCMCIA_DEVICE_PROD_ID12("Toshiba", "10/100 Ethernet PC Card", 0x44a09d9c, 0xb44deecf),
- /* also matches CFE-10 cards! */
- /* PCMCIA_DEVICE_MANF_CARD(0x0105, 0x010a), */
- PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, xirc2ps_ids);
-
-
static struct pcmcia_driver xirc2ps_cs_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -2017,7 +1990,6 @@ static struct pcmcia_driver xirc2ps_cs_driver = {
},
.attach = xirc2ps_attach,
.detach = xirc2ps_detach,
- .id_table = xirc2ps_ids,
};
static int __init
diff --git a/trunk/drivers/net/pcnet32.c b/trunk/drivers/net/pcnet32.c
index 3213f3e50487..13f114876965 100644
--- a/trunk/drivers/net/pcnet32.c
+++ b/trunk/drivers/net/pcnet32.c
@@ -850,7 +850,7 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data)
if ((!data) || (data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)))
data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
- msleep_interruptible(data * 1000);
+ schedule_timeout(data * HZ);
del_timer_sync(&lp->blink_timer);
/* Restore the original value of the bcrs */
diff --git a/trunk/drivers/net/sb1000.c b/trunk/drivers/net/sb1000.c
index d6388e1533f0..e15369c8d165 100644
--- a/trunk/drivers/net/sb1000.c
+++ b/trunk/drivers/net/sb1000.c
@@ -90,6 +90,7 @@ static int sb1000_close(struct net_device *dev);
/* SB1000 hardware routines to be used during open/configuration phases */
+static inline void nicedelay(unsigned long usecs);
static inline int card_wait_for_busy_clear(const int ioaddr[],
const char* name);
static inline int card_wait_for_ready(const int ioaddr[], const char* name,
@@ -253,6 +254,13 @@ static struct pnp_driver sb1000_driver = {
static const int TimeOutJiffies = (875 * HZ) / 100;
+static inline void nicedelay(unsigned long usecs)
+{
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(HZ);
+ return;
+}
+
/* Card Wait For Busy Clear (cannot be used during an interrupt) */
static inline int
card_wait_for_busy_clear(const int ioaddr[], const char* name)
@@ -467,7 +475,7 @@ sb1000_reset(const int ioaddr[], const char* name)
udelay(1000);
outb(0x0, port);
inb(port);
- ssleep(1);
+ nicedelay(60000);
outb(0x4, port);
inb(port);
udelay(1000);
@@ -529,7 +537,7 @@ sb1000_activate(const int ioaddr[], const char* name)
const unsigned char Command0[6] = {0x80, 0x11, 0x00, 0x00, 0x00, 0x00};
const unsigned char Command1[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00};
- ssleep(1);
+ nicedelay(50000);
if ((status = card_send_command(ioaddr, name, Command0, st)))
return status;
if ((status = card_send_command(ioaddr, name, Command1, st)))
@@ -936,7 +944,7 @@ sb1000_open(struct net_device *dev)
/* initialize sb1000 */
if ((status = sb1000_reset(ioaddr, name)))
return status;
- ssleep(1);
+ nicedelay(200000);
if ((status = sb1000_check_CRC(ioaddr, name)))
return status;
diff --git a/trunk/drivers/net/skfp/Makefile b/trunk/drivers/net/skfp/Makefile
index cb23580fcffa..5f4bb1a67400 100644
--- a/trunk/drivers/net/skfp/Makefile
+++ b/trunk/drivers/net/skfp/Makefile
@@ -6,8 +6,8 @@ obj-$(CONFIG_SKFP) += skfp.o
skfp-objs := skfddi.o hwmtm.o fplustm.o smt.o cfm.o \
ecm.o pcmplc.o pmf.o queue.o rmt.o \
- smtdef.o smtinit.o smttimer.o srf.o hwt.o \
- drvfbi.o ess.o
+ smtdef.o smtinit.o smttimer.o srf.o smtparse.o\
+ hwt.o drvfbi.o ess.o
# NOTE:
# Compiling this driver produces some warnings (and some more are
diff --git a/trunk/drivers/net/skfp/drvfbi.c b/trunk/drivers/net/skfp/drvfbi.c
index 5b475833f645..052e841ba187 100644
--- a/trunk/drivers/net/skfp/drvfbi.c
+++ b/trunk/drivers/net/skfp/drvfbi.c
@@ -105,8 +105,8 @@ extern int AIX_vpdReadByte() ;
#endif
-/* Prototype of a local function. */
-static void smt_stop_watchdog(struct s_smc *smc);
+/* Prototypes of local functions. */
+void smt_stop_watchdog(struct s_smc *smc);
#ifdef MCA
static int read_card_id() ;
@@ -631,7 +631,7 @@ void plc_clear_irq(struct s_smc *smc, int p)
* LED_Y_OFF just switch yellow LED off
* LED_Y_ON just switch yello LED on
*/
-static void led_indication(struct s_smc *smc, int led_event)
+void led_indication(struct s_smc *smc, int led_event)
{
/* use smc->hw.mac_ring_is_up == TRUE
* as indication for Ring Operational
@@ -764,6 +764,122 @@ void llc_recover_tx(struct s_smc *smc)
#endif
}
+/*--------------------------- DMA init ----------------------------*/
+#ifdef ISA
+
+/*
+ * init DMA
+ */
+void init_dma(struct s_smc *smc, int dma)
+{
+ SK_UNUSED(smc) ;
+
+ /*
+ * set cascade mode,
+ * clear mask bit (enable DMA cannal)
+ */
+ if (dma > 3) {
+ outp(0xd6,(dma & 0x03) | 0xc0) ;
+ outp(0xd4, dma & 0x03) ;
+ }
+ else {
+ outp(0x0b,(dma & 0x03) | 0xc0) ;
+ outp(0x0a,dma & 0x03) ;
+ }
+}
+
+/*
+ * disable DMA
+ */
+void dis_dma(struct s_smc *smc, int dma)
+{
+ SK_UNUSED(smc) ;
+
+ /*
+ * set mask bit (disable DMA cannal)
+ */
+ if (dma > 3) {
+ outp(0xd4,(dma & 0x03) | 0x04) ;
+ }
+ else {
+ outp(0x0a,(dma & 0x03) | 0x04) ;
+ }
+}
+
+#endif /* ISA */
+
+#ifdef EISA
+
+/*arrays with io addresses of dma controller length and address registers*/
+static const int cntr[8] = { 0x001,0x003,0x005,0x007,0,0x0c6,0x0ca,0x0ce } ;
+static const int base[8] = { 0x000,0x002,0x004,0x006,0,0x0c4,0x0c8,0x0cc } ;
+static const int page[8] = { 0x087,0x083,0x081,0x082,0,0x08b,0x089,0x08a } ;
+
+void init_dma(struct s_smc *smc, int dma)
+{
+ /*
+ * extended mode register
+ * 32 bit IO
+ * type c
+ * TC output
+ * disable stop
+ */
+
+ /* mode read (write) demand */
+ smc->hw.dma_rmode = (dma & 3) | 0x08 | 0x0 ;
+ smc->hw.dma_wmode = (dma & 3) | 0x04 | 0x0 ;
+
+ /* 32 bit IO's, burst DMA mode (type "C") */
+ smc->hw.dma_emode = (dma & 3) | 0x08 | 0x30 ;
+
+ outp((dma < 4) ? 0x40b : 0x4d6,smc->hw.dma_emode) ;
+
+ /* disable chaining */
+ outp((dma < 4) ? 0x40a : 0x4d4,(dma&3)) ;
+
+ /*load dma controller addresses for fast access during set dma*/
+ smc->hw.dma_base_word_count = cntr[smc->hw.dma];
+ smc->hw.dma_base_address = base[smc->hw.dma];
+ smc->hw.dma_base_address_page = page[smc->hw.dma];
+
+}
+
+void dis_dma(struct s_smc *smc, int dma)
+{
+ SK_UNUSED(smc) ;
+
+ outp((dma < 4) ? 0x0a : 0xd4,(dma&3)|4) ;/* mask bit */
+}
+#endif /* EISA */
+
+#ifdef MCA
+void init_dma(struct s_smc *smc, int dma)
+{
+ SK_UNUSED(smc) ;
+ SK_UNUSED(dma) ;
+}
+
+void dis_dma(struct s_smc *smc, int dma)
+{
+ SK_UNUSED(smc) ;
+ SK_UNUSED(dma) ;
+}
+#endif
+
+#ifdef PCI
+void init_dma(struct s_smc *smc, int dma)
+{
+ SK_UNUSED(smc) ;
+ SK_UNUSED(dma) ;
+}
+
+void dis_dma(struct s_smc *smc, int dma)
+{
+ SK_UNUSED(smc) ;
+ SK_UNUSED(dma) ;
+}
+#endif
+
#ifdef MULT_OEM
static int is_equal_num(char comp1[], char comp2[], int num)
{
@@ -1291,7 +1407,7 @@ void smt_start_watchdog(struct s_smc *smc)
#endif /* DEBUG */
}
-static void smt_stop_watchdog(struct s_smc *smc)
+void smt_stop_watchdog(struct s_smc *smc)
{
SK_UNUSED(smc) ; /* Make LINT happy. */
#ifndef DEBUG
@@ -1306,6 +1422,104 @@ static void smt_stop_watchdog(struct s_smc *smc)
}
#ifdef PCI
+static char get_rom_byte(struct s_smc *smc, u_short addr)
+{
+ GET_PAGE(addr) ;
+ return (READ_PROM(ADDR(B2_FDP))) ;
+}
+
+/*
+ * ROM image defines
+ */
+#define ROM_SIG_1 0
+#define ROM_SIG_2 1
+#define PCI_DATA_1 0x18
+#define PCI_DATA_2 0x19
+
+/*
+ * PCI data structure defines
+ */
+#define VPD_DATA_1 0x08
+#define VPD_DATA_2 0x09
+#define IMAGE_LEN_1 0x10
+#define IMAGE_LEN_2 0x11
+#define CODE_TYPE 0x14
+#define INDICATOR 0x15
+
+/*
+ * BEGIN_MANUAL_ENTRY(mac_drv_vpd_read)
+ * mac_drv_vpd_read(smc,buf,size,image)
+ *
+ * function DOWNCALL (FDDIWARE)
+ * reads the VPD data of the FPROM and writes it into the
+ * buffer
+ *
+ * para buf points to the buffer for the VPD data
+ * size size of the VPD data buffer
+ * image boot image; code type of the boot image
+ * image = 0 Intel x86, PC-AT compatible
+ * 1 OPENBOOT standard for PCI
+ * 2-FF reserved
+ *
+ * returns len number of VPD data bytes read form the FPROM
+ * <0 number of read bytes
+ * >0 error: data invalid
+ *
+ * END_MANUAL_ENTRY
+ */
+int mac_drv_vpd_read(struct s_smc *smc, char *buf, int size, char image)
+{
+ u_short ibase ;
+ u_short pci_base ;
+ u_short vpd ;
+ int len ;
+
+ len = 0 ;
+ ibase = 0 ;
+ /*
+ * as long images defined
+ */
+ while (get_rom_byte(smc,ibase+ROM_SIG_1) == 0x55 &&
+ (u_char) get_rom_byte(smc,ibase+ROM_SIG_2) == 0xaa) {
+ /*
+ * get the pointer to the PCI data structure
+ */
+ pci_base = ibase + get_rom_byte(smc,ibase+PCI_DATA_1) +
+ (get_rom_byte(smc,ibase+PCI_DATA_2) << 8) ;
+
+ if (image == get_rom_byte(smc,pci_base+CODE_TYPE)) {
+ /*
+ * we have the right image, read the VPD data
+ */
+ vpd = ibase + get_rom_byte(smc,pci_base+VPD_DATA_1) +
+ (get_rom_byte(smc,pci_base+VPD_DATA_2) << 8) ;
+ if (vpd == ibase) {
+ break ; /* no VPD data */
+ }
+ for (len = 0; len < size; len++,buf++,vpd++) {
+ *buf = get_rom_byte(smc,vpd) ;
+ }
+ break ;
+ }
+ else {
+ /*
+ * try the next image
+ */
+ if (get_rom_byte(smc,pci_base+INDICATOR) & 0x80) {
+ break ; /* this was the last image */
+ }
+ ibase = ibase + get_rom_byte(smc,ibase+IMAGE_LEN_1) +
+ (get_rom_byte(smc,ibase+IMAGE_LEN_2) << 8) ;
+ }
+ }
+
+ return(len) ;
+}
+
+void mac_drv_pci_fix(struct s_smc *smc, u_long fix_value)
+{
+ smc->hw.pci_fix_value = fix_value ;
+}
void mac_do_pci_fix(struct s_smc *smc)
{
diff --git a/trunk/drivers/net/skfp/ess.c b/trunk/drivers/net/skfp/ess.c
index 62b01328c496..fd39b4b2ef7d 100644
--- a/trunk/drivers/net/skfp/ess.c
+++ b/trunk/drivers/net/skfp/ess.c
@@ -102,7 +102,7 @@ void ess_timer_poll(struct s_smc *smc);
void ess_para_change(struct s_smc *smc);
int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
int fs);
-static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead);
+int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead);
/*
@@ -375,7 +375,7 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
* determines the synchronous bandwidth, set the TSYNC register and the
* mib variables SBAPayload, SBAOverhead and fddiMACT-NEG.
*/
-static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead)
+int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead)
{
/*
* determine the synchronous bandwidth (sync_bw) in bytes per T-NEG,
diff --git a/trunk/drivers/net/skfp/fplustm.c b/trunk/drivers/net/skfp/fplustm.c
index a2ed47f1cc70..76e78442fc24 100644
--- a/trunk/drivers/net/skfp/fplustm.c
+++ b/trunk/drivers/net/skfp/fplustm.c
@@ -1114,6 +1114,30 @@ void mac_clear_multicast(struct s_smc *smc)
}
}
+/*
+ BEGIN_MANUAL_ENTRY(if,func;others;2)
+
+ int mac_set_func_addr(smc,f_addr)
+ struct s_smc *smc ;
+ u_long f_addr ;
+
+Function DOWNCALL (SMT, fplustm.c)
+ Set a Token-Ring functional address, the address will
+ be activated after calling mac_update_multicast()
+
+Para f_addr functional bits in non-canonical format
+
+Returns 0: always success
+
+ END_MANUAL_ENTRY()
+ */
+int mac_set_func_addr(struct s_smc *smc, u_long f_addr)
+{
+ smc->hw.fp.func_addr = f_addr ;
+ return(0) ;
+}
+
+
/*
BEGIN_MANUAL_ENTRY(if,func;others;2)
@@ -1178,6 +1202,52 @@ int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can)
return(0) ;
}
+/*
+ BEGIN_MANUAL_ENTRY(if,func;others;2)
+
+ void mac_del_multicast(smc,addr,can)
+ struct s_smc *smc ;
+ struct fddi_addr *addr ;
+ int can ;
+
+Function DOWNCALL (SMT, fplustm.c)
+ Delete an entry from the multicast table
+
+Para addr pointer to a multicast address
+ can = 0: the multicast address has the physical format
+ = 1: the multicast address has the canonical format
+ | 0x80 permanent
+
+ END_MANUAL_ENTRY()
+ */
+void mac_del_multicast(struct s_smc *smc, struct fddi_addr *addr, int can)
+{
+ SK_LOC_DECL(struct fddi_addr,own) ;
+ struct s_fpmc *tb ;
+
+ if (!(tb = mac_get_mc_table(smc,addr,&own,1,can & ~0x80)))
+ return ;
+ /*
+ * permanent addresses must be deleted with perm bit
+ * and vice versa
+ */
+ if (( tb->perm && (can & 0x80)) ||
+ (!tb->perm && !(can & 0x80))) {
+ /*
+ * delete it
+ */
+ if (tb->n) {
+ tb->n-- ;
+ if (tb->perm) {
+ smc->hw.fp.smt_slots_used-- ;
+ }
+ else {
+ smc->hw.fp.os_slots_used-- ;
+ }
+ }
+ }
+}
+
/*
* mode
*/
diff --git a/trunk/drivers/net/skfp/h/cmtdef.h b/trunk/drivers/net/skfp/h/cmtdef.h
index f2f771d8be76..603982debc71 100644
--- a/trunk/drivers/net/skfp/h/cmtdef.h
+++ b/trunk/drivers/net/skfp/h/cmtdef.h
@@ -507,6 +507,7 @@ void pcm_status_state(struct s_smc *smc, int np, int *type, int *state,
int *remote, int *mac);
void plc_config_mux(struct s_smc *smc, int mux);
void sm_lem_evaluate(struct s_smc *smc);
+void smt_clear_una_dna(struct s_smc *smc);
void mac_update_counter(struct s_smc *smc);
void sm_pm_ls_latch(struct s_smc *smc, int phy, int on_off);
void sm_ma_control(struct s_smc *smc, int mode);
@@ -540,9 +541,11 @@ void smt_timer_poll(struct s_smc *smc);
u_long smt_get_time(void);
u_long smt_get_tid(struct s_smc *smc);
void smt_timer_done(struct s_smc *smc);
+void smt_set_defaults(struct s_smc *smc);
void smt_fixup_mib(struct s_smc *smc);
void smt_reset_defaults(struct s_smc *smc, int level);
void smt_agent_task(struct s_smc *smc);
+void smt_please_reconnect(struct s_smc *smc, int reconn_time);
int smt_check_para(struct s_smc *smc, struct smt_header *sm,
const u_short list[]);
void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr);
@@ -565,6 +568,7 @@ int pcm_get_s_port(struct s_smc *smc);
int pcm_rooted_station(struct s_smc *smc);
int cfm_get_mac_input(struct s_smc *smc);
int cfm_get_mac_output(struct s_smc *smc);
+int port_to_mib(struct s_smc *smc, int p);
int cem_build_path(struct s_smc *smc, char *to, int path_index);
int sm_mac_get_tx_state(struct s_smc *smc);
char *get_pcmstate(struct s_smc *smc, int np);
@@ -576,6 +580,8 @@ void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local);
void smt_set_timestamp(struct s_smc *smc, u_char *p);
void mac_set_rx_mode(struct s_smc *smc, int mode);
int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can);
+int mac_set_func_addr(struct s_smc *smc, u_long f_addr);
+void mac_del_multicast(struct s_smc *smc, struct fddi_addr *addr, int can);
void mac_update_multicast(struct s_smc *smc);
void mac_clear_multicast(struct s_smc *smc);
void set_formac_tsync(struct s_smc *smc, long sync_bw);
@@ -593,6 +599,7 @@ void plc_irq(struct s_smc *smc, int np, unsigned int cmd);
int smt_set_mac_opvalues(struct s_smc *smc);
#ifdef TAG_MODE
+void mac_drv_pci_fix(struct s_smc *smc, u_long fix_value);
void mac_do_pci_fix(struct s_smc *smc);
void mac_drv_clear_tx_queue(struct s_smc *smc);
void mac_drv_repair_descr(struct s_smc *smc);
diff --git a/trunk/drivers/net/skfp/h/hwmtm.h b/trunk/drivers/net/skfp/h/hwmtm.h
index 1a606d4bfe5e..4e360af07d77 100644
--- a/trunk/drivers/net/skfp/h/hwmtm.h
+++ b/trunk/drivers/net/skfp/h/hwmtm.h
@@ -261,6 +261,31 @@ struct os_debug {
#define HWM_GET_CURR_TXD(smc,queue) (struct s_smt_fp_txd volatile *)\
(smc)->hw.fp.tx_q[queue].tx_curr_put
+/*
+ * BEGIN_MANUAL_ENTRY(HWM_TX_CHECK)
+ * void HWM_TX_CHECK(smc,frame_status,low_water)
+ *
+ * function MACRO (hardware module, hwmtm.h)
+ * This macro is invoked by the OS-specific before it left it's
+ * driver_send function. This macro calls mac_drv_clear_txd
+ * if the free TxDs of the current transmit queue is equal or
+ * lower than the given low water mark.
+ *
+ * para frame_status status of the frame, see design description
+ * low_water low water mark of free TxD's
+ *
+ * END_MANUAL_ENTRY
+ */
+#ifndef HWM_NO_FLOW_CTL
+#define HWM_TX_CHECK(smc,frame_status,low_water) {\
+ if ((low_water)>=(smc)->hw.fp.tx_q[(frame_status)&QUEUE_A0].tx_free) {\
+ mac_drv_clear_txd(smc) ;\
+ }\
+}
+#else
+#define HWM_TX_CHECK(smc,frame_status,low_water) mac_drv_clear_txd(smc)
+#endif
+
/*
* BEGIN_MANUAL_ENTRY(HWM_GET_RX_FRAG_LEN)
* int HWM_GET_RX_FRAG_LEN(rxd)
diff --git a/trunk/drivers/net/skfp/hwmtm.c b/trunk/drivers/net/skfp/hwmtm.c
index 438f424e6361..18d429021edb 100644
--- a/trunk/drivers/net/skfp/hwmtm.c
+++ b/trunk/drivers/net/skfp/hwmtm.c
@@ -86,7 +86,6 @@ static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue);
static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue);
static SMbuf* get_llc_rx(struct s_smc *smc);
static SMbuf* get_txd_mb(struct s_smc *smc);
-static void mac_drv_clear_txd(struct s_smc *smc);
/*
-------------------------------------------------------------
@@ -147,6 +146,7 @@ extern int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead,
*/
void process_receive(struct s_smc *smc);
void fddi_isr(struct s_smc *smc);
+void mac_drv_clear_txd(struct s_smc *smc);
void smt_free_mbuf(struct s_smc *smc, SMbuf *mb);
void init_driver_fplus(struct s_smc *smc);
void mac_drv_rx_mode(struct s_smc *smc, int mode);
@@ -158,6 +158,7 @@ void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
int frame_status);
+int mac_drv_rx_frag(struct s_smc *smc, void far *virt, int len);
int mac_drv_init(struct s_smc *smc);
int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len,
int frame_status);
@@ -1447,6 +1448,35 @@ void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
NDD_TRACE("RHfE",r,AIX_REVERSE(r->rxd_rbadr),0) ;
}
+#ifndef NDIS_OS2
+/*
+ * BEGIN_MANUAL_ENTRY(mac_drv_rx_frag)
+ * int mac_drv_rx_frag(smc,virt,len)
+ *
+ * function DOWNCALL (hwmtm.c)
+ * mac_drv_rx_frag fills the fragment with a part of the frame.
+ *
+ * para virt the virtual address of the fragment
+ * len the length in bytes of the fragment
+ *
+ * return 0: success code, no errors possible
+ *
+ * END_MANUAL_ENTRY
+ */
+int mac_drv_rx_frag(struct s_smc *smc, void far *virt, int len)
+{
+ NDD_TRACE("RHSB",virt,len,smc->os.hwm.r.mb_pos) ;
+
+ DB_RX("receive from queue: len/virt: = %d/%x",len,virt,4) ;
+ memcpy((char far *)virt,smc->os.hwm.r.mb_pos,len) ;
+ smc->os.hwm.r.mb_pos += len ;
+
+ NDD_TRACE("RHSE",smc->os.hwm.r.mb_pos,0,0) ;
+ return(0) ;
+}
+#endif
+
+
/*
* BEGINN_MANUAL_ENTRY(mac_drv_clear_rx_queue)
*
@@ -1948,7 +1978,7 @@ void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc)
*
* END_MANUAL_ENTRY
*/
-static void mac_drv_clear_txd(struct s_smc *smc)
+void mac_drv_clear_txd(struct s_smc *smc)
{
struct s_smt_tx_queue *queue ;
struct s_smt_fp_txd volatile *t1 ;
diff --git a/trunk/drivers/net/skfp/pcmplc.c b/trunk/drivers/net/skfp/pcmplc.c
index cd0aa4c151b0..571f055c096b 100644
--- a/trunk/drivers/net/skfp/pcmplc.c
+++ b/trunk/drivers/net/skfp/pcmplc.c
@@ -1861,6 +1861,13 @@ void plc_irq(struct s_smc *smc, int np, unsigned int cmd)
#endif
}
+void pcm_set_lct_short(struct s_smc *smc, int n)
+{
+ if (n <= 0 || n > 1000)
+ return ;
+ smc->s.lct_short = n ;
+}
+
#ifdef DEBUG
/*
* fill state struct
diff --git a/trunk/drivers/net/skfp/pmf.c b/trunk/drivers/net/skfp/pmf.c
index efc639c013fd..f2b446d8b0bf 100644
--- a/trunk/drivers/net/skfp/pmf.c
+++ b/trunk/drivers/net/skfp/pmf.c
@@ -36,13 +36,12 @@ static int smt_authorize(struct s_smc *smc, struct smt_header *sm);
static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm);
static const struct s_p_tab* smt_get_ptab(u_short para);
static int smt_mib_phys(struct s_smc *smc);
-static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index,
- int local, int set);
+int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, int local,
+ int set);
void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para,
int index, int local);
static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req,
int set, int local);
-static int port_to_mib(struct s_smc *smc, int p);
#define MOFFSS(e) ((int)&(((struct fddi_mib *)0)->e))
#define MOFFSA(e) ((int) (((struct fddi_mib *)0)->e))
@@ -1079,8 +1078,8 @@ void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para,
/*
* set parameter
*/
-static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index,
- int local, int set)
+int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, int local,
+ int set)
{
#define IFSET(x) if (set) (x)
@@ -1550,7 +1549,7 @@ static int smt_mib_phys(struct s_smc *smc)
#endif
}
-static int port_to_mib(struct s_smc *smc, int p)
+int port_to_mib(struct s_smc *smc, int p)
{
#ifdef CONCENTRATOR
SK_UNUSED(smc) ;
diff --git a/trunk/drivers/net/skfp/skfddi.c b/trunk/drivers/net/skfp/skfddi.c
index 4b5ed2c63177..c88aad6edd74 100644
--- a/trunk/drivers/net/skfp/skfddi.c
+++ b/trunk/drivers/net/skfp/skfddi.c
@@ -149,6 +149,7 @@ extern void hwm_rx_frag(struct s_smc *smc, char far * virt, u_long phys,
extern void mac_drv_rx_mode(struct s_smc *smc, int mode);
extern void mac_drv_clear_rx_queue(struct s_smc *smc);
extern void enable_tx_irq(struct s_smc *smc, u_short queue);
+extern void mac_drv_clear_txd(struct s_smc *smc);
static struct pci_device_id skfddi_pci_tbl[] = {
{ PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP, PCI_ANY_ID, PCI_ANY_ID, },
diff --git a/trunk/drivers/net/skfp/smt.c b/trunk/drivers/net/skfp/smt.c
index f17c05cbe44b..c3a0d2f10b2b 100644
--- a/trunk/drivers/net/skfp/smt.c
+++ b/trunk/drivers/net/skfp/smt.c
@@ -110,7 +110,7 @@ static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount
static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed,
int len);
-static void smt_clear_una_dna(struct s_smc *smc);
+void smt_clear_una_dna(struct s_smc *smc);
static void smt_clear_old_una_dna(struct s_smc *smc);
#ifdef CONCENTRATOR
static int entity_to_index(void);
@@ -118,7 +118,7 @@ static int entity_to_index(void);
static void update_dac(struct s_smc *smc, int report);
static int div_ratio(u_long upper, u_long lower);
#ifdef USE_CAN_ADDR
-static void hwm_conv_can(struct s_smc *smc, char *data, int len);
+void hwm_conv_can(struct s_smc *smc, char *data, int len);
#else
#define hwm_conv_can(smc,data,len)
#endif
@@ -216,6 +216,24 @@ void smt_agent_task(struct s_smc *smc)
DB_SMT("SMT agent task\n",0,0) ;
}
+void smt_please_reconnect(struct s_smc *smc, int reconn_time)
+/* struct s_smc *smc; Pointer to SMT context */
+/* int reconn_time; Wait for reconnect time in seconds */
+{
+ /*
+ * The please reconnect variable is used as a timer.
+ * It is decremented each time smt_event is called.
+ * This happens every second or when smt_force_irq is called.
+ * Note: smt_force_irq () is called on some packet receives and
+ * when a multicast address is changed. Since nothing
+ * is received during the disconnect and the multicast
+ * address changes can be viewed as not very often and
+ * the timer runs out close to its given value
+ * (reconn_time).
+ */
+ smc->sm.please_reconnect = reconn_time ;
+}
+
#ifndef SMT_REAL_TOKEN_CT
void smt_emulate_token_ct(struct s_smc *smc, int mac_index)
{
@@ -1556,7 +1574,7 @@ static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long see
* clear DNA and UNA
* called from CFM if configuration changes
*/
-static void smt_clear_una_dna(struct s_smc *smc)
+void smt_clear_una_dna(struct s_smc *smc)
{
smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ;
smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ;
@@ -2039,11 +2057,31 @@ int smt_action(struct s_smc *smc, int class, int code, int index)
return(0) ;
}
+/*
+ * change tneg
+ * set T_Req in MIB (Path Attribute)
+ * calculate new values for MAC
+ * if change required
+ * disconnect
+ * set reconnect
+ * end
+ */
+void smt_change_t_neg(struct s_smc *smc, u_long tneg)
+{
+ smc->mib.a[PATH0].fddiPATHMaxT_Req = tneg ;
+
+ if (smt_set_mac_opvalues(smc)) {
+ RS_SET(smc,RS_EVENT) ;
+ smc->sm.please_reconnect = 1 ;
+ queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
+ }
+}
+
/*
* canonical conversion of bytes beginning form *data
*/
#ifdef USE_CAN_ADDR
-static void hwm_conv_can(struct s_smc *smc, char *data, int len)
+void hwm_conv_can(struct s_smc *smc, char *data, int len)
{
int i ;
diff --git a/trunk/drivers/net/skfp/smtdef.c b/trunk/drivers/net/skfp/smtdef.c
index 4e07ff7073f1..5a0c8db816d8 100644
--- a/trunk/drivers/net/skfp/smtdef.c
+++ b/trunk/drivers/net/skfp/smtdef.c
@@ -76,6 +76,11 @@ void smt_reset_defaults(struct s_smc *smc, int level);
static void smt_init_mib(struct s_smc *smc, int level);
static int set_min_max(int maxflag, u_long mib, u_long limit, u_long *oper);
+void smt_set_defaults(struct s_smc *smc)
+{
+ smt_reset_defaults(smc,0) ;
+}
+
#define MS2BCLK(x) ((x)*12500L)
#define US2BCLK(x) ((x)*1250L)
diff --git a/trunk/drivers/net/skfp/smtparse.c b/trunk/drivers/net/skfp/smtparse.c
new file mode 100644
index 000000000000..d5779e414dbe
--- /dev/null
+++ b/trunk/drivers/net/skfp/smtparse.c
@@ -0,0 +1,467 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+
+/*
+ parser for SMT parameters
+*/
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/smt_p.h"
+
+#define KERNEL
+#include "h/smtstate.h"
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)smtparse.c 1.12 98/10/06 (C) SK " ;
+#endif
+
+#ifdef sun
+#define _far
+#endif
+
+/*
+ * convert to BCLK units
+ */
+#define MS2BCLK(x) ((x)*12500L)
+#define US2BCLK(x) ((x/10)*125L)
+
+/*
+ * parameter table
+ */
+static struct s_ptab {
+ char *pt_name ;
+ u_short pt_num ;
+ u_short pt_type ;
+ u_long pt_min ;
+ u_long pt_max ;
+} ptab[] = {
+ { "PMFPASSWD",0, 0 } ,
+ { "USERDATA",1, 0 } ,
+ { "LERCUTOFFA",2, 1, 4, 15 } ,
+ { "LERCUTOFFB",3, 1, 4, 15 } ,
+ { "LERALARMA",4, 1, 4, 15 } ,
+ { "LERALARMB",5, 1, 4, 15 } ,
+ { "TMAX",6, 1, 5, 165 } ,
+ { "TMIN",7, 1, 5, 165 } ,
+ { "TREQ",8, 1, 5, 165 } ,
+ { "TVX",9, 1, 2500, 10000 } ,
+#ifdef ESS
+ { "SBAPAYLOAD",10, 1, 0, 1562 } ,
+ { "SBAOVERHEAD",11, 1, 50, 5000 } ,
+ { "MAXTNEG",12, 1, 5, 165 } ,
+ { "MINSEGMENTSIZE",13, 1, 0, 4478 } ,
+ { "SBACATEGORY",14, 1, 0, 0xffff } ,
+ { "SYNCHTXMODE",15, 0 } ,
+#endif
+#ifdef SBA
+ { "SBACOMMAND",16, 0 } ,
+ { "SBAAVAILABLE",17, 1, 0, 100 } ,
+#endif
+ { NULL }
+} ;
+
+/* Define maximum string size for values and keybuffer */
+#define MAX_VAL 40
+
+/*
+ * local function declarations
+ */
+static u_long parse_num(int type, char _far *value, char *v, u_long mn,
+ u_long mx, int scale);
+static int parse_word(char *buf, char _far *text);
+
+#ifdef SIM
+#define DB_MAIN(a,b,c) printf(a,b,c)
+#else
+#define DB_MAIN(a,b,c)
+#endif
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ * int smt_parse_arg(struct s_smc *,char _far *keyword,int type,
+ char _far *value)
+ *
+ * parse SMT parameter
+ * *keyword
+ * pointer to keyword, must be \0, \n or \r terminated
+ * *value pointer to value, either char * or u_long *
+ * if char *
+ * pointer to value, must be \0, \n or \r terminated
+ * if u_long *
+ * contains binary value
+ *
+ * type 0: integer
+ * 1: string
+ * return
+ * 0 parameter parsed ok
+ * != 0 error
+ * NOTE:
+ * function can be called with DS != SS
+ *
+ *
+ * END_MANUAL_ENTRY()
+ */
+int smt_parse_arg(struct s_smc *smc, char _far *keyword, int type,
+ char _far *value)
+{
+ char keybuf[MAX_VAL+1];
+ char valbuf[MAX_VAL+1];
+ char c ;
+ char *p ;
+ char *v ;
+ char *d ;
+ u_long val = 0 ;
+ struct s_ptab *pt ;
+ int st ;
+ int i ;
+
+ /*
+ * parse keyword
+ */
+ if ((st = parse_word(keybuf,keyword)))
+ return(st) ;
+ /*
+ * parse value if given as string
+ */
+ if (type == 1) {
+ if ((st = parse_word(valbuf,value)))
+ return(st) ;
+ }
+ /*
+ * search in table
+ */
+ st = 0 ;
+ for (pt = ptab ; (v = pt->pt_name) ; pt++) {
+ for (p = keybuf ; (c = *p) ; p++,v++) {
+ if (c != *v)
+ break ;
+ }
+ if (!c && !*v)
+ break ;
+ }
+ if (!v)
+ return(-1) ;
+#if 0
+ printf("=>%s<==>%s<=\n",pt->pt_name,valbuf) ;
+#endif
+ /*
+ * set value in MIB
+ */
+ if (pt->pt_type)
+ val = parse_num(type,value,valbuf,pt->pt_min,pt->pt_max,1) ;
+ switch (pt->pt_num) {
+ case 0 :
+ v = valbuf ;
+ d = (char *) smc->mib.fddiPRPMFPasswd ;
+ for (i = 0 ; i < (signed)sizeof(smc->mib.fddiPRPMFPasswd) ; i++)
+ *d++ = *v++ ;
+ DB_MAIN("SET %s = %s\n",pt->pt_name,smc->mib.fddiPRPMFPasswd) ;
+ break ;
+ case 1 :
+ v = valbuf ;
+ d = (char *) smc->mib.fddiSMTUserData ;
+ for (i = 0 ; i < (signed)sizeof(smc->mib.fddiSMTUserData) ; i++)
+ *d++ = *v++ ;
+ DB_MAIN("SET %s = %s\n",pt->pt_name,smc->mib.fddiSMTUserData) ;
+ break ;
+ case 2 :
+ smc->mib.p[PA].fddiPORTLer_Cutoff = (u_char) val ;
+ DB_MAIN("SET %s = %d\n",
+ pt->pt_name,smc->mib.p[PA].fddiPORTLer_Cutoff) ;
+ break ;
+ case 3 :
+ smc->mib.p[PB].fddiPORTLer_Cutoff = (u_char) val ;
+ DB_MAIN("SET %s = %d\n",
+ pt->pt_name,smc->mib.p[PB].fddiPORTLer_Cutoff) ;
+ break ;
+ case 4 :
+ smc->mib.p[PA].fddiPORTLer_Alarm = (u_char) val ;
+ DB_MAIN("SET %s = %d\n",
+ pt->pt_name,smc->mib.p[PA].fddiPORTLer_Alarm) ;
+ break ;
+ case 5 :
+ smc->mib.p[PB].fddiPORTLer_Alarm = (u_char) val ;
+ DB_MAIN("SET %s = %d\n",
+ pt->pt_name,smc->mib.p[PB].fddiPORTLer_Alarm) ;
+ break ;
+ case 6 : /* TMAX */
+ DB_MAIN("SET %s = %d\n",pt->pt_name,val) ;
+ smc->mib.a[PATH0].fddiPATHT_MaxLowerBound =
+ (u_long) -MS2BCLK((long)val) ;
+ break ;
+ case 7 : /* TMIN */
+ DB_MAIN("SET %s = %d\n",pt->pt_name,val) ;
+ smc->mib.m[MAC0].fddiMACT_Min =
+ (u_long) -MS2BCLK((long)val) ;
+ break ;
+ case 8 : /* TREQ */
+ DB_MAIN("SET %s = %d\n",pt->pt_name,val) ;
+ smc->mib.a[PATH0].fddiPATHMaxT_Req =
+ (u_long) -MS2BCLK((long)val) ;
+ break ;
+ case 9 : /* TVX */
+ DB_MAIN("SET %s = %d \n",pt->pt_name,val) ;
+ smc->mib.a[PATH0].fddiPATHTVXLowerBound =
+ (u_long) -US2BCLK((long)val) ;
+ break ;
+#ifdef ESS
+ case 10 : /* SBAPAYLOAD */
+ DB_MAIN("SET %s = %d\n",pt->pt_name,val) ;
+ if (smc->mib.fddiESSPayload != val) {
+ smc->ess.raf_act_timer_poll = TRUE ;
+ smc->mib.fddiESSPayload = val ;
+ }
+ break ;
+ case 11 : /* SBAOVERHEAD */
+ DB_MAIN("SET %s = %d\n",pt->pt_name,val) ;
+ smc->mib.fddiESSOverhead = val ;
+ break ;
+ case 12 : /* MAXTNEG */
+ DB_MAIN("SET %s = %d\n",pt->pt_name,val) ;
+ smc->mib.fddiESSMaxTNeg = (u_long) -MS2BCLK((long)val) ;
+ break ;
+ case 13 : /* MINSEGMENTSIZE */
+ DB_MAIN("SET %s = %d\n",pt->pt_name,val) ;
+ smc->mib.fddiESSMinSegmentSize = val ;
+ break ;
+ case 14 : /* SBACATEGORY */
+ DB_MAIN("SET %s = %d\n",pt->pt_name,val) ;
+ smc->mib.fddiESSCategory =
+ (smc->mib.fddiESSCategory & 0xffff) |
+ ((u_long)(val << 16)) ;
+ break ;
+ case 15 : /* SYNCHTXMODE */
+ /* do not use memcmp(valbuf,"ALL",3) because DS != SS */
+ if (valbuf[0] == 'A' && valbuf[1] == 'L' && valbuf[2] == 'L') {
+ smc->mib.fddiESSSynchTxMode = TRUE ;
+ DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ;
+ }
+ /* if (!memcmp(valbuf,"SPLIT",5)) { */
+ if (valbuf[0] == 'S' && valbuf[1] == 'P' && valbuf[2] == 'L' &&
+ valbuf[3] == 'I' && valbuf[4] == 'T') {
+ DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ;
+ smc->mib.fddiESSSynchTxMode = FALSE ;
+ }
+ break ;
+#endif
+#ifdef SBA
+ case 16 : /* SBACOMMAND */
+ /* if (!memcmp(valbuf,"START",5)) { */
+ if (valbuf[0] == 'S' && valbuf[1] == 'T' && valbuf[2] == 'A' &&
+ valbuf[3] == 'R' && valbuf[4] == 'T') {
+ DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ;
+ smc->mib.fddiSBACommand = SB_START ;
+ }
+ /* if (!memcmp(valbuf,"STOP",4)) { */
+ if (valbuf[0] == 'S' && valbuf[1] == 'T' && valbuf[2] == 'O' &&
+ valbuf[3] == 'P') {
+ DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ;
+ smc->mib.fddiSBACommand = SB_STOP ;
+ }
+ break ;
+ case 17 : /* SBAAVAILABLE */
+ DB_MAIN("SET %s = %d\n",pt->pt_name,val) ;
+ smc->mib.fddiSBAAvailable = (u_char) val ;
+ break ;
+#endif
+ }
+ return(0) ;
+}
+
+static int parse_word(char *buf, char _far *text)
+{
+ char c ;
+ char *p ;
+ int p_len ;
+ int quote ;
+ int i ;
+ int ok ;
+
+ /*
+ * skip leading white space
+ */
+ p = buf ;
+ for (i = 0 ; i < MAX_VAL ; i++)
+ *p++ = 0 ;
+ p = buf ;
+ p_len = 0 ;
+ ok = 0 ;
+ while ( (c = *text++) && (c != '\n') && (c != '\r')) {
+ if ((c != ' ') && (c != '\t')) {
+ ok = 1 ;
+ break ;
+ }
+ }
+ if (!ok)
+ return(-1) ;
+ if (c == '"') {
+ quote = 1 ;
+ }
+ else {
+ quote = 0 ;
+ text-- ;
+ }
+ /*
+ * parse valbuf
+ */
+ ok = 0 ;
+ while (!ok && p_len < MAX_VAL-1 && (c = *text++) && (c != '\n')
+ && (c != '\r')) {
+ switch (quote) {
+ case 0 :
+ if ((c == ' ') || (c == '\t') || (c == '=')) {
+ ok = 1 ;
+ break ;
+ }
+ *p++ = c ;
+ p_len++ ;
+ break ;
+ case 2 :
+ *p++ = c ;
+ p_len++ ;
+ quote = 1 ;
+ break ;
+ case 1 :
+ switch (c) {
+ case '"' :
+ ok = 1 ;
+ break ;
+ case '\\' :
+ quote = 2 ;
+ break ;
+ default :
+ *p++ = c ;
+ p_len++ ;
+ }
+ }
+ }
+ *p++ = 0 ;
+ for (p = buf ; (c = *p) ; p++) {
+ if (c >= 'a' && c <= 'z')
+ *p = c + 'A' - 'a' ;
+ }
+ return(0) ;
+}
+
+static u_long parse_num(int type, char _far *value, char *v, u_long mn,
+ u_long mx, int scale)
+{
+ u_long x = 0 ;
+ char c ;
+
+ if (type == 0) { /* integer */
+ u_long _far *l ;
+ u_long u1 ;
+
+ l = (u_long _far *) value ;
+ u1 = *l ;
+ /*
+ * if the value is negative take the lower limit
+ */
+ if ((long)u1 < 0) {
+ if (- ((long)u1) > (long) mx) {
+ u1 = 0 ;
+ }
+ else {
+ u1 = (u_long) - ((long)u1) ;
+ }
+ }
+ x = u1 ;
+ }
+ else { /* string */
+ int sign = 0 ;
+
+ if (*v == '-') {
+ sign = 1 ;
+ }
+ while ((c = *v++) && (c >= '0') && (c <= '9')) {
+ x = x * 10 + c - '0' ;
+ }
+ if (scale == 10) {
+ x *= 10 ;
+ if (c == '.') {
+ if ((c = *v++) && (c >= '0') && (c <= '9')) {
+ x += c - '0' ;
+ }
+ }
+ }
+ if (sign)
+ x = (u_long) - ((long)x) ;
+ }
+ /*
+ * if the value is negative
+ * and the absolute value is outside the limits
+ * take the lower limit
+ * else
+ * take the absoute value
+ */
+ if ((long)x < 0) {
+ if (- ((long)x) > (long) mx) {
+ x = 0 ;
+ }
+ else {
+ x = (u_long) - ((long)x) ;
+ }
+ }
+ if (x < mn)
+ return(mn) ;
+ else if (x > mx)
+ return(mx) ;
+ return(x) ;
+}
+
+#if 0
+struct s_smc SMC ;
+main()
+{
+ char *p ;
+ char *v ;
+ char buf[100] ;
+ int toggle = 0 ;
+
+ while (gets(buf)) {
+ p = buf ;
+ while (*p && ((*p == ' ') || (*p == '\t')))
+ p++ ;
+
+ while (*p && ((*p != ' ') && (*p != '\t')))
+ p++ ;
+
+ v = p ;
+ while (*v && ((*v == ' ') || (*v == '\t')))
+ v++ ;
+ if ((*v >= '0') && (*v <= '9')) {
+ toggle = !toggle ;
+ if (toggle) {
+ u_long l ;
+ l = atol(v) ;
+ smt_parse_arg(&SMC,buf,0,(char _far *)&l) ;
+ }
+ else
+ smt_parse_arg(&SMC,buf,1,(char _far *)p) ;
+ }
+ else {
+ smt_parse_arg(&SMC,buf,1,(char _far *)p) ;
+ }
+ }
+ exit(0) ;
+}
+#endif
+
diff --git a/trunk/drivers/net/smc91x.c b/trunk/drivers/net/smc91x.c
index cfb9d3cdb04a..fd80048f7f7a 100644
--- a/trunk/drivers/net/smc91x.c
+++ b/trunk/drivers/net/smc91x.c
@@ -315,25 +315,15 @@ static void smc_reset(struct net_device *dev)
struct smc_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
unsigned int ctl, cfg;
- struct sk_buff *pending_skb;
DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
- /* Disable all interrupts, block TX tasklet */
+ /* Disable all interrupts */
spin_lock(&lp->lock);
SMC_SELECT_BANK(2);
SMC_SET_INT_MASK(0);
- pending_skb = lp->pending_tx_skb;
- lp->pending_tx_skb = NULL;
spin_unlock(&lp->lock);
- /* free any pending tx skb */
- if (pending_skb) {
- dev_kfree_skb(pending_skb);
- lp->stats.tx_errors++;
- lp->stats.tx_aborted_errors++;
- }
-
/*
* This resets the registers mostly to defaults, but doesn't
* affect EEPROM. That seems unnecessary
@@ -399,6 +389,14 @@ static void smc_reset(struct net_device *dev)
SMC_SELECT_BANK(2);
SMC_SET_MMU_CMD(MC_RESET);
SMC_WAIT_MMU_BUSY();
+
+ /* clear anything saved */
+ if (lp->pending_tx_skb != NULL) {
+ dev_kfree_skb (lp->pending_tx_skb);
+ lp->pending_tx_skb = NULL;
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
+ }
}
/*
@@ -442,7 +440,6 @@ static void smc_shutdown(struct net_device *dev)
{
struct smc_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
- struct sk_buff *pending_skb;
DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
@@ -450,11 +447,7 @@ static void smc_shutdown(struct net_device *dev)
spin_lock(&lp->lock);
SMC_SELECT_BANK(2);
SMC_SET_INT_MASK(0);
- pending_skb = lp->pending_tx_skb;
- lp->pending_tx_skb = NULL;
spin_unlock(&lp->lock);
- if (pending_skb)
- dev_kfree_skb(pending_skb);
/* and tell the card to stay away from that nasty outside world */
SMC_SELECT_BANK(0);
@@ -634,12 +627,7 @@ static void smc_hardware_send_pkt(unsigned long data)
}
skb = lp->pending_tx_skb;
- if (unlikely(!skb)) {
- smc_special_unlock(&lp->lock);
- return;
- }
lp->pending_tx_skb = NULL;
-
packet_no = SMC_GET_AR();
if (unlikely(packet_no & AR_FAILED)) {
printk("%s: Memory allocation failed.\n", dev->name);
@@ -714,6 +702,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
BUG_ON(lp->pending_tx_skb != NULL);
+ lp->pending_tx_skb = skb;
/*
* The MMU wants the number of pages to be the number of 256 bytes
@@ -729,6 +718,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
numPages = ((skb->len & ~1) + (6 - 1)) >> 8;
if (unlikely(numPages > 7)) {
printk("%s: Far too big packet error.\n", dev->name);
+ lp->pending_tx_skb = NULL;
lp->stats.tx_errors++;
lp->stats.tx_dropped++;
dev_kfree_skb(skb);
@@ -755,7 +745,6 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
smc_special_unlock(&lp->lock);
- lp->pending_tx_skb = skb;
if (!poll_count) {
/* oh well, wait until the chip finds memory later */
netif_stop_queue(dev);
@@ -1073,7 +1062,7 @@ static void smc_phy_powerdown(struct net_device *dev)
above). linkwatch_event() also wants the netlink semaphore.
*/
while(lp->work_pending)
- yield();
+ schedule();
bmcr = smc_phy_read(dev, phy, MII_BMCR);
smc_phy_write(dev, phy, MII_BMCR, bmcr | BMCR_PDOWN);
@@ -1617,8 +1606,14 @@ static int smc_close(struct net_device *dev)
/* clear everything */
smc_shutdown(dev);
- tasklet_kill(&lp->tx_task);
+
smc_phy_powerdown(dev);
+
+ if (lp->pending_tx_skb) {
+ dev_kfree_skb(lp->pending_tx_skb);
+ lp->pending_tx_skb = NULL;
+ }
+
return 0;
}
diff --git a/trunk/drivers/net/tokenring/lanstreamer.c b/trunk/drivers/net/tokenring/lanstreamer.c
index 97712c3c4e07..6e5ade99a38f 100644
--- a/trunk/drivers/net/tokenring/lanstreamer.c
+++ b/trunk/drivers/net/tokenring/lanstreamer.c
@@ -455,7 +455,8 @@ static int streamer_reset(struct net_device *dev)
writew(readw(streamer_mmio + BCTL) | BCTL_SOFTRESET, streamer_mmio + BCTL);
t = jiffies;
/* Hold soft reset bit for a while */
- ssleep(1);
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout(HZ);
writew(readw(streamer_mmio + BCTL) & ~BCTL_SOFTRESET,
streamer_mmio + BCTL);
@@ -511,7 +512,8 @@ static int streamer_reset(struct net_device *dev)
writew(SISR_MI, streamer_mmio + SISR_MASK_SUM);
while (!((readw(streamer_mmio + SISR)) & SISR_SRB_REPLY)) {
- msleep_interruptible(100);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(HZ/10);
if (jiffies - t > 40 * HZ) {
printk(KERN_ERR
"IBM PCI tokenring card not responding\n");
diff --git a/trunk/drivers/net/tulip/tulip_core.c b/trunk/drivers/net/tulip/tulip_core.c
index 08e0f80f89d5..cfc346e72d62 100644
--- a/trunk/drivers/net/tulip/tulip_core.c
+++ b/trunk/drivers/net/tulip/tulip_core.c
@@ -242,7 +242,6 @@ static struct pci_device_id tulip_pci_tbl[] = {
{ 0x10b9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */
{ 0x10b9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ULI526X }, /* ALi 1563 integrated ethernet */
{ 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */
- { 0x14ea, 0xab08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Planex FNW-3602-TX */
{ } /* terminate list */
};
MODULE_DEVICE_TABLE(pci, tulip_pci_tbl);
@@ -1757,19 +1756,11 @@ static int tulip_suspend (struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
- if (!dev)
- return -EINVAL;
-
- if (netif_running(dev))
- tulip_down(dev);
-
- netif_device_detach(dev);
- free_irq(dev->irq, dev);
-
- pci_save_state(pdev);
- pci_disable_device(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
+ if (dev && netif_running (dev) && netif_device_present (dev)) {
+ netif_device_detach (dev);
+ tulip_down (dev);
+ /* pci_power_off(pdev, -1); */
+ }
return 0;
}
@@ -1777,26 +1768,15 @@ static int tulip_suspend (struct pci_dev *pdev, pm_message_t state)
static int tulip_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
- int retval;
-
- if (!dev)
- return -EINVAL;
-
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
- pci_enable_device(pdev);
-
- if ((retval = request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev))) {
- printk (KERN_ERR "tulip: request_irq failed in resume\n");
- return retval;
+ if (dev && netif_running (dev) && !netif_device_present (dev)) {
+#if 1
+ pci_enable_device (pdev);
+#endif
+ /* pci_power_on(pdev); */
+ tulip_up (dev);
+ netif_device_attach (dev);
}
-
- netif_device_attach(dev);
-
- if (netif_running(dev))
- tulip_up(dev);
-
return 0;
}
diff --git a/trunk/drivers/net/via-rhine.c b/trunk/drivers/net/via-rhine.c
index be1c1047b9ba..6200cfc4244e 100644
--- a/trunk/drivers/net/via-rhine.c
+++ b/trunk/drivers/net/via-rhine.c
@@ -1398,7 +1398,7 @@ static void rhine_tx(struct net_device *dev)
while (rp->dirty_tx != rp->cur_tx) {
txstatus = le32_to_cpu(rp->tx_ring[entry].tx_status);
if (debug > 6)
- printk(KERN_DEBUG "Tx scavenge %d status %8.8x.\n",
+ printk(KERN_DEBUG " Tx scavenge %d status %8.8x.\n",
entry, txstatus);
if (txstatus & DescOwn)
break;
@@ -1469,7 +1469,7 @@ static void rhine_rx(struct net_device *dev)
int data_size = desc_status >> 16;
if (debug > 4)
- printk(KERN_DEBUG "rhine_rx() status is %8.8x.\n",
+ printk(KERN_DEBUG " rhine_rx() status is %8.8x.\n",
desc_status);
if (--boguscnt < 0)
break;
@@ -1487,7 +1487,7 @@ static void rhine_rx(struct net_device *dev)
} else if (desc_status & RxErr) {
/* There was a error. */
if (debug > 2)
- printk(KERN_DEBUG "rhine_rx() Rx "
+ printk(KERN_DEBUG " rhine_rx() Rx "
"error was %8.8x.\n",
desc_status);
rp->stats.rx_errors++;
diff --git a/trunk/drivers/net/wan/farsync.c b/trunk/drivers/net/wan/farsync.c
index 7217d44e8854..7575b799ce53 100644
--- a/trunk/drivers/net/wan/farsync.c
+++ b/trunk/drivers/net/wan/farsync.c
@@ -981,7 +981,6 @@ fst_issue_cmd(struct fst_port_info *port, unsigned short cmd)
/* Wait for any previous command to complete */
while (mbval > NAK) {
spin_unlock_irqrestore(&card->card_lock, flags);
- set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
spin_lock_irqsave(&card->card_lock, flags);
diff --git a/trunk/drivers/net/wireless/airo.c b/trunk/drivers/net/wireless/airo.c
index c12648d8192b..180968899cad 100644
--- a/trunk/drivers/net/wireless/airo.c
+++ b/trunk/drivers/net/wireless/airo.c
@@ -900,7 +900,7 @@ typedef struct aironet_ioctl {
unsigned char __user *data; // d-data
} aironet_ioctl;
-static char swversion[] = "2.1";
+static char *swversion = "2.1";
#endif /* CISCO_EXT */
#define NUM_MODULES 2
diff --git a/trunk/drivers/net/wireless/airo_cs.c b/trunk/drivers/net/wireless/airo_cs.c
index f10a9523034a..fbf53af6cda4 100644
--- a/trunk/drivers/net/wireless/airo_cs.c
+++ b/trunk/drivers/net/wireless/airo_cs.c
@@ -559,15 +559,6 @@ static int airo_event(event_t event, int priority,
return 0;
} /* airo_event */
-static struct pcmcia_device_id airo_ids[] = {
- PCMCIA_DEVICE_MANF_CARD(0x015f, 0x000a),
- PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0005),
- PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0007),
- PCMCIA_DEVICE_MANF_CARD(0x0105, 0x0007),
- PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, airo_ids);
-
static struct pcmcia_driver airo_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -575,7 +566,6 @@ static struct pcmcia_driver airo_driver = {
},
.attach = airo_attach,
.detach = airo_detach,
- .id_table = airo_ids,
};
static int airo_cs_init(void)
diff --git a/trunk/drivers/net/wireless/atmel_cs.c b/trunk/drivers/net/wireless/atmel_cs.c
index 86379d4998ac..a4ed28d9c783 100644
--- a/trunk/drivers/net/wireless/atmel_cs.c
+++ b/trunk/drivers/net/wireless/atmel_cs.c
@@ -646,27 +646,6 @@ static int atmel_event(event_t event, int priority,
} /* atmel_event */
/*====================================================================*/
-static struct pcmcia_device_id atmel_ids[] = {
- PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0620),
- PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0696),
- PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x3302),
- PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0007),
- PCMCIA_DEVICE_PROD_ID12("11WAVE", "11WP611AL-E", 0x9eb2da1f, 0xc9a0d3f9),
- PCMCIA_DEVICE_PROD_ID12("ATMEL", "AT76C502AR", 0xabda4164, 0x41b37e1f),
- PCMCIA_DEVICE_PROD_ID12("ATMEL", "AT76C504", 0xabda4164, 0x5040670a),
- PCMCIA_DEVICE_PROD_ID12("ATMEL", "AT76C504A", 0xabda4164, 0xe15ed87f),
- PCMCIA_DEVICE_PROD_ID12("BT", "Voyager 1020 Laptop Adapter", 0xae49b86a, 0x1e957cd5),
- PCMCIA_DEVICE_PROD_ID12("CNet", "CNWLC 11Mbps Wireless PC Card V-5", 0xbc477dde, 0x502fae6b),
- PCMCIA_DEVICE_PROD_ID12("IEEE 802.11b", "Wireless LAN PC Card", 0x5b878724, 0x122f1df6),
- PCMCIA_DEVICE_PROD_ID12("OEM", "11Mbps Wireless LAN PC Card V-3", 0xfea54c90, 0x1c5b0f68),
- PCMCIA_DEVICE_PROD_ID12("SMC", "2632W", 0xc4f8b18b, 0x30f38774),
- PCMCIA_DEVICE_PROD_ID12("SMC", "2632W-V2", 0xc4f8b18b, 0x172d1377),
- PCMCIA_DEVICE_PROD_ID12("Wireless", "PC", 0xa407ecdd, 0x556e4d7e),
- PCMCIA_DEVICE_PROD_ID12("WLAN", "802.11b PC CARD", 0x575c516c, 0xb1f6dbc4),
- PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, atmel_ids);
-
static struct pcmcia_driver atmel_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -674,7 +653,6 @@ static struct pcmcia_driver atmel_driver = {
},
.attach = atmel_attach,
.detach = atmel_detach,
- .id_table = atmel_ids,
};
static int atmel_cs_init(void)
diff --git a/trunk/drivers/net/wireless/netwave_cs.c b/trunk/drivers/net/wireless/netwave_cs.c
index e12bd75b2694..382241e7edbb 100644
--- a/trunk/drivers/net/wireless/netwave_cs.c
+++ b/trunk/drivers/net/wireless/netwave_cs.c
@@ -1668,12 +1668,6 @@ static int netwave_close(struct net_device *dev) {
return 0;
}
-static struct pcmcia_device_id netwave_ids[] = {
- PCMCIA_DEVICE_PROD_ID12("Xircom", "CreditCard Netwave", 0x2e3ee845, 0x54e28a28),
- PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, netwave_ids);
-
static struct pcmcia_driver netwave_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -1681,7 +1675,6 @@ static struct pcmcia_driver netwave_driver = {
},
.attach = netwave_attach,
.detach = netwave_detach,
- .id_table = netwave_ids,
};
static int __init init_netwave_cs(void)
diff --git a/trunk/drivers/net/wireless/orinoco.c b/trunk/drivers/net/wireless/orinoco.c
index aabcdc2be05e..b1078baa1d5e 100644
--- a/trunk/drivers/net/wireless/orinoco.c
+++ b/trunk/drivers/net/wireless/orinoco.c
@@ -46,9 +46,382 @@
* under either the MPL or the GPL. */
/*
+ * v0.01 -> v0.02 - 21/3/2001 - Jean II
+ * o Allow to use regular ethX device name instead of dldwdX
+ * o Warning on IBSS with ESSID=any for firmware 6.06
+ * o Put proper range.throughput values (optimistic)
+ * o IWSPY support (IOCTL and stat gather in Rx path)
+ * o Allow setting frequency in Ad-Hoc mode
+ * o Disable WEP setting if !has_wep to work on old firmware
+ * o Fix txpower range
+ * o Start adding support for Samsung/Compaq firmware
+ *
+ * v0.02 -> v0.03 - 23/3/2001 - Jean II
+ * o Start adding Symbol support - need to check all that
+ * o Fix Prism2/Symbol WEP to accept 128 bits keys
+ * o Add Symbol WEP (add authentication type)
+ * o Add Prism2/Symbol rate
+ * o Add PM timeout (holdover duration)
+ * o Enable "iwconfig eth0 key off" and friends (toggle flags)
+ * o Enable "iwconfig eth0 power unicast/all" (toggle flags)
+ * o Try with an Intel card. It report firmware 1.01, behave like
+ * an antiquated firmware, however on windows it says 2.00. Yuck !
+ * o Workaround firmware bug in allocate buffer (Intel 1.01)
+ * o Finish external renaming to orinoco...
+ * o Testing with various Wavelan firmwares
+ *
+ * v0.03 -> v0.04 - 30/3/2001 - Jean II
+ * o Update to Wireless 11 -> add retry limit/lifetime support
+ * o Tested with a D-Link DWL 650 card, fill in firmware support
+ * o Warning on Vcc mismatch (D-Link 3.3v card in Lucent 5v only slot)
+ * o Fixed the Prism2 WEP bugs that I introduced in v0.03 :-(
+ * It works on D-Link *only* after a tcpdump. Weird...
+ * And still doesn't work on Intel card. Grrrr...
+ * o Update the mode after a setport3
+ * o Add preamble setting for Symbol cards (not yet enabled)
+ * o Don't complain as much about Symbol cards...
+ *
+ * v0.04 -> v0.04b - 22/4/2001 - David Gibson
+ * o Removed the 'eth' parameter - always use ethXX as the
+ * interface name instead of dldwdXX. The other was racy
+ * anyway.
+ * o Clean up RID definitions in hermes.h, other cleanups
+ *
+ * v0.04b -> v0.04c - 24/4/2001 - Jean II
+ * o Tim Hurley reported a D-Link card
+ * with vendor 02 and firmware 0.08. Added in the capabilities...
+ * o Tested Lucent firmware 7.28, everything works...
+ *
+ * v0.04c -> v0.05 - 3/5/2001 - Benjamin Herrenschmidt
+ * o Spin-off Pcmcia code. This file is renamed orinoco.c,
+ * and orinoco_cs.c now contains only the Pcmcia specific stuff
+ * o Add Airport driver support on top of orinoco.c (see airport.c)
+ *
+ * v0.05 -> v0.05a - 4/5/2001 - Jean II
+ * o Revert to old Pcmcia code to fix breakage of Ben's changes...
+ *
+ * v0.05a -> v0.05b - 4/5/2001 - Jean II
+ * o add module parameter 'ignore_cis_vcc' for D-Link @ 5V
+ * o D-Link firmware doesn't support multicast. We just print a few
+ * error messages, but otherwise everything works...
+ * o For David : set/getport3 works fine, just upgrade iwpriv...
+ *
+ * v0.05b -> v0.05c - 5/5/2001 - Benjamin Herrenschmidt
+ * o Adapt airport.c to latest changes in orinoco.c
+ * o Remove deferred power enabling code
+ *
+ * v0.05c -> v0.05d - 5/5/2001 - Jean II
+ * o Workaround to SNAP decapsulate frame from Linksys AP
+ * original patch from : Dong Liu
+ * (note : the memcmp bug was mine - fixed)
+ * o Remove set_retry stuff, no firmware support it (bloat--).
+ *
+ * v0.05d -> v0.06 - 25/5/2001 - Jean II
+ * Original patch from "Hong Lin" ,
+ * "Ian Kinner"
+ * and "David Smith"
+ * o Init of priv->tx_rate_ctrl in firmware specific section.
+ * o Prism2/Symbol rate, upto should be 0xF and not 0x15. Doh !
+ * o Spectrum card always need cor_reset (for every reset)
+ * o Fix cor_reset to not lose bit 7 in the register
+ * o flush_stale_links to remove zombie Pcmcia instances
+ * o Ack previous hermes event before reset
+ * Me (with my little hands)
+ * o Allow orinoco.c to call cor_reset via priv->card_reset_handler
+ * o Add priv->need_card_reset to toggle this feature
+ * o Fix various buglets when setting WEP in Symbol firmware
+ * Now, encryption is fully functional on Symbol cards. Youpi !
+ *
+ * v0.06 -> v0.06b - 25/5/2001 - Jean II
+ * o IBSS on Symbol use port_mode = 4. Please don't ask...
+ *
+ * v0.06b -> v0.06c - 29/5/2001 - Jean II
+ * o Show first spy address in /proc/net/wireless for IBSS mode as well
+ *
+ * v0.06c -> v0.06d - 6/7/2001 - David Gibson
+ * o Change a bunch of KERN_INFO messages to KERN_DEBUG, as per Linus'
+ * wishes to reduce the number of unnecessary messages.
+ * o Removed bogus message on CRC error.
+ * o Merged fixes for v0.08 Prism 2 firmware from William Waghorn
+ *
+ * o Slight cleanup/re-arrangement of firmware detection code.
+ *
+ * v0.06d -> v0.06e - 1/8/2001 - David Gibson
+ * o Removed some redundant global initializers (orinoco_cs.c).
+ * o Added some module metadata
+ *
+ * v0.06e -> v0.06f - 14/8/2001 - David Gibson
+ * o Wording fix to license
+ * o Added a 'use_alternate_encaps' module parameter for APs which need an
+ * oui of 00:00:00. We really need a better way of handling this, but
+ * the module flag is better than nothing for now.
+ *
+ * v0.06f -> v0.07 - 20/8/2001 - David Gibson
+ * o Removed BAP error retries from hermes_bap_seek(). For Tx we now
+ * let the upper layers handle the retry, we retry explicitly in the
+ * Rx path, but don't make as much noise about it.
+ * o Firmware detection cleanups.
+ *
+ * v0.07 -> v0.07a - 1/10/3001 - Jean II
+ * o Add code to read Symbol firmware revision, inspired by latest code
+ * in Spectrum24 by Lee John Keyser-Allen - Thanks Lee !
+ * o Thanks to Jared Valentine for "providing" me
+ * a 3Com card with a recent firmware, fill out Symbol firmware
+ * capabilities of latest rev (2.20), as well as older Symbol cards.
+ * o Disable Power Management in newer Symbol firmware, the API
+ * has changed (documentation needed).
+ *
+ * v0.07a -> v0.08 - 3/10/2001 - David Gibson
+ * o Fixed a possible buffer overrun found by the Stanford checker (in
+ * dldwd_ioctl_setiwencode()). Can only be called by root anyway, so not
+ * a big problem.
+ * o Turned has_big_wep on for Intersil cards. That's not true for all of
+ * them but we should at least let the capable ones try.
+ * o Wait for BUSY to clear at the beginning of hermes_bap_seek(). I
+ * realized that my assumption that the driver's serialization
+ * would prevent the BAP being busy on entry was possibly false, because
+ * things other than seeks may make the BAP busy.
+ * o Use "alternate" (oui 00:00:00) encapsulation by default.
+ * Setting use_old_encaps will mimic the old behaviour, but I think we
+ * will be able to eliminate this.
+ * o Don't try to make __initdata const (the version string). This can't
+ * work because of the way the __initdata sectioning works.
+ * o Added MODULE_LICENSE tags.
+ * o Support for PLX (transparent PCMCIA->PCI bridge) cards.
+ * o Changed to using the new type-fascist min/max.
+ *
+ * v0.08 -> v0.08a - 9/10/2001 - David Gibson
+ * o Inserted some missing acknowledgements/info into the Changelog.
+ * o Fixed some bugs in the normalization of signal level reporting.
+ * o Fixed bad bug in WEP key handling on Intersil and Symbol firmware,
+ * which led to an instant crash on big-endian machines.
+ *
+ * v0.08a -> v0.08b - 20/11/2001 - David Gibson
+ * o Lots of cleanup and bugfixes in orinoco_plx.c
+ * o Cleanup to handling of Tx rate setting.
+ * o Removed support for old encapsulation method.
+ * o Removed old "dldwd" names.
+ * o Split RID constants into a new file hermes_rid.h
+ * o Renamed RID constants to match linux-wlan-ng and prism2.o
+ * o Bugfixes in hermes.c
+ * o Poke the PLX's INTCSR register, so it actually starts
+ * generating interrupts. These cards might actually work now.
+ * o Update to wireless extensions v12 (Jean II)
+ * o Support for tallies and inquire command (Jean II)
+ * o Airport updates for newer PPC kernels (BenH)
+ *
+ * v0.08b -> v0.09 - 21/12/2001 - David Gibson
+ * o Some new PCI IDs for PLX cards.
+ * o Removed broken attempt to do ALLMULTI reception. Just use
+ * promiscuous mode instead
+ * o Preliminary work for list-AP (Jean II)
+ * o Airport updates from (BenH)
+ * o Eliminated racy hw_ready stuff
+ * o Fixed generation of fake events in irq handler. This should
+ * finally kill the EIO problems (Jean II & dgibson)
+ * o Fixed breakage of bitrate set/get on Agere firmware (Jean II)
+ *
+ * v0.09 -> v0.09a - 2/1/2002 - David Gibson
+ * o Fixed stupid mistake in multicast list handling, triggering
+ * a BUG()
+ *
+ * v0.09a -> v0.09b - 16/1/2002 - David Gibson
+ * o Fixed even stupider mistake in new interrupt handling, which
+ * seriously broke things on big-endian machines.
+ * o Removed a bunch of redundant includes and exports.
+ * o Removed a redundant MOD_{INC,DEC}_USE_COUNT pair in airport.c
+ * o Don't attempt to do hardware level multicast reception on
+ * Intersil firmware, just go promisc instead.
+ * o Typo fixed in hermes_issue_cmd()
+ * o Eliminated WIRELESS_SPY #ifdefs
+ * o Status code reported on Tx exceptions
+ * o Moved netif_wake_queue() from ALLOC interrupts to TX and TXEXC
+ * interrupts, which should fix the timeouts we're seeing.
+ *
+ * v0.09b -> v0.10 - 25 Feb 2002 - David Gibson
+ * o Removed nested structures used for header parsing, so the
+ * driver should now work without hackery on ARM
+ * o Fix for WEP handling on Intersil (Hawk Newton)
+ * o Eliminated the /proc/hermes/ethXX/regs debugging file. It
+ * was never very useful.
+ * o Make Rx errors less noisy.
+ *
+ * v0.10 -> v0.11 - 5 Apr 2002 - David Gibson
+ * o Laid the groundwork in hermes.[ch] for devices which map
+ * into PCI memory space rather than IO space.
+ * o Fixed bug in multicast handling (cleared multicast list when
+ * leaving promiscuous mode).
+ * o Relegated Tx error messages to debug.
+ * o Cleaned up / corrected handling of allocation lengths.
+ * o Set OWNSSID in IBSS mode for WinXP interoperability (jimc).
+ * o Change to using alloc_etherdev() for structure allocations.
+ * o Check for and drop undersized packets.
+ * o Fixed a race in stopping/waking the queue. This should fix
+ * the timeout problems (Pavel Roskin)
+ * o Reverted to netif_wake_queue() on the ALLOC event.
+ * o Fixes for recent Symbol firmwares which lack AP density
+ * (Pavel Roskin).
+ *
+ * v0.11 -> v0.11a - 29 Apr 2002 - David Gibson
+ * o Handle different register spacing, necessary for Prism 2.5
+ * PCI adaptors (Steve Hill).
+ * o Cleaned up initialization of card structures in orinoco_cs
+ * and airport. Removed card->priv field.
+ * o Make response structure optional for hermes_docmd_wait()
+ * Pavel Roskin)
+ * o Added PCI id for Nortel emobility to orinoco_plx.c.
+ * o Cleanup to handling of Symbol's allocation bug. (Pavel Roskin)
+ * o Cleanups to firmware capability detection.
+ * o Arrange for orinoco_pci.c to override firmware detection.
+ * We should be able to support the PCI Intersil cards now.
+ * o Cleanup handling of reset_cor and hard_reset (Pavel Roskin).
+ * o Remove erroneous use of USER_BAP in the TxExc handler (Jouni
+ * Malinen).
+ * o Makefile changes for better integration into David Hinds
+ * pcmcia-cs package.
+ *
+ * v0.11a -> v0.11b - 1 May 2002 - David Gibson
+ * o Better error reporting in orinoco_plx_init_one()
+ * o Fixed multiple bad kfree() bugs introduced by the
+ * alloc_orinocodev() changes.
+ *
+ * v0.11b -> v0.12 - 19 Jun 2002 - David Gibson
+ * o Support changing the MAC address.
+ * o Correct display of Intersil firmware revision numbers.
+ * o Entirely revised locking scheme. Should be both simpler and
+ * better.
+ * o Merged some common code in orinoco_plx, orinoco_pci and
+ * airport by creating orinoco_default_{open,stop,reset}()
+ * which are used as the dev->open, dev->stop, priv->reset
+ * callbacks if none are specified when alloc_orinocodev() is
+ * called.
+ * o Removed orinoco_plx_interrupt() and orinoco_pci_interrupt().
+ * They didn't do anything.
+ *
+ * v0.12 -> v0.12a - 4 Jul 2002 - David Gibson
+ * o Some rearrangement of code.
+ * o Numerous fixups to locking and rest handling, particularly
+ * for PCMCIA.
+ * o This allows open and stop net_device methods to be in
+ * orinoco.c now, rather than in the init modules.
+ * o In orinoco_cs.c link->priv now points to the struct
+ * net_device not to the struct orinoco_private.
+ * o Added a check for undersized SNAP frames, which could cause
+ * crashes.
+ *
+ * v0.12a -> v0.12b - 11 Jul 2002 - David Gibson
+ * o Fix hw->num_init testing code, so num_init is actually
+ * incremented.
+ * o Fix very stupid bug in orinoco_cs which broke compile with
+ * CONFIG_SMP.
+ * o Squashed a warning.
+ *
+ * v0.12b -> v0.12c - 26 Jul 2002 - David Gibson
+ * o Change to C9X style designated initializers.
+ * o Add support for 3Com AirConnect PCI.
+ * o No longer ignore the hard_reset argument to
+ * alloc_orinocodev(). Oops.
+ *
+ * v0.12c -> v0.13beta1 - 13 Sep 2002 - David Gibson
+ * o Revert the broken 0.12* locking scheme and go to a new yet
+ * simpler scheme.
+ * o Do firmware resets only in orinoco_init() and when waking
+ * the card from hard sleep.
+ *
+ * v0.13beta1 -> v0.13 - 27 Sep 2002 - David Gibson
+ * o Re-introduced full resets (via schedule_task()) on Tx
+ * timeout.
+ *
+ * v0.13 -> v0.13a - 30 Sep 2002 - David Gibson
+ * o Minor cleanups to info frame handling. Add basic support
+ * for linkstatus info frames.
+ * o Include required kernel headers in orinoco.h, to avoid
+ * compile problems.
+ *
+ * v0.13a -> v0.13b - 10 Feb 2003 - David Gibson
+ * o Implemented hard reset for Airport cards
+ * o Experimental suspend/resume implementation for orinoco_pci
+ * o Abolished /proc debugging support, replaced with a debugging
+ * iwpriv. Now it's ugly and simple instead of ugly and complex.
+ * o Bugfix in hermes.c if the firmware returned a record length
+ * of 0, we could go clobbering memory.
+ * o Bugfix in orinoco_stop() - it used to fail if hw_unavailable
+ * was set, which was usually true on PCMCIA hot removes.
+ * o Track LINKSTATUS messages, silently drop Tx packets before
+ * we are connected (avoids confusing the firmware), and only
+ * give LINKSTATUS printk()s if the status has changed.
+ *
+ * v0.13b -> v0.13c - 11 Mar 2003 - David Gibson
+ * o Cleanup: use dev instead of priv in various places.
+ * o Bug fix: Don't ReleaseConfiguration on RESET_PHYSICAL event
+ * if we're in the middle of a (driver initiated) hard reset.
+ * o Bug fix: ETH_ZLEN is supposed to include the header
+ * (Dionysus Blazakis & Manish Karir)
+ * o Convert to using workqueues instead of taskqueues (and
+ * backwards compatibility macros for pre 2.5.41 kernels).
+ * o Drop redundant (I think...) MOD_{INC,DEC}_USE_COUNT in
+ * airport.c
+ * o New orinoco_tmd.c init module from Joerg Dorchain for
+ * TMD7160 based PCI to PCMCIA bridges (similar to
+ * orinoco_plx.c).
+ *
+ * v0.13c -> v0.13d - 22 Apr 2003 - David Gibson
+ * o Make hw_unavailable a counter, rather than just a flag, this
+ * is necessary to avoid some races (such as a card being
+ * removed in the middle of orinoco_reset().
+ * o Restore Release/RequestConfiguration in the PCMCIA event handler
+ * when dealing with a driver initiated hard reset. This is
+ * necessary to prevent hangs due to a spurious interrupt while
+ * the reset is in progress.
+ * o Clear the 802.11 header when transmitting, even though we
+ * don't use it. This fixes a long standing bug on some
+ * firmwares, which seem to get confused if that isn't done.
+ * o Be less eager to de-encapsulate SNAP frames, only do so if
+ * the OUI is 00:00:00 or 00:00:f8, leave others alone. The old
+ * behaviour broke CDP (Cisco Discovery Protocol).
+ * o Use dev instead of priv for free_irq() as well as
+ * request_irq() (oops).
+ * o Attempt to reset rather than giving up if we get too many
+ * IRQs.
+ * o Changed semantics of __orinoco_down() so it can be called
+ * safely with hw_unavailable set. It also now clears the
+ * linkstatus (since we're going to have to reassociate).
+ *
+ * v0.13d -> v0.13e - 12 May 2003 - David Gibson
+ * o Support for post-2.5.68 return values from irq handler.
+ * o Fixed bug where underlength packets would be double counted
+ * in the rx_dropped statistics.
+ * o Provided a module parameter to suppress linkstatus messages.
+ *
+ * v0.13e -> v0.14alpha1 - 30 Sep 2003 - David Gibson
+ * o Replaced priv->connected logic with netif_carrier_on/off()
+ * calls.
+ * o Remove has_ibss_any and never set the CREATEIBSS RID when
+ * the ESSID is empty. Too many firmwares break if we do.
+ * o 2.6 merges: Replace pdev->slot_name with pci_name(), remove
+ * __devinitdata from PCI ID tables, use free_netdev().
+ * o Enabled shared-key authentication for Agere firmware (from
+ * Robert J. Moore
+ * o Move netif_wake_queue() (back) to the Tx completion from the
+ * ALLOC event. This seems to prevent/mitigate the rolling
+ * error -110 problems at least on some Intersil firmwares.
+ * Theoretically reduces performance, but I can't measure it.
+ * Patch from Andrew Tridgell
+ *
+ * v0.14alpha1 -> v0.14alpha2 - 20 Oct 2003 - David Gibson
+ * o Correctly turn off shared-key authentication when requested
+ * (bugfix from Robert J. Moore).
+ * o Correct airport sleep interfaces for current 2.6 kernels.
+ * o Add code for key change without disabling/enabling the MAC
+ * port. This is supposed to allow 802.1x to work sanely, but
+ * doesn't seem to yet.
+ *
* TODO
+ * o New wireless extensions API (patch from Moustafa
+ * Youssef, updated by Jim Carter and Pavel Roskin).
* o Handle de-encapsulation within network layer, provide 802.11
* headers (patch from Thomas 'Dent' Mirlacher)
+ * o RF monitor mode support
* o Fix possible races in SPY handling.
* o Disconnect wireless extensions from fundamental configuration.
* o (maybe) Software WEP support (patch from Stano Meduna).
@@ -89,10 +462,7 @@
#include
#include
#include
-#include
#include
-#include
-#include
#include
#include
@@ -126,10 +496,6 @@ static int ignore_disconnect; /* = 0 */
module_param(ignore_disconnect, int, 0644);
MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer");
-static int force_monitor; /* = 0 */
-module_param(force_monitor, int, 0644);
-MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions");
-
/********************************************************************/
/* Compile time configuration and compatibility stuff */
/********************************************************************/
@@ -145,10 +511,6 @@ MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions");
/* Internal constants */
/********************************************************************/
-/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */
-static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
-#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2)
-
#define ORINOCO_MIN_MTU 256
#define ORINOCO_MAX_MTU (IEEE802_11_DATA_LEN - ENCAPS_OVERHEAD)
@@ -175,11 +537,6 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
| HERMES_EV_WTERR | HERMES_EV_INFO \
| HERMES_EV_INFDROP )
-#define MAX_RID_LEN 1024
-
-static const struct iw_handler_def orinoco_handler_def;
-static struct ethtool_ops orinoco_ethtool_ops;
-
/********************************************************************/
/* Data tables */
/********************************************************************/
@@ -214,45 +571,26 @@ static struct {
/* Data types */
/********************************************************************/
-/* Used in Event handling.
- * We avoid nested structres as they break on ARM -- Moustafa */
-struct hermes_tx_descriptor_802_11 {
- /* hermes_tx_descriptor */
- u16 status;
- u16 reserved1;
- u16 reserved2;
- u32 sw_support;
- u8 retry_count;
- u8 tx_rate;
- u16 tx_control;
-
- /* ieee802_11_hdr */
- u16 frame_ctl;
- u16 duration_id;
- u8 addr1[ETH_ALEN];
- u8 addr2[ETH_ALEN];
- u8 addr3[ETH_ALEN];
- u16 seq_ctl;
- u8 addr4[ETH_ALEN];
- u16 data_len;
-
- /* ethhdr */
- unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
- unsigned char h_source[ETH_ALEN]; /* source ether addr */
- unsigned short h_proto; /* packet type ID field */
-
- /* p8022_hdr */
+struct header_struct {
+ /* 802.3 */
+ u8 dest[ETH_ALEN];
+ u8 src[ETH_ALEN];
+ u16 len;
+ /* 802.2 */
u8 dsap;
u8 ssap;
u8 ctrl;
+ /* SNAP */
u8 oui[3];
-
u16 ethertype;
} __attribute__ ((packed));
-/* Rx frame header except compatibility 802.3 header */
+/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */
+u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
+
+#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2)
+
struct hermes_rx_descriptor {
- /* Control */
u16 status;
u32 time;
u8 silence;
@@ -260,24 +598,13 @@ struct hermes_rx_descriptor {
u8 rate;
u8 rxflow;
u32 reserved;
-
- /* 802.11 header */
- u16 frame_ctl;
- u16 duration_id;
- u8 addr1[ETH_ALEN];
- u8 addr2[ETH_ALEN];
- u8 addr3[ETH_ALEN];
- u16 seq_ctl;
- u8 addr4[ETH_ALEN];
-
- /* Data length */
- u16 data_len;
} __attribute__ ((packed));
/********************************************************************/
/* Function prototypes */
/********************************************************************/
+static int orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static int __orinoco_program_rids(struct net_device *dev);
static void __orinoco_set_multicast_list(struct net_device *dev);
@@ -301,10 +628,6 @@ static inline void set_port_type(struct orinoco_private *priv)
priv->createibss = 1;
}
break;
- case IW_MODE_MONITOR:
- priv->port_type = 3;
- priv->createibss = 0;
- break;
default:
printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
priv->ndev->name);
@@ -491,7 +814,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
return 1;
}
- if (! netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) {
+ if (! netif_carrier_ok(dev)) {
/* Oops, the firmware hasn't established a connection,
silently drop the packet (this seems to be the
safest approach). */
@@ -628,55 +951,26 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
struct orinoco_private *priv = netdev_priv(dev);
struct net_device_stats *stats = &priv->stats;
u16 fid = hermes_read_regn(hw, TXCOMPLFID);
- struct hermes_tx_descriptor_802_11 hdr;
+ struct hermes_tx_descriptor desc;
int err = 0;
if (fid == DUMMY_FID)
return; /* Nothing's really happened */
- /* Read the frame header */
- err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
- sizeof(struct hermes_tx_descriptor) +
- sizeof(struct ieee80211_hdr),
- fid, 0);
-
- hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
- stats->tx_errors++;
-
+ err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), fid, 0);
if (err) {
printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "
"(FID=%04X error %d)\n",
dev->name, fid, err);
- return;
+ } else {
+ DEBUG(1, "%s: Tx error, status %d\n",
+ dev->name, le16_to_cpu(desc.status));
}
- DEBUG(1, "%s: Tx error, err %d (FID=%04X)\n", dev->name,
- err, fid);
-
- /* We produce a TXDROP event only for retry or lifetime
- * exceeded, because that's the only status that really mean
- * that this particular node went away.
- * Other errors means that *we* screwed up. - Jean II */
- hdr.status = le16_to_cpu(hdr.status);
- if (hdr.status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
- union iwreq_data wrqu;
-
- /* Copy 802.11 dest address.
- * We use the 802.11 header because the frame may
- * not be 802.3 or may be mangled...
- * In Ad-Hoc mode, it will be the node address.
- * In managed mode, it will be most likely the AP addr
- * User space will figure out how to convert it to
- * whatever it needs (IP address or else).
- * - Jean II */
- memcpy(wrqu.addr.sa_data, hdr.addr1, ETH_ALEN);
- wrqu.addr.sa_family = ARPHRD_ETHER;
-
- /* Send event to user space */
- wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL);
- }
+ stats->tx_errors++;
netif_wake_queue(dev);
+ hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
}
static void orinoco_tx_timeout(struct net_device *dev)
@@ -753,127 +1047,18 @@ static void orinoco_stat_gather(struct net_device *dev,
}
}
-/*
- * orinoco_rx_monitor - handle received monitor frames.
- *
- * Arguments:
- * dev network device
- * rxfid received FID
- * desc rx descriptor of the frame
- *
- * Call context: interrupt
- */
-static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
- struct hermes_rx_descriptor *desc)
-{
- u32 hdrlen = 30; /* return full header by default */
- u32 datalen = 0;
- u16 fc;
- int err;
- int len;
- struct sk_buff *skb;
- struct orinoco_private *priv = netdev_priv(dev);
- struct net_device_stats *stats = &priv->stats;
- hermes_t *hw = &priv->hw;
-
- len = le16_to_cpu(desc->data_len);
-
- /* Determine the size of the header and the data */
- fc = le16_to_cpu(desc->frame_ctl);
- switch (fc & IEEE80211_FCTL_FTYPE) {
- case IEEE80211_FTYPE_DATA:
- if ((fc & IEEE80211_FCTL_TODS)
- && (fc & IEEE80211_FCTL_FROMDS))
- hdrlen = 30;
- else
- hdrlen = 24;
- datalen = len;
- break;
- case IEEE80211_FTYPE_MGMT:
- hdrlen = 24;
- datalen = len;
- break;
- case IEEE80211_FTYPE_CTL:
- switch (fc & IEEE80211_FCTL_STYPE) {
- case IEEE80211_STYPE_PSPOLL:
- case IEEE80211_STYPE_RTS:
- case IEEE80211_STYPE_CFEND:
- case IEEE80211_STYPE_CFENDACK:
- hdrlen = 16;
- break;
- case IEEE80211_STYPE_CTS:
- case IEEE80211_STYPE_ACK:
- hdrlen = 10;
- break;
- }
- break;
- default:
- /* Unknown frame type */
- break;
- }
-
- /* sanity check the length */
- if (datalen > IEEE80211_DATA_LEN + 12) {
- printk(KERN_DEBUG "%s: oversized monitor frame, "
- "data length = %d\n", dev->name, datalen);
- err = -EIO;
- stats->rx_length_errors++;
- goto update_stats;
- }
-
- skb = dev_alloc_skb(hdrlen + datalen);
- if (!skb) {
- printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n",
- dev->name);
- err = -ENOMEM;
- goto drop;
- }
-
- /* Copy the 802.11 header to the skb */
- memcpy(skb_put(skb, hdrlen), &(desc->frame_ctl), hdrlen);
- skb->mac.raw = skb->data;
-
- /* If any, copy the data from the card to the skb */
- if (datalen > 0) {
- err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),
- ALIGN(datalen, 2), rxfid,
- HERMES_802_2_OFFSET);
- if (err) {
- printk(KERN_ERR "%s: error %d reading monitor frame\n",
- dev->name, err);
- goto drop;
- }
- }
-
- skb->dev = dev;
- skb->ip_summed = CHECKSUM_NONE;
- skb->pkt_type = PACKET_OTHERHOST;
- skb->protocol = __constant_htons(ETH_P_802_2);
-
- dev->last_rx = jiffies;
- stats->rx_packets++;
- stats->rx_bytes += skb->len;
-
- netif_rx(skb);
- return;
-
- drop:
- dev_kfree_skb_irq(skb);
- update_stats:
- stats->rx_errors++;
- stats->rx_dropped++;
-}
-
static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
{
struct orinoco_private *priv = netdev_priv(dev);
struct net_device_stats *stats = &priv->stats;
struct iw_statistics *wstats = &priv->wstats;
struct sk_buff *skb = NULL;
- u16 rxfid, status, fc;
- int length;
+ u16 rxfid, status;
+ int length, data_len, data_off;
+ char *p;
struct hermes_rx_descriptor desc;
- struct ethhdr *hdr;
+ struct header_struct hdr;
+ struct ethhdr *eh;
int err;
rxfid = hermes_read_regn(hw, RXFID);
@@ -883,46 +1068,53 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
if (err) {
printk(KERN_ERR "%s: error %d reading Rx descriptor. "
"Frame dropped.\n", dev->name, err);
- goto update_stats;
+ stats->rx_errors++;
+ goto drop;
}
status = le16_to_cpu(desc.status);
- if (status & HERMES_RXSTAT_BADCRC) {
- DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n",
- dev->name);
- stats->rx_crc_errors++;
- goto update_stats;
+ if (status & HERMES_RXSTAT_ERR) {
+ if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
+ wstats->discard.code++;
+ DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
+ dev->name);
+ } else {
+ stats->rx_crc_errors++;
+ DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name);
+ }
+ stats->rx_errors++;
+ goto drop;
}
- /* Handle frames in monitor mode */
- if (priv->iw_mode == IW_MODE_MONITOR) {
- orinoco_rx_monitor(dev, rxfid, &desc);
- return;
- }
+ /* For now we ignore the 802.11 header completely, assuming
+ that the card's firmware has handled anything vital */
- if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
- DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
- dev->name);
- wstats->discard.code++;
- goto update_stats;
+ err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr),
+ rxfid, HERMES_802_3_OFFSET);
+ if (err) {
+ printk(KERN_ERR "%s: error %d reading frame header. "
+ "Frame dropped.\n", dev->name, err);
+ stats->rx_errors++;
+ goto drop;
}
- length = le16_to_cpu(desc.data_len);
- fc = le16_to_cpu(desc.frame_ctl);
-
+ length = ntohs(hdr.len);
+
/* Sanity checks */
if (length < 3) { /* No for even an 802.2 LLC header */
/* At least on Symbol firmware with PCF we get quite a
lot of these legitimately - Poll frames with no
data. */
- return;
+ stats->rx_dropped++;
+ goto drop;
}
if (length > IEEE802_11_DATA_LEN) {
printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
dev->name, length);
stats->rx_length_errors++;
- goto update_stats;
+ stats->rx_errors++;
+ goto drop;
}
/* We need space for the packet data itself, plus an ethernet
@@ -934,53 +1126,60 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
if (!skb) {
printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
dev->name);
- goto update_stats;
- }
-
- /* We'll prepend the header, so reserve space for it. The worst
- case is no decapsulation, when 802.3 header is prepended and
- nothing is removed. 2 is for aligning the IP header. */
- skb_reserve(skb, ETH_HLEN + 2);
-
- err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length),
- ALIGN(length, 2), rxfid,
- HERMES_802_2_OFFSET);
- if (err) {
- printk(KERN_ERR "%s: error %d reading frame. "
- "Frame dropped.\n", dev->name, err);
goto drop;
}
+ skb_reserve(skb, 2); /* This way the IP header is aligned */
+
/* Handle decapsulation
* In most cases, the firmware tell us about SNAP frames.
* For some reason, the SNAP frames sent by LinkSys APs
* are not properly recognised by most firmwares.
* So, check ourselves */
- if (length >= ENCAPS_OVERHEAD &&
- (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
- ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
- is_ethersnap(skb->data))) {
+ if (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
+ ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
+ is_ethersnap(&hdr)) {
/* These indicate a SNAP within 802.2 LLC within
802.11 frame which we'll need to de-encapsulate to
the original EthernetII frame. */
- hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN - ENCAPS_OVERHEAD);
+
+ if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */
+ stats->rx_length_errors++;
+ goto drop;
+ }
+
+ /* Remove SNAP header, reconstruct EthernetII frame */
+ data_len = length - ENCAPS_OVERHEAD;
+ data_off = HERMES_802_3_OFFSET + sizeof(hdr);
+
+ eh = (struct ethhdr *)skb_put(skb, ETH_HLEN);
+
+ memcpy(eh, &hdr, 2 * ETH_ALEN);
+ eh->h_proto = hdr.ethertype;
} else {
- /* 802.3 frame - prepend 802.3 header as is */
- hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN);
- hdr->h_proto = htons(length);
+ /* All other cases indicate a genuine 802.3 frame. No
+ decapsulation needed. We just throw the whole
+ thing in, and hope the protocol layer can deal with
+ it as 802.3 */
+ data_len = length;
+ data_off = HERMES_802_3_OFFSET;
+ /* FIXME: we re-read from the card data we already read here */
+ }
+
+ p = skb_put(skb, data_len);
+ err = hermes_bap_pread(hw, IRQ_BAP, p, ALIGN(data_len, 2),
+ rxfid, data_off);
+ if (err) {
+ printk(KERN_ERR "%s: error %d reading frame. "
+ "Frame dropped.\n", dev->name, err);
+ stats->rx_errors++;
+ goto drop;
}
- memcpy(hdr->h_dest, desc.addr1, ETH_ALEN);
- if (fc & IEEE80211_FCTL_FROMDS)
- memcpy(hdr->h_source, desc.addr3, ETH_ALEN);
- else
- memcpy(hdr->h_source, desc.addr2, ETH_ALEN);
dev->last_rx = jiffies;
skb->dev = dev;
skb->protocol = eth_type_trans(skb, dev);
skb->ip_summed = CHECKSUM_NONE;
- if (fc & IEEE80211_FCTL_TODS)
- skb->pkt_type = PACKET_OTHERHOST;
/* Process the wireless stats if needed */
orinoco_stat_gather(dev, skb, &desc);
@@ -993,10 +1192,11 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
return;
drop:
- dev_kfree_skb_irq(skb);
- update_stats:
- stats->rx_errors++;
stats->rx_dropped++;
+
+ if (skb)
+ dev_kfree_skb_irq(skb);
+ return;
}
/********************************************************************/
@@ -1040,99 +1240,6 @@ static void print_linkstatus(struct net_device *dev, u16 status)
dev->name, s, status);
}
-/* Search scan results for requested BSSID, join it if found */
-static void orinoco_join_ap(struct net_device *dev)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- struct hermes *hw = &priv->hw;
- int err;
- unsigned long flags;
- struct join_req {
- u8 bssid[ETH_ALEN];
- u16 channel;
- } __attribute__ ((packed)) req;
- const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
- struct prism2_scan_apinfo *atom;
- int offset = 4;
- u8 *buf;
- u16 len;
-
- /* Allocate buffer for scan results */
- buf = kmalloc(MAX_SCAN_LEN, GFP_KERNEL);
- if (! buf)
- return;
-
- if (orinoco_lock(priv, &flags) != 0)
- goto out;
-
- /* Sanity checks in case user changed something in the meantime */
- if (! priv->bssid_fixed)
- goto out;
-
- if (strlen(priv->desired_essid) == 0)
- goto out;
-
- /* Read scan results from the firmware */
- err = hermes_read_ltv(hw, USER_BAP,
- HERMES_RID_SCANRESULTSTABLE,
- MAX_SCAN_LEN, &len, buf);
- if (err) {
- printk(KERN_ERR "%s: Cannot read scan results\n",
- dev->name);
- goto out;
- }
-
- len = HERMES_RECLEN_TO_BYTES(len);
-
- /* Go through the scan results looking for the channel of the AP
- * we were requested to join */
- for (; offset + atom_len <= len; offset += atom_len) {
- atom = (struct prism2_scan_apinfo *) (buf + offset);
- if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0)
- goto found;
- }
-
- DEBUG(1, "%s: Requested AP not found in scan results\n",
- dev->name);
- goto out;
-
- found:
- memcpy(req.bssid, priv->desired_bssid, ETH_ALEN);
- req.channel = atom->channel; /* both are little-endian */
- err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST,
- &req);
- if (err)
- printk(KERN_ERR "%s: Error issuing join request\n", dev->name);
-
- out:
- kfree(buf);
- orinoco_unlock(priv, &flags);
-}
-
-/* Send new BSSID to userspace */
-static void orinoco_send_wevents(struct net_device *dev)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- struct hermes *hw = &priv->hw;
- union iwreq_data wrqu;
- int err;
- unsigned long flags;
-
- if (orinoco_lock(priv, &flags) != 0)
- return;
-
- err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID,
- ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
- if (err != 0)
- return;
-
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-
- /* Send event to user space */
- wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
- orinoco_unlock(priv, &flags);
-}
-
static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
{
struct orinoco_private *priv = netdev_priv(dev);
@@ -1200,9 +1307,6 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
u16 newstatus;
int connected;
- if (priv->iw_mode == IW_MODE_MONITOR)
- break;
-
if (len != sizeof(linkstatus)) {
printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",
dev->name, len);
@@ -1215,15 +1319,6 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
break;
newstatus = le16_to_cpu(linkstatus.linkstatus);
- /* Symbol firmware uses "out of range" to signal that
- * the hostscan frame can be requested. */
- if (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE &&
- priv->firmware_type == FIRMWARE_TYPE_SYMBOL &&
- priv->has_hostscan && priv->scan_inprogress) {
- hermes_inquire(hw, HERMES_INQ_HOSTSCAN_SYMBOL);
- break;
- }
-
connected = (newstatus == HERMES_LINKSTATUS_CONNECTED)
|| (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
|| (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE);
@@ -1233,89 +1328,12 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
else if (!ignore_disconnect)
netif_carrier_off(dev);
- if (newstatus != priv->last_linkstatus) {
- priv->last_linkstatus = newstatus;
+ if (newstatus != priv->last_linkstatus)
print_linkstatus(dev, newstatus);
- /* The info frame contains only one word which is the
- * status (see hermes.h). The status is pretty boring
- * in itself, that's why we export the new BSSID...
- * Jean II */
- schedule_work(&priv->wevent_work);
- }
- }
- break;
- case HERMES_INQ_SCAN:
- if (!priv->scan_inprogress && priv->bssid_fixed &&
- priv->firmware_type == FIRMWARE_TYPE_INTERSIL) {
- schedule_work(&priv->join_work);
- break;
- }
- /* fall through */
- case HERMES_INQ_HOSTSCAN:
- case HERMES_INQ_HOSTSCAN_SYMBOL: {
- /* Result of a scanning. Contains information about
- * cells in the vicinity - Jean II */
- union iwreq_data wrqu;
- unsigned char *buf;
-
- /* Sanity check */
- if (len > 4096) {
- printk(KERN_WARNING "%s: Scan results too large (%d bytes)\n",
- dev->name, len);
- break;
- }
-
- /* We are a strict producer. If the previous scan results
- * have not been consumed, we just have to drop this
- * frame. We can't remove the previous results ourselves,
- * that would be *very* racy... Jean II */
- if (priv->scan_result != NULL) {
- printk(KERN_WARNING "%s: Previous scan results not consumed, dropping info frame.\n", dev->name);
- break;
- }
-
- /* Allocate buffer for results */
- buf = kmalloc(len, GFP_ATOMIC);
- if (buf == NULL)
- /* No memory, so can't printk()... */
- break;
- /* Read scan data */
- err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len,
- infofid, sizeof(info));
- if (err)
- break;
-
-#ifdef ORINOCO_DEBUG
- {
- int i;
- printk(KERN_DEBUG "Scan result [%02X", buf[0]);
- for(i = 1; i < (len * 2); i++)
- printk(":%02X", buf[i]);
- printk("]\n");
- }
-#endif /* ORINOCO_DEBUG */
-
- /* Allow the clients to access the results */
- priv->scan_len = len;
- priv->scan_result = buf;
-
- /* Send an empty event to user space.
- * We don't send the received data on the event because
- * it would require us to do complex transcoding, and
- * we want to minimise the work done in the irq handler
- * Use a request to extract the data - Jean II */
- wrqu.data.length = 0;
- wrqu.data.flags = 0;
- wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
+ priv->last_linkstatus = newstatus;
}
break;
- case HERMES_INQ_SEC_STAT_AGERE:
- /* Security status (Agere specific) */
- /* Ignore this frame for now */
- if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
- break;
- /* fall through */
default:
printk(KERN_DEBUG "%s: Unknown information frame received: "
"type 0x%04x, length %d\n", dev->name, type, len);
@@ -1452,36 +1470,6 @@ static int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
return err;
}
-/* Set fixed AP address */
-static int __orinoco_hw_set_wap(struct orinoco_private *priv)
-{
- int roaming_flag;
- int err = 0;
- hermes_t *hw = &priv->hw;
-
- switch (priv->firmware_type) {
- case FIRMWARE_TYPE_AGERE:
- /* not supported */
- break;
- case FIRMWARE_TYPE_INTERSIL:
- if (priv->bssid_fixed)
- roaming_flag = 2;
- else
- roaming_flag = 1;
-
- err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFROAMINGMODE,
- roaming_flag);
- break;
- case FIRMWARE_TYPE_SYMBOL:
- err = HERMES_WRITE_RECORD(hw, USER_BAP,
- HERMES_RID_CNFMANDATORYBSSID_SYMBOL,
- &priv->desired_bssid);
- break;
- }
- return err;
-}
-
/* Change the WEP keys and/or the current keys. Can be called
* either from __orinoco_hw_setup_wep() or directly from
* orinoco_ioctl_setiwencode(). In the later case the association
@@ -1667,13 +1655,6 @@ static int __orinoco_program_rids(struct net_device *dev)
}
}
- /* Set the desired BSSID */
- err = __orinoco_hw_set_wap(priv);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting AP address\n",
- dev->name, err);
- return err;
- }
/* Set the desired ESSID */
idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
@@ -1812,20 +1793,6 @@ static int __orinoco_program_rids(struct net_device *dev)
}
}
- if (priv->iw_mode == IW_MODE_MONITOR) {
- /* Enable monitor mode */
- dev->type = ARPHRD_IEEE80211;
- err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
- HERMES_TEST_MONITOR, 0, NULL);
- } else {
- /* Disable monitor mode */
- dev->type = ARPHRD_ETHER;
- err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
- HERMES_TEST_STOP, 0, NULL);
- }
- if (err)
- return err;
-
/* Set promiscuity / multicast*/
priv->promiscuous = 0;
priv->mc_count = 0;
@@ -1902,6 +1869,55 @@ __orinoco_set_multicast_list(struct net_device *dev)
dev->flags &= ~IFF_PROMISC;
}
+static int orinoco_reconfigure(struct net_device *dev)
+{
+ struct orinoco_private *priv = netdev_priv(dev);
+ struct hermes *hw = &priv->hw;
+ unsigned long flags;
+ int err = 0;
+
+ if (priv->broken_disableport) {
+ schedule_work(&priv->reset_work);
+ return 0;
+ }
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+
+ err = hermes_disable_port(hw, 0);
+ if (err) {
+ printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n",
+ dev->name);
+ priv->broken_disableport = 1;
+ goto out;
+ }
+
+ err = __orinoco_program_rids(dev);
+ if (err) {
+ printk(KERN_WARNING "%s: Unable to reconfigure card\n",
+ dev->name);
+ goto out;
+ }
+
+ err = hermes_enable_port(hw, 0);
+ if (err) {
+ printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
+ dev->name);
+ goto out;
+ }
+
+ out:
+ if (err) {
+ printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
+ schedule_work(&priv->reset_work);
+ err = 0;
+ }
+
+ orinoco_unlock(priv, &flags);
+ return err;
+
+}
+
/* This must be called from user context, without locks held - use
* schedule_work() */
static void orinoco_reset(struct net_device *dev)
@@ -1930,11 +1946,6 @@ static void orinoco_reset(struct net_device *dev)
orinoco_unlock(priv, &flags);
- /* Scanning support: Cleanup of driver struct */
- kfree(priv->scan_result);
- priv->scan_result = NULL;
- priv->scan_inprogress = 0;
-
if (priv->hard_reset) {
err = (*priv->hard_reset)(priv);
if (err) {
@@ -2173,8 +2184,6 @@ static int determine_firmware(struct net_device *dev)
priv->has_mwo = (firmver >= 0x60000);
priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
priv->ibss_port = 1;
- priv->has_hostscan = (firmver >= 0x8000a);
- priv->broken_monitor = (firmver >= 0x80000);
/* Tested with Agere firmware :
* 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
@@ -2220,8 +2229,6 @@ static int determine_firmware(struct net_device *dev)
priv->ibss_port = 4;
priv->broken_disableport = (firmver == 0x25013) ||
(firmver >= 0x30000 && firmver <= 0x31000);
- priv->has_hostscan = (firmver >= 0x31001) ||
- (firmver >= 0x29057 && firmver < 0x30000);
/* Tested with Intel firmware : 0x20015 => Jean II */
/* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
break;
@@ -2241,7 +2248,6 @@ static int determine_firmware(struct net_device *dev)
priv->has_ibss = (firmver >= 0x000700); /* FIXME */
priv->has_big_wep = priv->has_wep = (firmver >= 0x000800);
priv->has_pm = (firmver >= 0x000700);
- priv->has_hostscan = (firmver >= 0x010301);
if (firmver >= 0x000800)
priv->ibss_port = 0;
@@ -2450,9 +2456,8 @@ struct net_device *alloc_orinocodev(int sizeof_card,
dev->tx_timeout = orinoco_tx_timeout;
dev->watchdog_timeo = HZ; /* 1 second timeout */
dev->get_stats = orinoco_get_stats;
- dev->ethtool_ops = &orinoco_ethtool_ops;
dev->get_wireless_stats = orinoco_get_wireless_stats;
- dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def;
+ dev->do_ioctl = orinoco_ioctl;
dev->change_mtu = orinoco_change_mtu;
dev->set_multicast_list = orinoco_set_multicast_list;
/* we use the default eth_mac_addr for setting the MAC addr */
@@ -2468,8 +2473,6 @@ struct net_device *alloc_orinocodev(int sizeof_card,
* before anything else touches the
* hardware */
INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev);
- INIT_WORK(&priv->join_work, (void (*)(void *))orinoco_join_ap, dev);
- INIT_WORK(&priv->wevent_work, (void (*)(void *))orinoco_send_wevents, dev);
netif_carrier_off(dev);
priv->last_linkstatus = 0xffff;
@@ -2480,9 +2483,6 @@ struct net_device *alloc_orinocodev(int sizeof_card,
void free_orinocodev(struct net_device *dev)
{
- struct orinoco_private *priv = netdev_priv(dev);
-
- kfree(priv->scan_result);
free_netdev(dev);
}
@@ -2490,6 +2490,24 @@ void free_orinocodev(struct net_device *dev)
/* Wireless extensions */
/********************************************************************/
+static int orinoco_hw_get_bssid(struct orinoco_private *priv,
+ char buf[ETH_ALEN])
+{
+ hermes_t *hw = &priv->hw;
+ int err = 0;
+ unsigned long flags;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+
+ err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
+ ETH_ALEN, NULL, buf);
+
+ orinoco_unlock(priv, &flags);
+
+ return err;
+}
+
static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
char buf[IW_ESSID_MAX_SIZE+1])
{
@@ -2615,271 +2633,140 @@ static int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
return 0;
}
-static int orinoco_ioctl_getname(struct net_device *dev,
- struct iw_request_info *info,
- char *name,
- char *extra)
+static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq)
{
struct orinoco_private *priv = netdev_priv(dev);
+ int err = 0;
+ int mode;
+ struct iw_range range;
int numrates;
- int err;
-
- err = orinoco_hw_get_bitratelist(priv, &numrates, NULL, 0);
-
- if (!err && (numrates > 2))
- strcpy(name, "IEEE 802.11b");
- else
- strcpy(name, "IEEE 802.11-DS");
-
- return 0;
-}
-
-static int orinoco_ioctl_setwap(struct net_device *dev,
- struct iw_request_info *info,
- struct sockaddr *ap_addr,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- int err = -EINPROGRESS; /* Call commit handler */
+ int i, k;
unsigned long flags;
- static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- static const u8 any_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- /* Enable automatic roaming - no sanity checks are needed */
- if (memcmp(&ap_addr->sa_data, off_addr, ETH_ALEN) == 0 ||
- memcmp(&ap_addr->sa_data, any_addr, ETH_ALEN) == 0) {
- priv->bssid_fixed = 0;
- memset(priv->desired_bssid, 0, ETH_ALEN);
-
- /* "off" means keep existing connection */
- if (ap_addr->sa_data[0] == 0) {
- __orinoco_hw_set_wap(priv);
- err = 0;
- }
- goto out;
- }
-
- if (priv->firmware_type == FIRMWARE_TYPE_AGERE) {
- printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't "
- "support manual roaming\n",
- dev->name);
- err = -EOPNOTSUPP;
- goto out;
- }
- if (priv->iw_mode != IW_MODE_INFRA) {
- printk(KERN_WARNING "%s: Manual roaming supported only in "
- "managed mode\n", dev->name);
- err = -EOPNOTSUPP;
- goto out;
- }
-
- /* Intersil firmware hangs without Desired ESSID */
- if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL &&
- strlen(priv->desired_essid) == 0) {
- printk(KERN_WARNING "%s: Desired ESSID must be set for "
- "manual roaming\n", dev->name);
- err = -EOPNOTSUPP;
- goto out;
- }
-
- /* Finally, enable manual roaming */
- priv->bssid_fixed = 1;
- memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN);
+ TRACE_ENTER(dev->name);
- out:
- orinoco_unlock(priv, &flags);
- return err;
-}
+ if (!access_ok(VERIFY_WRITE, rrq->pointer, sizeof(range)))
+ return -EFAULT;
-static int orinoco_ioctl_getwap(struct net_device *dev,
- struct iw_request_info *info,
- struct sockaddr *ap_addr,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
-
- hermes_t *hw = &priv->hw;
- int err = 0;
- unsigned long flags;
+ rrq->length = sizeof(range);
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
- ap_addr->sa_family = ARPHRD_ETHER;
- err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
- ETH_ALEN, NULL, ap_addr->sa_data);
-
+ mode = priv->iw_mode;
orinoco_unlock(priv, &flags);
- return err;
-}
+ memset(&range, 0, sizeof(range));
-static int orinoco_ioctl_setmode(struct net_device *dev,
- struct iw_request_info *info,
- u32 *mode,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- int err = -EINPROGRESS; /* Call commit handler */
- unsigned long flags;
+ /* Much of this shamelessly taken from wvlan_cs.c. No idea
+ * what it all means -dgibson */
+ range.we_version_compiled = WIRELESS_EXT;
+ range.we_version_source = 11;
- if (priv->iw_mode == *mode)
- return 0;
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- switch (*mode) {
- case IW_MODE_ADHOC:
- if (!priv->has_ibss && !priv->has_port3)
- err = -EOPNOTSUPP;
- break;
-
- case IW_MODE_INFRA:
- break;
-
- case IW_MODE_MONITOR:
- if (priv->broken_monitor && !force_monitor) {
- printk(KERN_WARNING "%s: Monitor mode support is "
- "buggy in this firmware, not enabling\n",
- dev->name);
- err = -EOPNOTSUPP;
- }
- break;
-
- default:
- err = -EOPNOTSUPP;
- break;
- }
-
- if (err == -EINPROGRESS) {
- priv->iw_mode = *mode;
- set_port_type(priv);
- }
-
- orinoco_unlock(priv, &flags);
-
- return err;
-}
-
-static int orinoco_ioctl_getmode(struct net_device *dev,
- struct iw_request_info *info,
- u32 *mode,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
-
- *mode = priv->iw_mode;
- return 0;
-}
-
-static int orinoco_ioctl_getiwrange(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *rrq,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- int err = 0;
- struct iw_range *range = (struct iw_range *) extra;
- int numrates;
- int i, k;
-
- TRACE_ENTER(dev->name);
-
- rrq->length = sizeof(struct iw_range);
- memset(range, 0, sizeof(struct iw_range));
-
- range->we_version_compiled = WIRELESS_EXT;
- range->we_version_source = 14;
+ range.min_nwid = range.max_nwid = 0; /* We don't use nwids */
/* Set available channels/frequencies */
- range->num_channels = NUM_CHANNELS;
+ range.num_channels = NUM_CHANNELS;
k = 0;
for (i = 0; i < NUM_CHANNELS; i++) {
if (priv->channel_mask & (1 << i)) {
- range->freq[k].i = i + 1;
- range->freq[k].m = channel_frequency[i] * 100000;
- range->freq[k].e = 1;
+ range.freq[k].i = i + 1;
+ range.freq[k].m = channel_frequency[i] * 100000;
+ range.freq[k].e = 1;
k++;
}
if (k >= IW_MAX_FREQUENCIES)
break;
}
- range->num_frequency = k;
- range->sensitivity = 3;
-
- if (priv->has_wep) {
- range->max_encoding_tokens = ORINOCO_MAX_KEYS;
- range->encoding_size[0] = SMALL_KEY_SIZE;
- range->num_encoding_sizes = 1;
+ range.num_frequency = k;
- if (priv->has_big_wep) {
- range->encoding_size[1] = LARGE_KEY_SIZE;
- range->num_encoding_sizes = 2;
- }
- }
+ range.sensitivity = 3;
- if ((priv->iw_mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){
+ if ((mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){
/* Quality stats meaningless in ad-hoc mode */
+ range.max_qual.qual = 0;
+ range.max_qual.level = 0;
+ range.max_qual.noise = 0;
+ range.avg_qual.qual = 0;
+ range.avg_qual.level = 0;
+ range.avg_qual.noise = 0;
} else {
- range->max_qual.qual = 0x8b - 0x2f;
- range->max_qual.level = 0x2f - 0x95 - 1;
- range->max_qual.noise = 0x2f - 0x95 - 1;
+ range.max_qual.qual = 0x8b - 0x2f;
+ range.max_qual.level = 0x2f - 0x95 - 1;
+ range.max_qual.noise = 0x2f - 0x95 - 1;
/* Need to get better values */
- range->avg_qual.qual = 0x24;
- range->avg_qual.level = 0xC2;
- range->avg_qual.noise = 0x9E;
+ range.avg_qual.qual = 0x24;
+ range.avg_qual.level = 0xC2;
+ range.avg_qual.noise = 0x9E;
}
err = orinoco_hw_get_bitratelist(priv, &numrates,
- range->bitrate, IW_MAX_BITRATES);
+ range.bitrate, IW_MAX_BITRATES);
if (err)
return err;
- range->num_bitrates = numrates;
-
+ range.num_bitrates = numrates;
+
/* Set an indication of the max TCP throughput in bit/s that we can
* expect using this interface. May be use for QoS stuff...
* Jean II */
- if (numrates > 2)
- range->throughput = 5 * 1000 * 1000; /* ~5 Mb/s */
+ if(numrates > 2)
+ range.throughput = 5 * 1000 * 1000; /* ~5 Mb/s */
else
- range->throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */
-
- range->min_rts = 0;
- range->max_rts = 2347;
- range->min_frag = 256;
- range->max_frag = 2346;
-
- range->min_pmp = 0;
- range->max_pmp = 65535000;
- range->min_pmt = 0;
- range->max_pmt = 65535 * 1000; /* ??? */
- range->pmp_flags = IW_POWER_PERIOD;
- range->pmt_flags = IW_POWER_TIMEOUT;
- range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;
-
- range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
- range->retry_flags = IW_RETRY_LIMIT;
- range->r_time_flags = IW_RETRY_LIFETIME;
- range->min_retry = 0;
- range->max_retry = 65535; /* ??? */
- range->min_r_time = 0;
- range->max_r_time = 65535 * 1000; /* ??? */
+ range.throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */
+
+ range.min_rts = 0;
+ range.max_rts = 2347;
+ range.min_frag = 256;
+ range.max_frag = 2346;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+ if (priv->has_wep) {
+ range.max_encoding_tokens = ORINOCO_MAX_KEYS;
+
+ range.encoding_size[0] = SMALL_KEY_SIZE;
+ range.num_encoding_sizes = 1;
+
+ if (priv->has_big_wep) {
+ range.encoding_size[1] = LARGE_KEY_SIZE;
+ range.num_encoding_sizes = 2;
+ }
+ } else {
+ range.num_encoding_sizes = 0;
+ range.max_encoding_tokens = 0;
+ }
+ orinoco_unlock(priv, &flags);
+
+ range.min_pmp = 0;
+ range.max_pmp = 65535000;
+ range.min_pmt = 0;
+ range.max_pmt = 65535 * 1000; /* ??? */
+ range.pmp_flags = IW_POWER_PERIOD;
+ range.pmt_flags = IW_POWER_TIMEOUT;
+ range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;
+
+ range.num_txpower = 1;
+ range.txpower[0] = 15; /* 15dBm */
+ range.txpower_capa = IW_TXPOW_DBM;
+
+ range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
+ range.retry_flags = IW_RETRY_LIMIT;
+ range.r_time_flags = IW_RETRY_LIFETIME;
+ range.min_retry = 0;
+ range.max_retry = 65535; /* ??? */
+ range.min_r_time = 0;
+ range.max_r_time = 65535 * 1000; /* ??? */
+
+ if (copy_to_user(rrq->pointer, &range, sizeof(range)))
+ return -EFAULT;
TRACE_EXIT(dev->name);
return 0;
}
-static int orinoco_ioctl_setiwencode(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq,
- char *keybuf)
+static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq)
{
struct orinoco_private *priv = netdev_priv(dev);
int index = (erq->flags & IW_ENCODE_INDEX) - 1;
@@ -2887,7 +2774,8 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
int enable = priv->wep_on;
int restricted = priv->wep_restrict;
u16 xlen = 0;
- int err = -EINPROGRESS; /* Call commit handler */
+ int err = 0;
+ char keybuf[ORINOCO_MAX_KEY_SIZE];
unsigned long flags;
if (! priv->has_wep)
@@ -2900,6 +2788,9 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
if ( (erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep )
return -E2BIG;
+
+ if (copy_from_user(keybuf, erq->pointer, erq->length))
+ return -EFAULT;
}
if (orinoco_lock(priv, &flags) != 0)
@@ -2973,14 +2864,12 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
return err;
}
-static int orinoco_ioctl_getiwencode(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq,
- char *keybuf)
+static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq)
{
struct orinoco_private *priv = netdev_priv(dev);
int index = (erq->flags & IW_ENCODE_INDEX) - 1;
u16 xlen = 0;
+ char keybuf[ORINOCO_MAX_KEY_SIZE];
unsigned long flags;
if (! priv->has_wep)
@@ -3009,47 +2898,51 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev,
memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);
orinoco_unlock(priv, &flags);
+
+ if (erq->pointer) {
+ if (copy_to_user(erq->pointer, keybuf, xlen))
+ return -EFAULT;
+ }
+
return 0;
}
-static int orinoco_ioctl_setessid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq,
- char *essidbuf)
+static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq)
{
struct orinoco_private *priv = netdev_priv(dev);
+ char essidbuf[IW_ESSID_MAX_SIZE+1];
unsigned long flags;
/* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
* anyway... - Jean II */
- /* Hum... Should not use Wireless Extension constant (may change),
- * should use our own... - Jean II */
- if (erq->length > IW_ESSID_MAX_SIZE)
- return -E2BIG;
+ memset(&essidbuf, 0, sizeof(essidbuf));
+
+ if (erq->flags) {
+ /* iwconfig includes the NUL in the specified length */
+ if (erq->length > IW_ESSID_MAX_SIZE+1)
+ return -E2BIG;
+
+ if (copy_from_user(&essidbuf, erq->pointer, erq->length))
+ return -EFAULT;
+
+ essidbuf[IW_ESSID_MAX_SIZE] = '\0';
+ }
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
- /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */
- memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
-
- /* If not ANY, get the new ESSID */
- if (erq->flags) {
- memcpy(priv->desired_essid, essidbuf, erq->length);
- }
+ memcpy(priv->desired_essid, essidbuf, sizeof(priv->desired_essid));
orinoco_unlock(priv, &flags);
- return -EINPROGRESS; /* Call commit handler */
+ return 0;
}
-static int orinoco_ioctl_getessid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq,
- char *essidbuf)
+static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq)
{
struct orinoco_private *priv = netdev_priv(dev);
+ char essidbuf[IW_ESSID_MAX_SIZE+1];
int active;
int err = 0;
unsigned long flags;
@@ -3063,46 +2956,51 @@ static int orinoco_ioctl_getessid(struct net_device *dev,
} else {
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
- memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE + 1);
+ memcpy(essidbuf, priv->desired_essid, sizeof(essidbuf));
orinoco_unlock(priv, &flags);
}
erq->flags = 1;
erq->length = strlen(essidbuf) + 1;
+ if (erq->pointer)
+ if (copy_to_user(erq->pointer, essidbuf, erq->length))
+ return -EFAULT;
TRACE_EXIT(dev->name);
return 0;
}
-static int orinoco_ioctl_setnick(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *nrq,
- char *nickbuf)
+static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq)
{
struct orinoco_private *priv = netdev_priv(dev);
+ char nickbuf[IW_ESSID_MAX_SIZE+1];
unsigned long flags;
if (nrq->length > IW_ESSID_MAX_SIZE)
return -E2BIG;
+ memset(nickbuf, 0, sizeof(nickbuf));
+
+ if (copy_from_user(nickbuf, nrq->pointer, nrq->length))
+ return -EFAULT;
+
+ nickbuf[nrq->length] = '\0';
+
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
- memset(priv->nick, 0, sizeof(priv->nick));
- memcpy(priv->nick, nickbuf, nrq->length);
+ memcpy(priv->nick, nickbuf, sizeof(priv->nick));
orinoco_unlock(priv, &flags);
- return -EINPROGRESS; /* Call commit handler */
+ return 0;
}
-static int orinoco_ioctl_getnick(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *nrq,
- char *nickbuf)
+static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq)
{
struct orinoco_private *priv = netdev_priv(dev);
+ char nickbuf[IW_ESSID_MAX_SIZE+1];
unsigned long flags;
if (orinoco_lock(priv, &flags) != 0)
@@ -3113,22 +3011,23 @@ static int orinoco_ioctl_getnick(struct net_device *dev,
nrq->length = strlen(nickbuf)+1;
+ if (copy_to_user(nrq->pointer, nickbuf, sizeof(nickbuf)))
+ return -EFAULT;
+
return 0;
}
-static int orinoco_ioctl_setfreq(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_freq *frq,
- char *extra)
+static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq)
{
struct orinoco_private *priv = netdev_priv(dev);
int chan = -1;
unsigned long flags;
- int err = -EINPROGRESS; /* Call commit handler */
- /* In infrastructure mode the AP sets the channel */
- if (priv->iw_mode == IW_MODE_INFRA)
- return -EBUSY;
+ /* We can only use this in Ad-Hoc demo mode to set the operating
+ * frequency, or in IBSS mode to set the frequency where the IBSS
+ * will be created - Jean II */
+ if (priv->iw_mode != IW_MODE_ADHOC)
+ return -EOPNOTSUPP;
if ( (frq->e == 0) && (frq->m <= 1000) ) {
/* Setting by channel number */
@@ -3152,44 +3051,13 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
-
priv->channel = chan;
- if (priv->iw_mode == IW_MODE_MONITOR) {
- /* Fast channel change - no commit if successful */
- hermes_t *hw = &priv->hw;
- err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
- HERMES_TEST_SET_CHANNEL,
- chan, NULL);
- }
orinoco_unlock(priv, &flags);
- return err;
-}
-
-static int orinoco_ioctl_getfreq(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_freq *frq,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- int tmp;
-
- /* Locking done in there */
- tmp = orinoco_hw_get_freq(priv);
- if (tmp < 0) {
- return tmp;
- }
-
- frq->m = tmp;
- frq->e = 1;
-
return 0;
}
-static int orinoco_ioctl_getsens(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *srq,
- char *extra)
+static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq)
{
struct orinoco_private *priv = netdev_priv(dev);
hermes_t *hw = &priv->hw;
@@ -3215,10 +3083,7 @@ static int orinoco_ioctl_getsens(struct net_device *dev,
return 0;
}
-static int orinoco_ioctl_setsens(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *srq,
- char *extra)
+static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq)
{
struct orinoco_private *priv = netdev_priv(dev);
int val = srq->value;
@@ -3235,13 +3100,10 @@ static int orinoco_ioctl_setsens(struct net_device *dev,
priv->ap_density = val;
orinoco_unlock(priv, &flags);
- return -EINPROGRESS; /* Call commit handler */
+ return 0;
}
-static int orinoco_ioctl_setrts(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *rrq,
- char *extra)
+static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq)
{
struct orinoco_private *priv = netdev_priv(dev);
int val = rrq->value;
@@ -3259,30 +3121,13 @@ static int orinoco_ioctl_setrts(struct net_device *dev,
priv->rts_thresh = val;
orinoco_unlock(priv, &flags);
- return -EINPROGRESS; /* Call commit handler */
-}
-
-static int orinoco_ioctl_getrts(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *rrq,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
-
- rrq->value = priv->rts_thresh;
- rrq->disabled = (rrq->value == 2347);
- rrq->fixed = 1;
-
return 0;
}
-static int orinoco_ioctl_setfrag(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *frq,
- char *extra)
+static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq)
{
struct orinoco_private *priv = netdev_priv(dev);
- int err = -EINPROGRESS; /* Call commit handler */
+ int err = 0;
unsigned long flags;
if (orinoco_lock(priv, &flags) != 0)
@@ -3314,14 +3159,11 @@ static int orinoco_ioctl_setfrag(struct net_device *dev,
return err;
}
-static int orinoco_ioctl_getfrag(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *frq,
- char *extra)
+static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq)
{
struct orinoco_private *priv = netdev_priv(dev);
hermes_t *hw = &priv->hw;
- int err;
+ int err = 0;
u16 val;
unsigned long flags;
@@ -3354,12 +3196,10 @@ static int orinoco_ioctl_getfrag(struct net_device *dev,
return err;
}
-static int orinoco_ioctl_setrate(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *rrq,
- char *extra)
+static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq)
{
struct orinoco_private *priv = netdev_priv(dev);
+ int err = 0;
int ratemode = -1;
int bitrate; /* 100s of kilobits */
int i;
@@ -3395,13 +3235,10 @@ static int orinoco_ioctl_setrate(struct net_device *dev,
priv->bitratemode = ratemode;
orinoco_unlock(priv, &flags);
- return -EINPROGRESS;
+ return err;
}
-static int orinoco_ioctl_getrate(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *rrq,
- char *extra)
+static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq)
{
struct orinoco_private *priv = netdev_priv(dev);
hermes_t *hw = &priv->hw;
@@ -3466,13 +3303,10 @@ static int orinoco_ioctl_getrate(struct net_device *dev,
return err;
}
-static int orinoco_ioctl_setpower(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *prq,
- char *extra)
+static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq)
{
struct orinoco_private *priv = netdev_priv(dev);
- int err = -EINPROGRESS; /* Call commit handler */
+ int err = 0;
unsigned long flags;
if (orinoco_lock(priv, &flags) != 0)
@@ -3521,10 +3355,7 @@ static int orinoco_ioctl_setpower(struct net_device *dev,
return err;
}
-static int orinoco_ioctl_getpower(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *prq,
- char *extra)
+static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq)
{
struct orinoco_private *priv = netdev_priv(dev);
hermes_t *hw = &priv->hw;
@@ -3572,10 +3403,7 @@ static int orinoco_ioctl_getpower(struct net_device *dev,
return err;
}
-static int orinoco_ioctl_getretry(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *rrq,
- char *extra)
+static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq)
{
struct orinoco_private *priv = netdev_priv(dev);
hermes_t *hw = &priv->hw;
@@ -3626,38 +3454,10 @@ static int orinoco_ioctl_getretry(struct net_device *dev,
return err;
}
-static int orinoco_ioctl_reset(struct net_device *dev,
- struct iw_request_info *info,
- void *wrqu,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
-
- if (! capable(CAP_NET_ADMIN))
- return -EPERM;
-
- if (info->cmd == (SIOCIWFIRSTPRIV + 0x1)) {
- printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name);
-
- /* Firmware reset */
- orinoco_reset(dev);
- } else {
- printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);
-
- schedule_work(&priv->reset_work);
- }
-
- return 0;
-}
-
-static int orinoco_ioctl_setibssport(struct net_device *dev,
- struct iw_request_info *info,
- void *wrqu,
- char *extra)
-
+static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq)
{
struct orinoco_private *priv = netdev_priv(dev);
- int val = *( (int *) extra );
+ int val = *( (int *) wrq->u.name );
unsigned long flags;
if (orinoco_lock(priv, &flags) != 0)
@@ -3669,28 +3469,28 @@ static int orinoco_ioctl_setibssport(struct net_device *dev,
set_port_type(priv);
orinoco_unlock(priv, &flags);
- return -EINPROGRESS; /* Call commit handler */
+ return 0;
}
-static int orinoco_ioctl_getibssport(struct net_device *dev,
- struct iw_request_info *info,
- void *wrqu,
- char *extra)
+static int orinoco_ioctl_getibssport(struct net_device *dev, struct iwreq *wrq)
{
struct orinoco_private *priv = netdev_priv(dev);
- int *val = (int *) extra;
+ int *val = (int *)wrq->u.name;
+ unsigned long flags;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
*val = priv->ibss_port;
+ orinoco_unlock(priv, &flags);
+
return 0;
}
-static int orinoco_ioctl_setport3(struct net_device *dev,
- struct iw_request_info *info,
- void *wrqu,
- char *extra)
+static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq)
{
struct orinoco_private *priv = netdev_priv(dev);
- int val = *( (int *) extra );
+ int val = *( (int *) wrq->u.name );
int err = 0;
unsigned long flags;
@@ -3719,131 +3519,51 @@ static int orinoco_ioctl_setport3(struct net_device *dev,
err = -EINVAL;
}
- if (! err) {
+ if (! err)
/* Actually update the mode we are using */
set_port_type(priv);
- err = -EINPROGRESS;
- }
orinoco_unlock(priv, &flags);
return err;
}
-static int orinoco_ioctl_getport3(struct net_device *dev,
- struct iw_request_info *info,
- void *wrqu,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- int *val = (int *) extra;
-
- *val = priv->prefer_port3;
- return 0;
-}
-
-static int orinoco_ioctl_setpreamble(struct net_device *dev,
- struct iw_request_info *info,
- void *wrqu,
- char *extra)
+static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq)
{
struct orinoco_private *priv = netdev_priv(dev);
+ int *val = (int *)wrq->u.name;
unsigned long flags;
- int val;
-
- if (! priv->has_preamble)
- return -EOPNOTSUPP;
-
- /* 802.11b has recently defined some short preamble.
- * Basically, the Phy header has been reduced in size.
- * This increase performance, especially at high rates
- * (the preamble is transmitted at 1Mb/s), unfortunately
- * this give compatibility troubles... - Jean II */
- val = *( (int *) extra );
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
- if (val)
- priv->preamble = 1;
- else
- priv->preamble = 0;
-
+ *val = priv->prefer_port3;
orinoco_unlock(priv, &flags);
-
- return -EINPROGRESS; /* Call commit handler */
-}
-
-static int orinoco_ioctl_getpreamble(struct net_device *dev,
- struct iw_request_info *info,
- void *wrqu,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- int *val = (int *) extra;
-
- if (! priv->has_preamble)
- return -EOPNOTSUPP;
-
- *val = priv->preamble;
return 0;
}
-/* ioctl interface to hermes_read_ltv()
- * To use with iwpriv, pass the RID as the token argument, e.g.
- * iwpriv get_rid [0xfc00]
- * At least Wireless Tools 25 is required to use iwpriv.
- * For Wireless Tools 25 and 26 append "dummy" are the end. */
-static int orinoco_ioctl_getrid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- hermes_t *hw = &priv->hw;
- int rid = data->flags;
- u16 length;
- int err;
- unsigned long flags;
-
- /* It's a "get" function, but we don't want users to access the
- * WEP key and other raw firmware data */
- if (! capable(CAP_NET_ADMIN))
- return -EPERM;
-
- if (rid < 0xfc00 || rid > 0xffff)
- return -EINVAL;
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length,
- extra);
- if (err)
- goto out;
-
- data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length),
- MAX_RID_LEN);
-
- out:
- orinoco_unlock(priv, &flags);
- return err;
-}
-
/* Spy is used for link quality/strength measurements in Ad-Hoc mode
* Jean II */
-static int orinoco_ioctl_setspy(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *srq,
- char *extra)
-
+static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq)
{
struct orinoco_private *priv = netdev_priv(dev);
- struct sockaddr *address = (struct sockaddr *) extra;
+ struct sockaddr address[IW_MAX_SPY];
int number = srq->length;
int i;
+ int err = 0;
unsigned long flags;
+ /* Check the number of addresses */
+ if (number > IW_MAX_SPY)
+ return -E2BIG;
+
+ /* Get the data in the driver */
+ if (srq->pointer) {
+ if (copy_from_user(address, srq->pointer,
+ sizeof(struct sockaddr) * number))
+ return -EFAULT;
+ }
+
/* Make sure nobody mess with the structure while we do */
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
@@ -3867,17 +3587,14 @@ static int orinoco_ioctl_setspy(struct net_device *dev,
/* Now, let the others play */
orinoco_unlock(priv, &flags);
- /* Do NOT call commit handler */
- return 0;
+ return err;
}
-static int orinoco_ioctl_getspy(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *srq,
- char *extra)
+static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq)
{
struct orinoco_private *priv = netdev_priv(dev);
- struct sockaddr *address = (struct sockaddr *) extra;
+ struct sockaddr address[IW_MAX_SPY];
+ struct iw_quality spy_stat[IW_MAX_SPY];
int number;
int i;
unsigned long flags;
@@ -3886,12 +3603,7 @@ static int orinoco_ioctl_getspy(struct net_device *dev,
return -EBUSY;
number = priv->spy_number;
- /* Create address struct */
- for (i = 0; i < number; i++) {
- memcpy(address[i].sa_data, priv->spy_address[i], ETH_ALEN);
- address[i].sa_family = AF_UNIX;
- }
- if (number > 0) {
+ if ((number > 0) && (srq->pointer)) {
/* Create address struct */
for (i = 0; i < number; i++) {
memcpy(address[i].sa_data, priv->spy_address[i],
@@ -3902,503 +3614,344 @@ static int orinoco_ioctl_getspy(struct net_device *dev,
/* In theory, we should disable irqs while copying the stats
* because the rx path might update it in the middle...
* Bah, who care ? - Jean II */
- memcpy(extra + (sizeof(struct sockaddr) * number),
- priv->spy_stat, sizeof(struct iw_quality) * number);
+ memcpy(&spy_stat, priv->spy_stat,
+ sizeof(struct iw_quality) * IW_MAX_SPY);
+ for (i=0; i < number; i++)
+ priv->spy_stat[i].updated = 0;
}
- /* Reset updated flags. */
- for (i = 0; i < number; i++)
- priv->spy_stat[i].updated = 0;
orinoco_unlock(priv, &flags);
+ /* Push stuff to user space */
srq->length = number;
+ if(copy_to_user(srq->pointer, address,
+ sizeof(struct sockaddr) * number))
+ return -EFAULT;
+ if(copy_to_user(srq->pointer + (sizeof(struct sockaddr)*number),
+ &spy_stat, sizeof(struct iw_quality) * number))
+ return -EFAULT;
return 0;
}
-/* Trigger a scan (look for other cells in the vicinity */
-static int orinoco_ioctl_setscan(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *srq,
- char *extra)
+static int
+orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct orinoco_private *priv = netdev_priv(dev);
- hermes_t *hw = &priv->hw;
+ struct iwreq *wrq = (struct iwreq *)rq;
int err = 0;
+ int tmp;
+ int changed = 0;
unsigned long flags;
- /* Note : you may have realised that, as this is a SET operation,
- * this is priviledged and therefore a normal user can't
- * perform scanning.
- * This is not an error, while the device perform scanning,
- * traffic doesn't flow, so it's a perfect DoS...
- * Jean II */
-
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
- /* Scanning with port 0 disabled would fail */
- if (!netif_running(dev)) {
- err = -ENETDOWN;
- goto out;
- }
+ TRACE_ENTER(dev->name);
- /* In monitor mode, the scan results are always empty.
- * Probe responses are passed to the driver as received
- * frames and could be processed in software. */
- if (priv->iw_mode == IW_MODE_MONITOR) {
- err = -EOPNOTSUPP;
- goto out;
- }
+ /* In theory, we could allow most of the the SET stuff to be
+ * done. In practice, the lapse of time at startup when the
+ * card is not ready is very short, so why bother... Note
+ * that netif_device_present is different from up/down
+ * (ifconfig), when the device is not yet up, it is usually
+ * already ready... Jean II */
+ if (! netif_device_present(dev))
+ return -ENODEV;
- /* Note : because we don't lock out the irq handler, the way
- * we access scan variables in priv is critical.
- * o scan_inprogress : not touched by irq handler
- * o scan_mode : not touched by irq handler
- * o scan_result : irq is strict producer, non-irq is strict
- * consumer.
- * o scan_len : synchronised with scan_result
- * Before modifying anything on those variables, please think hard !
- * Jean II */
+ switch (cmd) {
+ case SIOCGIWNAME:
+ strcpy(wrq->u.name, "IEEE 802.11-DS");
+ break;
+
+ case SIOCGIWAP:
+ wrq->u.ap_addr.sa_family = ARPHRD_ETHER;
+ err = orinoco_hw_get_bssid(priv, wrq->u.ap_addr.sa_data);
+ break;
- /* If there is still some left-over scan results, get rid of it */
- if (priv->scan_result != NULL) {
- /* What's likely is that a client did crash or was killed
- * between triggering the scan request and reading the
- * results, so we need to reset everything.
- * Some clients that are too slow may suffer from that...
- * Jean II */
- kfree(priv->scan_result);
- priv->scan_result = NULL;
- }
+ case SIOCGIWRANGE:
+ err = orinoco_ioctl_getiwrange(dev, &wrq->u.data);
+ break;
- /* Save flags */
- priv->scan_mode = srq->flags;
+ case SIOCSIWMODE:
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+ switch (wrq->u.mode) {
+ case IW_MODE_ADHOC:
+ if (! (priv->has_ibss || priv->has_port3) )
+ err = -EINVAL;
+ else {
+ priv->iw_mode = IW_MODE_ADHOC;
+ changed = 1;
+ }
+ break;
- /* Always trigger scanning, even if it's in progress.
- * This way, if the info frame get lost, we will recover somewhat
- * gracefully - Jean II */
+ case IW_MODE_INFRA:
+ priv->iw_mode = IW_MODE_INFRA;
+ changed = 1;
+ break;
- if (priv->has_hostscan) {
- switch (priv->firmware_type) {
- case FIRMWARE_TYPE_SYMBOL:
- err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFHOSTSCAN_SYMBOL,
- HERMES_HOSTSCAN_SYMBOL_ONCE |
- HERMES_HOSTSCAN_SYMBOL_BCAST);
+ default:
+ err = -EINVAL;
break;
- case FIRMWARE_TYPE_INTERSIL: {
- u16 req[3];
-
- req[0] = cpu_to_le16(0x3fff); /* All channels */
- req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */
- req[2] = 0; /* Any ESSID */
- err = HERMES_WRITE_RECORD(hw, USER_BAP,
- HERMES_RID_CNFHOSTSCAN, &req);
}
+ set_port_type(priv);
+ orinoco_unlock(priv, &flags);
+ break;
+
+ case SIOCGIWMODE:
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+ wrq->u.mode = priv->iw_mode;
+ orinoco_unlock(priv, &flags);
+ break;
+
+ case SIOCSIWENCODE:
+ err = orinoco_ioctl_setiwencode(dev, &wrq->u.encoding);
+ if (! err)
+ changed = 1;
break;
- case FIRMWARE_TYPE_AGERE:
- err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFSCANSSID_AGERE,
- 0); /* Any ESSID */
- if (err)
- break;
- err = hermes_inquire(hw, HERMES_INQ_SCAN);
+ case SIOCGIWENCODE:
+ if (! capable(CAP_NET_ADMIN)) {
+ err = -EPERM;
break;
}
- } else
- err = hermes_inquire(hw, HERMES_INQ_SCAN);
- /* One more client */
- if (! err)
- priv->scan_inprogress = 1;
+ err = orinoco_ioctl_getiwencode(dev, &wrq->u.encoding);
+ break;
- out:
- orinoco_unlock(priv, &flags);
- return err;
-}
+ case SIOCSIWESSID:
+ err = orinoco_ioctl_setessid(dev, &wrq->u.essid);
+ if (! err)
+ changed = 1;
+ break;
-/* Translate scan data returned from the card to a card independant
- * format that the Wireless Tools will understand - Jean II */
-static inline int orinoco_translate_scan(struct net_device *dev,
- char *buffer,
- char *scan,
- int scan_len)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- int offset; /* In the scan data */
- union hermes_scan_info *atom;
- int atom_len;
- u16 capabilities;
- u16 channel;
- struct iw_event iwe; /* Temporary buffer */
- char * current_ev = buffer;
- char * end_buf = buffer + IW_SCAN_MAX_DATA;
+ case SIOCGIWESSID:
+ err = orinoco_ioctl_getessid(dev, &wrq->u.essid);
+ break;
- switch (priv->firmware_type) {
- case FIRMWARE_TYPE_AGERE:
- atom_len = sizeof(struct agere_scan_apinfo);
- offset = 0;
+ case SIOCSIWNICKN:
+ err = orinoco_ioctl_setnick(dev, &wrq->u.data);
+ if (! err)
+ changed = 1;
break;
- case FIRMWARE_TYPE_SYMBOL:
- /* Lack of documentation necessitates this hack.
- * Different firmwares have 68 or 76 byte long atoms.
- * We try modulo first. If the length divides by both,
- * we check what would be the channel in the second
- * frame for a 68-byte atom. 76-byte atoms have 0 there.
- * Valid channel cannot be 0. */
- if (scan_len % 76)
- atom_len = 68;
- else if (scan_len % 68)
- atom_len = 76;
- else if (scan_len >= 1292 && scan[68] == 0)
- atom_len = 76;
- else
- atom_len = 68;
- offset = 0;
+
+ case SIOCGIWNICKN:
+ err = orinoco_ioctl_getnick(dev, &wrq->u.data);
break;
- case FIRMWARE_TYPE_INTERSIL:
- offset = 4;
- if (priv->has_hostscan)
- atom_len = scan[0] + (scan[1] << 8);
- else
- atom_len = offsetof(struct prism2_scan_apinfo, atim);
+
+ case SIOCGIWFREQ:
+ tmp = orinoco_hw_get_freq(priv);
+ if (tmp < 0) {
+ err = tmp;
+ } else {
+ wrq->u.freq.m = tmp;
+ wrq->u.freq.e = 1;
+ }
break;
- default:
- return 0;
- }
- /* Check that we got an whole number of atoms */
- if ((scan_len - offset) % atom_len) {
- printk(KERN_ERR "%s: Unexpected scan data length %d, "
- "atom_len %d, offset %d\n", dev->name, scan_len,
- atom_len, offset);
- return 0;
- }
+ case SIOCSIWFREQ:
+ err = orinoco_ioctl_setfreq(dev, &wrq->u.freq);
+ if (! err)
+ changed = 1;
+ break;
- /* Read the entries one by one */
- for (; offset + atom_len <= scan_len; offset += atom_len) {
- /* Get next atom */
- atom = (union hermes_scan_info *) (scan + offset);
-
- /* First entry *MUST* be the AP MAC address */
- iwe.cmd = SIOCGIWAP;
- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
- memcpy(iwe.u.ap_addr.sa_data, atom->a.bssid, ETH_ALEN);
- current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
-
- /* Other entries will be displayed in the order we give them */
-
- /* Add the ESSID */
- iwe.u.data.length = le16_to_cpu(atom->a.essid_len);
- if (iwe.u.data.length > 32)
- iwe.u.data.length = 32;
- iwe.cmd = SIOCGIWESSID;
- iwe.u.data.flags = 1;
- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid);
-
- /* Add mode */
- iwe.cmd = SIOCGIWMODE;
- capabilities = le16_to_cpu(atom->a.capabilities);
- if (capabilities & 0x3) {
- if (capabilities & 0x1)
- iwe.u.mode = IW_MODE_MASTER;
- else
- iwe.u.mode = IW_MODE_ADHOC;
- current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
- }
+ case SIOCGIWSENS:
+ err = orinoco_ioctl_getsens(dev, &wrq->u.sens);
+ break;
- channel = atom->s.channel;
- if ( (channel >= 1) && (channel <= NUM_CHANNELS) ) {
- /* Add frequency */
- iwe.cmd = SIOCGIWFREQ;
- iwe.u.freq.m = channel_frequency[channel-1] * 100000;
- iwe.u.freq.e = 1;
- current_ev = iwe_stream_add_event(current_ev, end_buf,
- &iwe, IW_EV_FREQ_LEN);
- }
+ case SIOCSIWSENS:
+ err = orinoco_ioctl_setsens(dev, &wrq->u.sens);
+ if (! err)
+ changed = 1;
+ break;
- /* Add quality statistics */
- iwe.cmd = IWEVQUAL;
- iwe.u.qual.updated = 0x10; /* no link quality */
- iwe.u.qual.level = (__u8) le16_to_cpu(atom->a.level) - 0x95;
- iwe.u.qual.noise = (__u8) le16_to_cpu(atom->a.noise) - 0x95;
- /* Wireless tools prior to 27.pre22 will show link quality
- * anyway, so we provide a reasonable value. */
- if (iwe.u.qual.level > iwe.u.qual.noise)
- iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
- else
- iwe.u.qual.qual = 0;
- current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
+ case SIOCGIWRTS:
+ wrq->u.rts.value = priv->rts_thresh;
+ wrq->u.rts.disabled = (wrq->u.rts.value == 2347);
+ wrq->u.rts.fixed = 1;
+ break;
- /* Add encryption capability */
- iwe.cmd = SIOCGIWENCODE;
- if (capabilities & 0x10)
- iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
- else
- iwe.u.data.flags = IW_ENCODE_DISABLED;
- iwe.u.data.length = 0;
- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid);
-
- /* Bit rate is not available in Lucent/Agere firmwares */
- if (priv->firmware_type != FIRMWARE_TYPE_AGERE) {
- char * current_val = current_ev + IW_EV_LCP_LEN;
- int i;
- int step;
-
- if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
- step = 2;
- else
- step = 1;
-
- iwe.cmd = SIOCGIWRATE;
- /* Those two flags are ignored... */
- iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
- /* Max 10 values */
- for (i = 0; i < 10; i += step) {
- /* NULL terminated */
- if (atom->p.rates[i] == 0x0)
- break;
- /* Bit rate given in 500 kb/s units (+ 0x80) */
- iwe.u.bitrate.value = ((atom->p.rates[i] & 0x7f) * 500000);
- current_val = iwe_stream_add_value(current_ev, current_val,
- end_buf, &iwe,
- IW_EV_PARAM_LEN);
- }
- /* Check if we added any event */
- if ((current_val - current_ev) > IW_EV_LCP_LEN)
- current_ev = current_val;
- }
+ case SIOCSIWRTS:
+ err = orinoco_ioctl_setrts(dev, &wrq->u.rts);
+ if (! err)
+ changed = 1;
+ break;
- /* The other data in the scan result are not really
- * interesting, so for now drop it - Jean II */
- }
- return current_ev - buffer;
-}
+ case SIOCSIWFRAG:
+ err = orinoco_ioctl_setfrag(dev, &wrq->u.frag);
+ if (! err)
+ changed = 1;
+ break;
-/* Return results of a scan */
-static int orinoco_ioctl_getscan(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *srq,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- int err = 0;
- unsigned long flags;
+ case SIOCGIWFRAG:
+ err = orinoco_ioctl_getfrag(dev, &wrq->u.frag);
+ break;
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
+ case SIOCSIWRATE:
+ err = orinoco_ioctl_setrate(dev, &wrq->u.bitrate);
+ if (! err)
+ changed = 1;
+ break;
- /* If no results yet, ask to try again later */
- if (priv->scan_result == NULL) {
- if (priv->scan_inprogress)
- /* Important note : we don't want to block the caller
- * until results are ready for various reasons.
- * First, managing wait queues is complex and racy.
- * Second, we grab some rtnetlink lock before comming
- * here (in dev_ioctl()).
- * Third, we generate an Wireless Event, so the
- * caller can wait itself on that - Jean II */
- err = -EAGAIN;
- else
- /* Client error, no scan results...
- * The caller need to restart the scan. */
- err = -ENODATA;
- } else {
- /* We have some results to push back to user space */
-
- /* Translate to WE format */
- srq->length = orinoco_translate_scan(dev, extra,
- priv->scan_result,
- priv->scan_len);
-
- /* Return flags */
- srq->flags = (__u16) priv->scan_mode;
-
- /* Results are here, so scan no longer in progress */
- priv->scan_inprogress = 0;
-
- /* In any case, Scan results will be cleaned up in the
- * reset function and when exiting the driver.
- * The person triggering the scanning may never come to
- * pick the results, so we need to do it in those places.
- * Jean II */
-
-#ifdef SCAN_SINGLE_READ
- /* If you enable this option, only one client (the first
- * one) will be able to read the result (and only one
- * time). If there is multiple concurent clients that
- * want to read scan results, this behavior is not
- * advisable - Jean II */
- kfree(priv->scan_result);
- priv->scan_result = NULL;
-#endif /* SCAN_SINGLE_READ */
- /* Here, if too much time has elapsed since last scan,
- * we may want to clean up scan results... - Jean II */
- }
-
- orinoco_unlock(priv, &flags);
- return err;
-}
+ case SIOCGIWRATE:
+ err = orinoco_ioctl_getrate(dev, &wrq->u.bitrate);
+ break;
-/* Commit handler, called after set operations */
-static int orinoco_ioctl_commit(struct net_device *dev,
- struct iw_request_info *info,
- void *wrqu,
- char *extra)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- struct hermes *hw = &priv->hw;
- unsigned long flags;
- int err = 0;
+ case SIOCSIWPOWER:
+ err = orinoco_ioctl_setpower(dev, &wrq->u.power);
+ if (! err)
+ changed = 1;
+ break;
- if (!priv->open)
- return 0;
+ case SIOCGIWPOWER:
+ err = orinoco_ioctl_getpower(dev, &wrq->u.power);
+ break;
- if (priv->broken_disableport) {
- orinoco_reset(dev);
- return 0;
- }
+ case SIOCGIWTXPOW:
+ /* The card only supports one tx power, so this is easy */
+ wrq->u.txpower.value = 15; /* dBm */
+ wrq->u.txpower.fixed = 1;
+ wrq->u.txpower.disabled = 0;
+ wrq->u.txpower.flags = IW_TXPOW_DBM;
+ break;
- if (orinoco_lock(priv, &flags) != 0)
- return err;
+ case SIOCSIWRETRY:
+ err = -EOPNOTSUPP;
+ break;
- err = hermes_disable_port(hw, 0);
- if (err) {
- printk(KERN_WARNING "%s: Unable to disable port "
- "while reconfiguring card\n", dev->name);
- priv->broken_disableport = 1;
- goto out;
- }
+ case SIOCGIWRETRY:
+ err = orinoco_ioctl_getretry(dev, &wrq->u.retry);
+ break;
- err = __orinoco_program_rids(dev);
- if (err) {
- printk(KERN_WARNING "%s: Unable to reconfigure card\n",
- dev->name);
- goto out;
- }
+ case SIOCSIWSPY:
+ err = orinoco_ioctl_setspy(dev, &wrq->u.data);
+ break;
- err = hermes_enable_port(hw, 0);
- if (err) {
- printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
- dev->name);
- goto out;
- }
+ case SIOCGIWSPY:
+ err = orinoco_ioctl_getspy(dev, &wrq->u.data);
+ break;
+
+ case SIOCGIWPRIV:
+ if (wrq->u.data.pointer) {
+ struct iw_priv_args privtab[] = {
+ { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" },
+ { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" },
+ { SIOCIWFIRSTPRIV + 0x2,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0, "set_port3" },
+ { SIOCIWFIRSTPRIV + 0x3, 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "get_port3" },
+ { SIOCIWFIRSTPRIV + 0x4,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0, "set_preamble" },
+ { SIOCIWFIRSTPRIV + 0x5, 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "get_preamble" },
+ { SIOCIWFIRSTPRIV + 0x6,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0, "set_ibssport" },
+ { SIOCIWFIRSTPRIV + 0x7, 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "get_ibssport" },
+ };
+
+ wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]);
+ if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab)))
+ err = -EFAULT;
+ }
+ break;
+
+ case SIOCIWFIRSTPRIV + 0x0: /* force_reset */
+ case SIOCIWFIRSTPRIV + 0x1: /* card_reset */
+ if (! capable(CAP_NET_ADMIN)) {
+ err = -EPERM;
+ break;
+ }
+
+ printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);
- out:
- if (err) {
- printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
schedule_work(&priv->reset_work);
- err = 0;
- }
+ break;
- orinoco_unlock(priv, &flags);
- return err;
-}
+ case SIOCIWFIRSTPRIV + 0x2: /* set_port3 */
+ if (! capable(CAP_NET_ADMIN)) {
+ err = -EPERM;
+ break;
+ }
-static const struct iw_priv_args orinoco_privtab[] = {
- { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" },
- { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" },
- { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
- 0, "set_port3" },
- { SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
- "get_port3" },
- { SIOCIWFIRSTPRIV + 0x4, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
- 0, "set_preamble" },
- { SIOCIWFIRSTPRIV + 0x5, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
- "get_preamble" },
- { SIOCIWFIRSTPRIV + 0x6, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
- 0, "set_ibssport" },
- { SIOCIWFIRSTPRIV + 0x7, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
- "get_ibssport" },
- { SIOCIWFIRSTPRIV + 0x9, 0, IW_PRIV_TYPE_BYTE | MAX_RID_LEN,
- "get_rid" },
-};
+ err = orinoco_ioctl_setport3(dev, wrq);
+ if (! err)
+ changed = 1;
+ break;
+ case SIOCIWFIRSTPRIV + 0x3: /* get_port3 */
+ err = orinoco_ioctl_getport3(dev, wrq);
+ break;
-/*
- * Structures to export the Wireless Handlers
- */
+ case SIOCIWFIRSTPRIV + 0x4: /* set_preamble */
+ if (! capable(CAP_NET_ADMIN)) {
+ err = -EPERM;
+ break;
+ }
-static const iw_handler orinoco_handler[] = {
- [SIOCSIWCOMMIT-SIOCIWFIRST] (iw_handler) orinoco_ioctl_commit,
- [SIOCGIWNAME -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getname,
- [SIOCSIWFREQ -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfreq,
- [SIOCGIWFREQ -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfreq,
- [SIOCSIWMODE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setmode,
- [SIOCGIWMODE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getmode,
- [SIOCSIWSENS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setsens,
- [SIOCGIWSENS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getsens,
- [SIOCGIWRANGE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwrange,
- [SIOCSIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setspy,
- [SIOCGIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getspy,
- [SIOCSIWAP -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setwap,
- [SIOCGIWAP -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getwap,
- [SIOCSIWSCAN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setscan,
- [SIOCGIWSCAN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getscan,
- [SIOCSIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setessid,
- [SIOCGIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getessid,
- [SIOCSIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setnick,
- [SIOCGIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getnick,
- [SIOCSIWRATE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrate,
- [SIOCGIWRATE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrate,
- [SIOCSIWRTS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrts,
- [SIOCGIWRTS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrts,
- [SIOCSIWFRAG -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfrag,
- [SIOCGIWFRAG -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfrag,
- [SIOCGIWRETRY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getretry,
- [SIOCSIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_setiwencode,
- [SIOCGIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwencode,
- [SIOCSIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setpower,
- [SIOCGIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getpower,
-};
+ /* 802.11b has recently defined some short preamble.
+ * Basically, the Phy header has been reduced in size.
+ * This increase performance, especially at high rates
+ * (the preamble is transmitted at 1Mb/s), unfortunately
+ * this give compatibility troubles... - Jean II */
+ if(priv->has_preamble) {
+ int val = *( (int *) wrq->u.name );
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+ if (val)
+ priv->preamble = 1;
+ else
+ priv->preamble = 0;
+ orinoco_unlock(priv, &flags);
+ changed = 1;
+ } else
+ err = -EOPNOTSUPP;
+ break;
+ case SIOCIWFIRSTPRIV + 0x5: /* get_preamble */
+ if(priv->has_preamble) {
+ int *val = (int *)wrq->u.name;
-/*
- Added typecasting since we no longer use iwreq_data -- Moustafa
- */
-static const iw_handler orinoco_private_handler[] = {
- [0] (iw_handler) orinoco_ioctl_reset,
- [1] (iw_handler) orinoco_ioctl_reset,
- [2] (iw_handler) orinoco_ioctl_setport3,
- [3] (iw_handler) orinoco_ioctl_getport3,
- [4] (iw_handler) orinoco_ioctl_setpreamble,
- [5] (iw_handler) orinoco_ioctl_getpreamble,
- [6] (iw_handler) orinoco_ioctl_setibssport,
- [7] (iw_handler) orinoco_ioctl_getibssport,
- [9] (iw_handler) orinoco_ioctl_getrid,
-};
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+ *val = priv->preamble;
+ orinoco_unlock(priv, &flags);
+ } else
+ err = -EOPNOTSUPP;
+ break;
+ case SIOCIWFIRSTPRIV + 0x6: /* set_ibssport */
+ if (! capable(CAP_NET_ADMIN)) {
+ err = -EPERM;
+ break;
+ }
-static const struct iw_handler_def orinoco_handler_def = {
- .num_standard = ARRAY_SIZE(orinoco_handler),
- .num_private = ARRAY_SIZE(orinoco_private_handler),
- .num_private_args = ARRAY_SIZE(orinoco_privtab),
- .standard = orinoco_handler,
- .private = orinoco_private_handler,
- .private_args = orinoco_privtab,
-};
+ err = orinoco_ioctl_setibssport(dev, wrq);
+ if (! err)
+ changed = 1;
+ break;
-static void orinoco_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- struct orinoco_private *priv = netdev_priv(dev);
+ case SIOCIWFIRSTPRIV + 0x7: /* get_ibssport */
+ err = orinoco_ioctl_getibssport(dev, wrq);
+ break;
- strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1);
- strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1);
- strncpy(info->fw_version, priv->fw_name, sizeof(info->fw_version) - 1);
- if (dev->class_dev.dev)
- strncpy(info->bus_info, dev->class_dev.dev->bus_id,
- sizeof(info->bus_info) - 1);
- else
- snprintf(info->bus_info, sizeof(info->bus_info) - 1,
- "PCMCIA %p", priv->hw.iobase);
+ default:
+ err = -EOPNOTSUPP;
+ }
+
+ if (! err && changed && netif_running(dev)) {
+ err = orinoco_reconfigure(dev);
+ }
+
+ TRACE_EXIT(dev->name);
+
+ return err;
}
-static struct ethtool_ops orinoco_ethtool_ops = {
- .get_drvinfo = orinoco_get_drvinfo,
- .get_link = ethtool_op_get_link,
-};
/********************************************************************/
/* Debugging */
diff --git a/trunk/drivers/net/wireless/orinoco.h b/trunk/drivers/net/wireless/orinoco.h
index 2f213a7103fe..f749b50d1088 100644
--- a/trunk/drivers/net/wireless/orinoco.h
+++ b/trunk/drivers/net/wireless/orinoco.h
@@ -7,7 +7,7 @@
#ifndef _ORINOCO_H
#define _ORINOCO_H
-#define DRIVER_VERSION "0.15rc2"
+#define DRIVER_VERSION "0.14alpha2"
#include
#include
@@ -22,8 +22,6 @@
#define WIRELESS_SPY // enable iwspy support
-#define MAX_SCAN_LEN 4096
-
#define ORINOCO_MAX_KEY_SIZE 14
#define ORINOCO_MAX_KEYS 4
@@ -32,20 +30,6 @@ struct orinoco_key {
char data[ORINOCO_MAX_KEY_SIZE];
} __attribute__ ((packed));
-struct header_struct {
- /* 802.3 */
- u8 dest[ETH_ALEN];
- u8 src[ETH_ALEN];
- u16 len;
- /* 802.2 */
- u8 dsap;
- u8 ssap;
- u8 ctrl;
- /* SNAP */
- u8 oui[3];
- u16 ethertype;
-} __attribute__ ((packed));
-
typedef enum {
FIRMWARE_TYPE_AGERE,
FIRMWARE_TYPE_INTERSIL,
@@ -64,8 +48,6 @@ struct orinoco_private {
/* driver state */
int open;
u16 last_linkstatus;
- struct work_struct join_work;
- struct work_struct wevent_work;
/* Net device stuff */
struct net_device *ndev;
@@ -92,9 +74,7 @@ struct orinoco_private {
unsigned int has_pm:1;
unsigned int has_preamble:1;
unsigned int has_sensitivity:1;
- unsigned int has_hostscan:1;
unsigned int broken_disableport:1;
- unsigned int broken_monitor:1;
/* Configuration paramaters */
u32 iw_mode;
@@ -104,8 +84,6 @@ struct orinoco_private {
int bitratemode;
char nick[IW_ESSID_MAX_SIZE+1];
char desired_essid[IW_ESSID_MAX_SIZE+1];
- char desired_bssid[ETH_ALEN];
- int bssid_fixed;
u16 frag_thresh, mwo_robust;
u16 channel;
u16 ap_density, rts_thresh;
@@ -120,12 +98,6 @@ struct orinoco_private {
/* Configuration dependent variables */
int port_type, createibss;
int promiscuous, mc_count;
-
- /* Scanning support */
- int scan_inprogress; /* Scan pending... */
- u32 scan_mode; /* Type of scan done */
- char * scan_result; /* Result of previous scan */
- int scan_len; /* Lenght of result */
};
#ifdef ORINOCO_DEBUG
diff --git a/trunk/drivers/net/wireless/orinoco_cs.c b/trunk/drivers/net/wireless/orinoco_cs.c
index 597c4586d049..74a8227256aa 100644
--- a/trunk/drivers/net/wireless/orinoco_cs.c
+++ b/trunk/drivers/net/wireless/orinoco_cs.c
@@ -608,56 +608,6 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
" (David Gibson , "
"Pavel Roskin , et al)";
-static struct pcmcia_device_id orinoco_cs_ids[] = {
- PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300),
- PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0001),
- PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a),
- PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001),
- PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305),
- PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613),
- PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673),
- PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001),
- PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300),
- PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021),
- PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002),
- PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005),
- PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005),
- PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3),
- PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
- PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5),
- PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169),
- PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3),
- PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
- PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
- PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
- PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac),
- PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab),
- PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
- PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c),
- PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18),
- PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a),
- PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410),
- PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3),
- PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01),
- PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a),
- PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1),
- PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264),
- PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
- PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
- PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
- PCMCIA_DEVICE_PROD_ID1("Symbol Technologies", 0x3f02b4d6),
- PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids);
-
static struct pcmcia_driver orinoco_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -665,7 +615,6 @@ static struct pcmcia_driver orinoco_driver = {
},
.attach = orinoco_cs_attach,
.detach = orinoco_cs_detach,
- .id_table = orinoco_cs_ids,
};
static int __init
diff --git a/trunk/drivers/net/wireless/prism54/isl_38xx.c b/trunk/drivers/net/wireless/prism54/isl_38xx.c
index adc7499136dc..4481ec18c5a0 100644
--- a/trunk/drivers/net/wireless/prism54/isl_38xx.c
+++ b/trunk/drivers/net/wireless/prism54/isl_38xx.c
@@ -112,10 +112,10 @@ isl38xx_handle_wakeup(isl38xx_control_block *control_block,
void
isl38xx_trigger_device(int asleep, void __iomem *device_base)
{
+ struct timeval current_time;
u32 reg, counter = 0;
#if VERBOSE > SHOW_ERROR_MESSAGES
- struct timeval current_time;
DEBUG(SHOW_FUNCTION_CALLS, "isl38xx trigger device\n");
#endif
@@ -126,11 +126,11 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base)
do_gettimeofday(¤t_time);
DEBUG(SHOW_TRACING, "%08li.%08li Device wakeup triggered\n",
current_time.tv_sec, (long)current_time.tv_usec);
+#endif
DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n",
current_time.tv_sec, (long)current_time.tv_usec,
readl(device_base + ISL38XX_CTRL_STAT_REG));
-#endif
udelay(ISL38XX_WRITEIO_DELAY);
reg = readl(device_base + ISL38XX_INT_IDENT_REG);
@@ -148,12 +148,10 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base)
counter++;
}
-#if VERBOSE > SHOW_ERROR_MESSAGES
DEBUG(SHOW_TRACING,
"%08li.%08li Device register read %08x\n",
current_time.tv_sec, (long)current_time.tv_usec,
readl(device_base + ISL38XX_CTRL_STAT_REG));
-#endif
udelay(ISL38XX_WRITEIO_DELAY);
#if VERBOSE > SHOW_ERROR_MESSAGES
diff --git a/trunk/drivers/net/wireless/ray_cs.c b/trunk/drivers/net/wireless/ray_cs.c
index 31652af52eac..6e5bda56b8f8 100644
--- a/trunk/drivers/net/wireless/ray_cs.c
+++ b/trunk/drivers/net/wireless/ray_cs.c
@@ -2904,12 +2904,6 @@ static int write_int(struct file *file, const char __user *buffer, unsigned long
}
#endif
-static struct pcmcia_device_id ray_ids[] = {
- PCMCIA_DEVICE_MANF_CARD(0x01a6, 0x0000),
- PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, ray_ids);
-
static struct pcmcia_driver ray_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -2917,7 +2911,6 @@ static struct pcmcia_driver ray_driver = {
},
.attach = ray_attach,
.detach = ray_detach,
- .id_table = ray_ids,
};
static int __init init_ray_cs(void)
diff --git a/trunk/drivers/net/wireless/wavelan_cs.c b/trunk/drivers/net/wireless/wavelan_cs.c
index 89532fd92941..ec8329788e49 100644
--- a/trunk/drivers/net/wireless/wavelan_cs.c
+++ b/trunk/drivers/net/wireless/wavelan_cs.c
@@ -4889,15 +4889,6 @@ wavelan_event(event_t event, /* The event received */
return 0;
}
-static struct pcmcia_device_id wavelan_ids[] = {
- PCMCIA_DEVICE_PROD_ID12("AT&T","WaveLAN/PCMCIA", 0xe7c5affd, 0x1bc50975),
- PCMCIA_DEVICE_PROD_ID12("Digital", "RoamAbout/DS", 0x9999ab35, 0x00d05e06),
- PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/PCMCIA", 0x23eb9949, 0x1bc50975),
- PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/PCMCIA", 0x24358cd4, 0x1bc50975),
- PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, wavelan_ids);
-
static struct pcmcia_driver wavelan_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -4905,7 +4896,6 @@ static struct pcmcia_driver wavelan_driver = {
},
.attach = wavelan_attach,
.detach = wavelan_detach,
- .id_table = wavelan_ids,
};
static int __init
diff --git a/trunk/drivers/net/wireless/wl3501_cs.c b/trunk/drivers/net/wireless/wl3501_cs.c
index e3a900482d92..1433e5aaf1b4 100644
--- a/trunk/drivers/net/wireless/wl3501_cs.c
+++ b/trunk/drivers/net/wireless/wl3501_cs.c
@@ -2239,12 +2239,6 @@ static int wl3501_event(event_t event, int pri, event_callback_args_t *args)
return 0;
}
-static struct pcmcia_device_id wl3501_ids[] = {
- PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0001),
- PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, wl3501_ids);
-
static struct pcmcia_driver wl3501_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -2252,7 +2246,6 @@ static struct pcmcia_driver wl3501_driver = {
},
.attach = wl3501_attach,
.detach = wl3501_detach,
- .id_table = wl3501_ids,
};
static int __init wl3501_init_module(void)
diff --git a/trunk/drivers/parport/parport_cs.c b/trunk/drivers/parport/parport_cs.c
index ff45662c4f7c..a3fa8185af2a 100644
--- a/trunk/drivers/parport/parport_cs.c
+++ b/trunk/drivers/parport/parport_cs.c
@@ -373,13 +373,6 @@ int parport_event(event_t event, int priority,
return 0;
} /* parport_event */
-static struct pcmcia_device_id parport_ids[] = {
- PCMCIA_DEVICE_FUNC_ID(3),
- PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0003),
- PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, parport_ids);
-
static struct pcmcia_driver parport_cs_driver = {
.owner = THIS_MODULE,
.drv = {
@@ -387,8 +380,6 @@ static struct pcmcia_driver parport_cs_driver = {
},
.attach = parport_attach,
.detach = parport_detach,
- .id_table = parport_ids,
-
};
static int __init init_parport_cs(void)
diff --git a/trunk/drivers/pcmcia/Kconfig b/trunk/drivers/pcmcia/Kconfig
index 52ea34594363..14e4124e1523 100644
--- a/trunk/drivers/pcmcia/Kconfig
+++ b/trunk/drivers/pcmcia/Kconfig
@@ -14,8 +14,8 @@ config PCCARD
Say Y here if you want to attach PCMCIA- or PC-cards to your Linux
computer. These are credit-card size devices such as network cards,
modems or hard drives often used with laptops computers. There are
- actually two varieties of these cards: 16 bit PCMCIA and 32 bit
- CardBus cards.
+ actually two varieties of these cards: the older 16 bit PCMCIA cards
+ and the newer 32 bit CardBus cards.
To compile this driver as modules, choose M here: the
module will be called pcmcia_core.
@@ -42,51 +42,22 @@ config PCMCIA_DEBUG
config PCMCIA
tristate "16-bit PCMCIA support"
- select CRC32
default y
---help---
This option enables support for 16-bit PCMCIA cards. Most older
PC-cards are such 16-bit PCMCIA cards, so unless you know you're
only using 32-bit CardBus cards, say Y or M here.
- To use 16-bit PCMCIA cards, you will need supporting software in
- most cases. (see the file for
- location and details).
+ To use 16-bit PCMCIA cards, you will need supporting software from
+ David Hinds' pcmcia-cs package (see the file
+ for location). Please also read the PCMCIA-HOWTO, available from
+ .
To compile this driver as modules, choose M here: the
module will be called pcmcia.
If unsure, say Y.
-config PCMCIA_LOAD_CIS
- bool "Load CIS updates from userspace (EXPERIMENTAL)"
- depends on PCMCIA && EXPERIMENTAL
- select FW_LOADER
- default y
- help
- Some PCMCIA cards require an updated Card Information Structure (CIS)
- to be loaded from userspace to work correctly. If you say Y here,
- and your userspace is arranged correctly, this will be loaded
- automatically using the in-kernel firmware loader and the hotplug
- subsystem, instead of relying on cardmgr from pcmcia-cs to do so.
-
- If unsure, say Y.
-
-config PCMCIA_IOCTL
- bool
- depends on PCMCIA
- default y
- help
- If you say Y here, the deprecated ioctl interface to the PCMCIA
- subsystem will be built. It is needed by cardmgr and cardctl
- (pcmcia-cs) to function properly.
-
- If you do not use the new pcmciautils package, and have a
- yenta, Cirrus PD6729, i82092, i82365 or tcic compatible bridge,
- you need to say Y here to be able to use 16-bit PCMCIA cards.
-
- If unsure, say Y.
-
config CARDBUS
bool "32-bit CardBus support"
depends on PCI
@@ -106,6 +77,8 @@ comment "PC-card bridges"
config YENTA
tristate "CardBus yenta-compatible bridge support"
+ depends on PCI
+#fixme: remove dependendcy on CARDBUS
depends on CARDBUS
select PCCARD_NONSTATIC
---help---
diff --git a/trunk/drivers/pcmcia/Makefile b/trunk/drivers/pcmcia/Makefile
index ef694c74dfb7..50c29361bc5f 100644
--- a/trunk/drivers/pcmcia/Makefile
+++ b/trunk/drivers/pcmcia/Makefile
@@ -10,8 +10,7 @@ pcmcia_core-y += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o
pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o
obj-$(CONFIG_PCCARD) += pcmcia_core.o
-pcmcia-y += ds.o pcmcia_compat.o pcmcia_resource.o
-pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o
+pcmcia-y += ds.o pcmcia_compat.o
obj-$(CONFIG_PCMCIA) += pcmcia.o
obj-$(CONFIG_PCCARD_NONSTATIC) += rsrc_nonstatic.o
diff --git a/trunk/drivers/pcmcia/cistpl.c b/trunk/drivers/pcmcia/cistpl.c
index dd7651ff5b43..e29a6ddf2fd7 100644
--- a/trunk/drivers/pcmcia/cistpl.c
+++ b/trunk/drivers/pcmcia/cistpl.c
@@ -89,10 +89,8 @@ static void __iomem *
set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags)
{
pccard_mem_map *mem = &s->cis_mem;
- int ret;
-
if (!(s->features & SS_CAP_STATIC_MAP) && mem->res == NULL) {
- mem->res = pcmcia_find_mem_region(0, s->map_size, s->map_size, 0, s);
+ mem->res = find_mem_region(0, s->map_size, s->map_size, 0, s);
if (mem->res == NULL) {
printk(KERN_NOTICE "cs: unable to map card memory!\n");
return NULL;
@@ -101,12 +99,7 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag
}
mem->card_start = card_offset;
mem->flags = flags;
- ret = s->ops->set_mem_map(s, mem);
- if (ret) {
- iounmap(s->cis_virt);
- return NULL;
- }
-
+ s->ops->set_mem_map(s, mem);
if (s->features & SS_CAP_STATIC_MAP) {
if (s->cis_virt)
iounmap(s->cis_virt);
@@ -126,13 +119,13 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag
#define IS_ATTR 1
#define IS_INDIRECT 8
-int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
+int read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
u_int len, void *ptr)
{
void __iomem *sys, *end;
unsigned char *buf = ptr;
- cs_dbg(s, 3, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
+ cs_dbg(s, 3, "read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
if (attr & IS_INDIRECT) {
/* Indirect accesses use a bunch of special registers at fixed
@@ -189,16 +182,14 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
*(u_char *)(ptr+2), *(u_char *)(ptr+3));
return 0;
}
-EXPORT_SYMBOL(pcmcia_read_cis_mem);
-
-void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
+void write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
u_int len, void *ptr)
{
void __iomem *sys, *end;
unsigned char *buf = ptr;
- cs_dbg(s, 3, "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
+ cs_dbg(s, 3, "write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
if (attr & IS_INDIRECT) {
/* Indirect accesses use a bunch of special registers at fixed
@@ -248,8 +239,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
}
}
}
-EXPORT_SYMBOL(pcmcia_write_cis_mem);
-
/*======================================================================
@@ -285,7 +274,7 @@ static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
ret = read_cb_mem(s, attr, addr, len, ptr);
else
#endif
- ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr);
+ ret = read_cis_mem(s, attr, addr, len, ptr);
if (ret == 0) {
/* Copy data into the cache */
@@ -359,7 +348,7 @@ int verify_cis_cache(struct pcmcia_socket *s)
read_cb_mem(s, cis->attr, cis->addr, len, buf);
else
#endif
- pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf);
+ read_cis_mem(s, cis->attr, cis->addr, len, buf);
if (memcmp(buf, cis->cache, len) != 0) {
kfree(buf);
@@ -392,7 +381,6 @@ int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis)
memcpy(s->fake_cis, cis->Data, cis->Length);
return CS_SUCCESS;
}
-EXPORT_SYMBOL(pcmcia_replace_cis);
/*======================================================================
diff --git a/trunk/drivers/pcmcia/cs.c b/trunk/drivers/pcmcia/cs.c
index e82859d3227a..48e4f04530d8 100644
--- a/trunk/drivers/pcmcia/cs.c
+++ b/trunk/drivers/pcmcia/cs.c
@@ -43,11 +43,36 @@
#include
#include "cs_internal.h"
+#ifdef CONFIG_PCI
+#define PCI_OPT " [pci]"
+#else
+#define PCI_OPT ""
+#endif
+#ifdef CONFIG_CARDBUS
+#define CB_OPT " [cardbus]"
+#else
+#define CB_OPT ""
+#endif
+#ifdef CONFIG_PM
+#define PM_OPT " [pm]"
+#else
+#define PM_OPT ""
+#endif
+#if !defined(CONFIG_CARDBUS) && !defined(CONFIG_PCI) && !defined(CONFIG_PM)
+#define OPTIONS " none"
+#else
+#define OPTIONS PCI_OPT CB_OPT PM_OPT
+#endif
+
+static const char *release = "Linux Kernel Card Services";
+static const char *options = "options: " OPTIONS;
+
+/*====================================================================*/
/* Module parameters */
MODULE_AUTHOR("David Hinds ");
-MODULE_DESCRIPTION("Linux Kernel Card Services");
+MODULE_DESCRIPTION("Linux Kernel Card Services\noptions:" OPTIONS);
MODULE_LICENSE("GPL");
#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
@@ -64,6 +89,9 @@ INT_MODULE_PARM(unreset_limit, 30); /* unreset_check's */
/* Access speed for attribute memory windows */
INT_MODULE_PARM(cis_speed, 300); /* ns */
+/* Access speed for IO windows */
+INT_MODULE_PARM(io_speed, 0); /* ns */
+
#ifdef DEBUG
static int pc_debug;
@@ -75,26 +103,34 @@ int cs_debug_level(int level)
}
#endif
+/*====================================================================*/
socket_state_t dead_socket = {
.csc_mask = SS_DETECT,
};
-EXPORT_SYMBOL(dead_socket);
/* List of all sockets, protected by a rwsem */
LIST_HEAD(pcmcia_socket_list);
-EXPORT_SYMBOL(pcmcia_socket_list);
-
DECLARE_RWSEM(pcmcia_socket_list_rwsem);
+EXPORT_SYMBOL(pcmcia_socket_list);
EXPORT_SYMBOL(pcmcia_socket_list_rwsem);
+#ifdef CONFIG_PCMCIA_PROBE
+/* mask ofIRQs already reserved by other cards, we should avoid using them */
+static u8 pcmcia_used_irq[NR_IRQS];
+#endif
+
+/*====================================================================
+
+ Low-level PC Card interface drivers need to register with Card
+ Services using these calls.
+
+======================================================================*/
+
/**
- * Low-level PCMCIA socket drivers need to register with the PCCard
- * core using pcmcia_register_socket.
- *
- * socket drivers are expected to use the following callbacks in their
+ * socket drivers are expected to use the following callbacks in their
* .drv struct:
* - pcmcia_socket_dev_suspend
* - pcmcia_socket_dev_resume
@@ -194,8 +230,8 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
}
/* try to obtain a socket number [yes, it gets ugly if we
- * register more than 2^sizeof(unsigned int) pcmcia
- * sockets... but the socket number is deprecated
+ * register more than 2^sizeof(unsigned int) pcmcia
+ * sockets... but the socket number is deprecated
* anyways, so I don't care] */
down_write(&pcmcia_socket_list_rwsem);
if (list_empty(&pcmcia_socket_list))
@@ -304,49 +340,54 @@ struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr)
EXPORT_SYMBOL(pcmcia_get_socket_by_nr);
-/**
- * socket_setup() and shutdown_socket() are called by the main event
- * handler when card insertion and removal events are received.
- * socket_setup() turns on socket power and resets the socket, in two stages.
- * shutdown_socket() unconfigures a socket and turns off socket power.
- */
+/*======================================================================
+
+ socket_setup() and shutdown_socket() are called by the main event
+ handler when card insertion and removal events are received.
+ socket_setup() turns on socket power and resets the socket, in two stages.
+ shutdown_socket() unconfigures a socket and turns off socket power.
+
+======================================================================*/
+
static void shutdown_socket(struct pcmcia_socket *s)
{
- cs_dbg(s, 1, "shutdown_socket\n");
-
- /* Blank out the socket state */
- s->socket = dead_socket;
- s->ops->init(s);
- s->ops->set_socket(s, &s->socket);
- s->irq.AssignedIRQ = s->irq.Config = 0;
- s->lock_count = 0;
- destroy_cis_cache(s);
+ cs_dbg(s, 1, "shutdown_socket\n");
+
+ /* Blank out the socket state */
+ s->socket = dead_socket;
+ s->ops->init(s);
+ s->ops->set_socket(s, &s->socket);
+ s->irq.AssignedIRQ = s->irq.Config = 0;
+ s->lock_count = 0;
+ destroy_cis_cache(s);
#ifdef CONFIG_CARDBUS
- cb_free(s);
+ cb_free(s);
#endif
- s->functions = 0;
- if (s->config) {
- kfree(s->config);
- s->config = NULL;
- }
-
- {
- int status;
- s->ops->get_status(s, &status);
- if (status & SS_POWERON) {
- printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s);
- }
+ s->functions = 0;
+ if (s->config) {
+ kfree(s->config);
+ s->config = NULL;
+ }
+
+ {
+ int status;
+ s->ops->get_status(s, &status);
+ if (status & SS_POWERON) {
+ printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s);
}
+ }
} /* shutdown_socket */
+/*======================================================================
+
+ The central event handler. Send_event() sends an event to the
+ 16-bit subsystem, which then calls the relevant device drivers.
+ Parse_events() interprets the event bits from
+ a card status change report. Do_shutdown() handles the high
+ priority stuff associated with a card removal.
+
+======================================================================*/
-/**
- * The central event handler. Send_event() sends an event to the
- * 16-bit subsystem, which then calls the relevant device drivers.
- * Parse_events() interprets the event bits from
- * a card status change report. Do_shutdown() handles the high
- * priority stuff associated with a card removal.
- */
/* NOTE: send_event needs to be called with skt->sem held. */
@@ -705,9 +746,420 @@ void pcmcia_parse_events(struct pcmcia_socket *s, u_int events)
wake_up(&s->thread_wait);
}
} /* pcmcia_parse_events */
-EXPORT_SYMBOL(pcmcia_parse_events);
+/*======================================================================
+
+ Special stuff for managing IO windows, because they are scarce.
+
+======================================================================*/
+
+static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
+ ioaddr_t num, u_int lines)
+{
+ int i;
+ kio_addr_t try, align;
+
+ align = (*base) ? (lines ? 1<features & SS_CAP_STATIC_MAP) && s->io_offset) {
+ *base = s->io_offset | (*base & 0x0fff);
+ return 0;
+ }
+ /* Check for an already-allocated window that must conflict with
+ what was asked for. It is a hack because it does not catch all
+ potential conflicts, just the most obvious ones. */
+ for (i = 0; i < MAX_IO_WIN; i++)
+ if ((s->io[i].NumPorts != 0) &&
+ ((s->io[i].BasePort & (align-1)) == *base))
+ return 1;
+ for (i = 0; i < MAX_IO_WIN; i++) {
+ if (s->io[i].NumPorts == 0) {
+ s->io[i].res = find_io_region(*base, num, align, s);
+ if (s->io[i].res) {
+ s->io[i].Attributes = attr;
+ s->io[i].BasePort = *base = s->io[i].res->start;
+ s->io[i].NumPorts = s->io[i].InUse = num;
+ break;
+ } else
+ return 1;
+ } else if (s->io[i].Attributes != attr)
+ continue;
+ /* Try to extend top of window */
+ try = s->io[i].BasePort + s->io[i].NumPorts;
+ if ((*base == 0) || (*base == try))
+ if (adjust_io_region(s->io[i].res, s->io[i].res->start,
+ s->io[i].res->end + num, s) == 0) {
+ *base = try;
+ s->io[i].NumPorts += num;
+ s->io[i].InUse += num;
+ break;
+ }
+ /* Try to extend bottom of window */
+ try = s->io[i].BasePort - num;
+ if ((*base == 0) || (*base == try))
+ if (adjust_io_region(s->io[i].res, s->io[i].res->start - num,
+ s->io[i].res->end, s) == 0) {
+ s->io[i].BasePort = *base = try;
+ s->io[i].NumPorts += num;
+ s->io[i].InUse += num;
+ break;
+ }
+ }
+ return (i == MAX_IO_WIN);
+} /* alloc_io_space */
+
+static void release_io_space(struct pcmcia_socket *s, ioaddr_t base,
+ ioaddr_t num)
+{
+ int i;
+
+ for (i = 0; i < MAX_IO_WIN; i++) {
+ if ((s->io[i].BasePort <= base) &&
+ (s->io[i].BasePort+s->io[i].NumPorts >= base+num)) {
+ s->io[i].InUse -= num;
+ /* Free the window if no one else is using it */
+ if (s->io[i].InUse == 0) {
+ s->io[i].NumPorts = 0;
+ release_resource(s->io[i].res);
+ kfree(s->io[i].res);
+ s->io[i].res = NULL;
+ }
+ }
+ }
+}
+
+/*======================================================================
+
+ Access_configuration_register() reads and writes configuration
+ registers in attribute memory. Memory window 0 is reserved for
+ this and the tuple reading services.
+
+======================================================================*/
+
+int pccard_access_configuration_register(struct pcmcia_socket *s,
+ unsigned int function,
+ conf_reg_t *reg)
+{
+ config_t *c;
+ int addr;
+ u_char val;
+
+ if (!s || !s->config)
+ return CS_NO_CARD;
+
+ c = &s->config[function];
+
+ if (c == NULL)
+ return CS_NO_CARD;
+
+ if (!(c->state & CONFIG_LOCKED))
+ return CS_CONFIGURATION_LOCKED;
+
+ addr = (c->ConfigBase + reg->Offset) >> 1;
+
+ switch (reg->Action) {
+ case CS_READ:
+ read_cis_mem(s, 1, addr, 1, &val);
+ reg->Value = val;
+ break;
+ case CS_WRITE:
+ val = reg->Value;
+ write_cis_mem(s, 1, addr, 1, &val);
+ break;
+ default:
+ return CS_BAD_ARGS;
+ break;
+ }
+ return CS_SUCCESS;
+} /* access_configuration_register */
+EXPORT_SYMBOL(pccard_access_configuration_register);
+
+
+/*====================================================================*/
+
+int pccard_get_configuration_info(struct pcmcia_socket *s,
+ unsigned int function,
+ config_info_t *config)
+{
+ config_t *c;
+
+ if (!(s->state & SOCKET_PRESENT))
+ return CS_NO_CARD;
+
+ config->Function = function;
+
+#ifdef CONFIG_CARDBUS
+ if (s->state & SOCKET_CARDBUS) {
+ memset(config, 0, sizeof(config_info_t));
+ config->Vcc = s->socket.Vcc;
+ config->Vpp1 = config->Vpp2 = s->socket.Vpp;
+ config->Option = s->cb_dev->subordinate->number;
+ if (s->state & SOCKET_CARDBUS_CONFIG) {
+ config->Attributes = CONF_VALID_CLIENT;
+ config->IntType = INT_CARDBUS;
+ config->AssignedIRQ = s->irq.AssignedIRQ;
+ if (config->AssignedIRQ)
+ config->Attributes |= CONF_ENABLE_IRQ;
+ config->BasePort1 = s->io[0].BasePort;
+ config->NumPorts1 = s->io[0].NumPorts;
+ }
+ return CS_SUCCESS;
+ }
+#endif
+
+ c = (s->config != NULL) ? &s->config[function] : NULL;
+
+ if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
+ config->Attributes = 0;
+ config->Vcc = s->socket.Vcc;
+ config->Vpp1 = config->Vpp2 = s->socket.Vpp;
+ return CS_SUCCESS;
+ }
+
+ /* !!! This is a hack !!! */
+ memcpy(&config->Attributes, &c->Attributes, sizeof(config_t));
+ config->Attributes |= CONF_VALID_CLIENT;
+ config->CardValues = c->CardValues;
+ config->IRQAttributes = c->irq.Attributes;
+ config->AssignedIRQ = s->irq.AssignedIRQ;
+ config->BasePort1 = c->io.BasePort1;
+ config->NumPorts1 = c->io.NumPorts1;
+ config->Attributes1 = c->io.Attributes1;
+ config->BasePort2 = c->io.BasePort2;
+ config->NumPorts2 = c->io.NumPorts2;
+ config->Attributes2 = c->io.Attributes2;
+ config->IOAddrLines = c->io.IOAddrLines;
+
+ return CS_SUCCESS;
+} /* get_configuration_info */
+EXPORT_SYMBOL(pccard_get_configuration_info);
+
+/*======================================================================
+
+ Return information about this version of Card Services.
+
+======================================================================*/
+
+int pcmcia_get_card_services_info(servinfo_t *info)
+{
+ unsigned int socket_count = 0;
+ struct list_head *tmp;
+ info->Signature[0] = 'C';
+ info->Signature[1] = 'S';
+ down_read(&pcmcia_socket_list_rwsem);
+ list_for_each(tmp, &pcmcia_socket_list)
+ socket_count++;
+ up_read(&pcmcia_socket_list_rwsem);
+ info->Count = socket_count;
+ info->Revision = CS_RELEASE_CODE;
+ info->CSLevel = 0x0210;
+ info->VendorString = (char *)release;
+ return CS_SUCCESS;
+} /* get_card_services_info */
+
+
+/*====================================================================*/
+
+int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, int idx, win_req_t *req)
+{
+ window_t *win;
+ int w;
+
+ if (!s || !(s->state & SOCKET_PRESENT))
+ return CS_NO_CARD;
+ for (w = idx; w < MAX_WIN; w++)
+ if (s->state & SOCKET_WIN_REQ(w)) break;
+ if (w == MAX_WIN)
+ return CS_NO_MORE_ITEMS;
+ win = &s->win[w];
+ req->Base = win->ctl.res->start;
+ req->Size = win->ctl.res->end - win->ctl.res->start + 1;
+ req->AccessSpeed = win->ctl.speed;
+ req->Attributes = 0;
+ if (win->ctl.flags & MAP_ATTRIB)
+ req->Attributes |= WIN_MEMORY_TYPE_AM;
+ if (win->ctl.flags & MAP_ACTIVE)
+ req->Attributes |= WIN_ENABLE;
+ if (win->ctl.flags & MAP_16BIT)
+ req->Attributes |= WIN_DATA_WIDTH_16;
+ if (win->ctl.flags & MAP_USE_WAIT)
+ req->Attributes |= WIN_USE_WAIT;
+ *handle = win;
+ return CS_SUCCESS;
+} /* get_window */
+EXPORT_SYMBOL(pcmcia_get_window);
+
+/*=====================================================================
+
+ Return the PCI device associated with a card..
+
+======================================================================*/
+
+#ifdef CONFIG_CARDBUS
+
+struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s)
+{
+ if (!s || !(s->state & SOCKET_CARDBUS))
+ return NULL;
+
+ return s->cb_dev->subordinate;
+}
+
+EXPORT_SYMBOL(pcmcia_lookup_bus);
+
+#endif
+
+/*======================================================================
+
+ Get the current socket state bits. We don't support the latched
+ SocketState yet: I haven't seen any point for it.
+
+======================================================================*/
+
+int pccard_get_status(struct pcmcia_socket *s, unsigned int function, cs_status_t *status)
+{
+ config_t *c;
+ int val;
+
+ s->ops->get_status(s, &val);
+ status->CardState = status->SocketState = 0;
+ status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0;
+ status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0;
+ status->CardState |= (val & SS_3VCARD) ? CS_EVENT_3VCARD : 0;
+ status->CardState |= (val & SS_XVCARD) ? CS_EVENT_XVCARD : 0;
+ if (s->state & SOCKET_SUSPEND)
+ status->CardState |= CS_EVENT_PM_SUSPEND;
+ if (!(s->state & SOCKET_PRESENT))
+ return CS_NO_CARD;
+
+ c = (s->config != NULL) ? &s->config[function] : NULL;
+ if ((c != NULL) && (c->state & CONFIG_LOCKED) &&
+ (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) {
+ u_char reg;
+ if (c->Present & PRESENT_PIN_REPLACE) {
+ read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, ®);
+ status->CardState |=
+ (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0;
+ status->CardState |=
+ (reg & PRR_READY_STATUS) ? CS_EVENT_READY_CHANGE : 0;
+ status->CardState |=
+ (reg & PRR_BVD2_STATUS) ? CS_EVENT_BATTERY_LOW : 0;
+ status->CardState |=
+ (reg & PRR_BVD1_STATUS) ? CS_EVENT_BATTERY_DEAD : 0;
+ } else {
+ /* No PRR? Then assume we're always ready */
+ status->CardState |= CS_EVENT_READY_CHANGE;
+ }
+ if (c->Present & PRESENT_EXT_STATUS) {
+ read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, ®);
+ status->CardState |=
+ (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
+ }
+ return CS_SUCCESS;
+ }
+ status->CardState |=
+ (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0;
+ status->CardState |=
+ (val & SS_BATDEAD) ? CS_EVENT_BATTERY_DEAD : 0;
+ status->CardState |=
+ (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0;
+ status->CardState |=
+ (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0;
+ return CS_SUCCESS;
+} /* get_status */
+EXPORT_SYMBOL(pccard_get_status);
+
+/*======================================================================
+
+ Change the card address of an already open memory window.
+
+======================================================================*/
+
+int pcmcia_get_mem_page(window_handle_t win, memreq_t *req)
+{
+ if ((win == NULL) || (win->magic != WINDOW_MAGIC))
+ return CS_BAD_HANDLE;
+ req->Page = 0;
+ req->CardOffset = win->ctl.card_start;
+ return CS_SUCCESS;
+} /* get_mem_page */
+
+int pcmcia_map_mem_page(window_handle_t win, memreq_t *req)
+{
+ struct pcmcia_socket *s;
+ if ((win == NULL) || (win->magic != WINDOW_MAGIC))
+ return CS_BAD_HANDLE;
+ if (req->Page != 0)
+ return CS_BAD_PAGE;
+ s = win->sock;
+ win->ctl.card_start = req->CardOffset;
+ if (s->ops->set_mem_map(s, &win->ctl) != 0)
+ return CS_BAD_OFFSET;
+ return CS_SUCCESS;
+} /* map_mem_page */
+
+/*======================================================================
+
+ Modify a locked socket configuration
+
+======================================================================*/
+
+int pcmcia_modify_configuration(client_handle_t handle,
+ modconf_t *mod)
+{
+ struct pcmcia_socket *s;
+ config_t *c;
+
+ if (CHECK_HANDLE(handle))
+ return CS_BAD_HANDLE;
+ s = SOCKET(handle); c = CONFIG(handle);
+ if (!(s->state & SOCKET_PRESENT))
+ return CS_NO_CARD;
+ if (!(c->state & CONFIG_LOCKED))
+ return CS_CONFIGURATION_LOCKED;
+
+ if (mod->Attributes & CONF_IRQ_CHANGE_VALID) {
+ if (mod->Attributes & CONF_ENABLE_IRQ) {
+ c->Attributes |= CONF_ENABLE_IRQ;
+ s->socket.io_irq = s->irq.AssignedIRQ;
+ } else {
+ c->Attributes &= ~CONF_ENABLE_IRQ;
+ s->socket.io_irq = 0;
+ }
+ s->ops->set_socket(s, &s->socket);
+ }
+
+ if (mod->Attributes & CONF_VCC_CHANGE_VALID)
+ return CS_BAD_VCC;
+
+ /* We only allow changing Vpp1 and Vpp2 to the same value */
+ if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
+ (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
+ if (mod->Vpp1 != mod->Vpp2)
+ return CS_BAD_VPP;
+ c->Vpp1 = c->Vpp2 = s->socket.Vpp = mod->Vpp1;
+ if (s->ops->set_socket(s, &s->socket))
+ return CS_BAD_VPP;
+ } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
+ (mod->Attributes & CONF_VPP2_CHANGE_VALID))
+ return CS_BAD_VPP;
+
+ return CS_SUCCESS;
+} /* modify_configuration */
+
/* register pcmcia_callback */
int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
{
@@ -736,16 +1188,543 @@ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
}
EXPORT_SYMBOL(pccard_register_pcmcia);
+/*====================================================================*/
-/* I'm not sure which "reset" function this is supposed to use,
- * but for now, it uses the low-level interface's reset, not the
- * CIS register.
- */
+int pcmcia_release_configuration(client_handle_t handle)
+{
+ pccard_io_map io = { 0, 0, 0, 0, 1 };
+ struct pcmcia_socket *s;
+ int i;
+
+ if (CHECK_HANDLE(handle) ||
+ !(handle->state & CLIENT_CONFIG_LOCKED))
+ return CS_BAD_HANDLE;
+ handle->state &= ~CLIENT_CONFIG_LOCKED;
+ s = SOCKET(handle);
+
+#ifdef CONFIG_CARDBUS
+ if (handle->state & CLIENT_CARDBUS)
+ return CS_SUCCESS;
+#endif
+
+ if (!(handle->state & CLIENT_STALE)) {
+ config_t *c = CONFIG(handle);
+ if (--(s->lock_count) == 0) {
+ s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */
+ s->socket.Vpp = 0;
+ s->socket.io_irq = 0;
+ s->ops->set_socket(s, &s->socket);
+ }
+ if (c->state & CONFIG_IO_REQ)
+ for (i = 0; i < MAX_IO_WIN; i++) {
+ if (s->io[i].NumPorts == 0)
+ continue;
+ s->io[i].Config--;
+ if (s->io[i].Config != 0)
+ continue;
+ io.map = i;
+ s->ops->set_io_map(s, &io);
+ }
+ c->state &= ~CONFIG_LOCKED;
+ }
+
+ return CS_SUCCESS;
+} /* release_configuration */
+
+/*======================================================================
+
+ Release_io() releases the I/O ranges allocated by a client. This
+ may be invoked some time after a card ejection has already dumped
+ the actual socket configuration, so if the client is "stale", we
+ don't bother checking the port ranges against the current socket
+ values.
+
+======================================================================*/
+
+int pcmcia_release_io(client_handle_t handle, io_req_t *req)
+{
+ struct pcmcia_socket *s;
+
+ if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ))
+ return CS_BAD_HANDLE;
+ handle->state &= ~CLIENT_IO_REQ;
+ s = SOCKET(handle);
+
+#ifdef CONFIG_CARDBUS
+ if (handle->state & CLIENT_CARDBUS)
+ return CS_SUCCESS;
+#endif
+
+ if (!(handle->state & CLIENT_STALE)) {
+ config_t *c = CONFIG(handle);
+ if (c->state & CONFIG_LOCKED)
+ return CS_CONFIGURATION_LOCKED;
+ if ((c->io.BasePort1 != req->BasePort1) ||
+ (c->io.NumPorts1 != req->NumPorts1) ||
+ (c->io.BasePort2 != req->BasePort2) ||
+ (c->io.NumPorts2 != req->NumPorts2))
+ return CS_BAD_ARGS;
+ c->state &= ~CONFIG_IO_REQ;
+ }
+
+ release_io_space(s, req->BasePort1, req->NumPorts1);
+ if (req->NumPorts2)
+ release_io_space(s, req->BasePort2, req->NumPorts2);
+
+ return CS_SUCCESS;
+} /* release_io */
+
+/*====================================================================*/
+
+int pcmcia_release_irq(client_handle_t handle, irq_req_t *req)
+{
+ struct pcmcia_socket *s;
+ if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IRQ_REQ))
+ return CS_BAD_HANDLE;
+ handle->state &= ~CLIENT_IRQ_REQ;
+ s = SOCKET(handle);
+
+ if (!(handle->state & CLIENT_STALE)) {
+ config_t *c = CONFIG(handle);
+ if (c->state & CONFIG_LOCKED)
+ return CS_CONFIGURATION_LOCKED;
+ if (c->irq.Attributes != req->Attributes)
+ return CS_BAD_ATTRIBUTE;
+ if (s->irq.AssignedIRQ != req->AssignedIRQ)
+ return CS_BAD_IRQ;
+ if (--s->irq.Config == 0) {
+ c->state &= ~CONFIG_IRQ_REQ;
+ s->irq.AssignedIRQ = 0;
+ }
+ }
+
+ if (req->Attributes & IRQ_HANDLE_PRESENT) {
+ free_irq(req->AssignedIRQ, req->Instance);
+ }
+
+#ifdef CONFIG_PCMCIA_PROBE
+ pcmcia_used_irq[req->AssignedIRQ]--;
+#endif
+
+ return CS_SUCCESS;
+} /* cs_release_irq */
+
+/*====================================================================*/
+
+int pcmcia_release_window(window_handle_t win)
+{
+ struct pcmcia_socket *s;
+
+ if ((win == NULL) || (win->magic != WINDOW_MAGIC))
+ return CS_BAD_HANDLE;
+ s = win->sock;
+ if (!(win->handle->state & CLIENT_WIN_REQ(win->index)))
+ return CS_BAD_HANDLE;
+
+ /* Shut down memory window */
+ win->ctl.flags &= ~MAP_ACTIVE;
+ s->ops->set_mem_map(s, &win->ctl);
+ s->state &= ~SOCKET_WIN_REQ(win->index);
+
+ /* Release system memory */
+ if (win->ctl.res) {
+ release_resource(win->ctl.res);
+ kfree(win->ctl.res);
+ win->ctl.res = NULL;
+ }
+ win->handle->state &= ~CLIENT_WIN_REQ(win->index);
+
+ win->magic = 0;
+
+ return CS_SUCCESS;
+} /* release_window */
+
+/*====================================================================*/
+
+int pcmcia_request_configuration(client_handle_t handle,
+ config_req_t *req)
+{
+ int i;
+ u_int base;
+ struct pcmcia_socket *s;
+ config_t *c;
+ pccard_io_map iomap;
+
+ if (CHECK_HANDLE(handle))
+ return CS_BAD_HANDLE;
+ s = SOCKET(handle);
+ if (!(s->state & SOCKET_PRESENT))
+ return CS_NO_CARD;
+
+#ifdef CONFIG_CARDBUS
+ if (handle->state & CLIENT_CARDBUS)
+ return CS_UNSUPPORTED_MODE;
+#endif
+
+ if (req->IntType & INT_CARDBUS)
+ return CS_UNSUPPORTED_MODE;
+ c = CONFIG(handle);
+ if (c->state & CONFIG_LOCKED)
+ return CS_CONFIGURATION_LOCKED;
+
+ /* Do power control. We don't allow changes in Vcc. */
+ if (s->socket.Vcc != req->Vcc)
+ return CS_BAD_VCC;
+ if (req->Vpp1 != req->Vpp2)
+ return CS_BAD_VPP;
+ s->socket.Vpp = req->Vpp1;
+ if (s->ops->set_socket(s, &s->socket))
+ return CS_BAD_VPP;
+
+ c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1;
+
+ /* Pick memory or I/O card, DMA mode, interrupt */
+ c->IntType = req->IntType;
+ c->Attributes = req->Attributes;
+ if (req->IntType & INT_MEMORY_AND_IO)
+ s->socket.flags |= SS_IOCARD;
+ if (req->IntType & INT_ZOOMED_VIDEO)
+ s->socket.flags |= SS_ZVCARD | SS_IOCARD;
+ if (req->Attributes & CONF_ENABLE_DMA)
+ s->socket.flags |= SS_DMA_MODE;
+ if (req->Attributes & CONF_ENABLE_SPKR)
+ s->socket.flags |= SS_SPKR_ENA;
+ if (req->Attributes & CONF_ENABLE_IRQ)
+ s->socket.io_irq = s->irq.AssignedIRQ;
+ else
+ s->socket.io_irq = 0;
+ s->ops->set_socket(s, &s->socket);
+ s->lock_count++;
+
+ /* Set up CIS configuration registers */
+ base = c->ConfigBase = req->ConfigBase;
+ c->Present = c->CardValues = req->Present;
+ if (req->Present & PRESENT_COPY) {
+ c->Copy = req->Copy;
+ write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy);
+ }
+ if (req->Present & PRESENT_OPTION) {
+ if (s->functions == 1) {
+ c->Option = req->ConfigIndex & COR_CONFIG_MASK;
+ } else {
+ c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK;
+ c->Option |= COR_FUNC_ENA|COR_IREQ_ENA;
+ if (req->Present & PRESENT_IOBASE_0)
+ c->Option |= COR_ADDR_DECODE;
+ }
+ if (c->state & CONFIG_IRQ_REQ)
+ if (!(c->irq.Attributes & IRQ_FORCED_PULSE))
+ c->Option |= COR_LEVEL_REQ;
+ write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option);
+ mdelay(40);
+ }
+ if (req->Present & PRESENT_STATUS) {
+ c->Status = req->Status;
+ write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status);
+ }
+ if (req->Present & PRESENT_PIN_REPLACE) {
+ c->Pin = req->Pin;
+ write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &c->Pin);
+ }
+ if (req->Present & PRESENT_EXT_STATUS) {
+ c->ExtStatus = req->ExtStatus;
+ write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus);
+ }
+ if (req->Present & PRESENT_IOBASE_0) {
+ u_char b = c->io.BasePort1 & 0xff;
+ write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b);
+ b = (c->io.BasePort1 >> 8) & 0xff;
+ write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b);
+ }
+ if (req->Present & PRESENT_IOSIZE) {
+ u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1;
+ write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b);
+ }
+
+ /* Configure I/O windows */
+ if (c->state & CONFIG_IO_REQ) {
+ iomap.speed = io_speed;
+ for (i = 0; i < MAX_IO_WIN; i++)
+ if (s->io[i].NumPorts != 0) {
+ iomap.map = i;
+ iomap.flags = MAP_ACTIVE;
+ switch (s->io[i].Attributes & IO_DATA_PATH_WIDTH) {
+ case IO_DATA_PATH_WIDTH_16:
+ iomap.flags |= MAP_16BIT; break;
+ case IO_DATA_PATH_WIDTH_AUTO:
+ iomap.flags |= MAP_AUTOSZ; break;
+ default:
+ break;
+ }
+ iomap.start = s->io[i].BasePort;
+ iomap.stop = iomap.start + s->io[i].NumPorts - 1;
+ s->ops->set_io_map(s, &iomap);
+ s->io[i].Config++;
+ }
+ }
+
+ c->state |= CONFIG_LOCKED;
+ handle->state |= CLIENT_CONFIG_LOCKED;
+ return CS_SUCCESS;
+} /* request_configuration */
+
+/*======================================================================
+
+ Request_io() reserves ranges of port addresses for a socket.
+ I have not implemented range sharing or alias addressing.
+
+======================================================================*/
+
+int pcmcia_request_io(client_handle_t handle, io_req_t *req)
+{
+ struct pcmcia_socket *s;
+ config_t *c;
+
+ if (CHECK_HANDLE(handle))
+ return CS_BAD_HANDLE;
+ s = SOCKET(handle);
+ if (!(s->state & SOCKET_PRESENT))
+ return CS_NO_CARD;
+
+ if (handle->state & CLIENT_CARDBUS) {
+#ifdef CONFIG_CARDBUS
+ handle->state |= CLIENT_IO_REQ;
+ return CS_SUCCESS;
+#else
+ return CS_UNSUPPORTED_FUNCTION;
+#endif
+ }
+
+ if (!req)
+ return CS_UNSUPPORTED_MODE;
+ c = CONFIG(handle);
+ if (c->state & CONFIG_LOCKED)
+ return CS_CONFIGURATION_LOCKED;
+ if (c->state & CONFIG_IO_REQ)
+ return CS_IN_USE;
+ if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))
+ return CS_BAD_ATTRIBUTE;
+ if ((req->NumPorts2 > 0) &&
+ (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)))
+ return CS_BAD_ATTRIBUTE;
+
+ if (alloc_io_space(s, req->Attributes1, &req->BasePort1,
+ req->NumPorts1, req->IOAddrLines))
+ return CS_IN_USE;
+
+ if (req->NumPorts2) {
+ if (alloc_io_space(s, req->Attributes2, &req->BasePort2,
+ req->NumPorts2, req->IOAddrLines)) {
+ release_io_space(s, req->BasePort1, req->NumPorts1);
+ return CS_IN_USE;
+ }
+ }
+
+ c->io = *req;
+ c->state |= CONFIG_IO_REQ;
+ handle->state |= CLIENT_IO_REQ;
+ return CS_SUCCESS;
+} /* request_io */
+
+/*======================================================================
+
+ Request_irq() reserves an irq for this client.
+
+ Also, since Linux only reserves irq's when they are actually
+ hooked, we don't guarantee that an irq will still be available
+ when the configuration is locked. Now that I think about it,
+ there might be a way to fix this using a dummy handler.
+
+======================================================================*/
+
+#ifdef CONFIG_PCMCIA_PROBE
+static irqreturn_t test_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+ return IRQ_NONE;
+}
+#endif
+
+int pcmcia_request_irq(client_handle_t handle, irq_req_t *req)
+{
+ struct pcmcia_socket *s;
+ config_t *c;
+ int ret = CS_IN_USE, irq = 0;
+ struct pcmcia_device *p_dev = handle_to_pdev(handle);
+
+ if (CHECK_HANDLE(handle))
+ return CS_BAD_HANDLE;
+ s = SOCKET(handle);
+ if (!(s->state & SOCKET_PRESENT))
+ return CS_NO_CARD;
+ c = CONFIG(handle);
+ if (c->state & CONFIG_LOCKED)
+ return CS_CONFIGURATION_LOCKED;
+ if (c->state & CONFIG_IRQ_REQ)
+ return CS_IN_USE;
+
+#ifdef CONFIG_PCMCIA_PROBE
+ if (s->irq.AssignedIRQ != 0) {
+ /* If the interrupt is already assigned, it must be the same */
+ irq = s->irq.AssignedIRQ;
+ } else {
+ int try;
+ u32 mask = s->irq_mask;
+ void *data = NULL;
+
+ for (try = 0; try < 64; try++) {
+ irq = try % 32;
+
+ /* marked as available by driver, and not blocked by userspace? */
+ if (!((mask >> irq) & 1))
+ continue;
+
+ /* avoid an IRQ which is already used by a PCMCIA card */
+ if ((try < 32) && pcmcia_used_irq[irq])
+ continue;
+
+ /* register the correct driver, if possible, of check whether
+ * registering a dummy handle works, i.e. if the IRQ isn't
+ * marked as used by the kernel resource management core */
+ ret = request_irq(irq,
+ (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Handler : test_action,
+ ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
+ (s->functions > 1) ||
+ (irq == s->pci_irq)) ? SA_SHIRQ : 0,
+ p_dev->dev.bus_id,
+ (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data);
+ if (!ret) {
+ if (!(req->Attributes & IRQ_HANDLE_PRESENT))
+ free_irq(irq, data);
+ break;
+ }
+ }
+ }
+#endif
+ if (ret) {
+ if (!s->pci_irq)
+ return ret;
+ irq = s->pci_irq;
+ }
+
+ if (ret && req->Attributes & IRQ_HANDLE_PRESENT) {
+ if (request_irq(irq, req->Handler,
+ ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
+ (s->functions > 1) ||
+ (irq == s->pci_irq)) ? SA_SHIRQ : 0,
+ p_dev->dev.bus_id, req->Instance))
+ return CS_IN_USE;
+ }
+
+ c->irq.Attributes = req->Attributes;
+ s->irq.AssignedIRQ = req->AssignedIRQ = irq;
+ s->irq.Config++;
+
+ c->state |= CONFIG_IRQ_REQ;
+ handle->state |= CLIENT_IRQ_REQ;
+
+#ifdef CONFIG_PCMCIA_PROBE
+ pcmcia_used_irq[irq]++;
+#endif
+
+ return CS_SUCCESS;
+} /* pcmcia_request_irq */
+
+/*======================================================================
+
+ Request_window() establishes a mapping between card memory space
+ and system memory space.
+
+======================================================================*/
+
+int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle_t *wh)
+{
+ struct pcmcia_socket *s;
+ window_t *win;
+ u_long align;
+ int w;
+
+ if (CHECK_HANDLE(*handle))
+ return CS_BAD_HANDLE;
+ s = (*handle)->Socket;
+ if (!(s->state & SOCKET_PRESENT))
+ return CS_NO_CARD;
+ if (req->Attributes & (WIN_PAGED | WIN_SHARED))
+ return CS_BAD_ATTRIBUTE;
+
+ /* Window size defaults to smallest available */
+ if (req->Size == 0)
+ req->Size = s->map_size;
+ align = (((s->features & SS_CAP_MEM_ALIGN) ||
+ (req->Attributes & WIN_STRICT_ALIGN)) ?
+ req->Size : s->map_size);
+ if (req->Size & (s->map_size-1))
+ return CS_BAD_SIZE;
+ if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) ||
+ (req->Base & (align-1)))
+ return CS_BAD_BASE;
+ if (req->Base)
+ align = 0;
+
+ /* Allocate system memory window */
+ for (w = 0; w < MAX_WIN; w++)
+ if (!(s->state & SOCKET_WIN_REQ(w))) break;
+ if (w == MAX_WIN)
+ return CS_OUT_OF_RESOURCE;
+
+ win = &s->win[w];
+ win->magic = WINDOW_MAGIC;
+ win->index = w;
+ win->handle = *handle;
+ win->sock = s;
+
+ if (!(s->features & SS_CAP_STATIC_MAP)) {
+ win->ctl.res = find_mem_region(req->Base, req->Size, align,
+ (req->Attributes & WIN_MAP_BELOW_1MB), s);
+ if (!win->ctl.res)
+ return CS_IN_USE;
+ }
+ (*handle)->state |= CLIENT_WIN_REQ(w);
+
+ /* Configure the socket controller */
+ win->ctl.map = w+1;
+ win->ctl.flags = 0;
+ win->ctl.speed = req->AccessSpeed;
+ if (req->Attributes & WIN_MEMORY_TYPE)
+ win->ctl.flags |= MAP_ATTRIB;
+ if (req->Attributes & WIN_ENABLE)
+ win->ctl.flags |= MAP_ACTIVE;
+ if (req->Attributes & WIN_DATA_WIDTH_16)
+ win->ctl.flags |= MAP_16BIT;
+ if (req->Attributes & WIN_USE_WAIT)
+ win->ctl.flags |= MAP_USE_WAIT;
+ win->ctl.card_start = 0;
+ if (s->ops->set_mem_map(s, &win->ctl) != 0)
+ return CS_BAD_ARGS;
+ s->state |= SOCKET_WIN_REQ(w);
+
+ /* Return window handle */
+ if (s->features & SS_CAP_STATIC_MAP) {
+ req->Base = win->ctl.static_start;
+ } else {
+ req->Base = win->ctl.res->start;
+ }
+ *wh = win;
+
+ return CS_SUCCESS;
+} /* request_window */
+
+/*======================================================================
+
+ I'm not sure which "reset" function this is supposed to use,
+ but for now, it uses the low-level interface's reset, not the
+ CIS register.
+
+======================================================================*/
int pccard_reset_card(struct pcmcia_socket *skt)
{
int ret;
-
+
cs_dbg(skt, 1, "resetting socket\n");
down(&skt->skt_sem);
@@ -778,14 +1757,17 @@ int pccard_reset_card(struct pcmcia_socket *skt)
} /* reset_card */
EXPORT_SYMBOL(pccard_reset_card);
+/*======================================================================
+
+ These shut down or wake up a socket. They are sort of user
+ initiated versions of the APM suspend and resume actions.
+
+======================================================================*/
-/* These shut down or wake up a socket. They are sort of user
- * initiated versions of the APM suspend and resume actions.
- */
int pcmcia_suspend_card(struct pcmcia_socket *skt)
{
int ret;
-
+
cs_dbg(skt, 1, "suspending socket\n");
down(&skt->skt_sem);
@@ -804,8 +1786,6 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt)
return ret;
} /* suspend_card */
-EXPORT_SYMBOL(pcmcia_suspend_card);
-
int pcmcia_resume_card(struct pcmcia_socket *skt)
{
@@ -829,10 +1809,13 @@ int pcmcia_resume_card(struct pcmcia_socket *skt)
return ret;
} /* resume_card */
-EXPORT_SYMBOL(pcmcia_resume_card);
+/*======================================================================
+
+ These handle user requests to eject or insert a card.
+
+======================================================================*/
-/* These handle user requests to eject or insert a card. */
int pcmcia_eject_card(struct pcmcia_socket *skt)
{
int ret;
@@ -859,8 +1842,6 @@ int pcmcia_eject_card(struct pcmcia_socket *skt)
return ret;
} /* eject_card */
-EXPORT_SYMBOL(pcmcia_eject_card);
-
int pcmcia_insert_card(struct pcmcia_socket *skt)
{
@@ -884,38 +1865,37 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
return ret;
} /* insert_card */
-EXPORT_SYMBOL(pcmcia_insert_card);
-
-
-static int pcmcia_socket_hotplug(struct class_device *dev, char **envp,
- int num_envp, char *buffer, int buffer_size)
-{
- struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev);
- int i = 0, length = 0;
-
- if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
- &length, "SOCKET_NO=%u", s->sock))
- return -ENOMEM;
-
- envp[i] = NULL;
- return 0;
-}
-
-
-static struct completion pcmcia_unload;
+/*======================================================================
-static void pcmcia_release_socket_class(struct class *data)
-{
- complete(&pcmcia_unload);
-}
+ OS-specific module glue goes here
+
+======================================================================*/
+/* in alpha order */
+EXPORT_SYMBOL(pcmcia_eject_card);
+EXPORT_SYMBOL(pcmcia_get_card_services_info);
+EXPORT_SYMBOL(pcmcia_get_mem_page);
+EXPORT_SYMBOL(pcmcia_insert_card);
+EXPORT_SYMBOL(pcmcia_map_mem_page);
+EXPORT_SYMBOL(pcmcia_modify_configuration);
+EXPORT_SYMBOL(pcmcia_release_configuration);
+EXPORT_SYMBOL(pcmcia_release_io);
+EXPORT_SYMBOL(pcmcia_release_irq);
+EXPORT_SYMBOL(pcmcia_release_window);
+EXPORT_SYMBOL(pcmcia_replace_cis);
+EXPORT_SYMBOL(pcmcia_request_configuration);
+EXPORT_SYMBOL(pcmcia_request_io);
+EXPORT_SYMBOL(pcmcia_request_irq);
+EXPORT_SYMBOL(pcmcia_request_window);
+EXPORT_SYMBOL(pcmcia_resume_card);
+EXPORT_SYMBOL(pcmcia_suspend_card);
+EXPORT_SYMBOL(dead_socket);
+EXPORT_SYMBOL(pcmcia_parse_events);
struct class pcmcia_socket_class = {
.name = "pcmcia_socket",
- .hotplug = pcmcia_socket_hotplug,
.release = pcmcia_release_socket,
- .class_release = pcmcia_release_socket_class,
};
EXPORT_SYMBOL(pcmcia_socket_class);
@@ -923,8 +1903,9 @@ EXPORT_SYMBOL(pcmcia_socket_class);
static int __init init_pcmcia_cs(void)
{
int ret;
+ printk(KERN_INFO "%s\n", release);
+ printk(KERN_INFO " %s\n", options);
- init_completion(&pcmcia_unload);
ret = class_register(&pcmcia_socket_class);
if (ret)
return (ret);
@@ -933,12 +1914,13 @@ static int __init init_pcmcia_cs(void)
static void __exit exit_pcmcia_cs(void)
{
- class_interface_unregister(&pccard_sysfs_interface);
- class_unregister(&pcmcia_socket_class);
-
- wait_for_completion(&pcmcia_unload);
+ printk(KERN_INFO "unloading Kernel Card Services\n");
+ class_interface_unregister(&pccard_sysfs_interface);
+ class_unregister(&pcmcia_socket_class);
}
subsys_initcall(init_pcmcia_cs);
module_exit(exit_pcmcia_cs);
+/*====================================================================*/
+
diff --git a/trunk/drivers/pcmcia/cs_internal.h b/trunk/drivers/pcmcia/cs_internal.h
index 0b4c18edfa49..7933a7db49d3 100644
--- a/trunk/drivers/pcmcia/cs_internal.h
+++ b/trunk/drivers/pcmcia/cs_internal.h
@@ -123,9 +123,9 @@ void cb_free(struct pcmcia_socket *s);
int read_cb_mem(struct pcmcia_socket *s, int space, u_int addr, u_int len, void *ptr);
/* In cistpl.c */
-int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr,
+int read_cis_mem(struct pcmcia_socket *s, int attr,
u_int addr, u_int len, void *ptr);
-void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr,
+void write_cis_mem(struct pcmcia_socket *s, int attr,
u_int addr, u_int len, void *ptr);
void release_cis_mem(struct pcmcia_socket *s);
void destroy_cis_cache(struct pcmcia_socket *s);
@@ -134,12 +134,13 @@ int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t
/* In rsrc_mgr */
void pcmcia_validate_mem(struct pcmcia_socket *s);
-struct resource *pcmcia_find_io_region(unsigned long base, int num, unsigned long align,
+struct resource *find_io_region(unsigned long base, int num, unsigned long align,
struct pcmcia_socket *s);
-int pcmcia_adjust_io_region(struct resource *res, unsigned long r_start,
+int adjust_io_region(struct resource *res, unsigned long r_start,
unsigned long r_end, struct pcmcia_socket *s);
-struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align,
+struct resource *find_mem_region(u_long base, u_long num, u_long align,
int low, struct pcmcia_socket *s);
+int adjust_resource_info(client_handle_t handle, adjust_t *adj);
void release_resource_db(struct pcmcia_socket *s);
/* In socket_sysfs.c */
@@ -158,7 +159,7 @@ int pccard_access_configuration_register(struct pcmcia_socket *s, unsigned int f
struct pcmcia_callback{
struct module *owner;
int (*event) (struct pcmcia_socket *s, event_t event, int priority);
- void (*requery) (struct pcmcia_socket *s);
+ int (*resources_done) (struct pcmcia_socket *s);
};
int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c);
diff --git a/trunk/drivers/pcmcia/ds.c b/trunk/drivers/pcmcia/ds.c
index cabddd49f6ff..569e55feecfd 100644
--- a/trunk/drivers/pcmcia/ds.c
+++ b/trunk/drivers/pcmcia/ds.c
@@ -10,29 +10,44 @@
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* (C) 1999 David A. Hinds
- * (C) 2003 - 2005 Dominik Brodowski
+ * (C) 2003 - 2004 Dominik Brodowski
*/
#include
-#include
#include
+#include
#include
+#include
+#include
+#include
#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
#include
#include
+#include
#include
-#include
-#include
+
+#include
#define IN_CARD_SERVICES
+#include
#include