diff --git a/[refs] b/[refs]
index 44b7c16bb956..ba0c12008839 100644
--- a/[refs]
+++ b/[refs]
@@ -1,2 +1,2 @@
---
-refs/heads/master: e33f6635da037ed4d2634ee6bdf5c4d601946c18
+refs/heads/master: 0ea9d70df8f8be741ee0525490370de06163d2de
diff --git a/trunk/Documentation/BUG-HUNTING b/trunk/Documentation/BUG-HUNTING
index 65022a87bf17..6c816751b868 100644
--- a/trunk/Documentation/BUG-HUNTING
+++ b/trunk/Documentation/BUG-HUNTING
@@ -214,23 +214,6 @@ And recompile the kernel with CONFIG_DEBUG_INFO enabled:
gdb vmlinux
(gdb) p vt_ioctl
(gdb) l *(0x
+ 0xda8)
-or, as one command
- (gdb) l *(vt_ioctl + 0xda8)
-
-If you have a call trace, such as :-
->Call Trace:
-> [] :jbd:log_wait_commit+0xa3/0xf5
-> [] autoremove_wake_function+0x0/0x2e
-> [] :jbd:journal_stop+0x1be/0x1ee
-> ...
-this shows the problem in the :jbd: module. You can load that module in gdb
-and list the relevant code.
- gdb fs/jbd/jbd.ko
- (gdb) p log_wait_commit
- (gdb) l *(0x + 0xa3)
-or
- (gdb) l *(log_wait_commit + 0xa3)
-
Another very useful option of the Kernel Hacking section in menuconfig is
Debug memory allocations. This will help you see whether data has been
diff --git a/trunk/Documentation/DocBook/kernel-locking.tmpl b/trunk/Documentation/DocBook/kernel-locking.tmpl
index 2e9d6b41f034..01825ee7db64 100644
--- a/trunk/Documentation/DocBook/kernel-locking.tmpl
+++ b/trunk/Documentation/DocBook/kernel-locking.tmpl
@@ -717,7 +717,7 @@ used, and when it gets full, throws out the least used one.
For our first example, we assume that all operations are in user
context (ie. from system calls), so we can sleep. This means we can
-use a mutex to protect the cache and all the objects within
+use a semaphore to protect the cache and all the objects within
it. Here's the code:
@@ -725,7 +725,7 @@ it. Here's the code:
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/string.h>
-#include <linux/mutex.h>
+#include <asm/semaphore.h>
#include <asm/errno.h>
struct object
@@ -737,7 +737,7 @@ struct object
};
/* Protects the cache, cache_num, and the objects within it */
-static DEFINE_MUTEX(cache_lock);
+static DECLARE_MUTEX(cache_lock);
static LIST_HEAD(cache);
static unsigned int cache_num = 0;
#define MAX_CACHE_SIZE 10
@@ -789,17 +789,17 @@ int cache_add(int id, const char *name)
obj->id = id;
obj->popularity = 0;
- mutex_lock(&cache_lock);
+ down(&cache_lock);
__cache_add(obj);
- mutex_unlock(&cache_lock);
+ up(&cache_lock);
return 0;
}
void cache_delete(int id)
{
- mutex_lock(&cache_lock);
+ down(&cache_lock);
__cache_delete(__cache_find(id));
- mutex_unlock(&cache_lock);
+ up(&cache_lock);
}
int cache_find(int id, char *name)
@@ -807,13 +807,13 @@ int cache_find(int id, char *name)
struct object *obj;
int ret = -ENOENT;
- mutex_lock(&cache_lock);
+ down(&cache_lock);
obj = __cache_find(id);
if (obj) {
ret = 0;
strcpy(name, obj->name);
}
- mutex_unlock(&cache_lock);
+ up(&cache_lock);
return ret;
}
@@ -853,7 +853,7 @@ The change is shown below, in standard patch format: the
int popularity;
};
--static DEFINE_MUTEX(cache_lock);
+-static DECLARE_MUTEX(cache_lock);
+static spinlock_t cache_lock = SPIN_LOCK_UNLOCKED;
static LIST_HEAD(cache);
static unsigned int cache_num = 0;
@@ -870,22 +870,22 @@ The change is shown below, in standard patch format: the
obj->id = id;
obj->popularity = 0;
-- mutex_lock(&cache_lock);
+- down(&cache_lock);
+ spin_lock_irqsave(&cache_lock, flags);
__cache_add(obj);
-- mutex_unlock(&cache_lock);
+- up(&cache_lock);
+ spin_unlock_irqrestore(&cache_lock, flags);
return 0;
}
void cache_delete(int id)
{
-- mutex_lock(&cache_lock);
+- down(&cache_lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&cache_lock, flags);
__cache_delete(__cache_find(id));
-- mutex_unlock(&cache_lock);
+- up(&cache_lock);
+ spin_unlock_irqrestore(&cache_lock, flags);
}
@@ -895,14 +895,14 @@ The change is shown below, in standard patch format: the
int ret = -ENOENT;
+ unsigned long flags;
-- mutex_lock(&cache_lock);
+- down(&cache_lock);
+ spin_lock_irqsave(&cache_lock, flags);
obj = __cache_find(id);
if (obj) {
ret = 0;
strcpy(name, obj->name);
}
-- mutex_unlock(&cache_lock);
+- up(&cache_lock);
+ spin_unlock_irqrestore(&cache_lock, flags);
return ret;
}
diff --git a/trunk/Documentation/fb/deferred_io.txt b/trunk/Documentation/fb/deferred_io.txt
index 748328370250..63883a892120 100644
--- a/trunk/Documentation/fb/deferred_io.txt
+++ b/trunk/Documentation/fb/deferred_io.txt
@@ -7,10 +7,10 @@ IO. The following example may be a useful explanation of how one such setup
works:
- userspace app like Xfbdev mmaps framebuffer
-- deferred IO and driver sets up fault and page_mkwrite handlers
+- deferred IO and driver sets up nopage and page_mkwrite handlers
- userspace app tries to write to mmaped vaddress
-- we get pagefault and reach fault handler
-- fault handler finds and returns physical page
+- we get pagefault and reach nopage handler
+- nopage handler finds and returns physical page
- we get page_mkwrite where we add this page to a list
- schedule a workqueue task to be run after a delay
- app continues writing to that page with no additional cost. this is
diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt
index 68ce1300a360..a7d9d179131a 100644
--- a/trunk/Documentation/feature-removal-schedule.txt
+++ b/trunk/Documentation/feature-removal-schedule.txt
@@ -208,6 +208,13 @@ Who: Randy Dunlap
---------------------------
+What: drivers depending on OSS_OBSOLETE
+When: options in 2.6.23, code in 2.6.25
+Why: obsolete OSS drivers
+Who: Adrian Bunk
+
+---------------------------
+
What: libata spindown skipping and warning
When: Dec 2008
Why: Some halt(8) implementations synchronize caches for and spin
diff --git a/trunk/Documentation/filesystems/proc.txt b/trunk/Documentation/filesystems/proc.txt
index 5681e2fa1496..e2799b5fafea 100644
--- a/trunk/Documentation/filesystems/proc.txt
+++ b/trunk/Documentation/filesystems/proc.txt
@@ -1029,14 +1029,6 @@ nr_inodes
Denotes the number of inodes the system has allocated. This number will
grow and shrink dynamically.
-nr_open
--------
-
-Denotes the maximum number of file-handles a process can
-allocate. Default value is 1024*1024 (1048576) which should be
-enough for most machines. Actual limit depends on RLIMIT_NOFILE
-resource limit.
-
nr_free_inodes
--------------
diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt
index 8fd5aa40585f..9ad4e6fc56fd 100644
--- a/trunk/Documentation/kernel-parameters.txt
+++ b/trunk/Documentation/kernel-parameters.txt
@@ -780,9 +780,6 @@ and is between 256 and 4096 characters. It is defined in the file
loop use the MONITOR/MWAIT idle loop anyways. Performance should be the same
as idle=poll.
- ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem
- Claim all unknown PCI IDE storage controllers.
-
ignore_loglevel [KNL]
Ignore loglevel setting - this will print /all/
kernel messages to the console. Useful for debugging.
diff --git a/trunk/Documentation/kprobes.txt b/trunk/Documentation/kprobes.txt
index 30c101761d0d..53a63890aea4 100644
--- a/trunk/Documentation/kprobes.txt
+++ b/trunk/Documentation/kprobes.txt
@@ -96,9 +96,7 @@ or in registers (e.g., for x86_64 or for an i386 fastcall function).
The jprobe will work in either case, so long as the handler's
prototype matches that of the probed function.
-1.3 Return Probes
-
-1.3.1 How Does a Return Probe Work?
+1.3 How Does a Return Probe Work?
When you call register_kretprobe(), Kprobes establishes a kprobe at
the entry to the function. When the probed function is called and this
@@ -109,9 +107,9 @@ At boot time, Kprobes registers a kprobe at the trampoline.
When the probed function executes its return instruction, control
passes to the trampoline and that probe is hit. Kprobes' trampoline
-handler calls the user-specified return handler associated with the
-kretprobe, then sets the saved instruction pointer to the saved return
-address, and that's where execution resumes upon return from the trap.
+handler calls the user-specified handler associated with the kretprobe,
+then sets the saved instruction pointer to the saved return address,
+and that's where execution resumes upon return from the trap.
While the probed function is executing, its return address is
stored in an object of type kretprobe_instance. Before calling
@@ -133,30 +131,6 @@ zero when the return probe is registered, and is incremented every
time the probed function is entered but there is no kretprobe_instance
object available for establishing the return probe.
-1.3.2 Kretprobe entry-handler
-
-Kretprobes also provides an optional user-specified handler which runs
-on function entry. This handler is specified by setting the entry_handler
-field of the kretprobe struct. Whenever the kprobe placed by kretprobe at the
-function entry is hit, the user-defined entry_handler, if any, is invoked.
-If the entry_handler returns 0 (success) then a corresponding return handler
-is guaranteed to be called upon function return. If the entry_handler
-returns a non-zero error then Kprobes leaves the return address as is, and
-the kretprobe has no further effect for that particular function instance.
-
-Multiple entry and return handler invocations are matched using the unique
-kretprobe_instance object associated with them. Additionally, a user
-may also specify per return-instance private data to be part of each
-kretprobe_instance object. This is especially useful when sharing private
-data between corresponding user entry and return handlers. The size of each
-private data object can be specified at kretprobe registration time by
-setting the data_size field of the kretprobe struct. This data can be
-accessed through the data field of each kretprobe_instance object.
-
-In case probed function is entered but there is no kretprobe_instance
-object available, then in addition to incrementing the nmissed count,
-the user entry_handler invocation is also skipped.
-
2. Architectures Supported
Kprobes, jprobes, and return probes are implemented on the following
@@ -300,8 +274,6 @@ of interest:
- ret_addr: the return address
- rp: points to the corresponding kretprobe object
- task: points to the corresponding task struct
-- data: points to per return-instance private data; see "Kretprobe
- entry-handler" for details.
The regs_return_value(regs) macro provides a simple abstraction to
extract the return value from the appropriate register as defined by
@@ -584,52 +556,23 @@ report failed calls to sys_open().
#include
#include
#include
-#include
-
-/* per-instance private data */
-struct my_data {
- ktime_t entry_stamp;
-};
static const char *probed_func = "sys_open";
-/* Timestamp function entry. */
-static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
-{
- struct my_data *data;
-
- if(!current->mm)
- return 1; /* skip kernel threads */
-
- data = (struct my_data *)ri->data;
- data->entry_stamp = ktime_get();
- return 0;
-}
-
-/* If the probed function failed, log the return value and duration.
- * Duration may turn out to be zero consistently, depending upon the
- * granularity of time accounting on the platform. */
-static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+/* Return-probe handler: If the probed function fails, log the return value. */
+static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
int retval = regs_return_value(regs);
- struct my_data *data = (struct my_data *)ri->data;
- s64 delta;
- ktime_t now;
-
if (retval < 0) {
- now = ktime_get();
- delta = ktime_to_ns(ktime_sub(now, data->entry_stamp));
- printk("%s: return val = %d (duration = %lld ns)\n",
- probed_func, retval, delta);
+ printk("%s returns %d\n", probed_func, retval);
}
return 0;
}
static struct kretprobe my_kretprobe = {
- .handler = return_handler,
- .entry_handler = entry_handler,
- .data_size = sizeof(struct my_data),
- .maxactive = 20, /* probe up to 20 instances concurrently */
+ .handler = ret_handler,
+ /* Probe up to 20 instances concurrently. */
+ .maxactive = 20
};
static int __init kretprobe_init(void)
@@ -641,7 +584,7 @@ static int __init kretprobe_init(void)
printk("register_kretprobe failed, returned %d\n", ret);
return -1;
}
- printk("Kretprobe active on %s\n", my_kretprobe.kp.symbol_name);
+ printk("Planted return probe at %p\n", my_kretprobe.kp.addr);
return 0;
}
@@ -651,7 +594,7 @@ static void __exit kretprobe_exit(void)
printk("kretprobe unregistered\n");
/* nmissed > 0 suggests that maxactive was set too low. */
printk("Missed probing %d instances of %s\n",
- my_kretprobe.nmissed, probed_func);
+ my_kretprobe.nmissed, probed_func);
}
module_init(kretprobe_init)
diff --git a/trunk/Documentation/kref.txt b/trunk/Documentation/kref.txt
index 130b6e87aa7e..f38b59d00c63 100644
--- a/trunk/Documentation/kref.txt
+++ b/trunk/Documentation/kref.txt
@@ -141,10 +141,10 @@ The last rule (rule 3) is the nastiest one to handle. Say, for
instance, you have a list of items that are each kref-ed, and you wish
to get the first one. You can't just pull the first item off the list
and kref_get() it. That violates rule 3 because you are not already
-holding a valid pointer. You must add a mutex (or some other lock).
-For instance:
+holding a valid pointer. You must add locks or semaphores. For
+instance:
-static DEFINE_MUTEX(mutex);
+static DECLARE_MUTEX(sem);
static LIST_HEAD(q);
struct my_data
{
@@ -155,12 +155,12 @@ struct my_data
static struct my_data *get_entry()
{
struct my_data *entry = NULL;
- mutex_lock(&mutex);
+ down(&sem);
if (!list_empty(&q)) {
entry = container_of(q.next, struct my_q_entry, link);
kref_get(&entry->refcount);
}
- mutex_unlock(&mutex);
+ up(&sem);
return entry;
}
@@ -174,9 +174,9 @@ static void release_entry(struct kref *ref)
static void put_entry(struct my_data *entry)
{
- mutex_lock(&mutex);
+ down(&sem);
kref_put(&entry->refcount, release_entry);
- mutex_unlock(&mutex);
+ up(&sem);
}
The kref_put() return value is useful if you do not want to hold the
@@ -191,13 +191,13 @@ static void release_entry(struct kref *ref)
static void put_entry(struct my_data *entry)
{
- mutex_lock(&mutex);
+ down(&sem);
if (kref_put(&entry->refcount, release_entry)) {
list_del(&entry->link);
- mutex_unlock(&mutex);
+ up(&sem);
kfree(entry);
} else
- mutex_unlock(&mutex);
+ up(&sem);
}
This is really more useful if you have to call other routines as part
diff --git a/trunk/Documentation/md.txt b/trunk/Documentation/md.txt
index 396cdd982c26..5818628207b5 100644
--- a/trunk/Documentation/md.txt
+++ b/trunk/Documentation/md.txt
@@ -416,16 +416,6 @@ also have
sectors in total that could need to be processed. The two
numbers are separated by a '/' thus effectively showing one
value, a fraction of the process that is complete.
- A 'select' on this attribute will return when resync completes,
- when it reaches the current sync_max (below) and possibly at
- other times.
-
- sync_max
- This is a number of sectors at which point a resync/recovery
- process will pause. When a resync is active, the value can
- only ever be increased, never decreased. The value of 'max'
- effectively disables the limit.
-
sync_speed
This shows the current actual speed, in K/sec, of the current
diff --git a/trunk/Documentation/rtc.txt b/trunk/Documentation/rtc.txt
index 8deffcd68cb8..e20b19c1b60d 100644
--- a/trunk/Documentation/rtc.txt
+++ b/trunk/Documentation/rtc.txt
@@ -182,8 +182,8 @@ driver returns ENOIOCTLCMD. Some common examples:
since the frequency is stored in the irq_freq member of the rtc_device
structure. Your driver needs to initialize the irq_freq member during
init. Make sure you check the requested frequency is in range of your
- hardware in the irq_set_freq function. If it isn't, return -EINVAL. If
- you cannot actually change the frequency, do not define irq_set_freq.
+ hardware in the irq_set_freq function. If you cannot actually change
+ the frequency, just return -ENOTTY.
If all else fails, check out the rtc-test.c driver!
@@ -268,8 +268,8 @@ int main(int argc, char **argv)
/* This read will block */
retval = read(fd, &data, sizeof(unsigned long));
if (retval == -1) {
- perror("read");
- exit(errno);
+ perror("read");
+ exit(errno);
}
fprintf(stderr, " %d",i);
fflush(stderr);
@@ -326,11 +326,11 @@ test_READ:
rtc_tm.tm_sec %= 60;
rtc_tm.tm_min++;
}
- if (rtc_tm.tm_min == 60) {
+ if (rtc_tm.tm_min == 60) {
rtc_tm.tm_min = 0;
rtc_tm.tm_hour++;
}
- if (rtc_tm.tm_hour == 24)
+ if (rtc_tm.tm_hour == 24)
rtc_tm.tm_hour = 0;
retval = ioctl(fd, RTC_ALM_SET, &rtc_tm);
@@ -407,8 +407,8 @@ test_PIE:
"\n...Periodic IRQ rate is fixed\n");
goto done;
}
- perror("RTC_IRQP_SET ioctl");
- exit(errno);
+ perror("RTC_IRQP_SET ioctl");
+ exit(errno);
}
fprintf(stderr, "\n%ldHz:\t", tmp);
@@ -417,27 +417,27 @@ test_PIE:
/* Enable periodic interrupts */
retval = ioctl(fd, RTC_PIE_ON, 0);
if (retval == -1) {
- perror("RTC_PIE_ON ioctl");
- exit(errno);
+ perror("RTC_PIE_ON ioctl");
+ exit(errno);
}
for (i=1; i<21; i++) {
- /* This blocks */
- retval = read(fd, &data, sizeof(unsigned long));
- if (retval == -1) {
- perror("read");
- exit(errno);
- }
- fprintf(stderr, " %d",i);
- fflush(stderr);
- irqcount++;
+ /* This blocks */
+ retval = read(fd, &data, sizeof(unsigned long));
+ if (retval == -1) {
+ perror("read");
+ exit(errno);
+ }
+ fprintf(stderr, " %d",i);
+ fflush(stderr);
+ irqcount++;
}
/* Disable periodic interrupts */
retval = ioctl(fd, RTC_PIE_OFF, 0);
if (retval == -1) {
- perror("RTC_PIE_OFF ioctl");
- exit(errno);
+ perror("RTC_PIE_OFF ioctl");
+ exit(errno);
}
}
diff --git a/trunk/Documentation/sysctl/fs.txt b/trunk/Documentation/sysctl/fs.txt
index f99254327ae5..aa986a35e994 100644
--- a/trunk/Documentation/sysctl/fs.txt
+++ b/trunk/Documentation/sysctl/fs.txt
@@ -23,7 +23,6 @@ Currently, these files are in /proc/sys/fs:
- inode-max
- inode-nr
- inode-state
-- nr_open
- overflowuid
- overflowgid
- suid_dumpable
@@ -92,15 +91,6 @@ usage of file handles and you don't need to increase the maximum.
==============================================================
-nr_open:
-
-This denotes the maximum number of file-handles a process can
-allocate. Default value is 1024*1024 (1048576) which should be
-enough for most machines. Actual limit depends on RLIMIT_NOFILE
-resource limit.
-
-==============================================================
-
inode-max, inode-nr & inode-state:
As with file handles, the kernel allocates the inode structures
diff --git a/trunk/Documentation/unaligned-memory-access.txt b/trunk/Documentation/unaligned-memory-access.txt
deleted file mode 100644
index 6223eace3c09..000000000000
--- a/trunk/Documentation/unaligned-memory-access.txt
+++ /dev/null
@@ -1,226 +0,0 @@
-UNALIGNED MEMORY ACCESSES
-=========================
-
-Linux runs on a wide variety of architectures which have varying behaviour
-when it comes to memory access. This document presents some details about
-unaligned accesses, why you need to write code that doesn't cause them,
-and how to write such code!
-
-
-The definition of an unaligned access
-=====================================
-
-Unaligned memory accesses occur when you try to read N bytes of data starting
-from an address that is not evenly divisible by N (i.e. addr % N != 0).
-For example, reading 4 bytes of data from address 0x10004 is fine, but
-reading 4 bytes of data from address 0x10005 would be an unaligned memory
-access.
-
-The above may seem a little vague, as memory access can happen in different
-ways. The context here is at the machine code level: certain instructions read
-or write a number of bytes to or from memory (e.g. movb, movw, movl in x86
-assembly). As will become clear, it is relatively easy to spot C statements
-which will compile to multiple-byte memory access instructions, namely when
-dealing with types such as u16, u32 and u64.
-
-
-Natural alignment
-=================
-
-The rule mentioned above forms what we refer to as natural alignment:
-When accessing N bytes of memory, the base memory address must be evenly
-divisible by N, i.e. addr % N == 0.
-
-When writing code, assume the target architecture has natural alignment
-requirements.
-
-In reality, only a few architectures require natural alignment on all sizes
-of memory access. However, we must consider ALL supported architectures;
-writing code that satisfies natural alignment requirements is the easiest way
-to achieve full portability.
-
-
-Why unaligned access is bad
-===========================
-
-The effects of performing an unaligned memory access vary from architecture
-to architecture. It would be easy to write a whole document on the differences
-here; a summary of the common scenarios is presented below:
-
- - Some architectures are able to perform unaligned memory accesses
- transparently, but there is usually a significant performance cost.
- - Some architectures raise processor exceptions when unaligned accesses
- happen. The exception handler is able to correct the unaligned access,
- at significant cost to performance.
- - Some architectures raise processor exceptions when unaligned accesses
- happen, but the exceptions do not contain enough information for the
- unaligned access to be corrected.
- - Some architectures are not capable of unaligned memory access, but will
- silently perform a different memory access to the one that was requested,
- resulting a a subtle code bug that is hard to detect!
-
-It should be obvious from the above that if your code causes unaligned
-memory accesses to happen, your code will not work correctly on certain
-platforms and will cause performance problems on others.
-
-
-Code that does not cause unaligned access
-=========================================
-
-At first, the concepts above may seem a little hard to relate to actual
-coding practice. After all, you don't have a great deal of control over
-memory addresses of certain variables, etc.
-
-Fortunately things are not too complex, as in most cases, the compiler
-ensures that things will work for you. For example, take the following
-structure:
-
- struct foo {
- u16 field1;
- u32 field2;
- u8 field3;
- };
-
-Let us assume that an instance of the above structure resides in memory
-starting at address 0x10000. With a basic level of understanding, it would
-not be unreasonable to expect that accessing field2 would cause an unaligned
-access. You'd be expecting field2 to be located at offset 2 bytes into the
-structure, i.e. address 0x10002, but that address is not evenly divisible
-by 4 (remember, we're reading a 4 byte value here).
-
-Fortunately, the compiler understands the alignment constraints, so in the
-above case it would insert 2 bytes of padding in between field1 and field2.
-Therefore, for standard structure types you can always rely on the compiler
-to pad structures so that accesses to fields are suitably aligned (assuming
-you do not cast the field to a type of different length).
-
-Similarly, you can also rely on the compiler to align variables and function
-parameters to a naturally aligned scheme, based on the size of the type of
-the variable.
-
-At this point, it should be clear that accessing a single byte (u8 or char)
-will never cause an unaligned access, because all memory addresses are evenly
-divisible by one.
-
-On a related topic, with the above considerations in mind you may observe
-that you could reorder the fields in the structure in order to place fields
-where padding would otherwise be inserted, and hence reduce the overall
-resident memory size of structure instances. The optimal layout of the
-above example is:
-
- struct foo {
- u32 field2;
- u16 field1;
- u8 field3;
- };
-
-For a natural alignment scheme, the compiler would only have to add a single
-byte of padding at the end of the structure. This padding is added in order
-to satisfy alignment constraints for arrays of these structures.
-
-Another point worth mentioning is the use of __attribute__((packed)) on a
-structure type. This GCC-specific attribute tells the compiler never to
-insert any padding within structures, useful when you want to use a C struct
-to represent some data that comes in a fixed arrangement 'off the wire'.
-
-You might be inclined to believe that usage of this attribute can easily
-lead to unaligned accesses when accessing fields that do not satisfy
-architectural alignment requirements. However, again, the compiler is aware
-of the alignment constraints and will generate extra instructions to perform
-the memory access in a way that does not cause unaligned access. Of course,
-the extra instructions obviously cause a loss in performance compared to the
-non-packed case, so the packed attribute should only be used when avoiding
-structure padding is of importance.
-
-
-Code that causes unaligned access
-=================================
-
-With the above in mind, let's move onto a real life example of a function
-that can cause an unaligned memory access. The following function adapted
-from include/linux/etherdevice.h is an optimized routine to compare two
-ethernet MAC addresses for equality.
-
-unsigned int compare_ether_addr(const u8 *addr1, const u8 *addr2)
-{
- const u16 *a = (const u16 *) addr1;
- const u16 *b = (const u16 *) addr2;
- return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;
-}
-
-In the above function, the reference to a[0] causes 2 bytes (16 bits) to
-be read from memory starting at address addr1. Think about what would happen
-if addr1 was an odd address such as 0x10003. (Hint: it'd be an unaligned
-access.)
-
-Despite the potential unaligned access problems with the above function, it
-is included in the kernel anyway but is understood to only work on
-16-bit-aligned addresses. It is up to the caller to ensure this alignment or
-not use this function at all. This alignment-unsafe function is still useful
-as it is a decent optimization for the cases when you can ensure alignment,
-which is true almost all of the time in ethernet networking context.
-
-
-Here is another example of some code that could cause unaligned accesses:
- void myfunc(u8 *data, u32 value)
- {
- [...]
- *((u32 *) data) = cpu_to_le32(value);
- [...]
- }
-
-This code will cause unaligned accesses every time the data parameter points
-to an address that is not evenly divisible by 4.
-
-In summary, the 2 main scenarios where you may run into unaligned access
-problems involve:
- 1. Casting variables to types of different lengths
- 2. Pointer arithmetic followed by access to at least 2 bytes of data
-
-
-Avoiding unaligned accesses
-===========================
-
-The easiest way to avoid unaligned access is to use the get_unaligned() and
-put_unaligned() macros provided by the header file.
-
-Going back to an earlier example of code that potentially causes unaligned
-access:
-
- void myfunc(u8 *data, u32 value)
- {
- [...]
- *((u32 *) data) = cpu_to_le32(value);
- [...]
- }
-
-To avoid the unaligned memory access, you would rewrite it as follows:
-
- void myfunc(u8 *data, u32 value)
- {
- [...]
- value = cpu_to_le32(value);
- put_unaligned(value, (u32 *) data);
- [...]
- }
-
-The get_unaligned() macro works similarly. Assuming 'data' is a pointer to
-memory and you wish to avoid unaligned access, its usage is as follows:
-
- u32 value = get_unaligned((u32 *) data);
-
-These macros work work for memory accesses of any length (not just 32 bits as
-in the examples above). Be aware that when compared to standard access of
-aligned memory, using these macros to access unaligned memory can be costly in
-terms of performance.
-
-If use of such macros is not convenient, another option is to use memcpy(),
-where the source or destination (or both) are of type u8* or unsigned char*.
-Due to the byte-wise nature of this operation, unaligned accesses are avoided.
-
---
-Author: Daniel Drake
-With help from: Alan Cox, Avuton Olrich, Heikki Orsila, Jan Engelhardt,
-Johannes Berg, Kyle McMartin, Kyle Moffett, Randy Dunlap, Robert Hancock,
-Uli Kunitz, Vadim Lobanov
-
diff --git a/trunk/Documentation/w1/masters/00-INDEX b/trunk/Documentation/w1/masters/00-INDEX
index 7b0ceaaad7af..752613c4cea2 100644
--- a/trunk/Documentation/w1/masters/00-INDEX
+++ b/trunk/Documentation/w1/masters/00-INDEX
@@ -4,5 +4,3 @@ ds2482
- The Maxim/Dallas Semiconductor DS2482 provides 1-wire busses.
ds2490
- The Maxim/Dallas Semiconductor DS2490 builds USB <-> W1 bridges.
-w1-gpio
- - GPIO 1-wire bus master driver.
diff --git a/trunk/Documentation/w1/masters/w1-gpio b/trunk/Documentation/w1/masters/w1-gpio
deleted file mode 100644
index af5d3b4aa851..000000000000
--- a/trunk/Documentation/w1/masters/w1-gpio
+++ /dev/null
@@ -1,33 +0,0 @@
-Kernel driver w1-gpio
-=====================
-
-Author: Ville Syrjala
-
-
-Description
------------
-
-GPIO 1-wire bus master driver. The driver uses the GPIO API to control the
-wire and the GPIO pin can be specified using platform data.
-
-
-Example (mach-at91)
--------------------
-
-#include
-
-static struct w1_gpio_platform_data foo_w1_gpio_pdata = {
- .pin = AT91_PIN_PB20,
- .is_open_drain = 1,
-};
-
-static struct platform_device foo_w1_device = {
- .name = "w1-gpio",
- .id = -1,
- .dev.platform_data = &foo_w1_gpio_pdata,
-};
-
-...
- at91_set_GPIO_periph(foo_w1_gpio_pdata.pin, 1);
- at91_set_multi_drive(foo_w1_gpio_pdata.pin, 1);
- platform_device_register(&foo_w1_device);
diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS
index c5325d2bb86d..4f3da8b56979 100644
--- a/trunk/MAINTAINERS
+++ b/trunk/MAINTAINERS
@@ -338,12 +338,13 @@ S: Maintained for 2.4; PCI support for 2.6.
AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER
P: Thomas Dahlmann
M: thomas.dahlmann@amd.com
-L: info-linux@geode.amd.com (subscribers-only)
+L: info-linux@geode.amd.com
S: Supported
AMD GEODE PROCESSOR/CHIPSET SUPPORT
P: Jordan Crouse
-L: info-linux@geode.amd.com (subscribers-only)
+M: info-linux@geode.amd.com
+L: info-linux@geode.amd.com
W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
S: Supported
@@ -840,12 +841,6 @@ L: linux-kernel@vger.kernel.org
T: git kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git
S: Maintained
-BLOCK2MTD DRIVER
-P: Joern Engel
-M: joern@lazybastard.org
-L: linux-mtd@lists.infradead.org
-S: Maintained
-
BLUETOOTH SUBSYSTEM
P: Marcel Holtmann
M: marcel@holtmann.org
@@ -3036,8 +3031,8 @@ L: linux-abi-devel@lists.sourceforge.net
S: Maintained
PHRAM MTD DRIVER
-P: Joern Engel
-M: joern@lazybastard.org
+P: Jörn Engel
+M: joern@wh.fh-wedel.de
L: linux-mtd@lists.infradead.org
S: Maintained
@@ -3861,12 +3856,6 @@ M: oliver@neukum.name
L: linux-usb@vger.kernel.org
S: Maintained
-USB AUERSWALD DRIVER
-P: Wolfgang Muees
-M: wolfgang@iksw-muees.de
-L: linux-usb@vger.kernel.org
-S: Maintained
-
USB BLOCK DRIVER (UB ub)
P: Pete Zaitcev
M: zaitcev@redhat.com
@@ -4017,6 +4006,12 @@ S: Maintained
W: http://geocities.com/i0xox0i
W: http://firstlight.net/cvs
+USB AUERSWALD DRIVER
+P: Wolfgang Muees
+M: wolfgang@iksw-muees.de
+L: linux-usb@vger.kernel.org
+S: Maintained
+
USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER
P: Gary Brubaker
M: xavyer@ix.netcom.com
diff --git a/trunk/arch/alpha/Kconfig.debug b/trunk/arch/alpha/Kconfig.debug
index 3f6265f2d9d4..f45f28cc10da 100644
--- a/trunk/arch/alpha/Kconfig.debug
+++ b/trunk/arch/alpha/Kconfig.debug
@@ -7,6 +7,15 @@ config EARLY_PRINTK
depends on ALPHA_GENERIC || ALPHA_SRM
default y
+config DEBUG_RWLOCK
+ bool "Read-write spinlock debugging"
+ depends on DEBUG_KERNEL
+ help
+ If you say Y here then read-write lock processing will count how many
+ times it has tried to get the lock and issue an error message after
+ too many attempts. If you suspect a rwlock problem or a kernel
+ hacker asks for this option then say Y. Otherwise say N.
+
config ALPHA_LEGACY_START_ADDRESS
bool "Legacy kernel start address"
depends on ALPHA_GENERIC
diff --git a/trunk/arch/alpha/defconfig b/trunk/arch/alpha/defconfig
index e43f68fd66b0..6da9c3dbde44 100644
--- a/trunk/arch/alpha/defconfig
+++ b/trunk/arch/alpha/defconfig
@@ -882,6 +882,7 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_SPINLOCK is not set
CONFIG_DEBUG_INFO=y
CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_RWLOCK is not set
# CONFIG_DEBUG_SEMAPHORE is not set
CONFIG_ALPHA_LEGACY_START_ADDRESS=y
CONFIG_MATHEMU=y
diff --git a/trunk/arch/alpha/kernel/osf_sys.c b/trunk/arch/alpha/kernel/osf_sys.c
index 72f9a619a66d..6413c5f23226 100644
--- a/trunk/arch/alpha/kernel/osf_sys.c
+++ b/trunk/arch/alpha/kernel/osf_sys.c
@@ -430,7 +430,7 @@ sys_getpagesize(void)
asmlinkage unsigned long
sys_getdtablesize(void)
{
- return sysctl_nr_open;
+ return NR_OPEN;
}
/*
diff --git a/trunk/arch/alpha/kernel/smp.c b/trunk/arch/alpha/kernel/smp.c
index 63c2073401ee..f4ab233201b2 100644
--- a/trunk/arch/alpha/kernel/smp.c
+++ b/trunk/arch/alpha/kernel/smp.c
@@ -77,6 +77,10 @@ int smp_num_probed; /* Internal processor count */
int smp_num_cpus = 1; /* Number that came online. */
EXPORT_SYMBOL(smp_num_cpus);
+extern void calibrate_delay(void);
+
+
+
/*
* Called by both boot and secondaries to move global data into
* per-processor storage.
diff --git a/trunk/arch/arm/mach-at91/board-sam9261ek.c b/trunk/arch/arm/mach-at91/board-sam9261ek.c
index 0ce38dfa6ebe..aa29ea58ca09 100644
--- a/trunk/arch/arm/mach-at91/board-sam9261ek.c
+++ b/trunk/arch/arm/mach-at91/board-sam9261ek.c
@@ -383,7 +383,6 @@ static void at91_lcdc_tft_power_control(int on)
}
static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
- .lcdcon_is_backlight = true,
.default_bpp = 16,
.default_dmacon = ATMEL_LCDC_DMAEN,
.default_lcdcon2 = AT91SAM9261_DEFAULT_TFT_LCDCON2,
diff --git a/trunk/arch/arm/mach-at91/board-sam9263ek.c b/trunk/arch/arm/mach-at91/board-sam9263ek.c
index 38313abef657..f09347a86e71 100644
--- a/trunk/arch/arm/mach-at91/board-sam9263ek.c
+++ b/trunk/arch/arm/mach-at91/board-sam9263ek.c
@@ -253,7 +253,6 @@ static void at91_lcdc_power_control(int on)
/* Driver datas */
static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
- .lcdcon_is_backlight = true,
.default_bpp = 16,
.default_dmacon = ATMEL_LCDC_DMAEN,
.default_lcdcon2 = AT91SAM9263_DEFAULT_LCDCON2,
diff --git a/trunk/arch/avr32/kernel/syscall_table.S b/trunk/arch/avr32/kernel/syscall_table.S
index 478bda4c4a09..75c81f2dd0b3 100644
--- a/trunk/arch/avr32/kernel/syscall_table.S
+++ b/trunk/arch/avr32/kernel/syscall_table.S
@@ -293,6 +293,6 @@ sys_call_table:
.long sys_shmctl
.long sys_utimensat
.long sys_signalfd
- .long sys_ni_syscall /* 280, was sys_timerfd */
+ .long sys_timerfd /* 280 */
.long sys_eventfd
.long sys_ni_syscall /* r8 is saturated at nr_syscalls */
diff --git a/trunk/arch/avr32/lib/delay.c b/trunk/arch/avr32/lib/delay.c
index 9aa8800830f3..b3bc0b56e2c6 100644
--- a/trunk/arch/avr32/lib/delay.c
+++ b/trunk/arch/avr32/lib/delay.c
@@ -12,15 +12,13 @@
#include
#include
-#include
#include
#include
-#include
#include
#include
-int __devinit read_current_timer(unsigned long *timer_value)
+int read_current_timer(unsigned long *timer_value)
{
*timer_value = sysreg_read(COUNT);
return 0;
diff --git a/trunk/arch/frv/kernel/entry.S b/trunk/arch/frv/kernel/entry.S
index ca6a345b87e4..99046b1f51c8 100644
--- a/trunk/arch/frv/kernel/entry.S
+++ b/trunk/arch/frv/kernel/entry.S
@@ -1494,7 +1494,7 @@ sys_call_table:
.long sys_epoll_pwait
.long sys_utimensat /* 320 */
.long sys_signalfd
- .long sys_ni_syscall
+ .long sys_timerfd
.long sys_eventfd
.long sys_fallocate
diff --git a/trunk/arch/frv/kernel/setup.c b/trunk/arch/frv/kernel/setup.c
index b38ae1fc15fd..a74c08786b21 100644
--- a/trunk/arch/frv/kernel/setup.c
+++ b/trunk/arch/frv/kernel/setup.c
@@ -708,7 +708,7 @@ static void __init reserve_dma_coherent(void)
/*
* calibrate the delay loop
*/
-void __cpuinit calibrate_delay(void)
+void __init calibrate_delay(void)
{
loops_per_jiffy = __delay_loops_MHz * (1000000 / HZ);
diff --git a/trunk/arch/h8300/kernel/irq.c b/trunk/arch/h8300/kernel/irq.c
index 5a1b4cfea05b..8dec4dd57b4e 100644
--- a/trunk/arch/h8300/kernel/irq.c
+++ b/trunk/arch/h8300/kernel/irq.c
@@ -14,7 +14,6 @@
#include
#include
#include
-#include
#include
#include
diff --git a/trunk/arch/ia64/kernel/smpboot.c b/trunk/arch/ia64/kernel/smpboot.c
index 32ee5979a042..480b1a5085d5 100644
--- a/trunk/arch/ia64/kernel/smpboot.c
+++ b/trunk/arch/ia64/kernel/smpboot.c
@@ -120,6 +120,7 @@ static volatile unsigned long go[SLAVE + 1];
#define DEBUG_ITC_SYNC 0
+extern void __devinit calibrate_delay (void);
extern void start_ap (void);
extern unsigned long ia64_iobase;
@@ -476,7 +477,7 @@ start_secondary (void *unused)
return 0;
}
-struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
+struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
{
return NULL;
}
diff --git a/trunk/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/trunk/arch/ia64/sn/pci/pcibr/pcibr_provider.c
index 2c676cc05418..ab3eaf85fe4d 100644
--- a/trunk/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+++ b/trunk/arch/ia64/sn/pci/pcibr/pcibr_provider.c
@@ -100,11 +100,11 @@ u16 sn_ioboard_to_pci_bus(struct pci_bus *pci_bus)
static irqreturn_t
pcibr_error_intr_handler(int irq, void *arg)
{
- struct pcibus_info *soft = arg;
+ struct pcibus_info *soft = (struct pcibus_info *)arg;
- if (sal_pcibr_error_interrupt(soft) < 0)
+ if (sal_pcibr_error_interrupt(soft) < 0) {
panic("pcibr_error_intr_handler(): Fatal Bridge Error");
-
+ }
return IRQ_HANDLED;
}
diff --git a/trunk/arch/m32r/kernel/syscall_table.S b/trunk/arch/m32r/kernel/syscall_table.S
index aa3bf4cfab37..95aa79874847 100644
--- a/trunk/arch/m32r/kernel/syscall_table.S
+++ b/trunk/arch/m32r/kernel/syscall_table.S
@@ -321,6 +321,6 @@ ENTRY(sys_call_table)
.long sys_epoll_pwait
.long sys_utimensat /* 320 */
.long sys_signalfd
- .long sys_ni_syscall
+ .long sys_timerfd
.long sys_eventfd
.long sys_fallocate
diff --git a/trunk/arch/m68k/amiga/chipram.c b/trunk/arch/m68k/amiga/chipram.c
index cbe36538af47..d10726f9038b 100644
--- a/trunk/arch/m68k/amiga/chipram.c
+++ b/trunk/arch/m68k/amiga/chipram.c
@@ -32,10 +32,12 @@ void __init amiga_chip_init(void)
if (!AMIGAHW_PRESENT(CHIP_RAM))
return;
+#ifndef CONFIG_APUS_FAST_EXCEPT
/*
* Remove the first 4 pages where PPC exception handlers will be located
*/
amiga_chip_size -= 0x4000;
+#endif
chipram_res.end = amiga_chip_size-1;
request_resource(&iomem_resource, &chipram_res);
diff --git a/trunk/arch/m68k/amiga/cia.c b/trunk/arch/m68k/amiga/cia.c
index 343fab49bd9a..c4a4ffd45bc0 100644
--- a/trunk/arch/m68k/amiga/cia.c
+++ b/trunk/arch/m68k/amiga/cia.c
@@ -84,7 +84,7 @@ unsigned char cia_able_irq(struct ciabase *base, unsigned char mask)
static irqreturn_t cia_handler(int irq, void *dev_id)
{
- struct ciabase *base = dev_id;
+ struct ciabase *base = (struct ciabase *)dev_id;
int mach_irq;
unsigned char ints;
diff --git a/trunk/arch/m68knommu/lib/memcpy.c b/trunk/arch/m68knommu/lib/memcpy.c
index b50dbcad4746..0d5577569e4c 100644
--- a/trunk/arch/m68knommu/lib/memcpy.c
+++ b/trunk/arch/m68knommu/lib/memcpy.c
@@ -1,5 +1,6 @@
#include
+#include
void * memcpy(void * to, const void * from, size_t n)
{
diff --git a/trunk/arch/mips/au1000/common/gpio.c b/trunk/arch/mips/au1000/common/gpio.c
index 0b658f1db4ce..8527856aec45 100644
--- a/trunk/arch/mips/au1000/common/gpio.c
+++ b/trunk/arch/mips/au1000/common/gpio.c
@@ -27,6 +27,7 @@
* others have a second one : GPIO2
*/
+#include
#include
#include
#include
diff --git a/trunk/arch/mips/kernel/smp.c b/trunk/arch/mips/kernel/smp.c
index 9d41dab90a80..1e5dfc28294a 100644
--- a/trunk/arch/mips/kernel/smp.c
+++ b/trunk/arch/mips/kernel/smp.c
@@ -52,6 +52,7 @@ int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */
EXPORT_SYMBOL(phys_cpu_present_map);
EXPORT_SYMBOL(cpu_online_map);
+extern void __init calibrate_delay(void);
extern void cpu_idle(void);
/* Number of TCs (or siblings in Intel speak) per CPU core */
diff --git a/trunk/arch/mips/kernel/sysirix.c b/trunk/arch/mips/kernel/sysirix.c
index 22fd41e946b2..4c477c7ff74a 100644
--- a/trunk/arch/mips/kernel/sysirix.c
+++ b/trunk/arch/mips/kernel/sysirix.c
@@ -356,7 +356,7 @@ asmlinkage int irix_syssgi(struct pt_regs *regs)
retval = NGROUPS_MAX;
goto out;
case 5:
- retval = sysctl_nr_open;
+ retval = NR_OPEN;
goto out;
case 6:
retval = 1;
diff --git a/trunk/arch/parisc/Kconfig.debug b/trunk/arch/parisc/Kconfig.debug
index bc989e522a04..9166bd117267 100644
--- a/trunk/arch/parisc/Kconfig.debug
+++ b/trunk/arch/parisc/Kconfig.debug
@@ -2,6 +2,15 @@ menu "Kernel hacking"
source "lib/Kconfig.debug"
+config DEBUG_RWLOCK
+ bool "Read-write spinlock debugging"
+ depends on DEBUG_KERNEL && SMP
+ help
+ If you say Y here then read-write lock processing will count how many
+ times it has tried to get the lock and issue an error message after
+ too many attempts. If you suspect a rwlock problem or a kernel
+ hacker asks for this option then say Y. Otherwise say N.
+
config DEBUG_RODATA
bool "Write protect kernel read-only data structures"
depends on DEBUG_KERNEL
diff --git a/trunk/arch/parisc/configs/a500_defconfig b/trunk/arch/parisc/configs/a500_defconfig
index ddacc72e38fb..ea071218a3ed 100644
--- a/trunk/arch/parisc/configs/a500_defconfig
+++ b/trunk/arch/parisc/configs/a500_defconfig
@@ -1050,6 +1050,7 @@ CONFIG_SCHED_DEBUG=y
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_RWLOCK is not set
# CONFIG_DEBUG_RODATA is not set
#
diff --git a/trunk/arch/powerpc/kernel/time.c b/trunk/arch/powerpc/kernel/time.c
index 3b26fbd6bec9..5cd3db5cae41 100644
--- a/trunk/arch/powerpc/kernel/time.c
+++ b/trunk/arch/powerpc/kernel/time.c
@@ -66,7 +66,6 @@
#include
#include
#include
-#include
#ifdef CONFIG_PPC_ISERIES
#include
#include
@@ -190,8 +189,6 @@ u64 __cputime_sec_factor;
EXPORT_SYMBOL(__cputime_sec_factor);
u64 __cputime_clockt_factor;
EXPORT_SYMBOL(__cputime_clockt_factor);
-DEFINE_PER_CPU(unsigned long, cputime_last_delta);
-DEFINE_PER_CPU(unsigned long, cputime_scaled_last_delta);
static void calc_cputime_factors(void)
{
@@ -260,8 +257,8 @@ void account_system_vtime(struct task_struct *tsk)
}
account_system_time(tsk, 0, delta);
account_system_time_scaled(tsk, deltascaled);
- per_cpu(cputime_last_delta, smp_processor_id()) = delta;
- per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled;
+ get_paca()->purrdelta = delta;
+ get_paca()->spurrdelta = deltascaled;
local_irq_restore(flags);
}
@@ -279,7 +276,10 @@ void account_process_tick(struct task_struct *tsk, int user_tick)
get_paca()->user_time = 0;
account_user_time(tsk, utime);
- utimescaled = cputime_to_scaled(utime);
+ /* Estimate the scaled utime by scaling the real utime based
+ * on the last spurr to purr ratio */
+ utimescaled = utime * get_paca()->spurrdelta / get_paca()->purrdelta;
+ get_paca()->spurrdelta = get_paca()->purrdelta = 0;
account_user_time_scaled(tsk, utimescaled);
}
diff --git a/trunk/arch/powerpc/platforms/powermac/cpufreq_32.c b/trunk/arch/powerpc/platforms/powermac/cpufreq_32.c
index 792d3ce8112e..c04abcc28a7a 100644
--- a/trunk/arch/powerpc/platforms/powermac/cpufreq_32.c
+++ b/trunk/arch/powerpc/platforms/powermac/cpufreq_32.c
@@ -113,6 +113,8 @@ static inline void debug_calc_bogomips(void)
* result. We backup/restore the value to avoid affecting the
* core cpufreq framework's own calculation.
*/
+ extern void calibrate_delay(void);
+
unsigned long save_lpj = loops_per_jiffy;
calibrate_delay();
loops_per_jiffy = save_lpj;
diff --git a/trunk/arch/ppc/8260_io/enet.c b/trunk/arch/ppc/8260_io/enet.c
index ec1defea9c1e..25ef55bacd99 100644
--- a/trunk/arch/ppc/8260_io/enet.c
+++ b/trunk/arch/ppc/8260_io/enet.c
@@ -418,7 +418,7 @@ scc_enet_rx(struct net_device *dev)
struct sk_buff *skb;
ushort pkt_len;
- cep = dev->priv;
+ cep = (struct scc_enet_private *)dev->priv;
/* First, grab all of the stats for the incoming packet.
* These get messed up if we get called due to a busy condition.
diff --git a/trunk/arch/ppc/8260_io/fcc_enet.c b/trunk/arch/ppc/8260_io/fcc_enet.c
index bcc3aa9d04f3..a3a27dafff1f 100644
--- a/trunk/arch/ppc/8260_io/fcc_enet.c
+++ b/trunk/arch/ppc/8260_io/fcc_enet.c
@@ -682,7 +682,7 @@ fcc_enet_rx(struct net_device *dev)
struct sk_buff *skb;
ushort pkt_len;
- cep = dev->priv;
+ cep = (struct fcc_enet_private *)dev->priv;
/* First, grab all of the stats for the incoming packet.
* These get messed up if we get called due to a busy condition.
diff --git a/trunk/arch/ppc/kernel/vmlinux.lds.S b/trunk/arch/ppc/kernel/vmlinux.lds.S
index 8a24bc47eb6c..52b64fcbdfc5 100644
--- a/trunk/arch/ppc/kernel/vmlinux.lds.S
+++ b/trunk/arch/ppc/kernel/vmlinux.lds.S
@@ -143,6 +143,11 @@ SECTIONS
. = ALIGN(4096);
__init_end = .;
+
+ . = ALIGN(4096);
+ _sextratext = .;
+ _eextratext = .;
+
__bss_start = .;
.bss :
{
diff --git a/trunk/arch/ppc/platforms/prep_setup.c b/trunk/arch/ppc/platforms/prep_setup.c
index 38449855d5ff..3c56654bfc6f 100644
--- a/trunk/arch/ppc/platforms/prep_setup.c
+++ b/trunk/arch/ppc/platforms/prep_setup.c
@@ -91,11 +91,20 @@ extern void prep_tiger1_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi
#define cached_21 (((char *)(ppc_cached_irq_mask))[3])
#define cached_A1 (((char *)(ppc_cached_irq_mask))[2])
+#ifdef CONFIG_SOUND_CS4232
+long ppc_cs4232_dma, ppc_cs4232_dma2;
+#endif
+
extern PTE *Hash, *Hash_end;
extern unsigned long Hash_size, Hash_mask;
extern int probingmem;
extern unsigned long loops_per_jiffy;
+#ifdef CONFIG_SOUND_CS4232
+EXPORT_SYMBOL(ppc_cs4232_dma);
+EXPORT_SYMBOL(ppc_cs4232_dma2);
+#endif
+
/* useful ISA ports */
#define PREP_SYSCTL 0x81c
/* present in the IBM reference design; possibly identical in Mot boxes: */
@@ -560,6 +569,74 @@ prep_show_percpuinfo(struct seq_file *m, int i)
return 0;
}
+#ifdef CONFIG_SOUND_CS4232
+static long __init masktoint(unsigned int i)
+{
+ int t = -1;
+ while (i >> ++t)
+ ;
+ return (t-1);
+}
+
+/*
+ * ppc_cs4232_dma and ppc_cs4232_dma2 are used in include/asm/dma.h
+ * to distinguish sound dma-channels from others. This is because
+ * blocksize on 16 bit dma-channels 5,6,7 is 128k, but
+ * the cs4232.c uses 64k like on 8 bit dma-channels 0,1,2,3
+ */
+
+static void __init prep_init_sound(void)
+{
+ PPC_DEVICE *audiodevice = NULL;
+
+ /*
+ * Get the needed resource information from residual data.
+ *
+ */
+ if (have_residual_data)
+ audiodevice = residual_find_device(~0, NULL,
+ MultimediaController, AudioController, -1, 0);
+
+ if (audiodevice != NULL) {
+ PnP_TAG_PACKET *pkt;
+
+ pkt = PnP_find_packet((unsigned char *)&res->DevicePnPHeap[audiodevice->AllocatedOffset],
+ S5_Packet, 0);
+ if (pkt != NULL)
+ ppc_cs4232_dma = masktoint(pkt->S5_Pack.DMAMask);
+ pkt = PnP_find_packet((unsigned char*)&res->DevicePnPHeap[audiodevice->AllocatedOffset],
+ S5_Packet, 1);
+ if (pkt != NULL)
+ ppc_cs4232_dma2 = masktoint(pkt->S5_Pack.DMAMask);
+ }
+
+ /*
+ * These are the PReP specs' defaults for the cs4231. We use these
+ * as fallback incase we don't have residual data.
+ * At least the IBM Thinkpad 850 with IDE DMA Channels at 6 and 7
+ * will use the other values.
+ */
+ if (audiodevice == NULL) {
+ switch (_prep_type) {
+ case _PREP_IBM:
+ ppc_cs4232_dma = 1;
+ ppc_cs4232_dma2 = -1;
+ break;
+ default:
+ ppc_cs4232_dma = 6;
+ ppc_cs4232_dma2 = 7;
+ }
+ }
+
+ /*
+ * Find a way to push this information to the cs4232 driver
+ * Give it out with printk, when not in cmd_line?
+ * Append it to cmd_line and boot_command_line?
+ * Format is cs4232=io,irq,dma,dma2
+ */
+}
+#endif /* CONFIG_SOUND_CS4232 */
+
/*
* Fill out screen_info according to the residual data. This allows us to use
* at least vesafb.
@@ -821,6 +898,10 @@ prep_setup_arch(void)
}
}
+#ifdef CONFIG_SOUND_CS4232
+ prep_init_sound();
+#endif /* CONFIG_SOUND_CS4232 */
+
prep_init_vesa();
switch (_prep_type) {
diff --git a/trunk/arch/sh/kernel/syscalls_32.S b/trunk/arch/sh/kernel/syscalls_32.S
index 719e127a7c05..10bec45415ba 100644
--- a/trunk/arch/sh/kernel/syscalls_32.S
+++ b/trunk/arch/sh/kernel/syscalls_32.S
@@ -338,6 +338,6 @@ ENTRY(sys_call_table)
.long sys_epoll_pwait
.long sys_utimensat /* 320 */
.long sys_signalfd
- .long sys_ni_syscall
+ .long sys_timerfd
.long sys_eventfd
.long sys_fallocate
diff --git a/trunk/arch/sh/kernel/syscalls_64.S b/trunk/arch/sh/kernel/syscalls_64.S
index 12c7340356ae..98a93efe3691 100644
--- a/trunk/arch/sh/kernel/syscalls_64.S
+++ b/trunk/arch/sh/kernel/syscalls_64.S
@@ -376,6 +376,6 @@ sys_call_table:
.long sys_epoll_pwait
.long sys_utimensat
.long sys_signalfd
- .long sys_ni_syscall /* 350 */
+ .long sys_timerfd /* 350 */
.long sys_eventfd
.long sys_fallocate
diff --git a/trunk/arch/sparc/kernel/sun4d_smp.c b/trunk/arch/sparc/kernel/sun4d_smp.c
index 0def48158c7d..89a6de95070c 100644
--- a/trunk/arch/sparc/kernel/sun4d_smp.c
+++ b/trunk/arch/sparc/kernel/sun4d_smp.c
@@ -19,12 +19,12 @@
#include
#include
#include
-#include
#include
#include
#include
+#include
#include
#include
#include
@@ -41,6 +41,8 @@
extern ctxd_t *srmmu_ctx_table_phys;
+extern void calibrate_delay(void);
+
static volatile int smp_processors_ready = 0;
static int smp_highest_cpu;
extern volatile unsigned long cpu_callin_map[NR_CPUS];
diff --git a/trunk/arch/sparc/kernel/sun4m_smp.c b/trunk/arch/sparc/kernel/sun4m_smp.c
index 0b9407267162..730eb5796f8e 100644
--- a/trunk/arch/sparc/kernel/sun4m_smp.c
+++ b/trunk/arch/sparc/kernel/sun4m_smp.c
@@ -16,8 +16,6 @@
#include
#include
#include
-#include
-
#include
#include
#include
@@ -25,6 +23,7 @@
#include
#include
+#include
#include
#include
#include
@@ -40,6 +39,8 @@
extern ctxd_t *srmmu_ctx_table_phys;
+extern void calibrate_delay(void);
+
extern volatile unsigned long cpu_callin_map[NR_CPUS];
extern unsigned char boot_cpu_id;
diff --git a/trunk/arch/sparc/kernel/systbls.S b/trunk/arch/sparc/kernel/systbls.S
index 9064485dc40b..ee010f4532a0 100644
--- a/trunk/arch/sparc/kernel/systbls.S
+++ b/trunk/arch/sparc/kernel/systbls.S
@@ -79,8 +79,7 @@ sys_call_table:
/*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
/*300*/ .long sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
/*305*/ .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
-/*310*/ .long sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
-/*315*/ .long sys_timerfd_settime, sys_timerfd_gettime
+/*310*/ .long sys_utimensat, sys_signalfd, sys_ni_syscall, sys_eventfd, sys_fallocate
#ifdef CONFIG_SUNOS_EMUL
/* Now the SunOS syscall table. */
@@ -198,7 +197,6 @@ sunos_sys_table:
.long sunos_nosys, sunos_nosys, sunos_nosys
.long sunos_nosys
/*310*/ .long sunos_nosys, sunos_nosys, sunos_nosys
- .long sunos_nosys, sunos_nosys, sunos_nosys
- .long sunos_nosys
+ .long sunos_nosys, sunos_nosys
#endif
diff --git a/trunk/arch/sparc64/defconfig b/trunk/arch/sparc64/defconfig
index 833d74b2b192..f62d9f6c5e2a 100644
--- a/trunk/arch/sparc64/defconfig
+++ b/trunk/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24
-# Tue Feb 5 17:28:19 2008
+# Linux kernel version: 2.6.24-rc4
+# Tue Dec 4 00:37:59 2007
#
CONFIG_SPARC=y
CONFIG_SPARC64=y
@@ -17,7 +17,6 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_AUDIT_ARCH=y
-CONFIG_HAVE_SETUP_PER_CPU_AREA=y
CONFIG_ARCH_NO_VIRT_TO_BUS=y
CONFIG_OF=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
@@ -31,15 +30,13 @@ CONFIG_HZ_100=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
-# CONFIG_SCHED_HRTICK is not set
-CONFIG_HOTPLUG_CPU=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
# General setup
#
CONFIG_EXPERIMENTAL=y
-CONFIG_LOCK_KERNEL=y
+CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
@@ -79,7 +76,6 @@ CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
@@ -87,14 +83,6 @@ CONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
-CONFIG_PROFILING=y
-# CONFIG_MARKERS is not set
-CONFIG_OPROFILE=m
-CONFIG_HAVE_OPROFILE=y
-CONFIG_KPROBES=y
-CONFIG_HAVE_KPROBES=y
-CONFIG_PROC_PAGE_MONITOR=y
-CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -104,7 +92,6 @@ CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
-CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_BLK_DEV_BSG=y
@@ -122,8 +109,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_PREEMPT_RCU is not set
CONFIG_SYSVIPC_COMPAT=y
CONFIG_GENERIC_HARDIRQS=y
@@ -134,8 +119,7 @@ CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=64
+# CONFIG_SMP is not set
# CONFIG_CPU_FREQ is not set
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -185,12 +169,9 @@ CONFIG_BINFMT_ELF32=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m
CONFIG_SOLARIS_EMUL=y
-CONFIG_SCHED_SMT=y
-CONFIG_SCHED_MC=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
-# CONFIG_RCU_TRACE is not set
# CONFIG_CMDLINE_BOOL is not set
#
@@ -208,7 +189,6 @@ CONFIG_XFRM=y
CONFIG_XFRM_USER=m
# CONFIG_XFRM_SUB_POLICY is not set
CONFIG_XFRM_MIGRATE=y
-# CONFIG_XFRM_STATISTICS is not set
CONFIG_NET_KEY=m
CONFIG_NET_KEY_MIGRATE=y
CONFIG_INET=y
@@ -269,9 +249,9 @@ CONFIG_IP_DCCP_ACKVEC=y
CONFIG_IP_DCCP_CCID2=m
# CONFIG_IP_DCCP_CCID2_DEBUG is not set
CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
# CONFIG_IP_DCCP_CCID3_DEBUG is not set
CONFIG_IP_DCCP_CCID3_RTO=100
-CONFIG_IP_DCCP_TFRC_LIB=m
#
# DCCP Kernel Hacking
@@ -299,7 +279,6 @@ CONFIG_VLAN_8021Q=m
CONFIG_NET_PKTGEN=m
CONFIG_NET_TCPPROBE=m
# CONFIG_HAMRADIO is not set
-# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
@@ -364,7 +343,6 @@ CONFIG_BLK_DEV_IDE=y
CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set
CONFIG_BLK_DEV_IDECD=y
-CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
@@ -381,6 +359,7 @@ CONFIG_IDE_GENERIC=y
# PCI IDE chipsets support
#
CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
CONFIG_IDEPCI_PCIBUS_ORDER=y
# CONFIG_BLK_DEV_GENERIC is not set
# CONFIG_BLK_DEV_OPTI621 is not set
@@ -410,6 +389,7 @@ CONFIG_BLK_DEV_ALI15X3=y
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
# CONFIG_BLK_DEV_TC86C001 is not set
+# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
CONFIG_IDE_ARCH_OBSOLETE_INIT=y
# CONFIG_BLK_DEV_HD is not set
@@ -521,6 +501,7 @@ CONFIG_NETDEVICES=y
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
# CONFIG_VETH is not set
+# CONFIG_IP1000 is not set
# CONFIG_ARCNET is not set
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
@@ -552,7 +533,6 @@ CONFIG_NET_PCI=y
# CONFIG_NE2K_PCI is not set
# CONFIG_8139CP is not set
# CONFIG_8139TOO is not set
-# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
@@ -565,9 +545,6 @@ CONFIG_E1000=m
CONFIG_E1000_NAPI=y
# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_E1000E is not set
-# CONFIG_E1000E_ENABLED is not set
-# CONFIG_IP1000 is not set
-# CONFIG_IGB is not set
# CONFIG_MYRI_SBUS is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
@@ -593,7 +570,6 @@ CONFIG_NETDEV_10000=y
CONFIG_NIU=m
# CONFIG_MLX4_CORE is not set
# CONFIG_TEHUTI is not set
-# CONFIG_BNX2X is not set
# CONFIG_TR is not set
#
@@ -626,6 +602,7 @@ CONFIG_PPPOE=m
# CONFIG_SLIP is not set
CONFIG_SLHC=m
# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -702,7 +679,6 @@ CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_NOZOMI is not set
#
# Serial drivers
@@ -771,13 +747,13 @@ CONFIG_I2C_ALGOBIT=y
#
# Miscellaneous I2C Chip support
#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -1014,7 +990,6 @@ CONFIG_SND_ALI5451=m
# CONFIG_SND_BT87X is not set
# CONFIG_SND_CA0106 is not set
# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_OXYGEN is not set
# CONFIG_SND_CS4281 is not set
# CONFIG_SND_CS46XX is not set
# CONFIG_SND_DARLA20 is not set
@@ -1039,7 +1014,6 @@ CONFIG_SND_ALI5451=m
# CONFIG_SND_HDA_INTEL is not set
# CONFIG_SND_HDSP is not set
# CONFIG_SND_HDSPM is not set
-# CONFIG_SND_HIFIER is not set
# CONFIG_SND_ICE1712 is not set
# CONFIG_SND_ICE1724 is not set
# CONFIG_SND_INTEL8X0 is not set
@@ -1057,7 +1031,6 @@ CONFIG_SND_ALI5451=m
# CONFIG_SND_TRIDENT is not set
# CONFIG_SND_VIA82XX is not set
# CONFIG_SND_VIA82XX_MODEM is not set
-# CONFIG_SND_VIRTUOSO is not set
# CONFIG_SND_VX222 is not set
# CONFIG_SND_YMFPCI is not set
# CONFIG_SND_AC97_POWER_SAVE is not set
@@ -1084,10 +1057,6 @@ CONFIG_SND_SUN_CS4231=m
# SoC Audio support for SuperH
#
-#
-# ALSA SoC audio for Freescale SOCs
-#
-
#
# Open Sound System
#
@@ -1111,7 +1080,6 @@ CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
#
# Miscellaneous USB options
@@ -1125,6 +1093,7 @@ CONFIG_USB_DEVICEFS=y
# USB Host Controller Drivers
#
CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
# CONFIG_USB_ISP116X_HCD is not set
@@ -1174,6 +1143,10 @@ CONFIG_USB_STORAGE=m
#
# USB port drivers
#
+
+#
+# USB Serial Converter support
+#
# CONFIG_USB_SERIAL is not set
#
@@ -1199,6 +1172,14 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
# CONFIG_NEW_LEDS is not set
@@ -1351,6 +1332,11 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
# CONFIG_DLM is not set
+CONFIG_INSTRUMENTATION=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+# CONFIG_MARKERS is not set
#
# Kernel hacking
@@ -1388,8 +1374,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_FORCED_INLINING=y
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
-# CONFIG_KPROBES_SANITY_TEST is not set
-# CONFIG_BACKTRACE_SELF_TEST is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_SAMPLES is not set
@@ -1412,9 +1396,8 @@ CONFIG_ASYNC_MEMCPY=m
CONFIG_ASYNC_XOR=m
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD=m
CONFIG_CRYPTO_BLKCIPHER=y
-# CONFIG_CRYPTO_SEQIV is not set
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_HMAC=y
@@ -1433,9 +1416,6 @@ CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_XTS=m
-# CONFIG_CRYPTO_CTR is not set
-# CONFIG_CRYPTO_GCM is not set
-# CONFIG_CRYPTO_CCM is not set
# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_FCRYPT=m
@@ -1451,16 +1431,13 @@ CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_SEED=m
-# CONFIG_CRYPTO_SALSA20 is not set
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_CRC32C=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_AUTHENC=m
-# CONFIG_CRYPTO_LZO is not set
CONFIG_CRYPTO_HW=y
-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
#
# Library routines
diff --git a/trunk/arch/sparc64/kernel/Makefile b/trunk/arch/sparc64/kernel/Makefile
index 4b78b24ef413..ef50d217432f 100644
--- a/trunk/arch/sparc64/kernel/Makefile
+++ b/trunk/arch/sparc64/kernel/Makefile
@@ -11,7 +11,7 @@ obj-y := process.o setup.o cpu.o idprom.o \
traps.o auxio.o una_asm.o sysfs.o iommu.o \
irq.o ptrace.o time.o sys_sparc.o signal.o \
unaligned.o central.o pci.o starfire.o semaphore.o \
- power.o sbus.o sparc64_ksyms.o chmc.o \
+ power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
diff --git a/trunk/arch/sparc64/kernel/iommu.c b/trunk/arch/sparc64/kernel/iommu.c
index 5623a4d59dff..4b9115a4d92e 100644
--- a/trunk/arch/sparc64/kernel/iommu.c
+++ b/trunk/arch/sparc64/kernel/iommu.c
@@ -472,15 +472,94 @@ static void dma_4u_unmap_single(struct device *dev, dma_addr_t bus_addr,
spin_unlock_irqrestore(&iommu->lock, flags);
}
+#define SG_ENT_PHYS_ADDRESS(SG) (__pa(sg_virt((SG))))
+
+static void fill_sg(iopte_t *iopte, struct scatterlist *sg,
+ int nused, int nelems,
+ unsigned long iopte_protection)
+{
+ struct scatterlist *dma_sg = sg;
+ int i;
+
+ for (i = 0; i < nused; i++) {
+ unsigned long pteval = ~0UL;
+ u32 dma_npages;
+
+ dma_npages = ((dma_sg->dma_address & (IO_PAGE_SIZE - 1UL)) +
+ dma_sg->dma_length +
+ ((IO_PAGE_SIZE - 1UL))) >> IO_PAGE_SHIFT;
+ do {
+ unsigned long offset;
+ signed int len;
+
+ /* If we are here, we know we have at least one
+ * more page to map. So walk forward until we
+ * hit a page crossing, and begin creating new
+ * mappings from that spot.
+ */
+ for (;;) {
+ unsigned long tmp;
+
+ tmp = SG_ENT_PHYS_ADDRESS(sg);
+ len = sg->length;
+ if (((tmp ^ pteval) >> IO_PAGE_SHIFT) != 0UL) {
+ pteval = tmp & IO_PAGE_MASK;
+ offset = tmp & (IO_PAGE_SIZE - 1UL);
+ break;
+ }
+ if (((tmp ^ (tmp + len - 1UL)) >> IO_PAGE_SHIFT) != 0UL) {
+ pteval = (tmp + IO_PAGE_SIZE) & IO_PAGE_MASK;
+ offset = 0UL;
+ len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL)));
+ break;
+ }
+ sg = sg_next(sg);
+ nelems--;
+ }
+
+ pteval = iopte_protection | (pteval & IOPTE_PAGE);
+ while (len > 0) {
+ *iopte++ = __iopte(pteval);
+ pteval += IO_PAGE_SIZE;
+ len -= (IO_PAGE_SIZE - offset);
+ offset = 0;
+ dma_npages--;
+ }
+
+ pteval = (pteval & IOPTE_PAGE) + len;
+ sg = sg_next(sg);
+ nelems--;
+
+ /* Skip over any tail mappings we've fully mapped,
+ * adjusting pteval along the way. Stop when we
+ * detect a page crossing event.
+ */
+ while (nelems &&
+ (pteval << (64 - IO_PAGE_SHIFT)) != 0UL &&
+ (pteval == SG_ENT_PHYS_ADDRESS(sg)) &&
+ ((pteval ^
+ (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) {
+ pteval += sg->length;
+ sg = sg_next(sg);
+ nelems--;
+ }
+ if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL)
+ pteval = ~0UL;
+ } while (dma_npages != 0);
+ dma_sg = sg_next(dma_sg);
+ }
+}
+
static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
- unsigned long flags, ctx, i, npages, iopte_protection;
- struct scatterlist *sg;
- struct strbuf *strbuf;
struct iommu *iommu;
+ struct strbuf *strbuf;
+ unsigned long flags, ctx, npages, iopte_protection;
iopte_t *base;
u32 dma_base;
+ struct scatterlist *sgtmp;
+ int used;
/* Fast path single entry scatterlists. */
if (nelems == 1) {
@@ -499,7 +578,11 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
if (unlikely(direction == DMA_NONE))
goto bad_no_ctx;
- npages = calc_npages(sglist, nelems);
+ /* Step 1: Prepare scatter list. */
+
+ npages = prepare_sg(dev, sglist, nelems);
+
+ /* Step 2: Allocate a cluster and context, if necessary. */
spin_lock_irqsave(&iommu->lock, flags);
@@ -516,6 +599,18 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
dma_base = iommu->page_table_map_base +
((base - iommu->page_table) << IO_PAGE_SHIFT);
+ /* Step 3: Normalize DMA addresses. */
+ used = nelems;
+
+ sgtmp = sglist;
+ while (used && sgtmp->dma_length) {
+ sgtmp->dma_address += dma_base;
+ sgtmp = sg_next(sgtmp);
+ used--;
+ }
+ used = nelems - used;
+
+ /* Step 4: Create the mappings. */
if (strbuf->strbuf_enabled)
iopte_protection = IOPTE_STREAMING(ctx);
else
@@ -523,27 +618,13 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
if (direction != DMA_TO_DEVICE)
iopte_protection |= IOPTE_WRITE;
- for_each_sg(sglist, sg, nelems, i) {
- unsigned long paddr = SG_ENT_PHYS_ADDRESS(sg);
- unsigned long slen = sg->length;
- unsigned long this_npages;
-
- this_npages = iommu_num_pages(paddr, slen);
-
- sg->dma_address = dma_base | (paddr & ~IO_PAGE_MASK);
- sg->dma_length = slen;
-
- paddr &= IO_PAGE_MASK;
- while (this_npages--) {
- iopte_val(*base) = iopte_protection | paddr;
+ fill_sg(base, sglist, used, nelems, iopte_protection);
- base++;
- paddr += IO_PAGE_SIZE;
- dma_base += IO_PAGE_SIZE;
- }
- }
+#ifdef VERIFY_SG
+ verify_sglist(sglist, nelems, base, npages);
+#endif
- return nelems;
+ return used;
bad:
iommu_free_ctx(iommu, ctx);
@@ -556,10 +637,11 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
- unsigned long flags, ctx, i, npages;
- struct strbuf *strbuf;
struct iommu *iommu;
+ struct strbuf *strbuf;
iopte_t *base;
+ unsigned long flags, ctx, i, npages;
+ struct scatterlist *sg, *sgprv;
u32 bus_addr;
if (unlikely(direction == DMA_NONE)) {
@@ -572,7 +654,15 @@ static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist,
bus_addr = sglist->dma_address & IO_PAGE_MASK;
- npages = calc_npages(sglist, nelems);
+ sgprv = NULL;
+ for_each_sg(sglist, sg, nelems, i) {
+ if (sg->dma_length == 0)
+ break;
+ sgprv = sg;
+ }
+
+ npages = (IO_PAGE_ALIGN(sgprv->dma_address + sgprv->dma_length) -
+ bus_addr) >> IO_PAGE_SHIFT;
base = iommu->page_table +
((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
diff --git a/trunk/arch/sparc64/kernel/iommu_common.c b/trunk/arch/sparc64/kernel/iommu_common.c
new file mode 100644
index 000000000000..72a4acfe8c7b
--- /dev/null
+++ b/trunk/arch/sparc64/kernel/iommu_common.c
@@ -0,0 +1,248 @@
+/* $Id: iommu_common.c,v 1.9 2001/12/17 07:05:09 davem Exp $
+ * iommu_common.c: UltraSparc SBUS/PCI common iommu code.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+#include
+#include "iommu_common.h"
+
+/* You are _strongly_ advised to enable the following debugging code
+ * any time you make changes to the sg code below, run it for a while
+ * with filesystems mounted read-only before buying the farm... -DaveM
+ */
+
+#ifdef VERIFY_SG
+static int verify_lengths(struct scatterlist *sglist, int nents, int npages)
+{
+ int sg_len, dma_len;
+ int i, pgcount;
+ struct scatterlist *sg;
+
+ sg_len = 0;
+ for_each_sg(sglist, sg, nents, i)
+ sg_len += sg->length;
+
+ dma_len = 0;
+ for_each_sg(sglist, sg, nents, i) {
+ if (!sg->dma_length)
+ break;
+ dma_len += sg->dma_length;
+ }
+
+ if (sg_len != dma_len) {
+ printk("verify_lengths: Error, different, sg[%d] dma[%d]\n",
+ sg_len, dma_len);
+ return -1;
+ }
+
+ pgcount = 0;
+ for_each_sg(sglist, sg, nents, i) {
+ unsigned long start, end;
+
+ if (!sg->dma_length)
+ break;
+
+ start = sg->dma_address;
+ start = start & IO_PAGE_MASK;
+
+ end = sg->dma_address + sg->dma_length;
+ end = (end + (IO_PAGE_SIZE - 1)) & IO_PAGE_MASK;
+
+ pgcount += ((end - start) >> IO_PAGE_SHIFT);
+ }
+
+ if (pgcount != npages) {
+ printk("verify_lengths: Error, page count wrong, "
+ "npages[%d] pgcount[%d]\n",
+ npages, pgcount);
+ return -1;
+ }
+
+ /* This test passes... */
+ return 0;
+}
+
+static int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int nents, iopte_t **__iopte)
+{
+ struct scatterlist *sg = *__sg;
+ iopte_t *iopte = *__iopte;
+ u32 dlen = dma_sg->dma_length;
+ u32 daddr;
+ unsigned int sglen;
+ unsigned long sgaddr;
+
+ daddr = dma_sg->dma_address;
+ sglen = sg->length;
+ sgaddr = (unsigned long) sg_virt(sg);
+ while (dlen > 0) {
+ unsigned long paddr;
+
+ /* SG and DMA_SG must begin at the same sub-page boundary. */
+ if ((sgaddr & ~IO_PAGE_MASK) != (daddr & ~IO_PAGE_MASK)) {
+ printk("verify_one_map: Wrong start offset "
+ "sg[%08lx] dma[%08x]\n",
+ sgaddr, daddr);
+ nents = -1;
+ goto out;
+ }
+
+ /* Verify the IOPTE points to the right page. */
+ paddr = iopte_val(*iopte) & IOPTE_PAGE;
+ if ((paddr + PAGE_OFFSET) != (sgaddr & IO_PAGE_MASK)) {
+ printk("verify_one_map: IOPTE[%08lx] maps the "
+ "wrong page, should be [%08lx]\n",
+ iopte_val(*iopte), (sgaddr & IO_PAGE_MASK) - PAGE_OFFSET);
+ nents = -1;
+ goto out;
+ }
+
+ /* If this SG crosses a page, adjust to that next page
+ * boundary and loop.
+ */
+ if ((sgaddr & IO_PAGE_MASK) ^ ((sgaddr + sglen - 1) & IO_PAGE_MASK)) {
+ unsigned long next_page, diff;
+
+ next_page = (sgaddr + IO_PAGE_SIZE) & IO_PAGE_MASK;
+ diff = next_page - sgaddr;
+ sgaddr += diff;
+ daddr += diff;
+ sglen -= diff;
+ dlen -= diff;
+ if (dlen > 0)
+ iopte++;
+ continue;
+ }
+
+ /* SG wholly consumed within this page. */
+ daddr += sglen;
+ dlen -= sglen;
+
+ if (dlen > 0 && ((daddr & ~IO_PAGE_MASK) == 0))
+ iopte++;
+
+ sg = sg_next(sg);
+ if (--nents <= 0)
+ break;
+ sgaddr = (unsigned long) sg_virt(sg);
+ sglen = sg->length;
+ }
+ if (dlen < 0) {
+ /* Transfer overrun, big problems. */
+ printk("verify_one_map: Transfer overrun by %d bytes.\n",
+ -dlen);
+ nents = -1;
+ } else {
+ /* Advance to next dma_sg implies that the next iopte will
+ * begin it.
+ */
+ iopte++;
+ }
+
+out:
+ *__sg = sg;
+ *__iopte = iopte;
+ return nents;
+}
+
+static int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte)
+{
+ struct scatterlist *dma_sg = sg;
+ struct scatterlist *orig_dma_sg = dma_sg;
+ int orig_nents = nents;
+
+ for (;;) {
+ nents = verify_one_map(dma_sg, &sg, nents, &iopte);
+ if (nents <= 0)
+ break;
+ dma_sg = sg_next(dma_sg);
+ if (dma_sg->dma_length == 0)
+ break;
+ }
+
+ if (nents > 0) {
+ printk("verify_maps: dma maps consumed by some sgs remain (%d)\n",
+ nents);
+ return -1;
+ }
+
+ if (nents < 0) {
+ printk("verify_maps: Error, messed up mappings, "
+ "at sg %d dma_sg %d\n",
+ (int) (orig_nents + nents), (int) (dma_sg - orig_dma_sg));
+ return -1;
+ }
+
+ /* This test passes... */
+ return 0;
+}
+
+void verify_sglist(struct scatterlist *sglist, int nents, iopte_t *iopte, int npages)
+{
+ struct scatterlist *sg;
+
+ if (verify_lengths(sglist, nents, npages) < 0 ||
+ verify_maps(sglist, nents, iopte) < 0) {
+ int i;
+
+ printk("verify_sglist: Crap, messed up mappings, dumping, iodma at ");
+ printk("%016lx.\n", sglist->dma_address & IO_PAGE_MASK);
+
+ for_each_sg(sglist, sg, nents, i) {
+ printk("sg(%d): page_addr(%p) off(%x) length(%x) "
+ "dma_address[%016x] dma_length[%016x]\n",
+ i,
+ page_address(sg_page(sg)), sg->offset,
+ sg->length,
+ sg->dma_address, sg->dma_length);
+ }
+ }
+
+ /* Seems to be ok */
+}
+#endif
+
+unsigned long prepare_sg(struct device *dev, struct scatterlist *sg, int nents)
+{
+ struct scatterlist *dma_sg = sg;
+ unsigned long prev;
+ u32 dent_addr, dent_len;
+ unsigned int max_seg_size;
+
+ prev = (unsigned long) sg_virt(sg);
+ prev += (unsigned long) (dent_len = sg->length);
+ dent_addr = (u32) ((unsigned long)(sg_virt(sg)) & (IO_PAGE_SIZE - 1UL));
+ max_seg_size = dma_get_max_seg_size(dev);
+ while (--nents) {
+ unsigned long addr;
+
+ sg = sg_next(sg);
+ addr = (unsigned long) sg_virt(sg);
+ if (! VCONTIG(prev, addr) ||
+ dent_len + sg->length > max_seg_size) {
+ dma_sg->dma_address = dent_addr;
+ dma_sg->dma_length = dent_len;
+ dma_sg = sg_next(dma_sg);
+
+ dent_addr = ((dent_addr +
+ dent_len +
+ (IO_PAGE_SIZE - 1UL)) >> IO_PAGE_SHIFT);
+ dent_addr <<= IO_PAGE_SHIFT;
+ dent_addr += addr & (IO_PAGE_SIZE - 1UL);
+ dent_len = 0;
+ }
+ dent_len += sg->length;
+ prev = addr + sg->length;
+ }
+ dma_sg->dma_address = dent_addr;
+ dma_sg->dma_length = dent_len;
+
+ if (dma_sg != sg) {
+ dma_sg = sg_next(dma_sg);
+ dma_sg->dma_length = 0;
+ }
+
+ return ((unsigned long) dent_addr +
+ (unsigned long) dent_len +
+ (IO_PAGE_SIZE - 1UL)) >> IO_PAGE_SHIFT;
+}
diff --git a/trunk/arch/sparc64/kernel/iommu_common.h b/trunk/arch/sparc64/kernel/iommu_common.h
index 4b5cafa2877a..a90d046e8024 100644
--- a/trunk/arch/sparc64/kernel/iommu_common.h
+++ b/trunk/arch/sparc64/kernel/iommu_common.h
@@ -30,32 +30,6 @@
*/
#define IOMMU_PAGE_SHIFT 13
-#define SG_ENT_PHYS_ADDRESS(SG) (__pa(sg_virt((SG))))
-
-static inline unsigned long iommu_num_pages(unsigned long vaddr,
- unsigned long slen)
-{
- unsigned long npages;
-
- npages = IO_PAGE_ALIGN(vaddr + slen) - (vaddr & IO_PAGE_MASK);
- npages >>= IO_PAGE_SHIFT;
-
- return npages;
-}
-
-static inline unsigned long calc_npages(struct scatterlist *sglist, int nelems)
-{
- unsigned long i, npages = 0;
- struct scatterlist *sg;
-
- for_each_sg(sglist, sg, nelems, i) {
- unsigned long paddr = SG_ENT_PHYS_ADDRESS(sg);
- npages += iommu_num_pages(paddr, sg->length);
- }
-
- return npages;
-}
-
/* You are _strongly_ advised to enable the following debugging code
* any time you make changes to the sg code below, run it for a while
* with filesystems mounted read-only before buying the farm... -DaveM
diff --git a/trunk/arch/sparc64/kernel/pci_sun4v.c b/trunk/arch/sparc64/kernel/pci_sun4v.c
index 61baf8dc095e..5ea2eab1ccda 100644
--- a/trunk/arch/sparc64/kernel/pci_sun4v.c
+++ b/trunk/arch/sparc64/kernel/pci_sun4v.c
@@ -365,14 +365,113 @@ static void dma_4v_unmap_single(struct device *dev, dma_addr_t bus_addr,
spin_unlock_irqrestore(&iommu->lock, flags);
}
+#define SG_ENT_PHYS_ADDRESS(SG) (__pa(sg_virt((SG))))
+
+static long fill_sg(long entry, struct device *dev,
+ struct scatterlist *sg,
+ int nused, int nelems, unsigned long prot)
+{
+ struct scatterlist *dma_sg = sg;
+ unsigned long flags;
+ int i;
+
+ local_irq_save(flags);
+
+ iommu_batch_start(dev, prot, entry);
+
+ for (i = 0; i < nused; i++) {
+ unsigned long pteval = ~0UL;
+ u32 dma_npages;
+
+ dma_npages = ((dma_sg->dma_address & (IO_PAGE_SIZE - 1UL)) +
+ dma_sg->dma_length +
+ ((IO_PAGE_SIZE - 1UL))) >> IO_PAGE_SHIFT;
+ do {
+ unsigned long offset;
+ signed int len;
+
+ /* If we are here, we know we have at least one
+ * more page to map. So walk forward until we
+ * hit a page crossing, and begin creating new
+ * mappings from that spot.
+ */
+ for (;;) {
+ unsigned long tmp;
+
+ tmp = SG_ENT_PHYS_ADDRESS(sg);
+ len = sg->length;
+ if (((tmp ^ pteval) >> IO_PAGE_SHIFT) != 0UL) {
+ pteval = tmp & IO_PAGE_MASK;
+ offset = tmp & (IO_PAGE_SIZE - 1UL);
+ break;
+ }
+ if (((tmp ^ (tmp + len - 1UL)) >> IO_PAGE_SHIFT) != 0UL) {
+ pteval = (tmp + IO_PAGE_SIZE) & IO_PAGE_MASK;
+ offset = 0UL;
+ len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL)));
+ break;
+ }
+ sg = sg_next(sg);
+ nelems--;
+ }
+
+ pteval = (pteval & IOPTE_PAGE);
+ while (len > 0) {
+ long err;
+
+ err = iommu_batch_add(pteval);
+ if (unlikely(err < 0L))
+ goto iommu_map_failed;
+
+ pteval += IO_PAGE_SIZE;
+ len -= (IO_PAGE_SIZE - offset);
+ offset = 0;
+ dma_npages--;
+ }
+
+ pteval = (pteval & IOPTE_PAGE) + len;
+ sg = sg_next(sg);
+ nelems--;
+
+ /* Skip over any tail mappings we've fully mapped,
+ * adjusting pteval along the way. Stop when we
+ * detect a page crossing event.
+ */
+ while (nelems &&
+ (pteval << (64 - IO_PAGE_SHIFT)) != 0UL &&
+ (pteval == SG_ENT_PHYS_ADDRESS(sg)) &&
+ ((pteval ^
+ (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) {
+ pteval += sg->length;
+ sg = sg_next(sg);
+ nelems--;
+ }
+ if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL)
+ pteval = ~0UL;
+ } while (dma_npages != 0);
+ dma_sg = sg_next(dma_sg);
+ }
+
+ if (unlikely(iommu_batch_end() < 0L))
+ goto iommu_map_failed;
+
+ local_irq_restore(flags);
+ return 0;
+
+iommu_map_failed:
+ local_irq_restore(flags);
+ return -1L;
+}
+
static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
- unsigned long flags, npages, i, prot;
- struct scatterlist *sg;
struct iommu *iommu;
- long entry, err;
+ unsigned long flags, npages, prot;
u32 dma_base;
+ struct scatterlist *sgtmp;
+ long entry, err;
+ int used;
/* Fast path single entry scatterlists. */
if (nelems == 1) {
@@ -390,8 +489,10 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
if (unlikely(direction == DMA_NONE))
goto bad;
- npages = calc_npages(sglist, nelems);
+ /* Step 1: Prepare scatter list. */
+ npages = prepare_sg(dev, sglist, nelems);
+ /* Step 2: Allocate a cluster and context, if necessary. */
spin_lock_irqsave(&iommu->lock, flags);
entry = arena_alloc(&iommu->arena, npages);
spin_unlock_irqrestore(&iommu->lock, flags);
@@ -402,45 +503,27 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
dma_base = iommu->page_table_map_base +
(entry << IO_PAGE_SHIFT);
- prot = HV_PCI_MAP_ATTR_READ;
- if (direction != DMA_TO_DEVICE)
- prot |= HV_PCI_MAP_ATTR_WRITE;
-
- local_irq_save(flags);
-
- iommu_batch_start(dev, prot, entry);
-
- for_each_sg(sglist, sg, nelems, i) {
- unsigned long paddr = SG_ENT_PHYS_ADDRESS(sg);
- unsigned long slen = sg->length;
- unsigned long this_npages;
+ /* Step 3: Normalize DMA addresses. */
+ used = nelems;
- this_npages = iommu_num_pages(paddr, slen);
-
- sg->dma_address = dma_base | (paddr & ~IO_PAGE_MASK);
- sg->dma_length = slen;
-
- paddr &= IO_PAGE_MASK;
- while (this_npages--) {
- err = iommu_batch_add(paddr);
- if (unlikely(err < 0L)) {
- local_irq_restore(flags);
- goto iommu_map_failed;
- }
-
- paddr += IO_PAGE_SIZE;
- dma_base += IO_PAGE_SIZE;
- }
+ sgtmp = sglist;
+ while (used && sgtmp->dma_length) {
+ sgtmp->dma_address += dma_base;
+ sgtmp = sg_next(sgtmp);
+ used--;
}
+ used = nelems - used;
- err = iommu_batch_end();
-
- local_irq_restore(flags);
+ /* Step 4: Create the mappings. */
+ prot = HV_PCI_MAP_ATTR_READ;
+ if (direction != DMA_TO_DEVICE)
+ prot |= HV_PCI_MAP_ATTR_WRITE;
+ err = fill_sg(entry, dev, sglist, used, nelems, prot);
if (unlikely(err < 0L))
goto iommu_map_failed;
- return nelems;
+ return used;
bad:
if (printk_ratelimit())
@@ -458,11 +541,12 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
- unsigned long flags, npages;
struct pci_pbm_info *pbm;
- u32 devhandle, bus_addr;
struct iommu *iommu;
+ unsigned long flags, i, npages;
+ struct scatterlist *sg, *sgprv;
long entry;
+ u32 devhandle, bus_addr;
if (unlikely(direction == DMA_NONE)) {
if (printk_ratelimit())
@@ -474,8 +558,16 @@ static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
devhandle = pbm->devhandle;
bus_addr = sglist->dma_address & IO_PAGE_MASK;
+ sgprv = NULL;
+ for_each_sg(sglist, sg, nelems, i) {
+ if (sg->dma_length == 0)
+ break;
+
+ sgprv = sg;
+ }
- npages = calc_npages(sglist, nelems);
+ npages = (IO_PAGE_ALIGN(sgprv->dma_address + sgprv->dma_length) -
+ bus_addr) >> IO_PAGE_SHIFT;
entry = ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
diff --git a/trunk/arch/sparc64/kernel/smp.c b/trunk/arch/sparc64/kernel/smp.c
index a8052b76df41..c39944927f1a 100644
--- a/trunk/arch/sparc64/kernel/smp.c
+++ b/trunk/arch/sparc64/kernel/smp.c
@@ -46,6 +46,8 @@
#include
#include
+extern void calibrate_delay(void);
+
int sparc64_multi_core __read_mostly;
cpumask_t cpu_possible_map __read_mostly = CPU_MASK_NONE;
diff --git a/trunk/arch/sparc64/kernel/sparc64_ksyms.c b/trunk/arch/sparc64/kernel/sparc64_ksyms.c
index 8649635d6d74..60765e314bd8 100644
--- a/trunk/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/trunk/arch/sparc64/kernel/sparc64_ksyms.c
@@ -277,7 +277,6 @@ EXPORT_SYMBOL(sys_getpid);
EXPORT_SYMBOL(sys_geteuid);
EXPORT_SYMBOL(sys_getuid);
EXPORT_SYMBOL(sys_getegid);
-EXPORT_SYMBOL(sysctl_nr_open);
EXPORT_SYMBOL(sys_getgid);
EXPORT_SYMBOL(svr4_getcontext);
EXPORT_SYMBOL(svr4_setcontext);
diff --git a/trunk/arch/sparc64/kernel/systbls.S b/trunk/arch/sparc64/kernel/systbls.S
index adc62f490f36..b8058906e727 100644
--- a/trunk/arch/sparc64/kernel/systbls.S
+++ b/trunk/arch/sparc64/kernel/systbls.S
@@ -80,8 +80,7 @@ sys_call_table32:
.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
/*300*/ .word compat_sys_set_robust_list, compat_sys_get_robust_list, compat_sys_migrate_pages, compat_sys_mbind, compat_sys_get_mempolicy
.word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait
-/*310*/ .word compat_sys_utimensat, compat_sys_signalfd, sys_timerfd_create, sys_eventfd, compat_sys_fallocate
- .word compat_sys_timerfd_settime, compat_sys_timerfd_gettime
+/*310*/ .word compat_sys_utimensat, compat_sys_signalfd, sys_ni_syscall, sys_eventfd, compat_sys_fallocate
#endif /* CONFIG_COMPAT */
@@ -153,8 +152,7 @@ sys_call_table:
.word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
/*300*/ .word sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
.word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
-/*310*/ .word sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
- .word sys_timerfd_settime, sys_timerfd_gettime
+/*310*/ .word sys_utimensat, sys_signalfd, sys_ni_syscall, sys_eventfd, sys_fallocate
#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
defined(CONFIG_SOLARIS_EMUL_MODULE)
@@ -273,7 +271,6 @@ sunos_sys_table:
.word sunos_nosys, sunos_nosys, sunos_nosys
.word sunos_nosys
/*310*/ .word sunos_nosys, sunos_nosys, sunos_nosys
- .word sunos_nosys, sunos_nosys, sunos_nosys
- .word sunos_nosys
+ .word sunos_nosys, sunos_nosys
#endif
diff --git a/trunk/arch/sparc64/kernel/time.c b/trunk/arch/sparc64/kernel/time.c
index d204f1ab1d4c..4352ee4d8dac 100644
--- a/trunk/arch/sparc64/kernel/time.c
+++ b/trunk/arch/sparc64/kernel/time.c
@@ -1707,11 +1707,6 @@ static void __exit rtc_mini_exit(void)
misc_deregister(&rtc_mini_dev);
}
-int __devinit read_current_timer(unsigned long *timer_val)
-{
- *timer_val = tick_ops->get_tick();
- return 0;
-}
module_init(rtc_mini_init);
module_exit(rtc_mini_exit);
diff --git a/trunk/arch/sparc64/solaris/fs.c b/trunk/arch/sparc64/solaris/fs.c
index 9311bfe4f2f7..61be597bf430 100644
--- a/trunk/arch/sparc64/solaris/fs.c
+++ b/trunk/arch/sparc64/solaris/fs.c
@@ -624,7 +624,7 @@ asmlinkage int solaris_ulimit(int cmd, int val)
case 3: /* UL_GMEMLIM */
return current->signal->rlim[RLIMIT_DATA].rlim_cur;
case 4: /* UL_GDESLIM */
- return sysctl_nr_open;
+ return NR_OPEN;
}
return -EINVAL;
}
diff --git a/trunk/arch/sparc64/solaris/timod.c b/trunk/arch/sparc64/solaris/timod.c
index f53123c02c2b..a9d32ceabf26 100644
--- a/trunk/arch/sparc64/solaris/timod.c
+++ b/trunk/arch/sparc64/solaris/timod.c
@@ -859,8 +859,7 @@ asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
SOLD("entry");
lock_kernel();
- if (fd >= sysctl_nr_open)
- goto out;
+ if(fd >= NR_OPEN) goto out;
fdt = files_fdtable(current->files);
filp = fdt->fd[fd];
@@ -928,8 +927,7 @@ asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
SOLD("entry");
lock_kernel();
- if (fd >= sysctl_nr_open)
- goto out;
+ if(fd >= NR_OPEN) goto out;
fdt = files_fdtable(current->files);
filp = fdt->fd[fd];
diff --git a/trunk/arch/x86/Kconfig b/trunk/arch/x86/Kconfig
index e6728bd61cc1..434821187cfc 100644
--- a/trunk/arch/x86/Kconfig
+++ b/trunk/arch/x86/Kconfig
@@ -415,7 +415,7 @@ config HPET_TIMER
config HPET_EMULATE_RTC
def_bool y
- depends on HPET_TIMER && (RTC=y || RTC=m || RTC_DRV_CMOS=m || RTC_DRV_CMOS=y)
+ depends on HPET_TIMER && (RTC=y || RTC=m)
# Mark as embedded because too many people got it wrong.
# The code disables itself when not needed.
diff --git a/trunk/arch/x86/kernel/cpu/common.c b/trunk/arch/x86/kernel/cpu/common.c
index f86a3c4a2669..d9313d9adced 100644
--- a/trunk/arch/x86/kernel/cpu/common.c
+++ b/trunk/arch/x86/kernel/cpu/common.c
@@ -637,7 +637,7 @@ void __init early_cpu_init(void)
}
/* Make sure %fs is initialized properly in idle threads */
-struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
+struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
{
memset(regs, 0, sizeof(struct pt_regs));
regs->fs = __KERNEL_PERCPU;
diff --git a/trunk/arch/x86/kernel/cpu/cyrix.c b/trunk/arch/x86/kernel/cpu/cyrix.c
index 7139b0262703..404a6a2d4016 100644
--- a/trunk/arch/x86/kernel/cpu/cyrix.c
+++ b/trunk/arch/x86/kernel/cpu/cyrix.c
@@ -83,6 +83,8 @@ static char cyrix_model_mult2[] __cpuinitdata = "12233445";
* FIXME: our newer udelay uses the tsc. We don't need to frob with SLOP
*/
+extern void calibrate_delay(void) __init;
+
static void __cpuinit check_cx686_slop(struct cpuinfo_x86 *c)
{
unsigned long flags;
diff --git a/trunk/arch/x86/kernel/smpboot_32.c b/trunk/arch/x86/kernel/smpboot_32.c
index 579b9b740c7c..5787a0c3e296 100644
--- a/trunk/arch/x86/kernel/smpboot_32.c
+++ b/trunk/arch/x86/kernel/smpboot_32.c
@@ -202,6 +202,8 @@ void __cpuinit smp_store_cpu_info(int id)
;
}
+extern void calibrate_delay(void);
+
static atomic_t init_deasserted;
static void __cpuinit smp_callin(void)
diff --git a/trunk/arch/x86/lib/delay_32.c b/trunk/arch/x86/lib/delay_32.c
index 4535e6d147ad..aad9d95469dc 100644
--- a/trunk/arch/x86/lib/delay_32.c
+++ b/trunk/arch/x86/lib/delay_32.c
@@ -12,10 +12,8 @@
#include
#include
-#include
#include
#include
-#include
#include
#include
@@ -65,7 +63,7 @@ void use_tsc_delay(void)
delay_fn = delay_tsc;
}
-int __devinit read_current_timer(unsigned long *timer_val)
+int read_current_timer(unsigned long *timer_val)
{
if (delay_fn == delay_tsc) {
rdtscl(*timer_val);
diff --git a/trunk/arch/x86/lib/delay_64.c b/trunk/arch/x86/lib/delay_64.c
index bbc610518516..45cdd3fbd91c 100644
--- a/trunk/arch/x86/lib/delay_64.c
+++ b/trunk/arch/x86/lib/delay_64.c
@@ -10,10 +10,8 @@
#include
#include
-#include
#include
#include
-#include
#include
#include
@@ -22,7 +20,7 @@
#include
#endif
-int __devinit read_current_timer(unsigned long *timer_value)
+int read_current_timer(unsigned long *timer_value)
{
rdtscll(*timer_value);
return 0;
diff --git a/trunk/arch/x86/mach-voyager/voyager_smp.c b/trunk/arch/x86/mach-voyager/voyager_smp.c
index 3cc8eb2f36a9..dffa786f61fe 100644
--- a/trunk/arch/x86/mach-voyager/voyager_smp.c
+++ b/trunk/arch/x86/mach-voyager/voyager_smp.c
@@ -444,6 +444,8 @@ static __u32 __init setup_trampoline(void)
static void __init start_secondary(void *unused)
{
__u8 cpuid = hard_smp_processor_id();
+ /* external functions not defined in the headers */
+ extern void calibrate_delay(void);
cpu_init();
diff --git a/trunk/arch/x86/mm/pageattr.c b/trunk/arch/x86/mm/pageattr.c
index 16ce841f08d6..bb55a78dcd62 100644
--- a/trunk/arch/x86/mm/pageattr.c
+++ b/trunk/arch/x86/mm/pageattr.c
@@ -237,6 +237,7 @@ static void __set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
if (!SHARED_KERNEL_PMD) {
struct page *page;
+ address = __pa(address);
list_for_each_entry(page, &pgd_list, lru) {
pgd_t *pgd;
pud_t *pud;
diff --git a/trunk/arch/xtensa/kernel/time.c b/trunk/arch/xtensa/kernel/time.c
index 8df1e842f6d4..60d29fe0b1bd 100644
--- a/trunk/arch/xtensa/kernel/time.c
+++ b/trunk/arch/xtensa/kernel/time.c
@@ -204,7 +204,7 @@ irqreturn_t timer_interrupt (int irq, void *dev_id)
}
#ifndef CONFIG_GENERIC_CALIBRATE_DELAY
-void __cpuinit calibrate_delay(void)
+void __devinit calibrate_delay(void)
{
loops_per_jiffy = CCOUNT_PER_JIFFY;
printk("Calibrating delay loop (skipped)... "
diff --git a/trunk/drivers/base/Makefile b/trunk/drivers/base/Makefile
index c66637392bbc..63e09c015ca0 100644
--- a/trunk/drivers/base/Makefile
+++ b/trunk/drivers/base/Makefile
@@ -5,7 +5,7 @@ obj-y := core.o sys.o bus.o dd.o \
cpu.o firmware.o init.o map.o devres.o \
attribute_container.o transport_class.o
obj-y += power/
-obj-$(CONFIG_HAS_DMA) += dma-mapping.o
+obj-$(CONFIG_HAS_DMA) += dma-mapping.o dmapool.o
obj-$(CONFIG_ISA) += isa.o
obj-$(CONFIG_FW_LOADER) += firmware_class.o
obj-$(CONFIG_NUMA) += node.o
diff --git a/trunk/drivers/base/cpu.c b/trunk/drivers/base/cpu.c
index 499b003f9278..c5885f5ce0ac 100644
--- a/trunk/drivers/base/cpu.c
+++ b/trunk/drivers/base/cpu.c
@@ -110,7 +110,7 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL);
*
* Initialize and register the CPU device.
*/
-int __cpuinit register_cpu(struct cpu *cpu, int num)
+int __devinit register_cpu(struct cpu *cpu, int num)
{
int error;
cpu->node_id = cpu_to_node(num);
diff --git a/trunk/drivers/base/dmapool.c b/trunk/drivers/base/dmapool.c
new file mode 100644
index 000000000000..b5034dc72a05
--- /dev/null
+++ b/trunk/drivers/base/dmapool.c
@@ -0,0 +1,481 @@
+
+#include
+#include
+#include /* Needed for i386 to build */
+#include
+#include
+#include
+#include
+#include
+#include
+
+/*
+ * Pool allocator ... wraps the dma_alloc_coherent page allocator, so
+ * small blocks are easily used by drivers for bus mastering controllers.
+ * This should probably be sharing the guts of the slab allocator.
+ */
+
+struct dma_pool { /* the pool */
+ struct list_head page_list;
+ spinlock_t lock;
+ size_t blocks_per_page;
+ size_t size;
+ struct device *dev;
+ size_t allocation;
+ char name [32];
+ wait_queue_head_t waitq;
+ struct list_head pools;
+};
+
+struct dma_page { /* cacheable header for 'allocation' bytes */
+ struct list_head page_list;
+ void *vaddr;
+ dma_addr_t dma;
+ unsigned in_use;
+ unsigned long bitmap [0];
+};
+
+#define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000)
+
+static DEFINE_MUTEX (pools_lock);
+
+static ssize_t
+show_pools (struct device *dev, struct device_attribute *attr, char *buf)
+{
+ unsigned temp;
+ unsigned size;
+ char *next;
+ struct dma_page *page;
+ struct dma_pool *pool;
+
+ next = buf;
+ size = PAGE_SIZE;
+
+ temp = scnprintf(next, size, "poolinfo - 0.1\n");
+ size -= temp;
+ next += temp;
+
+ mutex_lock(&pools_lock);
+ list_for_each_entry(pool, &dev->dma_pools, pools) {
+ unsigned pages = 0;
+ unsigned blocks = 0;
+
+ list_for_each_entry(page, &pool->page_list, page_list) {
+ pages++;
+ blocks += page->in_use;
+ }
+
+ /* per-pool info, no real statistics yet */
+ temp = scnprintf(next, size, "%-16s %4u %4Zu %4Zu %2u\n",
+ pool->name,
+ blocks, pages * pool->blocks_per_page,
+ pool->size, pages);
+ size -= temp;
+ next += temp;
+ }
+ mutex_unlock(&pools_lock);
+
+ return PAGE_SIZE - size;
+}
+static DEVICE_ATTR (pools, S_IRUGO, show_pools, NULL);
+
+/**
+ * dma_pool_create - Creates a pool of consistent memory blocks, for dma.
+ * @name: name of pool, for diagnostics
+ * @dev: device that will be doing the DMA
+ * @size: size of the blocks in this pool.
+ * @align: alignment requirement for blocks; must be a power of two
+ * @allocation: returned blocks won't cross this boundary (or zero)
+ * Context: !in_interrupt()
+ *
+ * Returns a dma allocation pool with the requested characteristics, or
+ * null if one can't be created. Given one of these pools, dma_pool_alloc()
+ * may be used to allocate memory. Such memory will all have "consistent"
+ * DMA mappings, accessible by the device and its driver without using
+ * cache flushing primitives. The actual size of blocks allocated may be
+ * larger than requested because of alignment.
+ *
+ * If allocation is nonzero, objects returned from dma_pool_alloc() won't
+ * cross that size boundary. This is useful for devices which have
+ * addressing restrictions on individual DMA transfers, such as not crossing
+ * boundaries of 4KBytes.
+ */
+struct dma_pool *
+dma_pool_create (const char *name, struct device *dev,
+ size_t size, size_t align, size_t allocation)
+{
+ struct dma_pool *retval;
+
+ if (align == 0)
+ align = 1;
+ if (size == 0)
+ return NULL;
+ else if (size < align)
+ size = align;
+ else if ((size % align) != 0) {
+ size += align + 1;
+ size &= ~(align - 1);
+ }
+
+ if (allocation == 0) {
+ if (PAGE_SIZE < size)
+ allocation = size;
+ else
+ allocation = PAGE_SIZE;
+ // FIXME: round up for less fragmentation
+ } else if (allocation < size)
+ return NULL;
+
+ if (!(retval = kmalloc_node (sizeof *retval, GFP_KERNEL, dev_to_node(dev))))
+ return retval;
+
+ strlcpy (retval->name, name, sizeof retval->name);
+
+ retval->dev = dev;
+
+ INIT_LIST_HEAD (&retval->page_list);
+ spin_lock_init (&retval->lock);
+ retval->size = size;
+ retval->allocation = allocation;
+ retval->blocks_per_page = allocation / size;
+ init_waitqueue_head (&retval->waitq);
+
+ if (dev) {
+ int ret;
+
+ mutex_lock(&pools_lock);
+ if (list_empty (&dev->dma_pools))
+ ret = device_create_file (dev, &dev_attr_pools);
+ else
+ ret = 0;
+ /* note: not currently insisting "name" be unique */
+ if (!ret)
+ list_add (&retval->pools, &dev->dma_pools);
+ else {
+ kfree(retval);
+ retval = NULL;
+ }
+ mutex_unlock(&pools_lock);
+ } else
+ INIT_LIST_HEAD (&retval->pools);
+
+ return retval;
+}
+
+
+static struct dma_page *
+pool_alloc_page (struct dma_pool *pool, gfp_t mem_flags)
+{
+ struct dma_page *page;
+ int mapsize;
+
+ mapsize = pool->blocks_per_page;
+ mapsize = (mapsize + BITS_PER_LONG - 1) / BITS_PER_LONG;
+ mapsize *= sizeof (long);
+
+ page = kmalloc(mapsize + sizeof *page, mem_flags);
+ if (!page)
+ return NULL;
+ page->vaddr = dma_alloc_coherent (pool->dev,
+ pool->allocation,
+ &page->dma,
+ mem_flags);
+ if (page->vaddr) {
+ memset (page->bitmap, 0xff, mapsize); // bit set == free
+#ifdef CONFIG_DEBUG_SLAB
+ memset (page->vaddr, POOL_POISON_FREED, pool->allocation);
+#endif
+ list_add (&page->page_list, &pool->page_list);
+ page->in_use = 0;
+ } else {
+ kfree (page);
+ page = NULL;
+ }
+ return page;
+}
+
+
+static inline int
+is_page_busy (int blocks, unsigned long *bitmap)
+{
+ while (blocks > 0) {
+ if (*bitmap++ != ~0UL)
+ return 1;
+ blocks -= BITS_PER_LONG;
+ }
+ return 0;
+}
+
+static void
+pool_free_page (struct dma_pool *pool, struct dma_page *page)
+{
+ dma_addr_t dma = page->dma;
+
+#ifdef CONFIG_DEBUG_SLAB
+ memset (page->vaddr, POOL_POISON_FREED, pool->allocation);
+#endif
+ dma_free_coherent (pool->dev, pool->allocation, page->vaddr, dma);
+ list_del (&page->page_list);
+ kfree (page);
+}
+
+
+/**
+ * dma_pool_destroy - destroys a pool of dma memory blocks.
+ * @pool: dma pool that will be destroyed
+ * Context: !in_interrupt()
+ *
+ * Caller guarantees that no more memory from the pool is in use,
+ * and that nothing will try to use the pool after this call.
+ */
+void
+dma_pool_destroy (struct dma_pool *pool)
+{
+ mutex_lock(&pools_lock);
+ list_del (&pool->pools);
+ if (pool->dev && list_empty (&pool->dev->dma_pools))
+ device_remove_file (pool->dev, &dev_attr_pools);
+ mutex_unlock(&pools_lock);
+
+ while (!list_empty (&pool->page_list)) {
+ struct dma_page *page;
+ page = list_entry (pool->page_list.next,
+ struct dma_page, page_list);
+ if (is_page_busy (pool->blocks_per_page, page->bitmap)) {
+ if (pool->dev)
+ dev_err(pool->dev, "dma_pool_destroy %s, %p busy\n",
+ pool->name, page->vaddr);
+ else
+ printk (KERN_ERR "dma_pool_destroy %s, %p busy\n",
+ pool->name, page->vaddr);
+ /* leak the still-in-use consistent memory */
+ list_del (&page->page_list);
+ kfree (page);
+ } else
+ pool_free_page (pool, page);
+ }
+
+ kfree (pool);
+}
+
+
+/**
+ * dma_pool_alloc - get a block of consistent memory
+ * @pool: dma pool that will produce the block
+ * @mem_flags: GFP_* bitmask
+ * @handle: pointer to dma address of block
+ *
+ * This returns the kernel virtual address of a currently unused block,
+ * and reports its dma address through the handle.
+ * If such a memory block can't be allocated, null is returned.
+ */
+void *
+dma_pool_alloc (struct dma_pool *pool, gfp_t mem_flags, dma_addr_t *handle)
+{
+ unsigned long flags;
+ struct dma_page *page;
+ int map, block;
+ size_t offset;
+ void *retval;
+
+restart:
+ spin_lock_irqsave (&pool->lock, flags);
+ list_for_each_entry(page, &pool->page_list, page_list) {
+ int i;
+ /* only cachable accesses here ... */
+ for (map = 0, i = 0;
+ i < pool->blocks_per_page;
+ i += BITS_PER_LONG, map++) {
+ if (page->bitmap [map] == 0)
+ continue;
+ block = ffz (~ page->bitmap [map]);
+ if ((i + block) < pool->blocks_per_page) {
+ clear_bit (block, &page->bitmap [map]);
+ offset = (BITS_PER_LONG * map) + block;
+ offset *= pool->size;
+ goto ready;
+ }
+ }
+ }
+ if (!(page = pool_alloc_page (pool, GFP_ATOMIC))) {
+ if (mem_flags & __GFP_WAIT) {
+ DECLARE_WAITQUEUE (wait, current);
+
+ __set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue (&pool->waitq, &wait);
+ spin_unlock_irqrestore (&pool->lock, flags);
+
+ schedule_timeout (POOL_TIMEOUT_JIFFIES);
+
+ remove_wait_queue (&pool->waitq, &wait);
+ goto restart;
+ }
+ retval = NULL;
+ goto done;
+ }
+
+ clear_bit (0, &page->bitmap [0]);
+ offset = 0;
+ready:
+ page->in_use++;
+ retval = offset + page->vaddr;
+ *handle = offset + page->dma;
+#ifdef CONFIG_DEBUG_SLAB
+ memset (retval, POOL_POISON_ALLOCATED, pool->size);
+#endif
+done:
+ spin_unlock_irqrestore (&pool->lock, flags);
+ return retval;
+}
+
+
+static struct dma_page *
+pool_find_page (struct dma_pool *pool, dma_addr_t dma)
+{
+ unsigned long flags;
+ struct dma_page *page;
+
+ spin_lock_irqsave (&pool->lock, flags);
+ list_for_each_entry(page, &pool->page_list, page_list) {
+ if (dma < page->dma)
+ continue;
+ if (dma < (page->dma + pool->allocation))
+ goto done;
+ }
+ page = NULL;
+done:
+ spin_unlock_irqrestore (&pool->lock, flags);
+ return page;
+}
+
+
+/**
+ * dma_pool_free - put block back into dma pool
+ * @pool: the dma pool holding the block
+ * @vaddr: virtual address of block
+ * @dma: dma address of block
+ *
+ * Caller promises neither device nor driver will again touch this block
+ * unless it is first re-allocated.
+ */
+void
+dma_pool_free (struct dma_pool *pool, void *vaddr, dma_addr_t dma)
+{
+ struct dma_page *page;
+ unsigned long flags;
+ int map, block;
+
+ if ((page = pool_find_page(pool, dma)) == NULL) {
+ if (pool->dev)
+ dev_err(pool->dev, "dma_pool_free %s, %p/%lx (bad dma)\n",
+ pool->name, vaddr, (unsigned long) dma);
+ else
+ printk (KERN_ERR "dma_pool_free %s, %p/%lx (bad dma)\n",
+ pool->name, vaddr, (unsigned long) dma);
+ return;
+ }
+
+ block = dma - page->dma;
+ block /= pool->size;
+ map = block / BITS_PER_LONG;
+ block %= BITS_PER_LONG;
+
+#ifdef CONFIG_DEBUG_SLAB
+ if (((dma - page->dma) + (void *)page->vaddr) != vaddr) {
+ if (pool->dev)
+ dev_err(pool->dev, "dma_pool_free %s, %p (bad vaddr)/%Lx\n",
+ pool->name, vaddr, (unsigned long long) dma);
+ else
+ printk (KERN_ERR "dma_pool_free %s, %p (bad vaddr)/%Lx\n",
+ pool->name, vaddr, (unsigned long long) dma);
+ return;
+ }
+ if (page->bitmap [map] & (1UL << block)) {
+ if (pool->dev)
+ dev_err(pool->dev, "dma_pool_free %s, dma %Lx already free\n",
+ pool->name, (unsigned long long)dma);
+ else
+ printk (KERN_ERR "dma_pool_free %s, dma %Lx already free\n",
+ pool->name, (unsigned long long)dma);
+ return;
+ }
+ memset (vaddr, POOL_POISON_FREED, pool->size);
+#endif
+
+ spin_lock_irqsave (&pool->lock, flags);
+ page->in_use--;
+ set_bit (block, &page->bitmap [map]);
+ if (waitqueue_active (&pool->waitq))
+ wake_up (&pool->waitq);
+ /*
+ * Resist a temptation to do
+ * if (!is_page_busy(bpp, page->bitmap)) pool_free_page(pool, page);
+ * Better have a few empty pages hang around.
+ */
+ spin_unlock_irqrestore (&pool->lock, flags);
+}
+
+/*
+ * Managed DMA pool
+ */
+static void dmam_pool_release(struct device *dev, void *res)
+{
+ struct dma_pool *pool = *(struct dma_pool **)res;
+
+ dma_pool_destroy(pool);
+}
+
+static int dmam_pool_match(struct device *dev, void *res, void *match_data)
+{
+ return *(struct dma_pool **)res == match_data;
+}
+
+/**
+ * dmam_pool_create - Managed dma_pool_create()
+ * @name: name of pool, for diagnostics
+ * @dev: device that will be doing the DMA
+ * @size: size of the blocks in this pool.
+ * @align: alignment requirement for blocks; must be a power of two
+ * @allocation: returned blocks won't cross this boundary (or zero)
+ *
+ * Managed dma_pool_create(). DMA pool created with this function is
+ * automatically destroyed on driver detach.
+ */
+struct dma_pool *dmam_pool_create(const char *name, struct device *dev,
+ size_t size, size_t align, size_t allocation)
+{
+ struct dma_pool **ptr, *pool;
+
+ ptr = devres_alloc(dmam_pool_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return NULL;
+
+ pool = *ptr = dma_pool_create(name, dev, size, align, allocation);
+ if (pool)
+ devres_add(dev, ptr);
+ else
+ devres_free(ptr);
+
+ return pool;
+}
+
+/**
+ * dmam_pool_destroy - Managed dma_pool_destroy()
+ * @pool: dma pool that will be destroyed
+ *
+ * Managed dma_pool_destroy().
+ */
+void dmam_pool_destroy(struct dma_pool *pool)
+{
+ struct device *dev = pool->dev;
+
+ dma_pool_destroy(pool);
+ WARN_ON(devres_destroy(dev, dmam_pool_release, dmam_pool_match, pool));
+}
+
+EXPORT_SYMBOL (dma_pool_create);
+EXPORT_SYMBOL (dma_pool_destroy);
+EXPORT_SYMBOL (dma_pool_alloc);
+EXPORT_SYMBOL (dma_pool_free);
+EXPORT_SYMBOL (dmam_pool_create);
+EXPORT_SYMBOL (dmam_pool_destroy);
diff --git a/trunk/drivers/block/ataflop.c b/trunk/drivers/block/ataflop.c
index 424995073c6b..94268c75d04f 100644
--- a/trunk/drivers/block/ataflop.c
+++ b/trunk/drivers/block/ataflop.c
@@ -90,7 +90,7 @@ static struct atari_disk_type {
unsigned blocks; /* total number of blocks */
unsigned fdc_speed; /* fdc_speed setting */
unsigned stretch; /* track doubling ? */
-} atari_disk_type[] = {
+} disk_type[] = {
{ "d360", 9, 720, 0, 0}, /* 0: 360kB diskette */
{ "D360", 9, 720, 0, 1}, /* 1: 360kb in 720k or 1.2MB drive */
{ "D720", 9,1440, 0, 0}, /* 2: 720kb in 720k or 1.2MB drive */
@@ -658,7 +658,7 @@ static int do_format(int drive, int type, struct atari_format_descr *desc)
return -EINVAL;
}
type = minor2disktype[type].index;
- UDT = &atari_disk_type[type];
+ UDT = &disk_type[type];
}
if (!UDT || desc->track >= UDT->blocks/UDT->spt/2 || desc->head >= 2) {
@@ -1064,7 +1064,7 @@ static void fd_rwsec_done1(int status)
searched for a non-existent sector! */
!(read_track && FDC_READ(FDCREG_SECTOR) > SUDT->spt)) {
if (Probing) {
- if (SUDT > atari_disk_type) {
+ if (SUDT > disk_type) {
if (SUDT[-1].blocks > ReqBlock) {
/* try another disk type */
SUDT--;
@@ -1082,7 +1082,7 @@ static void fd_rwsec_done1(int status)
} else {
/* record not found, but not probing. Maybe stretch wrong ? Restart probing */
if (SUD.autoprobe) {
- SUDT = atari_disk_type + StartDiskType[DriveType];
+ SUDT = disk_type + StartDiskType[DriveType];
set_capacity(unit[SelectedDrive].disk,
SUDT->blocks);
Probing = 1;
@@ -1421,7 +1421,7 @@ static void redo_fd_request(void)
if (type == 0) {
if (!UDT) {
Probing = 1;
- UDT = atari_disk_type + StartDiskType[DriveType];
+ UDT = disk_type + StartDiskType[DriveType];
set_capacity(floppy->disk, UDT->blocks);
UD.autoprobe = 1;
}
@@ -1439,7 +1439,7 @@ static void redo_fd_request(void)
goto repeat;
}
type = minor2disktype[type].index;
- UDT = &atari_disk_type[type];
+ UDT = &disk_type[type];
set_capacity(floppy->disk, UDT->blocks);
UD.autoprobe = 0;
}
@@ -1505,7 +1505,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
if (minor2disktype[type].drive_types > DriveType)
return -ENODEV;
type = minor2disktype[type].index;
- dtp = &atari_disk_type[type];
+ dtp = &disk_type[type];
if (UD.flags & FTD_MSG)
printk (KERN_ERR "floppy%d: found dtp %p name %s!\n",
drive, dtp, dtp->name);
@@ -1576,7 +1576,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
continue;
}
setidx = minor2disktype[settype].index;
- dtp = &atari_disk_type[setidx];
+ dtp = &disk_type[setidx];
/* found matching entry ?? */
if ( dtp->blocks == setprm.size
diff --git a/trunk/drivers/block/cciss.c b/trunk/drivers/block/cciss.c
index 9715be3f2487..855ce8e5efba 100644
--- a/trunk/drivers/block/cciss.c
+++ b/trunk/drivers/block/cciss.c
@@ -2630,14 +2630,12 @@ static void do_cciss_request(struct request_queue *q)
c->Request.CDB[8] = creq->nr_sectors & 0xff;
c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
} else {
- u32 upper32 = upper_32_bits(start_blk);
-
c->Request.CDBLen = 16;
c->Request.CDB[1]= 0;
- c->Request.CDB[2]= (upper32 >> 24) & 0xff; //MSB
- c->Request.CDB[3]= (upper32 >> 16) & 0xff;
- c->Request.CDB[4]= (upper32 >> 8) & 0xff;
- c->Request.CDB[5]= upper32 & 0xff;
+ c->Request.CDB[2]= (start_blk >> 56) & 0xff; //MSB
+ c->Request.CDB[3]= (start_blk >> 48) & 0xff;
+ c->Request.CDB[4]= (start_blk >> 40) & 0xff;
+ c->Request.CDB[5]= (start_blk >> 32) & 0xff;
c->Request.CDB[6]= (start_blk >> 24) & 0xff;
c->Request.CDB[7]= (start_blk >> 16) & 0xff;
c->Request.CDB[8]= (start_blk >> 8) & 0xff;
diff --git a/trunk/drivers/block/loop.c b/trunk/drivers/block/loop.c
index 91ebb007416c..b8af22e610df 100644
--- a/trunk/drivers/block/loop.c
+++ b/trunk/drivers/block/loop.c
@@ -973,10 +973,6 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
lo->transfer = xfer->transfer;
lo->ioctl = xfer->ioctl;
- if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) !=
- (info->lo_flags & LO_FLAGS_AUTOCLEAR))
- lo->lo_flags ^= LO_FLAGS_AUTOCLEAR;
-
lo->lo_encrypt_key_size = info->lo_encrypt_key_size;
lo->lo_init[0] = info->lo_init[0];
lo->lo_init[1] = info->lo_init[1];
@@ -1335,10 +1331,6 @@ static int lo_release(struct inode *inode, struct file *file)
mutex_lock(&lo->lo_ctl_mutex);
--lo->lo_refcnt;
-
- if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) && !lo->lo_refcnt)
- loop_clr_fd(lo, inode->i_bdev);
-
mutex_unlock(&lo->lo_ctl_mutex);
return 0;
diff --git a/trunk/drivers/block/paride/pt.c b/trunk/drivers/block/paride/pt.c
index 8b9549ab4a4e..76096cad798f 100644
--- a/trunk/drivers/block/paride/pt.c
+++ b/trunk/drivers/block/paride/pt.c
@@ -660,7 +660,7 @@ static int pt_open(struct inode *inode, struct file *file)
pt_identify(tape);
err = -ENODEV;
- if (!(tape->flags & PT_MEDIA))
+ if (!tape->flags & PT_MEDIA)
goto out;
err = -EROFS;
diff --git a/trunk/drivers/block/pktcdvd.c b/trunk/drivers/block/pktcdvd.c
index 674cd66dcaba..e9de1712e5a0 100644
--- a/trunk/drivers/block/pktcdvd.c
+++ b/trunk/drivers/block/pktcdvd.c
@@ -2212,11 +2212,11 @@ static int pkt_media_speed(struct pktcdvd_device *pd, unsigned *speed)
return ret;
}
- if (!(buf[6] & 0x40)) {
+ if (!buf[6] & 0x40) {
printk(DRIVER_NAME": Disc type is not CD-RW\n");
return 1;
}
- if (!(buf[6] & 0x4)) {
+ if (!buf[6] & 0x4) {
printk(DRIVER_NAME": A1 values on media are not valid, maybe not CDRW?\n");
return 1;
}
diff --git a/trunk/drivers/block/rd.c b/trunk/drivers/block/rd.c
index 06e23be70904..82f4eecc8699 100644
--- a/trunk/drivers/block/rd.c
+++ b/trunk/drivers/block/rd.c
@@ -56,7 +56,6 @@
#include
#include
#include
-#include
#include
@@ -451,7 +450,7 @@ static int __init rd_init(void)
err = -ENOMEM;
if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 ||
- !is_power_of_2(rd_blocksize)) {
+ (rd_blocksize & (rd_blocksize-1))) {
printk("RAMDISK: wrong blocksize %d, reverting to defaults\n",
rd_blocksize);
rd_blocksize = BLOCK_SIZE;
diff --git a/trunk/drivers/cdrom/cdrom.c b/trunk/drivers/cdrom/cdrom.c
index db259e60289b..47e5b40510cb 100644
--- a/trunk/drivers/cdrom/cdrom.c
+++ b/trunk/drivers/cdrom/cdrom.c
@@ -1206,26 +1206,25 @@ int check_for_audio_disc(struct cdrom_device_info * cdi,
return 0;
}
+/* Admittedly, the logic below could be performed in a nicer way. */
int cdrom_release(struct cdrom_device_info *cdi, struct file *fp)
{
struct cdrom_device_ops *cdo = cdi->ops;
int opened_for_data;
- cdinfo(CD_CLOSE, "entering cdrom_release\n");
+ cdinfo(CD_CLOSE, "entering cdrom_release\n");
if (cdi->use_count > 0)
cdi->use_count--;
-
- if (cdi->use_count == 0) {
+ if (cdi->use_count == 0)
cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name);
+ if (cdi->use_count == 0)
cdrom_dvd_rw_close_write(cdi);
-
- if ((cdo->capability & CDC_LOCK) && !keeplocked) {
- cdinfo(CD_CLOSE, "Unlocking door!\n");
- cdo->lock_door(cdi, 0);
- }
+ if (cdi->use_count == 0 &&
+ (cdo->capability & CDC_LOCK) && !keeplocked) {
+ cdinfo(CD_CLOSE, "Unlocking door!\n");
+ cdo->lock_door(cdi, 0);
}
-
opened_for_data = !(cdi->options & CDO_USE_FFLAGS) ||
!(fp && fp->f_flags & O_NONBLOCK);
diff --git a/trunk/drivers/char/Kconfig b/trunk/drivers/char/Kconfig
index 85bf9b2aa74a..466629594776 100644
--- a/trunk/drivers/char/Kconfig
+++ b/trunk/drivers/char/Kconfig
@@ -276,7 +276,7 @@ config N_HDLC
config RISCOM8
tristate "SDL RISCom/8 card support"
- depends on SERIAL_NONSTANDARD
+ depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
help
This is a driver for the SDL Communications RISCom/8 multiport card,
which gives you many serial ports. You would need something like
@@ -765,7 +765,7 @@ config JS_RTC
config SGI_DS1286
tristate "SGI DS1286 RTC support"
- depends on SGI_HAS_DS1286
+ depends on SGI_IP22
help
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
diff --git a/trunk/drivers/char/hvc_console.c b/trunk/drivers/char/hvc_console.c
index 44160d5ebca0..480fae29c9b2 100644
--- a/trunk/drivers/char/hvc_console.c
+++ b/trunk/drivers/char/hvc_console.c
@@ -93,7 +93,7 @@ struct hvc_struct {
};
/* dynamic list of hvc_struct instances */
-static LIST_HEAD(hvc_structs);
+static struct list_head hvc_structs = LIST_HEAD_INIT(hvc_structs);
/*
* Protect the list of hvc_struct instances from inserts and removals during
diff --git a/trunk/drivers/char/hvcs.c b/trunk/drivers/char/hvcs.c
index 786d518e9477..3402def22007 100644
--- a/trunk/drivers/char/hvcs.c
+++ b/trunk/drivers/char/hvcs.c
@@ -306,7 +306,7 @@ struct hvcs_struct {
/* Required to back map a kref to its containing object */
#define from_kref(k) container_of(k, struct hvcs_struct, kref)
-static LIST_HEAD(hvcs_structs);
+static struct list_head hvcs_structs = LIST_HEAD_INIT(hvcs_structs);
static DEFINE_SPINLOCK(hvcs_structs_lock);
static void hvcs_unthrottle(struct tty_struct *tty);
diff --git a/trunk/drivers/char/hw_random/via-rng.c b/trunk/drivers/char/hw_random/via-rng.c
index f7feae4ebb5e..868e39fd42e4 100644
--- a/trunk/drivers/char/hw_random/via-rng.c
+++ b/trunk/drivers/char/hw_random/via-rng.c
@@ -42,8 +42,6 @@ enum {
VIA_STRFILT_ENABLE = (1 << 14),
VIA_RAWBITS_ENABLE = (1 << 13),
VIA_RNG_ENABLE = (1 << 6),
- VIA_NOISESRC1 = (1 << 8),
- VIA_NOISESRC2 = (1 << 9),
VIA_XSTORE_CNT_MASK = 0x0F,
VIA_RNG_CHUNK_8 = 0x00, /* 64 rand bits, 64 stored bits */
@@ -121,7 +119,6 @@ static int via_rng_data_read(struct hwrng *rng, u32 *data)
static int via_rng_init(struct hwrng *rng)
{
- struct cpuinfo_x86 *c = &cpu_data(0);
u32 lo, hi, old_lo;
/* Control the RNG via MSR. Tread lightly and pay very close
@@ -137,17 +134,6 @@ static int via_rng_init(struct hwrng *rng)
lo &= ~VIA_XSTORE_CNT_MASK;
lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE);
lo |= VIA_RNG_ENABLE;
- lo |= VIA_NOISESRC1;
-
- /* Enable secondary noise source on CPUs where it is present. */
-
- /* Nehemiah stepping 8 and higher */
- if ((c->x86_model == 9) && (c->x86_mask > 7))
- lo |= VIA_NOISESRC2;
-
- /* Esther */
- if (c->x86_model >= 10)
- lo |= VIA_NOISESRC2;
if (lo != old_lo)
wrmsr(MSR_VIA_RNG, lo, hi);
diff --git a/trunk/drivers/char/i8k.c b/trunk/drivers/char/i8k.c
index 179223a17414..30e564516422 100644
--- a/trunk/drivers/char/i8k.c
+++ b/trunk/drivers/char/i8k.c
@@ -439,13 +439,6 @@ static struct dmi_system_id __initdata i8k_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
},
},
- { /* UK Inspiron 6400 */
- .ident = "Dell Inspiron 3",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "MM061"),
- },
- },
{ }
};
diff --git a/trunk/drivers/char/ip27-rtc.c b/trunk/drivers/char/ip27-rtc.c
index 86e6538a77b0..932264a657d0 100644
--- a/trunk/drivers/char/ip27-rtc.c
+++ b/trunk/drivers/char/ip27-rtc.c
@@ -46,8 +46,8 @@
#include
#include
-static long rtc_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg);
+static int rtc_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg);
static int rtc_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data);
@@ -75,7 +75,8 @@ static unsigned long epoch = 1970; /* year corresponding to 0x00 */
static const unsigned char days_in_mo[] =
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-static long rtc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
{
struct rtc_time wtime;
@@ -196,7 +197,7 @@ static int rtc_release(struct inode *inode, struct file *file)
static const struct file_operations rtc_fops = {
.owner = THIS_MODULE,
- .unlocked_ioctl = rtc_ioctl,
+ .ioctl = rtc_ioctl,
.open = rtc_open,
.release = rtc_release,
};
diff --git a/trunk/drivers/char/ipmi/ipmi_msghandler.c b/trunk/drivers/char/ipmi/ipmi_msghandler.c
index 32b2b22996dc..5dc1265ce1d5 100644
--- a/trunk/drivers/char/ipmi/ipmi_msghandler.c
+++ b/trunk/drivers/char/ipmi/ipmi_msghandler.c
@@ -365,12 +365,12 @@ static struct device_driver ipmidriver = {
};
static DEFINE_MUTEX(ipmidriver_mutex);
-static LIST_HEAD(ipmi_interfaces);
+static struct list_head ipmi_interfaces = LIST_HEAD_INIT(ipmi_interfaces);
static DEFINE_MUTEX(ipmi_interfaces_mutex);
/* List of watchers that want to know when smi's are added and
deleted. */
-static LIST_HEAD(smi_watchers);
+static struct list_head smi_watchers = LIST_HEAD_INIT(smi_watchers);
static DEFINE_MUTEX(smi_watchers_mutex);
@@ -441,7 +441,7 @@ struct watcher_entry {
int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
{
ipmi_smi_t intf;
- LIST_HEAD(to_deliver);
+ struct list_head to_deliver = LIST_HEAD_INIT(to_deliver);
struct watcher_entry *e, *e2;
mutex_lock(&smi_watchers_mutex);
diff --git a/trunk/drivers/char/lp.c b/trunk/drivers/char/lp.c
index 60ac642752be..81674d7c56c7 100644
--- a/trunk/drivers/char/lp.c
+++ b/trunk/drivers/char/lp.c
@@ -312,7 +312,7 @@ static ssize_t lp_write(struct file * file, const char __user * buf,
if (copy_size > LP_BUFFER_SIZE)
copy_size = LP_BUFFER_SIZE;
- if (mutex_lock_interruptible(&lp_table[minor].port_mutex))
+ if (down_interruptible (&lp_table[minor].port_mutex))
return -EINTR;
if (copy_from_user (kbuf, buf, copy_size)) {
@@ -399,7 +399,7 @@ static ssize_t lp_write(struct file * file, const char __user * buf,
lp_release_parport (&lp_table[minor]);
}
out_unlock:
- mutex_unlock(&lp_table[minor].port_mutex);
+ up (&lp_table[minor].port_mutex);
return retv;
}
@@ -421,7 +421,7 @@ static ssize_t lp_read(struct file * file, char __user * buf,
if (count > LP_BUFFER_SIZE)
count = LP_BUFFER_SIZE;
- if (mutex_lock_interruptible(&lp_table[minor].port_mutex))
+ if (down_interruptible (&lp_table[minor].port_mutex))
return -EINTR;
lp_claim_parport_or_block (&lp_table[minor]);
@@ -479,7 +479,7 @@ static ssize_t lp_read(struct file * file, char __user * buf,
if (retval > 0 && copy_to_user (buf, kbuf, retval))
retval = -EFAULT;
- mutex_unlock(&lp_table[minor].port_mutex);
+ up (&lp_table[minor].port_mutex);
return retval;
}
@@ -888,7 +888,7 @@ static int __init lp_init (void)
lp_table[i].last_error = 0;
init_waitqueue_head (&lp_table[i].waitq);
init_waitqueue_head (&lp_table[i].dataq);
- mutex_init(&lp_table[i].port_mutex);
+ init_MUTEX (&lp_table[i].port_mutex);
lp_table[i].timeout = 10 * HZ;
}
diff --git a/trunk/drivers/char/mxser.c b/trunk/drivers/char/mxser.c
index 47420787a017..fd0abef7ee08 100644
--- a/trunk/drivers/char/mxser.c
+++ b/trunk/drivers/char/mxser.c
@@ -37,6 +37,7 @@
#include
+#include
#include
#include
#include
diff --git a/trunk/drivers/char/mxser_new.c b/trunk/drivers/char/mxser_new.c
index bf1bee4e1f5e..081c84c7b548 100644
--- a/trunk/drivers/char/mxser_new.c
+++ b/trunk/drivers/char/mxser_new.c
@@ -20,6 +20,7 @@
*/
#include
+#include
#include
#include
#include
diff --git a/trunk/drivers/char/n_tty.c b/trunk/drivers/char/n_tty.c
index 90c3969012a3..596c7173997b 100644
--- a/trunk/drivers/char/n_tty.c
+++ b/trunk/drivers/char/n_tty.c
@@ -695,16 +695,17 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
return;
}
+ if (tty->stopped && !tty->flow_stopped &&
+ I_IXON(tty) && I_IXANY(tty)) {
+ start_tty(tty);
+ return;
+ }
+
if (I_ISTRIP(tty))
c &= 0x7f;
if (I_IUCLC(tty) && L_IEXTEN(tty))
c=tolower(c);
- if (tty->stopped && !tty->flow_stopped && I_IXON(tty) &&
- ((I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty)) ||
- c == INTR_CHAR(tty) || c == QUIT_CHAR(tty)))
- start_tty(tty);
-
if (tty->closing) {
if (I_IXON(tty)) {
if (c == START_CHAR(tty))
@@ -768,21 +769,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
signal = SIGTSTP;
if (c == SUSP_CHAR(tty)) {
send_signal:
- /*
- * Echo character, and then send the signal.
- * Note that we do not use isig() here because we want
- * the order to be:
- * 1) flush, 2) echo, 3) signal
- */
- if (!L_NOFLSH(tty)) {
- n_tty_flush_buffer(tty);
- if (tty->driver->flush_buffer)
- tty->driver->flush_buffer(tty);
- }
- if (L_ECHO(tty))
- echo_char(c, tty);
- if (tty->pgrp)
- kill_pgrp(tty->pgrp, signal, 1);
+ isig(signal, tty, 0);
return;
}
}
diff --git a/trunk/drivers/char/pcmcia/synclink_cs.c b/trunk/drivers/char/pcmcia/synclink_cs.c
index 279ff5005cec..8caff0ca80ff 100644
--- a/trunk/drivers/char/pcmcia/synclink_cs.c
+++ b/trunk/drivers/char/pcmcia/synclink_cs.c
@@ -57,7 +57,6 @@
#include
#include
#include
-#include
#include
#include
@@ -88,6 +87,8 @@
#include
+#include "linux/synclink.h"
+
static MGSL_PARAMS default_params = {
MGSL_MODE_HDLC, /* unsigned long mode */
0, /* unsigned char loopback; */
diff --git a/trunk/drivers/char/random.c b/trunk/drivers/char/random.c
index f43c89f7c449..c511a831f0c0 100644
--- a/trunk/drivers/char/random.c
+++ b/trunk/drivers/char/random.c
@@ -1039,7 +1039,6 @@ write_pool(struct entropy_store *r, const char __user *buffer, size_t count)
p += bytes;
add_entropy_words(r, buf, (bytes + 3) / 4);
- cond_resched();
}
return 0;
diff --git a/trunk/drivers/char/riscom8.c b/trunk/drivers/char/riscom8.c
index d130b87d8ed7..102ece4c4e0e 100644
--- a/trunk/drivers/char/riscom8.c
+++ b/trunk/drivers/char/riscom8.c
@@ -47,7 +47,6 @@
#include
#include
#include
-#include
#include
@@ -82,8 +81,6 @@
static struct tty_driver *riscom_driver;
-static DEFINE_SPINLOCK(riscom_lock);
-
static struct riscom_board rc_board[RC_NBOARD] = {
{
.base = RC_IOBASE1,
@@ -220,14 +217,13 @@ static void __init rc_init_CD180(struct riscom_board const * bp)
{
unsigned long flags;
- spin_lock_irqsave(&riscom_lock, flags);
-
+ save_flags(flags); cli();
rc_out(bp, RC_CTOUT, 0); /* Clear timeout */
rc_wait_CCR(bp); /* Wait for CCR ready */
rc_out(bp, CD180_CCR, CCR_HARDRESET); /* Reset CD180 chip */
- spin_unlock_irqrestore(&riscom_lock, flags);
+ sti();
msleep(50); /* Delay 0.05 sec */
- spin_lock_irqsave(&riscom_lock, flags);
+ cli();
rc_out(bp, CD180_GIVR, RC_ID); /* Set ID for this chip */
rc_out(bp, CD180_GICR, 0); /* Clear all bits */
rc_out(bp, CD180_PILR1, RC_ACK_MINT); /* Prio for modem intr */
@@ -238,7 +234,7 @@ static void __init rc_init_CD180(struct riscom_board const * bp)
rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8);
rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff);
- spin_unlock_irqrestore(&riscom_lock, flags);
+ restore_flags(flags);
}
/* Main probing routine, also sets irq. */
@@ -816,9 +812,9 @@ static int rc_setup_port(struct riscom_board *bp, struct riscom_port *port)
}
port->xmit_buf = (unsigned char *) tmp;
}
-
- spin_lock_irqsave(&riscom_lock, flags);
-
+
+ save_flags(flags); cli();
+
if (port->tty)
clear_bit(TTY_IO_ERROR, &port->tty->flags);
@@ -829,7 +825,7 @@ static int rc_setup_port(struct riscom_board *bp, struct riscom_port *port)
rc_change_speed(bp, port);
port->flags |= ASYNC_INITIALIZED;
- spin_unlock_irqrestore(&riscom_lock, flags);
+ restore_flags(flags);
return 0;
}
@@ -905,7 +901,6 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
int retval;
int do_clocal = 0;
int CD;
- unsigned long flags;
/*
* If the device is in the middle of being closed, then block
@@ -941,26 +936,19 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
*/
retval = 0;
add_wait_queue(&port->open_wait, &wait);
-
- spin_lock_irqsave(&riscom_lock, flags);
-
+ cli();
if (!tty_hung_up_p(filp))
port->count--;
-
- spin_unlock_irqrestore(&riscom_lock, flags);
-
+ sti();
port->blocked_open++;
while (1) {
- spin_lock_irqsave(&riscom_lock, flags);
-
+ cli();
rc_out(bp, CD180_CAR, port_No(port));
CD = rc_in(bp, CD180_MSVR) & MSVR_CD;
rc_out(bp, CD180_MSVR, MSVR_RTS);
bp->DTR &= ~(1u << port_No(port));
rc_out(bp, RC_DTR, bp->DTR);
-
- spin_unlock_irqrestore(&riscom_lock, flags);
-
+ sti();
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(port->flags & ASYNC_INITIALIZED)) {
@@ -1032,9 +1020,8 @@ static void rc_close(struct tty_struct * tty, struct file * filp)
if (!port || rc_paranoia_check(port, tty->name, "close"))
return;
-
- spin_lock_irqsave(&riscom_lock, flags);
-
+
+ save_flags(flags); cli();
if (tty_hung_up_p(filp))
goto out;
@@ -1101,9 +1088,7 @@ static void rc_close(struct tty_struct * tty, struct file * filp)
}
port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
wake_up_interruptible(&port->close_wait);
-
-out:
- spin_unlock_irqrestore(&riscom_lock, flags);
+out: restore_flags(flags);
}
static int rc_write(struct tty_struct * tty,
@@ -1122,33 +1107,34 @@ static int rc_write(struct tty_struct * tty,
if (!tty || !port->xmit_buf)
return 0;
+ save_flags(flags);
while (1) {
- spin_lock_irqsave(&riscom_lock, flags);
-
+ cli();
c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
SERIAL_XMIT_SIZE - port->xmit_head));
- if (c <= 0)
- break; /* lock continues to be held */
+ if (c <= 0) {
+ restore_flags(flags);
+ break;
+ }
memcpy(port->xmit_buf + port->xmit_head, buf, c);
port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
port->xmit_cnt += c;
-
- spin_unlock_irqrestore(&riscom_lock, flags);
+ restore_flags(flags);
buf += c;
count -= c;
total += c;
}
+ cli();
if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
!(port->IER & IER_TXRDY)) {
port->IER |= IER_TXRDY;
rc_out(bp, CD180_CAR, port_No(port));
rc_out(bp, CD180_IER, port->IER);
}
-
- spin_unlock_irqrestore(&riscom_lock, flags);
+ restore_flags(flags);
return total;
}
@@ -1164,7 +1150,7 @@ static void rc_put_char(struct tty_struct * tty, unsigned char ch)
if (!tty || !port->xmit_buf)
return;
- spin_lock_irqsave(&riscom_lock, flags);
+ save_flags(flags); cli();
if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
goto out;
@@ -1172,9 +1158,7 @@ static void rc_put_char(struct tty_struct * tty, unsigned char ch)
port->xmit_buf[port->xmit_head++] = ch;
port->xmit_head &= SERIAL_XMIT_SIZE - 1;
port->xmit_cnt++;
-
-out:
- spin_unlock_irqrestore(&riscom_lock, flags);
+out: restore_flags(flags);
}
static void rc_flush_chars(struct tty_struct * tty)
@@ -1189,13 +1173,11 @@ static void rc_flush_chars(struct tty_struct * tty)
!port->xmit_buf)
return;
- spin_lock_irqsave(&riscom_lock, flags);
-
+ save_flags(flags); cli();
port->IER |= IER_TXRDY;
rc_out(port_Board(port), CD180_CAR, port_No(port));
rc_out(port_Board(port), CD180_IER, port->IER);
-
- spin_unlock_irqrestore(&riscom_lock, flags);
+ restore_flags(flags);
}
static int rc_write_room(struct tty_struct * tty)
@@ -1230,11 +1212,9 @@ static void rc_flush_buffer(struct tty_struct *tty)
if (rc_paranoia_check(port, tty->name, "rc_flush_buffer"))
return;
- spin_lock_irqsave(&riscom_lock, flags);
-
+ save_flags(flags); cli();
port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-
- spin_unlock_irqrestore(&riscom_lock, flags);
+ restore_flags(flags);
tty_wakeup(tty);
}
@@ -1251,15 +1231,11 @@ static int rc_tiocmget(struct tty_struct *tty, struct file *file)
return -ENODEV;
bp = port_Board(port);
-
- spin_lock_irqsave(&riscom_lock, flags);
-
+ save_flags(flags); cli();
rc_out(bp, CD180_CAR, port_No(port));
status = rc_in(bp, CD180_MSVR);
result = rc_in(bp, RC_RI) & (1u << port_No(port)) ? 0 : TIOCM_RNG;
-
- spin_unlock_irqrestore(&riscom_lock, flags);
-
+ restore_flags(flags);
result |= ((status & MSVR_RTS) ? TIOCM_RTS : 0)
| ((status & MSVR_DTR) ? TIOCM_DTR : 0)
| ((status & MSVR_CD) ? TIOCM_CAR : 0)
@@ -1280,8 +1256,7 @@ static int rc_tiocmset(struct tty_struct *tty, struct file *file,
bp = port_Board(port);
- spin_lock_irqsave(&riscom_lock, flags);
-
+ save_flags(flags); cli();
if (set & TIOCM_RTS)
port->MSVR |= MSVR_RTS;
if (set & TIOCM_DTR)
@@ -1295,9 +1270,7 @@ static int rc_tiocmset(struct tty_struct *tty, struct file *file,
rc_out(bp, CD180_CAR, port_No(port));
rc_out(bp, CD180_MSVR, port->MSVR);
rc_out(bp, RC_DTR, bp->DTR);
-
- spin_unlock_irqrestore(&riscom_lock, flags);
-
+ restore_flags(flags);
return 0;
}
@@ -1306,8 +1279,7 @@ static inline void rc_send_break(struct riscom_port * port, unsigned long length
struct riscom_board *bp = port_Board(port);
unsigned long flags;
- spin_lock_irqsave(&riscom_lock, flags);
-
+ save_flags(flags); cli();
port->break_length = RISCOM_TPS / HZ * length;
port->COR2 |= COR2_ETC;
port->IER |= IER_TXRDY;
@@ -1317,8 +1289,7 @@ static inline void rc_send_break(struct riscom_port * port, unsigned long length
rc_wait_CCR(bp);
rc_out(bp, CD180_CCR, CCR_CORCHG2);
rc_wait_CCR(bp);
-
- spin_unlock_irqrestore(&riscom_lock, flags);
+ restore_flags(flags);
}
static inline int rc_set_serial_info(struct riscom_port * port,
@@ -1327,6 +1298,7 @@ static inline int rc_set_serial_info(struct riscom_port * port,
struct serial_struct tmp;
struct riscom_board *bp = port_Board(port);
int change_speed;
+ unsigned long flags;
if (copy_from_user(&tmp, newinfo, sizeof(tmp)))
return -EFAULT;
@@ -1360,11 +1332,9 @@ static inline int rc_set_serial_info(struct riscom_port * port,
port->closing_wait = tmp.closing_wait;
}
if (change_speed) {
- unsigned long flags;
-
- spin_lock_irqsave(&riscom_lock, flags);
+ save_flags(flags); cli();
rc_change_speed(bp, port);
- spin_unlock_irqrestore(&riscom_lock, flags);
+ restore_flags(flags);
}
return 0;
}
@@ -1444,19 +1414,17 @@ static void rc_throttle(struct tty_struct * tty)
return;
bp = port_Board(port);
-
- spin_lock_irqsave(&riscom_lock, flags);
-
+
+ save_flags(flags); cli();
port->MSVR &= ~MSVR_RTS;
rc_out(bp, CD180_CAR, port_No(port));
- if (I_IXOFF(tty)) {
+ if (I_IXOFF(tty)) {
rc_wait_CCR(bp);
rc_out(bp, CD180_CCR, CCR_SSCH2);
rc_wait_CCR(bp);
}
rc_out(bp, CD180_MSVR, port->MSVR);
-
- spin_unlock_irqrestore(&riscom_lock, flags);
+ restore_flags(flags);
}
static void rc_unthrottle(struct tty_struct * tty)
@@ -1470,8 +1438,7 @@ static void rc_unthrottle(struct tty_struct * tty)
bp = port_Board(port);
- spin_lock_irqsave(&riscom_lock, flags);
-
+ save_flags(flags); cli();
port->MSVR |= MSVR_RTS;
rc_out(bp, CD180_CAR, port_No(port));
if (I_IXOFF(tty)) {
@@ -1480,8 +1447,7 @@ static void rc_unthrottle(struct tty_struct * tty)
rc_wait_CCR(bp);
}
rc_out(bp, CD180_MSVR, port->MSVR);
-
- spin_unlock_irqrestore(&riscom_lock, flags);
+ restore_flags(flags);
}
static void rc_stop(struct tty_struct * tty)
@@ -1495,13 +1461,11 @@ static void rc_stop(struct tty_struct * tty)
bp = port_Board(port);
- spin_lock_irqsave(&riscom_lock, flags);
-
+ save_flags(flags); cli();
port->IER &= ~IER_TXRDY;
rc_out(bp, CD180_CAR, port_No(port));
rc_out(bp, CD180_IER, port->IER);
-
- spin_unlock_irqrestore(&riscom_lock, flags);
+ restore_flags(flags);
}
static void rc_start(struct tty_struct * tty)
@@ -1515,15 +1479,13 @@ static void rc_start(struct tty_struct * tty)
bp = port_Board(port);
- spin_lock_irqsave(&riscom_lock, flags);
-
+ save_flags(flags); cli();
if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
port->IER |= IER_TXRDY;
rc_out(bp, CD180_CAR, port_No(port));
rc_out(bp, CD180_IER, port->IER);
}
-
- spin_unlock_irqrestore(&riscom_lock, flags);
+ restore_flags(flags);
}
/*
@@ -1575,9 +1537,9 @@ static void rc_set_termios(struct tty_struct * tty, struct ktermios * old_termio
tty->termios->c_iflag == old_termios->c_iflag)
return;
- spin_lock_irqsave(&riscom_lock, flags);
+ save_flags(flags); cli();
rc_change_speed(port_Board(port), port);
- spin_unlock_irqrestore(&riscom_lock, flags);
+ restore_flags(flags);
if ((old_termios->c_cflag & CRTSCTS) &&
!(tty->termios->c_cflag & CRTSCTS)) {
@@ -1665,12 +1627,11 @@ static void rc_release_drivers(void)
{
unsigned long flags;
- spin_lock_irqsave(&riscom_lock, flags);
-
+ save_flags(flags);
+ cli();
tty_unregister_driver(riscom_driver);
put_tty_driver(riscom_driver);
-
- spin_unlock_irqrestore(&riscom_lock, flags);
+ restore_flags(flags);
}
#ifndef MODULE
diff --git a/trunk/drivers/char/ser_a2232.c b/trunk/drivers/char/ser_a2232.c
index 4ba3aec9e1cd..3c869145bfdc 100644
--- a/trunk/drivers/char/ser_a2232.c
+++ b/trunk/drivers/char/ser_a2232.c
@@ -653,7 +653,7 @@ static void a2232_init_portstructs(void)
port->gs.closing_wait = 30 * HZ;
port->gs.rd = &a2232_real_driver;
#ifdef NEW_WRITE_LOCKING
- mutex_init(&(port->gs.port_write_mutex));
+ init_MUTEX(&(port->gs.port_write_mutex));
#endif
init_waitqueue_head(&port->gs.open_wait);
init_waitqueue_head(&port->gs.close_wait);
diff --git a/trunk/drivers/char/synclink.c b/trunk/drivers/char/synclink.c
index ddc74d1f4f1b..d010ed95ed3b 100644
--- a/trunk/drivers/char/synclink.c
+++ b/trunk/drivers/char/synclink.c
@@ -85,7 +85,6 @@
#include
#include
#include
-#include
#include
#include
@@ -111,6 +110,8 @@
#include
+#include "linux/synclink.h"
+
#define RCLRVALUE 0xffff
static MGSL_PARAMS default_params = {
diff --git a/trunk/drivers/char/synclink_gt.c b/trunk/drivers/char/synclink_gt.c
index 1f954acf2bac..64e835f62438 100644
--- a/trunk/drivers/char/synclink_gt.c
+++ b/trunk/drivers/char/synclink_gt.c
@@ -73,7 +73,6 @@
#include
#include
#include
-#include
#include
#include
@@ -82,6 +81,8 @@
#include
#include
+#include "linux/synclink.h"
+
#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_GT_MODULE))
#define SYNCLINK_GENERIC_HDLC 1
#else
@@ -2039,41 +2040,37 @@ static void bh_transmit(struct slgt_info *info)
tty_wakeup(tty);
}
-static void dsr_change(struct slgt_info *info, unsigned short status)
+static void dsr_change(struct slgt_info *info)
{
- if (status & BIT3) {
- info->signals |= SerialSignal_DSR;
- info->input_signal_events.dsr_up++;
- } else {
- info->signals &= ~SerialSignal_DSR;
- info->input_signal_events.dsr_down++;
- }
+ get_signals(info);
DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals));
if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
slgt_irq_off(info, IRQ_DSR);
return;
}
info->icount.dsr++;
+ if (info->signals & SerialSignal_DSR)
+ info->input_signal_events.dsr_up++;
+ else
+ info->input_signal_events.dsr_down++;
wake_up_interruptible(&info->status_event_wait_q);
wake_up_interruptible(&info->event_wait_q);
info->pending_bh |= BH_STATUS;
}
-static void cts_change(struct slgt_info *info, unsigned short status)
+static void cts_change(struct slgt_info *info)
{
- if (status & BIT2) {
- info->signals |= SerialSignal_CTS;
- info->input_signal_events.cts_up++;
- } else {
- info->signals &= ~SerialSignal_CTS;
- info->input_signal_events.cts_down++;
- }
+ get_signals(info);
DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals));
if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
slgt_irq_off(info, IRQ_CTS);
return;
}
info->icount.cts++;
+ if (info->signals & SerialSignal_CTS)
+ info->input_signal_events.cts_up++;
+ else
+ info->input_signal_events.cts_down++;
wake_up_interruptible(&info->status_event_wait_q);
wake_up_interruptible(&info->event_wait_q);
info->pending_bh |= BH_STATUS;
@@ -2094,21 +2091,20 @@ static void cts_change(struct slgt_info *info, unsigned short status)
}
}
-static void dcd_change(struct slgt_info *info, unsigned short status)
+static void dcd_change(struct slgt_info *info)
{
- if (status & BIT1) {
- info->signals |= SerialSignal_DCD;
- info->input_signal_events.dcd_up++;
- } else {
- info->signals &= ~SerialSignal_DCD;
- info->input_signal_events.dcd_down++;
- }
+ get_signals(info);
DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals));
if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
slgt_irq_off(info, IRQ_DCD);
return;
}
info->icount.dcd++;
+ if (info->signals & SerialSignal_DCD) {
+ info->input_signal_events.dcd_up++;
+ } else {
+ info->input_signal_events.dcd_down++;
+ }
#if SYNCLINK_GENERIC_HDLC
if (info->netcount) {
if (info->signals & SerialSignal_DCD)
@@ -2131,21 +2127,20 @@ static void dcd_change(struct slgt_info *info, unsigned short status)
}
}
-static void ri_change(struct slgt_info *info, unsigned short status)
+static void ri_change(struct slgt_info *info)
{
- if (status & BIT0) {
- info->signals |= SerialSignal_RI;
- info->input_signal_events.ri_up++;
- } else {
- info->signals &= ~SerialSignal_RI;
- info->input_signal_events.ri_down++;
- }
+ get_signals(info);
DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals));
if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
slgt_irq_off(info, IRQ_RI);
return;
}
- info->icount.rng++;
+ info->icount.dcd++;
+ if (info->signals & SerialSignal_RI) {
+ info->input_signal_events.ri_up++;
+ } else {
+ info->input_signal_events.ri_down++;
+ }
wake_up_interruptible(&info->status_event_wait_q);
wake_up_interruptible(&info->event_wait_q);
info->pending_bh |= BH_STATUS;
@@ -2196,13 +2191,13 @@ static void isr_serial(struct slgt_info *info)
}
if (status & IRQ_DSR)
- dsr_change(info, status);
+ dsr_change(info);
if (status & IRQ_CTS)
- cts_change(info, status);
+ cts_change(info);
if (status & IRQ_DCD)
- dcd_change(info, status);
+ dcd_change(info);
if (status & IRQ_RI)
- ri_change(info, status);
+ ri_change(info);
}
static void isr_rdma(struct slgt_info *info)
diff --git a/trunk/drivers/char/synclinkmp.c b/trunk/drivers/char/synclinkmp.c
index f3e7807f78d9..c63013b2fc36 100644
--- a/trunk/drivers/char/synclinkmp.c
+++ b/trunk/drivers/char/synclinkmp.c
@@ -66,7 +66,6 @@
#include
#include
#include
-#include
#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINKMP_MODULE))
#define SYNCLINK_GENERIC_HDLC 1
@@ -81,6 +80,8 @@
#include
+#include "linux/synclink.h"
+
static MGSL_PARAMS default_params = {
MGSL_MODE_HDLC, /* unsigned long mode */
0, /* unsigned char loopback; */
diff --git a/trunk/drivers/char/tpm/tpm.c b/trunk/drivers/char/tpm/tpm.c
index a5d8bcb40000..c88424a0c89b 100644
--- a/trunk/drivers/char/tpm/tpm.c
+++ b/trunk/drivers/char/tpm/tpm.c
@@ -1031,13 +1031,18 @@ void tpm_remove_hardware(struct device *dev)
spin_unlock(&driver_lock);
+ dev_set_drvdata(dev, NULL);
misc_deregister(&chip->vendor.miscdev);
+ kfree(chip->vendor.miscdev.name);
sysfs_remove_group(&dev->kobj, chip->vendor.attr_group);
tpm_bios_log_teardown(chip->bios_dir);
- /* write it this way to be explicit (chip->dev == dev) */
- put_device(chip->dev);
+ clear_bit(chip->dev_num, dev_mask);
+
+ kfree(chip);
+
+ put_device(dev);
}
EXPORT_SYMBOL_GPL(tpm_remove_hardware);
@@ -1077,26 +1082,6 @@ int tpm_pm_resume(struct device *dev)
}
EXPORT_SYMBOL_GPL(tpm_pm_resume);
-/*
- * Once all references to platform device are down to 0,
- * release all allocated structures.
- * In case vendor provided release function,
- * call it too.
- */
-static void tpm_dev_release(struct device *dev)
-{
- struct tpm_chip *chip = dev_get_drvdata(dev);
-
- if (chip->vendor.release)
- chip->vendor.release(dev);
-
- chip->release(dev);
-
- clear_bit(chip->dev_num, dev_mask);
- kfree(chip->vendor.miscdev.name);
- kfree(chip);
-}
-
/*
* Called from tpm_.c probe function only for devices
* the driver has determined it should claim. Prior to calling
@@ -1151,21 +1136,23 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend
chip->vendor.miscdev.parent = dev;
chip->dev = get_device(dev);
- chip->release = dev->release;
- dev->release = tpm_dev_release;
- dev_set_drvdata(dev, chip);
if (misc_register(&chip->vendor.miscdev)) {
dev_err(chip->dev,
"unable to misc_register %s, minor %d\n",
chip->vendor.miscdev.name,
chip->vendor.miscdev.minor);
- put_device(chip->dev);
+ put_device(dev);
+ clear_bit(chip->dev_num, dev_mask);
+ kfree(chip);
+ kfree(devname);
return NULL;
}
spin_lock(&driver_lock);
+ dev_set_drvdata(dev, chip);
+
list_add(&chip->list, &tpm_chip_list);
spin_unlock(&driver_lock);
@@ -1173,7 +1160,10 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend
if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) {
list_del(&chip->list);
misc_deregister(&chip->vendor.miscdev);
- put_device(chip->dev);
+ put_device(dev);
+ clear_bit(chip->dev_num, dev_mask);
+ kfree(chip);
+ kfree(devname);
return NULL;
}
diff --git a/trunk/drivers/char/tpm/tpm.h b/trunk/drivers/char/tpm/tpm.h
index e885148b4cfb..d15ccddc92eb 100644
--- a/trunk/drivers/char/tpm/tpm.h
+++ b/trunk/drivers/char/tpm/tpm.h
@@ -74,7 +74,6 @@ struct tpm_vendor_specific {
int (*send) (struct tpm_chip *, u8 *, size_t);
void (*cancel) (struct tpm_chip *);
u8 (*status) (struct tpm_chip *);
- void (*release) (struct device *);
struct miscdevice miscdev;
struct attribute_group *attr_group;
struct list_head list;
@@ -107,7 +106,6 @@ struct tpm_chip {
struct dentry **bios_dir;
struct list_head list;
- void (*release) (struct device *);
};
#define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor)
diff --git a/trunk/drivers/char/tpm/tpm_infineon.c b/trunk/drivers/char/tpm/tpm_infineon.c
index 726ee8a0277f..967002a5a1e5 100644
--- a/trunk/drivers/char/tpm/tpm_infineon.c
+++ b/trunk/drivers/char/tpm/tpm_infineon.c
@@ -611,7 +611,7 @@ static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev)
}
}
-static struct pnp_driver tpm_inf_pnp_driver = {
+static struct pnp_driver tpm_inf_pnp = {
.name = "tpm_inf_pnp",
.driver = {
.owner = THIS_MODULE,
@@ -625,12 +625,12 @@ static struct pnp_driver tpm_inf_pnp_driver = {
static int __init init_inf(void)
{
- return pnp_register_driver(&tpm_inf_pnp_driver);
+ return pnp_register_driver(&tpm_inf_pnp);
}
static void __exit cleanup_inf(void)
{
- pnp_unregister_driver(&tpm_inf_pnp_driver);
+ pnp_unregister_driver(&tpm_inf_pnp);
}
module_init(init_inf);
diff --git a/trunk/drivers/char/tty_io.c b/trunk/drivers/char/tty_io.c
index 79c86c47947f..f36fecd3fd26 100644
--- a/trunk/drivers/char/tty_io.c
+++ b/trunk/drivers/char/tty_io.c
@@ -138,7 +138,7 @@ EXPORT_SYMBOL(tty_mutex);
extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */
extern int pty_limit; /* Config limit on Unix98 ptys */
static DEFINE_IDR(allocated_ptys);
-static DEFINE_MUTEX(allocated_ptys_lock);
+static DECLARE_MUTEX(allocated_ptys_lock);
static int ptmx_open(struct inode *, struct file *);
#endif
@@ -2571,9 +2571,9 @@ static void release_dev(struct file * filp)
#ifdef CONFIG_UNIX98_PTYS
/* Make this pty number available for reallocation */
if (devpts) {
- mutex_lock(&allocated_ptys_lock);
+ down(&allocated_ptys_lock);
idr_remove(&allocated_ptys, idx);
- mutex_unlock(&allocated_ptys_lock);
+ up(&allocated_ptys_lock);
}
#endif
@@ -2737,24 +2737,24 @@ static int ptmx_open(struct inode * inode, struct file * filp)
nonseekable_open(inode, filp);
/* find a device that is not in use. */
- mutex_lock(&allocated_ptys_lock);
+ down(&allocated_ptys_lock);
if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) {
- mutex_unlock(&allocated_ptys_lock);
+ up(&allocated_ptys_lock);
return -ENOMEM;
}
idr_ret = idr_get_new(&allocated_ptys, NULL, &index);
if (idr_ret < 0) {
- mutex_unlock(&allocated_ptys_lock);
+ up(&allocated_ptys_lock);
if (idr_ret == -EAGAIN)
return -ENOMEM;
return -EIO;
}
if (index >= pty_limit) {
idr_remove(&allocated_ptys, index);
- mutex_unlock(&allocated_ptys_lock);
+ up(&allocated_ptys_lock);
return -EIO;
}
- mutex_unlock(&allocated_ptys_lock);
+ up(&allocated_ptys_lock);
mutex_lock(&tty_mutex);
retval = init_dev(ptm_driver, index, &tty);
@@ -2781,9 +2781,9 @@ static int ptmx_open(struct inode * inode, struct file * filp)
release_dev(filp);
return retval;
out:
- mutex_lock(&allocated_ptys_lock);
+ down(&allocated_ptys_lock);
idr_remove(&allocated_ptys, index);
- mutex_unlock(&allocated_ptys_lock);
+ up(&allocated_ptys_lock);
return retval;
}
#endif
@@ -3721,6 +3721,7 @@ static void initialize_tty_struct(struct tty_struct *tty)
tty->buf.head = tty->buf.tail = NULL;
tty_buffer_init(tty);
INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc);
+ init_MUTEX(&tty->buf.pty_sem);
mutex_init(&tty->termios_mutex);
init_waitqueue_head(&tty->write_wait);
init_waitqueue_head(&tty->read_wait);
@@ -4047,6 +4048,10 @@ void __init console_init(void)
}
}
+#ifdef CONFIG_VT
+extern int vty_init(void);
+#endif
+
static int __init tty_class_init(void)
{
tty_class = class_create(THIS_MODULE, "tty");
diff --git a/trunk/drivers/char/vt.c b/trunk/drivers/char/vt.c
index 367be9175061..7a5badfb7d84 100644
--- a/trunk/drivers/char/vt.c
+++ b/trunk/drivers/char/vt.c
@@ -2400,15 +2400,13 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
{
struct vc_data *vc = vc_cons[fg_console].d;
unsigned char c;
- static DEFINE_SPINLOCK(printing_lock);
+ static unsigned long printing;
const ushort *start;
ushort cnt = 0;
ushort myx;
/* console busy or not yet initialized */
- if (!printable)
- return;
- if (!spin_trylock(&printing_lock))
+ if (!printable || test_and_set_bit(0, &printing))
return;
if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
@@ -2483,7 +2481,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
notify_update(vc);
quit:
- spin_unlock(&printing_lock);
+ clear_bit(0, &printing);
}
static struct tty_driver *vt_console_device(struct console *c, int *index)
diff --git a/trunk/drivers/firmware/dcdbas.c b/trunk/drivers/firmware/dcdbas.c
index 1636806ec55e..18cdcb3ae1ca 100644
--- a/trunk/drivers/firmware/dcdbas.c
+++ b/trunk/drivers/firmware/dcdbas.c
@@ -658,5 +658,4 @@ MODULE_DESCRIPTION(DRIVER_DESCRIPTION " (version " DRIVER_VERSION ")");
MODULE_VERSION(DRIVER_VERSION);
MODULE_AUTHOR("Dell Inc.");
MODULE_LICENSE("GPL");
-/* Any System or BIOS claiming to be by Dell */
-MODULE_ALIAS("dmi:*:[bs]vnD[Ee][Ll][Ll]*:*");
+
diff --git a/trunk/drivers/firmware/dmi-id.c b/trunk/drivers/firmware/dmi-id.c
index e880d6c8d896..313c99cbdc62 100644
--- a/trunk/drivers/firmware/dmi-id.c
+++ b/trunk/drivers/firmware/dmi-id.c
@@ -11,6 +11,7 @@
#include
#include
#include
+#include
struct dmi_device_attribute{
struct device_attribute dev_attr;
diff --git a/trunk/drivers/gpio/Kconfig b/trunk/drivers/gpio/Kconfig
index bbd28342e771..74fac0f5c348 100644
--- a/trunk/drivers/gpio/Kconfig
+++ b/trunk/drivers/gpio/Kconfig
@@ -27,16 +27,15 @@ config DEBUG_GPIO
comment "I2C GPIO expanders:"
-config GPIO_PCA953X
- tristate "PCA953x I/O ports"
+config GPIO_PCA9539
+ tristate "PCA9539 16-bit I/O port"
depends on I2C
help
- Say yes here to support the PCA9534 (8-bit), PCA9535 (16-bit),
- PCA9536 (4-bit), PCA9537 (4-bit), PCA9538 (8-bit), and PCA9539
- (16-bit) I/O ports. These parts are made by NXP and TI.
+ Say yes here to support the PCA9539 16-bit I/O port. These
+ parts are made by NXP and TI.
This driver can also be built as a module. If so, the module
- will be called pca953x.
+ will be called pca9539.
config GPIO_PCF857X
tristate "PCF857x, PCA857x, and PCA967x I2C GPIO expanders"
diff --git a/trunk/drivers/gpio/Makefile b/trunk/drivers/gpio/Makefile
index fdde9923cf33..470ecd6aa778 100644
--- a/trunk/drivers/gpio/Makefile
+++ b/trunk/drivers/gpio/Makefile
@@ -5,5 +5,5 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
obj-$(CONFIG_HAVE_GPIO_LIB) += gpiolib.o
obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o
-obj-$(CONFIG_GPIO_PCA953X) += pca953x.o
+obj-$(CONFIG_GPIO_PCA9539) += pca9539.o
obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
diff --git a/trunk/drivers/gpio/pca9539.c b/trunk/drivers/gpio/pca9539.c
new file mode 100644
index 000000000000..3e85c92a7d59
--- /dev/null
+++ b/trunk/drivers/gpio/pca9539.c
@@ -0,0 +1,271 @@
+/*
+ * pca9539.c - 16-bit I/O port with interrupt and reset
+ *
+ * Copyright (C) 2005 Ben Gardner
+ * Copyright (C) 2007 Marvell International Ltd.
+ *
+ * Derived from drivers/i2c/chips/pca9539.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include
+#include
+#include
+#include
+
+#include
+
+
+#define NR_PCA9539_GPIOS 16
+
+#define PCA9539_INPUT 0
+#define PCA9539_OUTPUT 2
+#define PCA9539_INVERT 4
+#define PCA9539_DIRECTION 6
+
+struct pca9539_chip {
+ unsigned gpio_start;
+ uint16_t reg_output;
+ uint16_t reg_direction;
+
+ struct i2c_client *client;
+ struct gpio_chip gpio_chip;
+};
+
+/* NOTE: we can't currently rely on fault codes to come from SMBus
+ * calls, so we map all errors to EIO here and return zero otherwise.
+ */
+static int pca9539_write_reg(struct pca9539_chip *chip, int reg, uint16_t val)
+{
+ if (i2c_smbus_write_word_data(chip->client, reg, val) < 0)
+ return -EIO;
+ else
+ return 0;
+}
+
+static int pca9539_read_reg(struct pca9539_chip *chip, int reg, uint16_t *val)
+{
+ int ret;
+
+ ret = i2c_smbus_read_word_data(chip->client, reg);
+ if (ret < 0) {
+ dev_err(&chip->client->dev, "failed reading register\n");
+ return -EIO;
+ }
+
+ *val = (uint16_t)ret;
+ return 0;
+}
+
+static int pca9539_gpio_direction_input(struct gpio_chip *gc, unsigned off)
+{
+ struct pca9539_chip *chip;
+ uint16_t reg_val;
+ int ret;
+
+ chip = container_of(gc, struct pca9539_chip, gpio_chip);
+
+ reg_val = chip->reg_direction | (1u << off);
+ ret = pca9539_write_reg(chip, PCA9539_DIRECTION, reg_val);
+ if (ret)
+ return ret;
+
+ chip->reg_direction = reg_val;
+ return 0;
+}
+
+static int pca9539_gpio_direction_output(struct gpio_chip *gc,
+ unsigned off, int val)
+{
+ struct pca9539_chip *chip;
+ uint16_t reg_val;
+ int ret;
+
+ chip = container_of(gc, struct pca9539_chip, gpio_chip);
+
+ /* set output level */
+ if (val)
+ reg_val = chip->reg_output | (1u << off);
+ else
+ reg_val = chip->reg_output & ~(1u << off);
+
+ ret = pca9539_write_reg(chip, PCA9539_OUTPUT, reg_val);
+ if (ret)
+ return ret;
+
+ chip->reg_output = reg_val;
+
+ /* then direction */
+ reg_val = chip->reg_direction & ~(1u << off);
+ ret = pca9539_write_reg(chip, PCA9539_DIRECTION, reg_val);
+ if (ret)
+ return ret;
+
+ chip->reg_direction = reg_val;
+ return 0;
+}
+
+static int pca9539_gpio_get_value(struct gpio_chip *gc, unsigned off)
+{
+ struct pca9539_chip *chip;
+ uint16_t reg_val;
+ int ret;
+
+ chip = container_of(gc, struct pca9539_chip, gpio_chip);
+
+ ret = pca9539_read_reg(chip, PCA9539_INPUT, ®_val);
+ if (ret < 0) {
+ /* NOTE: diagnostic already emitted; that's all we should
+ * do unless gpio_*_value_cansleep() calls become different
+ * from their nonsleeping siblings (and report faults).
+ */
+ return 0;
+ }
+
+ return (reg_val & (1u << off)) ? 1 : 0;
+}
+
+static void pca9539_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
+{
+ struct pca9539_chip *chip;
+ uint16_t reg_val;
+ int ret;
+
+ chip = container_of(gc, struct pca9539_chip, gpio_chip);
+
+ if (val)
+ reg_val = chip->reg_output | (1u << off);
+ else
+ reg_val = chip->reg_output & ~(1u << off);
+
+ ret = pca9539_write_reg(chip, PCA9539_OUTPUT, reg_val);
+ if (ret)
+ return;
+
+ chip->reg_output = reg_val;
+}
+
+static int pca9539_init_gpio(struct pca9539_chip *chip)
+{
+ struct gpio_chip *gc;
+
+ gc = &chip->gpio_chip;
+
+ gc->direction_input = pca9539_gpio_direction_input;
+ gc->direction_output = pca9539_gpio_direction_output;
+ gc->get = pca9539_gpio_get_value;
+ gc->set = pca9539_gpio_set_value;
+
+ gc->base = chip->gpio_start;
+ gc->ngpio = NR_PCA9539_GPIOS;
+ gc->label = "pca9539";
+
+ return gpiochip_add(gc);
+}
+
+static int __devinit pca9539_probe(struct i2c_client *client)
+{
+ struct pca9539_platform_data *pdata;
+ struct pca9539_chip *chip;
+ int ret;
+
+ pdata = client->dev.platform_data;
+ if (pdata == NULL)
+ return -ENODEV;
+
+ chip = kzalloc(sizeof(struct pca9539_chip), GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+
+ chip->client = client;
+
+ chip->gpio_start = pdata->gpio_base;
+
+ /* initialize cached registers from their original values.
+ * we can't share this chip with another i2c master.
+ */
+ ret = pca9539_read_reg(chip, PCA9539_OUTPUT, &chip->reg_output);
+ if (ret)
+ goto out_failed;
+
+ ret = pca9539_read_reg(chip, PCA9539_DIRECTION, &chip->reg_direction);
+ if (ret)
+ goto out_failed;
+
+ /* set platform specific polarity inversion */
+ ret = pca9539_write_reg(chip, PCA9539_INVERT, pdata->invert);
+ if (ret)
+ goto out_failed;
+
+ ret = pca9539_init_gpio(chip);
+ if (ret)
+ goto out_failed;
+
+ if (pdata->setup) {
+ ret = pdata->setup(client, chip->gpio_chip.base,
+ chip->gpio_chip.ngpio, pdata->context);
+ if (ret < 0)
+ dev_warn(&client->dev, "setup failed, %d\n", ret);
+ }
+
+ i2c_set_clientdata(client, chip);
+ return 0;
+
+out_failed:
+ kfree(chip);
+ return ret;
+}
+
+static int pca9539_remove(struct i2c_client *client)
+{
+ struct pca9539_platform_data *pdata = client->dev.platform_data;
+ struct pca9539_chip *chip = i2c_get_clientdata(client);
+ int ret = 0;
+
+ if (pdata->teardown) {
+ ret = pdata->teardown(client, chip->gpio_chip.base,
+ chip->gpio_chip.ngpio, pdata->context);
+ if (ret < 0) {
+ dev_err(&client->dev, "%s failed, %d\n",
+ "teardown", ret);
+ return ret;
+ }
+ }
+
+ ret = gpiochip_remove(&chip->gpio_chip);
+ if (ret) {
+ dev_err(&client->dev, "%s failed, %d\n",
+ "gpiochip_remove()", ret);
+ return ret;
+ }
+
+ kfree(chip);
+ return 0;
+}
+
+static struct i2c_driver pca9539_driver = {
+ .driver = {
+ .name = "pca9539",
+ },
+ .probe = pca9539_probe,
+ .remove = pca9539_remove,
+};
+
+static int __init pca9539_init(void)
+{
+ return i2c_add_driver(&pca9539_driver);
+}
+module_init(pca9539_init);
+
+static void __exit pca9539_exit(void)
+{
+ i2c_del_driver(&pca9539_driver);
+}
+module_exit(pca9539_exit);
+
+MODULE_AUTHOR("eric miao ");
+MODULE_DESCRIPTION("GPIO expander driver for PCA9539");
+MODULE_LICENSE("GPL");
diff --git a/trunk/drivers/gpio/pca953x.c b/trunk/drivers/gpio/pca953x.c
deleted file mode 100644
index 92583cd4bffd..000000000000
--- a/trunk/drivers/gpio/pca953x.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * pca953x.c - 4/8/16 bit I/O ports
- *
- * Copyright (C) 2005 Ben Gardner
- * Copyright (C) 2007 Marvell International Ltd.
- *
- * Derived from drivers/i2c/chips/pca9539.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- */
-
-#include
-#include
-#include
-#include
-
-#include
-
-#define PCA953X_INPUT 0
-#define PCA953X_OUTPUT 1
-#define PCA953X_INVERT 2
-#define PCA953X_DIRECTION 3
-
-/* This is temporary - in 2.6.26 i2c_driver_data should replace it. */
-struct pca953x_desc {
- char name[I2C_NAME_SIZE];
- unsigned long driver_data;
-};
-
-static const struct pca953x_desc pca953x_descs[] = {
- { "pca9534", 8, },
- { "pca9535", 16, },
- { "pca9536", 4, },
- { "pca9537", 4, },
- { "pca9538", 8, },
- { "pca9539", 16, },
- /* REVISIT several pca955x parts should work here too */
-};
-
-struct pca953x_chip {
- unsigned gpio_start;
- uint16_t reg_output;
- uint16_t reg_direction;
-
- struct i2c_client *client;
- struct gpio_chip gpio_chip;
-};
-
-/* NOTE: we can't currently rely on fault codes to come from SMBus
- * calls, so we map all errors to EIO here and return zero otherwise.
- */
-static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
-{
- int ret;
-
- if (chip->gpio_chip.ngpio <= 8)
- ret = i2c_smbus_write_byte_data(chip->client, reg, val);
- else
- ret = i2c_smbus_write_word_data(chip->client, reg << 1, val);
-
- if (ret < 0) {
- dev_err(&chip->client->dev, "failed writing register\n");
- return -EIO;
- }
-
- return 0;
-}
-
-static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val)
-{
- int ret;
-
- if (chip->gpio_chip.ngpio <= 8)
- ret = i2c_smbus_read_byte_data(chip->client, reg);
- else
- ret = i2c_smbus_read_word_data(chip->client, reg << 1);
-
- if (ret < 0) {
- dev_err(&chip->client->dev, "failed reading register\n");
- return -EIO;
- }
-
- *val = (uint16_t)ret;
- return 0;
-}
-
-static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
-{
- struct pca953x_chip *chip;
- uint16_t reg_val;
- int ret;
-
- chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
- reg_val = chip->reg_direction | (1u << off);
- ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
- if (ret)
- return ret;
-
- chip->reg_direction = reg_val;
- return 0;
-}
-
-static int pca953x_gpio_direction_output(struct gpio_chip *gc,
- unsigned off, int val)
-{
- struct pca953x_chip *chip;
- uint16_t reg_val;
- int ret;
-
- chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
- /* set output level */
- if (val)
- reg_val = chip->reg_output | (1u << off);
- else
- reg_val = chip->reg_output & ~(1u << off);
-
- ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val);
- if (ret)
- return ret;
-
- chip->reg_output = reg_val;
-
- /* then direction */
- reg_val = chip->reg_direction & ~(1u << off);
- ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
- if (ret)
- return ret;
-
- chip->reg_direction = reg_val;
- return 0;
-}
-
-static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
-{
- struct pca953x_chip *chip;
- uint16_t reg_val;
- int ret;
-
- chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
- ret = pca953x_read_reg(chip, PCA953X_INPUT, ®_val);
- if (ret < 0) {
- /* NOTE: diagnostic already emitted; that's all we should
- * do unless gpio_*_value_cansleep() calls become different
- * from their nonsleeping siblings (and report faults).
- */
- return 0;
- }
-
- return (reg_val & (1u << off)) ? 1 : 0;
-}
-
-static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
-{
- struct pca953x_chip *chip;
- uint16_t reg_val;
- int ret;
-
- chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
- if (val)
- reg_val = chip->reg_output | (1u << off);
- else
- reg_val = chip->reg_output & ~(1u << off);
-
- ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val);
- if (ret)
- return;
-
- chip->reg_output = reg_val;
-}
-
-static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
-{
- struct gpio_chip *gc;
-
- gc = &chip->gpio_chip;
-
- gc->direction_input = pca953x_gpio_direction_input;
- gc->direction_output = pca953x_gpio_direction_output;
- gc->get = pca953x_gpio_get_value;
- gc->set = pca953x_gpio_set_value;
-
- gc->base = chip->gpio_start;
- gc->ngpio = gpios;
- gc->label = chip->client->name;
-}
-
-static int __devinit pca953x_probe(struct i2c_client *client)
-{
- struct pca953x_platform_data *pdata;
- struct pca953x_chip *chip;
- int ret, i;
- const struct pca953x_desc *id = NULL;
-
- pdata = client->dev.platform_data;
- if (pdata == NULL)
- return -ENODEV;
-
- /* this loop vanishes when we get i2c_device_id */
- for (i = 0; i < ARRAY_SIZE(pca953x_descs); i++)
- if (!strcmp(pca953x_descs[i].name, client->name)) {
- id = pca953x_descs + i;
- break;
- }
- if (!id)
- return -ENODEV;
-
- chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
- if (chip == NULL)
- return -ENOMEM;
-
- chip->client = client;
-
- chip->gpio_start = pdata->gpio_base;
-
- /* initialize cached registers from their original values.
- * we can't share this chip with another i2c master.
- */
- pca953x_setup_gpio(chip, id->driver_data);
-
- ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
- if (ret)
- goto out_failed;
-
- ret = pca953x_read_reg(chip, PCA953X_DIRECTION, &chip->reg_direction);
- if (ret)
- goto out_failed;
-
- /* set platform specific polarity inversion */
- ret = pca953x_write_reg(chip, PCA953X_INVERT, pdata->invert);
- if (ret)
- goto out_failed;
-
-
- ret = gpiochip_add(&chip->gpio_chip);
- if (ret)
- goto out_failed;
-
- if (pdata->setup) {
- ret = pdata->setup(client, chip->gpio_chip.base,
- chip->gpio_chip.ngpio, pdata->context);
- if (ret < 0)
- dev_warn(&client->dev, "setup failed, %d\n", ret);
- }
-
- i2c_set_clientdata(client, chip);
- return 0;
-
-out_failed:
- kfree(chip);
- return ret;
-}
-
-static int pca953x_remove(struct i2c_client *client)
-{
- struct pca953x_platform_data *pdata = client->dev.platform_data;
- struct pca953x_chip *chip = i2c_get_clientdata(client);
- int ret = 0;
-
- if (pdata->teardown) {
- ret = pdata->teardown(client, chip->gpio_chip.base,
- chip->gpio_chip.ngpio, pdata->context);
- if (ret < 0) {
- dev_err(&client->dev, "%s failed, %d\n",
- "teardown", ret);
- return ret;
- }
- }
-
- ret = gpiochip_remove(&chip->gpio_chip);
- if (ret) {
- dev_err(&client->dev, "%s failed, %d\n",
- "gpiochip_remove()", ret);
- return ret;
- }
-
- kfree(chip);
- return 0;
-}
-
-static struct i2c_driver pca953x_driver = {
- .driver = {
- .name = "pca953x",
- },
- .probe = pca953x_probe,
- .remove = pca953x_remove,
-};
-
-static int __init pca953x_init(void)
-{
- return i2c_add_driver(&pca953x_driver);
-}
-module_init(pca953x_init);
-
-static void __exit pca953x_exit(void)
-{
- i2c_del_driver(&pca953x_driver);
-}
-module_exit(pca953x_exit);
-
-MODULE_AUTHOR("eric miao ");
-MODULE_DESCRIPTION("GPIO expander driver for PCA953x");
-MODULE_LICENSE("GPL");
diff --git a/trunk/drivers/ide/Kconfig b/trunk/drivers/ide/Kconfig
index ab8fb257528e..45b26ed351cf 100644
--- a/trunk/drivers/ide/Kconfig
+++ b/trunk/drivers/ide/Kconfig
@@ -1009,15 +1009,6 @@ config BLK_DEV_Q40IDE
normally be on; disable it only if you are running a custom hard
drive subsystem through an expansion card.
-config BLK_DEV_PALMCHIP_BK3710
- tristate "Palmchip bk3710 IDE controller support"
- depends on ARCH_DAVINCI
- select BLK_DEV_IDEDMA_PCI
- help
- Say Y here if you want to support the onchip IDE controller on the
- TI DaVinci SoC
-
-
config BLK_DEV_MPC8xx_IDE
tristate "MPC8xx IDE support"
depends on 8xx && (LWMON || IVMS8 || IVML24 || TQM8xxL) && IDE=y && BLK_DEV_IDE=y && !PPC_MERGE
diff --git a/trunk/drivers/ide/arm/Makefile b/trunk/drivers/ide/arm/Makefile
index 936e7b0237f5..5f63ad216862 100644
--- a/trunk/drivers/ide/arm/Makefile
+++ b/trunk/drivers/ide/arm/Makefile
@@ -2,7 +2,6 @@
obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o
obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o
obj-$(CONFIG_BLK_DEV_IDE_BAST) += bast-ide.o
-obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710) += palm_bk3710.o
ifeq ($(CONFIG_IDE_ARM), m)
obj-m += ide_arm.o
diff --git a/trunk/drivers/ide/arm/icside.c b/trunk/drivers/ide/arm/icside.c
index e816b0ffcfe6..fb00f3827ecd 100644
--- a/trunk/drivers/ide/arm/icside.c
+++ b/trunk/drivers/ide/arm/icside.c
@@ -365,7 +365,7 @@ static void icside_dma_timeout(ide_drive_t *drive)
if (icside_dma_test_irq(drive))
return;
- ide_dump_status(drive, "DMA timeout", ide_read_status(drive));
+ ide_dump_status(drive, "DMA timeout", HWIF(drive)->INB(IDE_STATUS_REG));
icside_dma_end(drive);
}
diff --git a/trunk/drivers/ide/arm/palm_bk3710.c b/trunk/drivers/ide/arm/palm_bk3710.c
deleted file mode 100644
index c3069970a012..000000000000
--- a/trunk/drivers/ide/arm/palm_bk3710.c
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * Palmchip bk3710 IDE controller
- *
- * Copyright (C) 2006 Texas Instruments.
- * Copyright (C) 2007 MontaVista Software, Inc.,
- *
- * ----------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- * ----------------------------------------------------------------------------
- *
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-/* Offset of the primary interface registers */
-#define IDE_PALM_ATA_PRI_REG_OFFSET 0x1F0
-
-/* Primary Control Offset */
-#define IDE_PALM_ATA_PRI_CTL_OFFSET 0x3F6
-
-/*
- * PalmChip 3710 IDE Controller UDMA timing structure Definition
- */
-struct palm_bk3710_udmatiming {
- unsigned int rptime; /* Ready to pause time */
- unsigned int cycletime; /* Cycle Time */
-};
-
-#define BK3710_BMICP 0x00
-#define BK3710_BMISP 0x02
-#define BK3710_BMIDTP 0x04
-#define BK3710_BMICS 0x08
-#define BK3710_BMISS 0x0A
-#define BK3710_BMIDTS 0x0C
-#define BK3710_IDETIMP 0x40
-#define BK3710_IDETIMS 0x42
-#define BK3710_SIDETIM 0x44
-#define BK3710_SLEWCTL 0x45
-#define BK3710_IDESTATUS 0x47
-#define BK3710_UDMACTL 0x48
-#define BK3710_UDMATIM 0x4A
-#define BK3710_MISCCTL 0x50
-#define BK3710_REGSTB 0x54
-#define BK3710_REGRCVR 0x58
-#define BK3710_DATSTB 0x5C
-#define BK3710_DATRCVR 0x60
-#define BK3710_DMASTB 0x64
-#define BK3710_DMARCVR 0x68
-#define BK3710_UDMASTB 0x6C
-#define BK3710_UDMATRP 0x70
-#define BK3710_UDMAENV 0x74
-#define BK3710_IORDYTMP 0x78
-#define BK3710_IORDYTMS 0x7C
-
-#include "../ide-timing.h"
-
-static long ide_palm_clk;
-
-static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
- {160, 240}, /* UDMA Mode 0 */
- {125, 160}, /* UDMA Mode 1 */
- {100, 120}, /* UDMA Mode 2 */
- {100, 90}, /* UDMA Mode 3 */
- {85, 60}, /* UDMA Mode 4 */
-};
-
-static struct clk *ideclkp;
-
-static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
- unsigned int mode)
-{
- u8 tenv, trp, t0;
- u32 val32;
- u16 val16;
-
- /* DMA Data Setup */
- t0 = (palm_bk3710_udmatimings[mode].cycletime + ide_palm_clk - 1)
- / ide_palm_clk - 1;
- tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1;
- trp = (palm_bk3710_udmatimings[mode].rptime + ide_palm_clk - 1)
- / ide_palm_clk - 1;
-
- /* udmatim Register */
- val16 = readw(base + BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);
- val16 |= (mode << (dev ? 4 : 0));
- writew(val16, base + BK3710_UDMATIM);
-
- /* udmastb Ultra DMA Access Strobe Width */
- val32 = readl(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
- val32 |= (t0 << (dev ? 8 : 0));
- writel(val32, base + BK3710_UDMASTB);
-
- /* udmatrp Ultra DMA Ready to Pause Time */
- val32 = readl(base + BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8));
- val32 |= (trp << (dev ? 8 : 0));
- writel(val32, base + BK3710_UDMATRP);
-
- /* udmaenv Ultra DMA envelop Time */
- val32 = readl(base + BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8));
- val32 |= (tenv << (dev ? 8 : 0));
- writel(val32, base + BK3710_UDMAENV);
-
- /* Enable UDMA for Device */
- val16 = readw(base + BK3710_UDMACTL) | (1 << dev);
- writew(val16, base + BK3710_UDMACTL);
-}
-
-static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev,
- unsigned short min_cycle,
- unsigned int mode)
-{
- u8 td, tkw, t0;
- u32 val32;
- u16 val16;
- struct ide_timing *t;
- int cycletime;
-
- t = ide_timing_find_mode(mode);
- cycletime = max_t(int, t->cycle, min_cycle);
-
- /* DMA Data Setup */
- t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
- td = (t->active + ide_palm_clk - 1) / ide_palm_clk;
- tkw = t0 - td - 1;
- td -= 1;
-
- val32 = readl(base + BK3710_DMASTB) & (0xFF << (dev ? 0 : 8));
- val32 |= (td << (dev ? 8 : 0));
- writel(val32, base + BK3710_DMASTB);
-
- val32 = readl(base + BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8));
- val32 |= (tkw << (dev ? 8 : 0));
- writel(val32, base + BK3710_DMARCVR);
-
- /* Disable UDMA for Device */
- val16 = readw(base + BK3710_UDMACTL) & ~(1 << dev);
- writew(val16, base + BK3710_UDMACTL);
-}
-
-static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
- unsigned int dev, unsigned int cycletime,
- unsigned int mode)
-{
- u8 t2, t2i, t0;
- u32 val32;
- struct ide_timing *t;
-
- /* PIO Data Setup */
- t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
- t2 = (ide_timing_find_mode(XFER_PIO_0 + mode)->active +
- ide_palm_clk - 1) / ide_palm_clk;
-
- t2i = t0 - t2 - 1;
- t2 -= 1;
-
- val32 = readl(base + BK3710_DATSTB) & (0xFF << (dev ? 0 : 8));
- val32 |= (t2 << (dev ? 8 : 0));
- writel(val32, base + BK3710_DATSTB);
-
- val32 = readl(base + BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8));
- val32 |= (t2i << (dev ? 8 : 0));
- writel(val32, base + BK3710_DATRCVR);
-
- if (mate && mate->present) {
- u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);
-
- if (mode2 < mode)
- mode = mode2;
- }
-
- /* TASKFILE Setup */
- t = ide_timing_find_mode(XFER_PIO_0 + mode);
- t0 = (t->cyc8b + ide_palm_clk - 1) / ide_palm_clk;
- t2 = (t->act8b + ide_palm_clk - 1) / ide_palm_clk;
-
- t2i = t0 - t2 - 1;
- t2 -= 1;
-
- val32 = readl(base + BK3710_REGSTB) & (0xFF << (dev ? 0 : 8));
- val32 |= (t2 << (dev ? 8 : 0));
- writel(val32, base + BK3710_REGSTB);
-
- val32 = readl(base + BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8));
- val32 |= (t2i << (dev ? 8 : 0));
- writel(val32, base + BK3710_REGRCVR);
-}
-
-static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed)
-{
- int is_slave = drive->dn & 1;
- void __iomem *base = (void *)drive->hwif->dma_base;
-
- if (xferspeed >= XFER_UDMA_0) {
- palm_bk3710_setudmamode(base, is_slave,
- xferspeed - XFER_UDMA_0);
- } else {
- palm_bk3710_setdmamode(base, is_slave, drive->id->eide_dma_min,
- xferspeed);
- }
-}
-
-static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio)
-{
- unsigned int cycle_time;
- int is_slave = drive->dn & 1;
- ide_drive_t *mate;
- void __iomem *base = (void *)drive->hwif->dma_base;
-
- /*
- * Obtain the drive PIO data for tuning the Palm Chip registers
- */
- cycle_time = ide_pio_cycle_time(drive, pio);
- mate = ide_get_paired_drive(drive);
- palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio);
-}
-
-static void __devinit palm_bk3710_chipinit(void __iomem *base)
-{
- /*
- * enable the reset_en of ATA controller so that when ata signals
- * are brought out, by writing into device config. at that
- * time por_n signal should not be 'Z' and have a stable value.
- */
- writel(0x0300, base + BK3710_MISCCTL);
-
- /* wait for some time and deassert the reset of ATA Device. */
- mdelay(100);
-
- /* Deassert the Reset */
- writel(0x0200, base + BK3710_MISCCTL);
-
- /*
- * Program the IDETIMP Register Value based on the following assumptions
- *
- * (ATA_IDETIMP_IDEEN , ENABLE ) |
- * (ATA_IDETIMP_SLVTIMEN , DISABLE) |
- * (ATA_IDETIMP_RDYSMPL , 70NS) |
- * (ATA_IDETIMP_RDYRCVRY , 50NS) |
- * (ATA_IDETIMP_DMAFTIM1 , PIOCOMP) |
- * (ATA_IDETIMP_PREPOST1 , DISABLE) |
- * (ATA_IDETIMP_RDYSEN1 , DISABLE) |
- * (ATA_IDETIMP_PIOFTIM1 , DISABLE) |
- * (ATA_IDETIMP_DMAFTIM0 , PIOCOMP) |
- * (ATA_IDETIMP_PREPOST0 , DISABLE) |
- * (ATA_IDETIMP_RDYSEN0 , DISABLE) |
- * (ATA_IDETIMP_PIOFTIM0 , DISABLE)
- */
- writew(0xB388, base + BK3710_IDETIMP);
-
- /*
- * Configure SIDETIM Register
- * (ATA_SIDETIM_RDYSMPS1 ,120NS ) |
- * (ATA_SIDETIM_RDYRCYS1 ,120NS )
- */
- writeb(0, base + BK3710_SIDETIM);
-
- /*
- * UDMACTL Ultra-ATA DMA Control
- * (ATA_UDMACTL_UDMAP1 , 0 ) |
- * (ATA_UDMACTL_UDMAP0 , 0 )
- *
- */
- writew(0, base + BK3710_UDMACTL);
-
- /*
- * MISCCTL Miscellaneous Conrol Register
- * (ATA_MISCCTL_RSTMODEP , 1) |
- * (ATA_MISCCTL_RESETP , 0) |
- * (ATA_MISCCTL_TIMORIDE , 1)
- */
- writel(0x201, base + BK3710_MISCCTL);
-
- /*
- * IORDYTMP IORDY Timer for Primary Register
- * (ATA_IORDYTMP_IORDYTMP , 0xffff )
- */
- writel(0xFFFF, base + BK3710_IORDYTMP);
-
- /*
- * Configure BMISP Register
- * (ATA_BMISP_DMAEN1 , DISABLE ) |
- * (ATA_BMISP_DMAEN0 , DISABLE ) |
- * (ATA_BMISP_IORDYINT , CLEAR) |
- * (ATA_BMISP_INTRSTAT , CLEAR) |
- * (ATA_BMISP_DMAERROR , CLEAR)
- */
- writew(0, base + BK3710_BMISP);
-
- palm_bk3710_setpiomode(base, NULL, 0, 600, 0);
- palm_bk3710_setpiomode(base, NULL, 1, 600, 0);
-}
-static int __devinit palm_bk3710_probe(struct platform_device *pdev)
-{
- hw_regs_t ide_ctlr_info;
- int index = 0;
- int pribase;
- struct clk *clkp;
- struct resource *mem, *irq;
- ide_hwif_t *hwif;
- void __iomem *base;
-
- clkp = clk_get(NULL, "IDECLK");
- if (IS_ERR(clkp))
- return -ENODEV;
-
- ideclkp = clkp;
- clk_enable(ideclkp);
- ide_palm_clk = clk_get_rate(ideclkp)/100000;
- ide_palm_clk = (10000/ide_palm_clk) + 1;
- /* Register the IDE interface with Linux ATA Interface */
- memset(&ide_ctlr_info, 0, sizeof(ide_ctlr_info));
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (mem == NULL) {
- printk(KERN_ERR "failed to get memory region resource\n");
- return -ENODEV;
- }
- irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (irq == NULL) {
- printk(KERN_ERR "failed to get IRQ resource\n");
- return -ENODEV;
- }
-
- base = (void *)mem->start;
-
- /* Configure the Palm Chip controller */
- palm_bk3710_chipinit(base);
-
- pribase = mem->start + IDE_PALM_ATA_PRI_REG_OFFSET;
- for (index = 0; index < IDE_NR_PORTS - 2; index++)
- ide_ctlr_info.io_ports[index] = pribase + index;
- ide_ctlr_info.io_ports[IDE_CONTROL_OFFSET] = mem->start +
- IDE_PALM_ATA_PRI_CTL_OFFSET;
- ide_ctlr_info.irq = irq->start;
- ide_ctlr_info.chipset = ide_palm3710;
-
- if (ide_register_hw(&ide_ctlr_info, NULL, &hwif) < 0) {
- printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
- return -ENODEV;
- }
-
- hwif->set_pio_mode = &palm_bk3710_set_pio_mode;
- hwif->set_dma_mode = &palm_bk3710_set_dma_mode;
- hwif->mmio = 1;
- default_hwif_mmiops(hwif);
- hwif->cbl = ATA_CBL_PATA80;
- hwif->ultra_mask = 0x1f; /* Ultra DMA Mode 4 Max
- (input clk 99MHz) */
- hwif->mwdma_mask = 0x7;
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
-
- ide_setup_dma(hwif, mem->start);
-
- return 0;
-}
-
-static struct platform_driver platform_bk_driver = {
- .driver = {
- .name = "palm_bk3710",
- },
- .probe = palm_bk3710_probe,
- .remove = NULL,
-};
-
-static int __init palm_bk3710_init(void)
-{
- return platform_driver_register(&platform_bk_driver);
-}
-
-module_init(palm_bk3710_init);
-MODULE_LICENSE("GPL");
-
diff --git a/trunk/drivers/ide/cris/ide-cris.c b/trunk/drivers/ide/cris/ide-cris.c
index e79bf8f9b7db..00587a8c2ba1 100644
--- a/trunk/drivers/ide/cris/ide-cris.c
+++ b/trunk/drivers/ide/cris/ide-cris.c
@@ -753,25 +753,6 @@ static void cris_set_dma_mode(ide_drive_t *drive, const u8 speed)
cris_ide_set_speed(TYPE_DMA, 0, strobe, hold);
}
-static void __init cris_setup_ports(hw_regs_t *hw, unsigned long base)
-{
- int i;
-
- memset(hw, 0, sizeof(*hw));
-
- for (i = 0; i <= 7; i++)
- hw->io_ports[i] = base + cris_ide_reg_addr(i, 0, 1);
-
- /*
- * the IDE control register is at ATA address 6,
- * with CS1 active instead of CS0
- */
- hw->io_ports[IDE_CONTROL_OFFSET] = base + cris_ide_reg_addr(6, 1, 0);
-
- hw->irq = ide_default_irq(0);
- hw->ack_intr = cris_ide_ack_intr;
-}
-
static const struct ide_port_info cris_port_info __initdata = {
.chipset = ide_etrax100,
.host_flags = IDE_HFLAG_NO_ATAPI_DMA |
@@ -784,16 +765,24 @@ static const struct ide_port_info cris_port_info __initdata = {
static int __init init_e100_ide(void)
{
hw_regs_t hw;
- int h;
+ int ide_offsets[IDE_NR_PORTS], h, i;
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
printk("ide: ETRAX FS built-in ATA DMA controller\n");
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+ ide_offsets[i] = cris_ide_reg_addr(i, 0, 1);
+
+ /* the IDE control register is at ATA address 6, with CS1 active instead of CS0 */
+ ide_offsets[IDE_CONTROL_OFFSET] = cris_ide_reg_addr(6, 1, 0);
+
for (h = 0; h < 4; h++) {
ide_hwif_t *hwif = NULL;
- cris_setup_ports(&hw, cris_ide_base_address(h));
-
+ ide_setup_ports(&hw, cris_ide_base_address(h),
+ ide_offsets,
+ 0, 0, cris_ide_ack_intr,
+ ide_default_irq(0));
hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
if (hwif == NULL)
continue;
diff --git a/trunk/drivers/ide/ide-acpi.c b/trunk/drivers/ide/ide-acpi.c
index e07b189f3ec8..25aaeae1e830 100644
--- a/trunk/drivers/ide/ide-acpi.c
+++ b/trunk/drivers/ide/ide-acpi.c
@@ -171,7 +171,7 @@ static int ide_get_dev_handle(struct device *dev, acpi_handle *handle,
static acpi_handle ide_acpi_hwif_get_handle(ide_hwif_t *hwif)
{
struct device *dev = hwif->gendev.parent;
- acpi_handle uninitialized_var(dev_handle);
+ acpi_handle dev_handle;
acpi_integer pcidevfn;
acpi_handle chan_handle;
int err;
diff --git a/trunk/drivers/ide/ide-cd.c b/trunk/drivers/ide/ide-cd.c
index 5e42c19a03e3..ee4d458e2bbf 100644
--- a/trunk/drivers/ide/ide-cd.c
+++ b/trunk/drivers/ide/ide-cd.c
@@ -295,8 +295,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
int stat, err, sense_key;
/* Check for errors. */
- stat = ide_read_status(drive);
-
+ stat = HWIF(drive)->INB(IDE_STATUS_REG);
if (stat_ret)
*stat_ret = stat;
@@ -304,7 +303,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
return 0;
/* Get the IDE error register. */
- err = ide_read_error(drive);
+ err = HWIF(drive)->INB(IDE_ERROR_REG);
sense_key = err >> 4;
if (rq == NULL) {
@@ -693,7 +692,7 @@ int ide_cd_check_ireason(ide_drive_t *drive, int len, int ireason, int rw)
/* Some drives (ASUS) seem to tell us that status
* info is available. just get it and ignore.
*/
- (void)ide_read_status(drive);
+ (void) HWIF(drive)->INB(IDE_STATUS_REG);
return 0;
} else {
/* Drive wants a command packet, or invalid ireason... */
@@ -1327,7 +1326,7 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
if (blk_fs_request(rq)) {
if (info->cd_flags & IDE_CD_FLAG_SEEKING) {
unsigned long elapsed = jiffies - info->start_seek;
- int stat = ide_read_status(drive);
+ int stat = HWIF(drive)->INB(IDE_STATUS_REG);
if ((stat & SEEK_STAT) != SEEK_STAT) {
if (elapsed < IDECD_SEEK_TIMEOUT) {
diff --git a/trunk/drivers/ide/ide-dma.c b/trunk/drivers/ide/ide-dma.c
index a4bb32883c6b..3cf59f2c3928 100644
--- a/trunk/drivers/ide/ide-dma.c
+++ b/trunk/drivers/ide/ide-dma.c
@@ -147,8 +147,7 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive)
u8 stat = 0, dma_stat = 0;
dma_stat = HWIF(drive)->ide_dma_end(drive);
- stat = ide_read_status(drive);
-
+ stat = HWIF(drive)->INB(IDE_STATUS_REG); /* get drive status */
if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
if (!dma_stat) {
struct request *rq = HWGROUP(drive)->rq;
diff --git a/trunk/drivers/ide/ide-floppy.c b/trunk/drivers/ide/ide-floppy.c
index faf22d716f80..f8fe6ee128f3 100644
--- a/trunk/drivers/ide/ide-floppy.c
+++ b/trunk/drivers/ide/ide-floppy.c
@@ -465,7 +465,7 @@ static void idefloppy_retry_pc(ide_drive_t *drive)
idefloppy_pc_t *pc;
struct request *rq;
- (void)ide_read_error(drive);
+ (void)drive->hwif->INB(IDE_ERROR_REG);
pc = idefloppy_next_pc_storage(drive);
rq = idefloppy_next_rq_storage(drive);
idefloppy_create_request_sense_cmd(pc);
@@ -501,7 +501,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
}
/* Clear the interrupt */
- stat = ide_read_status(drive);
+ stat = drive->hwif->INB(IDE_STATUS_REG);
/* No more interrupts */
if ((stat & DRQ_STAT) == 0) {
@@ -1246,7 +1246,7 @@ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
u8 stat;
local_irq_save(flags);
- stat = ide_read_status(drive);
+ stat = drive->hwif->INB(IDE_STATUS_REG);
local_irq_restore(flags);
progress_indication = ((stat & SEEK_STAT) == 0) ? 0 : 0x10000;
diff --git a/trunk/drivers/ide/ide-generic.c b/trunk/drivers/ide/ide-generic.c
index 709b9e4d2871..be469dbbe8fb 100644
--- a/trunk/drivers/ide/ide-generic.c
+++ b/trunk/drivers/ide/ide-generic.c
@@ -20,14 +20,8 @@ static int __init ide_generic_init(void)
if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET])
ide_get_lock(NULL, NULL); /* for atari only */
- for (i = 0; i < MAX_HWIFS; i++) {
- ide_hwif_t *hwif = &ide_hwifs[i];
-
- if (hwif->io_ports[IDE_DATA_OFFSET] && !hwif->present)
- idx[i] = i;
- else
- idx[i] = 0xff;
- }
+ for (i = 0; i < MAX_HWIFS; i++)
+ idx[i] = ide_hwifs[i].present ? 0xff : i;
ide_device_add_all(idx, NULL);
diff --git a/trunk/drivers/ide/ide-io.c b/trunk/drivers/ide/ide-io.c
index 3addbe478d26..4bddef0c0b96 100644
--- a/trunk/drivers/ide/ide-io.c
+++ b/trunk/drivers/ide/ide-io.c
@@ -466,7 +466,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
return ide_stopped;
}
- if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+ if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
rq->errors |= ERROR_RESET;
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
@@ -493,7 +493,7 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u
/* add decoding error stuff */
}
- if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+ if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
/* force an abort */
hwif->OUTB(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG);
@@ -821,8 +821,9 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
#ifdef DEBUG
printk("%s: DRIVE_CMD (null)\n", drive->name);
#endif
- ide_end_drive_cmd(drive, ide_read_status(drive), ide_read_error(drive));
-
+ ide_end_drive_cmd(drive,
+ hwif->INB(IDE_STATUS_REG),
+ hwif->INB(IDE_ERROR_REG));
return ide_stopped;
}
@@ -1230,7 +1231,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
(void)HWIF(drive)->ide_dma_end(drive);
ret = ide_error(drive, "dma timeout error",
- ide_read_status(drive));
+ hwif->INB(IDE_STATUS_REG));
} else {
printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
hwif->dma_timeout(drive);
@@ -1354,8 +1355,7 @@ void ide_timer_expiry (unsigned long data)
startstop = ide_dma_timeout_retry(drive, wait);
} else
startstop =
- ide_error(drive, "irq timeout",
- ide_read_status(drive));
+ ide_error(drive, "irq timeout", hwif->INB(IDE_STATUS_REG));
}
drive->service_time = jiffies - drive->service_start;
spin_lock_irq(&ide_lock);
diff --git a/trunk/drivers/ide/ide-iops.c b/trunk/drivers/ide/ide-iops.c
index c32e759df208..a95178f5e1bb 100644
--- a/trunk/drivers/ide/ide-iops.c
+++ b/trunk/drivers/ide/ide-iops.c
@@ -430,10 +430,10 @@ int drive_is_ready (ide_drive_t *drive)
* about possible isa-pnp and pci-pnp issues yet.
*/
if (IDE_CONTROL_REG)
- stat = ide_read_altstatus(drive);
+ stat = hwif->INB(IDE_ALTSTATUS_REG);
else
/* Note: this may clear a pending IRQ!! */
- stat = ide_read_status(drive);
+ stat = hwif->INB(IDE_STATUS_REG);
if (stat & BUSY_STAT)
/* drive busy: definitely not interrupting */
@@ -458,24 +458,23 @@ EXPORT_SYMBOL(drive_is_ready);
*/
static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout, u8 *rstat)
{
+ ide_hwif_t *hwif = drive->hwif;
unsigned long flags;
int i;
u8 stat;
udelay(1); /* spec allows drive 400ns to assert "BUSY" */
- stat = ide_read_status(drive);
-
- if (stat & BUSY_STAT) {
+ if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) {
local_irq_set(flags);
timeout += jiffies;
- while ((stat = ide_read_status(drive)) & BUSY_STAT) {
+ while ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) {
if (time_after(jiffies, timeout)) {
/*
* One last read after the timeout in case
* heavy interrupt load made us not make any
* progress during the timeout..
*/
- stat = ide_read_status(drive);
+ stat = hwif->INB(IDE_STATUS_REG);
if (!(stat & BUSY_STAT))
break;
@@ -495,9 +494,7 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti
*/
for (i = 0; i < 10; i++) {
udelay(1);
- stat = ide_read_status(drive);
-
- if (OK_STAT(stat, good, bad)) {
+ if (OK_STAT((stat = hwif->INB(IDE_STATUS_REG)), good, bad)) {
*rstat = stat;
return 0;
}
@@ -620,7 +617,6 @@ int ide_driveid_update(ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
struct hd_driveid *id;
unsigned long timeout, flags;
- u8 stat;
/*
* Re-read drive->id for possible DMA mode
@@ -637,15 +633,10 @@ int ide_driveid_update(ide_drive_t *drive)
SELECT_MASK(drive, 0);
return 0; /* drive timed-out */
}
-
msleep(50); /* give drive a breather */
- stat = ide_read_altstatus(drive);
- } while (stat & BUSY_STAT);
-
+ } while (hwif->INB(IDE_ALTSTATUS_REG) & BUSY_STAT);
msleep(50); /* wait for IRQ and DRQ_STAT */
- stat = ide_read_status(drive);
-
- if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) {
+ if (!OK_STAT(hwif->INB(IDE_STATUS_REG),DRQ_STAT,BAD_R_STAT)) {
SELECT_MASK(drive, 0);
printk("%s: CHECK for good STATUS\n", drive->name);
return 0;
@@ -658,7 +649,7 @@ int ide_driveid_update(ide_drive_t *drive)
return 0;
}
ata_input_data(drive, id, SECTOR_WORDS);
- (void)ide_read_status(drive); /* clear drive IRQ */
+ (void) hwif->INB(IDE_STATUS_REG); /* clear drive IRQ */
local_irq_enable();
local_irq_restore(flags);
ide_fix_driveid(id);
@@ -859,16 +850,17 @@ static ide_startstop_t do_reset1 (ide_drive_t *, int);
static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
{
ide_hwgroup_t *hwgroup = HWGROUP(drive);
+ ide_hwif_t *hwif = HWIF(drive);
u8 stat;
SELECT_DRIVE(drive);
udelay (10);
- stat = ide_read_status(drive);
- if (OK_STAT(stat, 0, BUSY_STAT))
+ if (OK_STAT(stat = hwif->INB(IDE_STATUS_REG), 0, BUSY_STAT)) {
printk("%s: ATAPI reset complete\n", drive->name);
- else {
+ } else {
if (time_before(jiffies, hwgroup->poll_timeout)) {
+ BUG_ON(HWGROUP(drive)->handler != NULL);
ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
/* continue polling */
return ide_started;
@@ -906,10 +898,9 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
}
}
- tmp = ide_read_status(drive);
-
- if (!OK_STAT(tmp, 0, BUSY_STAT)) {
+ if (!OK_STAT(tmp = hwif->INB(IDE_STATUS_REG), 0, BUSY_STAT)) {
if (time_before(jiffies, hwgroup->poll_timeout)) {
+ BUG_ON(HWGROUP(drive)->handler != NULL);
ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
/* continue polling */
return ide_started;
@@ -918,9 +909,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
drive->failures++;
} else {
printk("%s: reset: ", hwif->name);
- tmp = ide_read_error(drive);
-
- if (tmp == 1) {
+ if ((tmp = hwif->INB(IDE_ERROR_REG)) == 1) {
printk("success\n");
drive->failures = 0;
} else {
diff --git a/trunk/drivers/ide/ide-lib.c b/trunk/drivers/ide/ide-lib.c
index 1ff676cc6473..b42940d8bf70 100644
--- a/trunk/drivers/ide/ide-lib.c
+++ b/trunk/drivers/ide/ide-lib.c
@@ -578,7 +578,7 @@ u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
}
printk("}\n");
if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
- err = ide_read_error(drive);
+ err = drive->hwif->INB(IDE_ERROR_REG);
printk("%s: %s: error=0x%02x ", drive->name, msg, err);
if (drive->media == ide_disk)
ide_dump_ata_error(drive, err);
diff --git a/trunk/drivers/ide/ide-probe.c b/trunk/drivers/ide/ide-probe.c
index 6daea896c5db..9c07bdb68d1a 100644
--- a/trunk/drivers/ide/ide-probe.c
+++ b/trunk/drivers/ide/ide-probe.c
@@ -264,7 +264,8 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
{
ide_hwif_t *hwif = HWIF(drive);
- int use_altstatus = 0, rc;
+ int rc;
+ unsigned long hd_status;
unsigned long timeout;
u8 s = 0, a = 0;
@@ -272,17 +273,19 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
msleep(50);
if (IDE_CONTROL_REG) {
- a = ide_read_altstatus(drive);
- s = ide_read_status(drive);
- if ((a ^ s) & ~INDEX_STAT)
+ a = hwif->INB(IDE_ALTSTATUS_REG);
+ s = hwif->INB(IDE_STATUS_REG);
+ if ((a ^ s) & ~INDEX_STAT) {
+ printk(KERN_INFO "%s: probing with STATUS(0x%02x) instead of "
+ "ALTSTATUS(0x%02x)\n", drive->name, s, a);
/* ancient Seagate drives, broken interfaces */
- printk(KERN_INFO "%s: probing with STATUS(0x%02x) "
- "instead of ALTSTATUS(0x%02x)\n",
- drive->name, s, a);
- else
+ hd_status = IDE_STATUS_REG;
+ } else {
/* use non-intrusive polling */
- use_altstatus = 1;
- }
+ hd_status = IDE_ALTSTATUS_REG;
+ }
+ } else
+ hd_status = IDE_STATUS_REG;
/* set features register for atapi
* identify command to be sure of reply
@@ -303,15 +306,11 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
}
/* give drive a breather */
msleep(50);
- s = use_altstatus ? ide_read_altstatus(drive)
- : ide_read_status(drive);
- } while (s & BUSY_STAT);
+ } while ((hwif->INB(hd_status)) & BUSY_STAT);
/* wait for IRQ and DRQ_STAT */
msleep(50);
- s = ide_read_status(drive);
-
- if (OK_STAT(s, DRQ_STAT, BAD_R_STAT)) {
+ if (OK_STAT((hwif->INB(IDE_STATUS_REG)), DRQ_STAT, BAD_R_STAT)) {
unsigned long flags;
/* local CPU only; some systems need this */
@@ -321,7 +320,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
/* drive responded with ID */
rc = 0;
/* clear drive IRQ */
- (void)ide_read_status(drive);
+ (void) hwif->INB(IDE_STATUS_REG);
local_irq_restore(flags);
} else {
/* drive refused ID */
@@ -368,7 +367,7 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
ide_set_irq(drive, 0);
/* clear drive IRQ */
- (void)ide_read_status(drive);
+ (void) hwif->INB(IDE_STATUS_REG);
udelay(5);
irq = probe_irq_off(cookie);
if (!hwif->irq) {
@@ -456,9 +455,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
return 3;
}
- stat = ide_read_status(drive);
-
- if (OK_STAT(stat, READY_STAT, BUSY_STAT) ||
+ if (OK_STAT((hwif->INB(IDE_STATUS_REG)), READY_STAT, BUSY_STAT) ||
drive->present || cmd == WIN_PIDENTIFY) {
/* send cmd and wait */
if ((rc = try_to_identify(drive, cmd))) {
@@ -466,7 +463,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
rc = try_to_identify(drive,cmd);
}
- stat = ide_read_status(drive);
+ stat = hwif->INB(IDE_STATUS_REG);
if (stat == (BUSY_STAT | READY_STAT))
return 4;
@@ -485,7 +482,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
}
/* ensure drive IRQ is clear */
- stat = ide_read_status(drive);
+ stat = hwif->INB(IDE_STATUS_REG);
if (rc == 1)
printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
@@ -499,7 +496,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
SELECT_DRIVE(&hwif->drives[0]);
msleep(50);
/* ensure drive irq is clear */
- (void)ide_read_status(drive);
+ (void) hwif->INB(IDE_STATUS_REG);
}
return rc;
}
@@ -524,7 +521,7 @@ static void enable_nest (ide_drive_t *drive)
msleep(50);
- stat = ide_read_status(drive);
+ stat = hwif->INB(IDE_STATUS_REG);
if (!OK_STAT(stat, 0, BAD_STAT))
printk(KERN_CONT "failed (status = 0x%02x)\n", stat);
@@ -1049,7 +1046,7 @@ static int init_irq (ide_hwif_t *hwif)
*/
if (!match || match->irq != hwif->irq) {
int sa = 0;
-#if defined(__mc68000__)
+#if defined(__mc68000__) || defined(CONFIG_APUS)
sa = IRQF_SHARED;
#endif /* __mc68000__ || CONFIG_APUS */
@@ -1072,7 +1069,7 @@ static int init_irq (ide_hwif_t *hwif)
hwif->rqsize = 65536;
}
-#if !defined(__mc68000__)
+#if !defined(__mc68000__) && !defined(CONFIG_APUS)
printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
hwif->io_ports[IDE_DATA_OFFSET],
hwif->io_ports[IDE_DATA_OFFSET]+7,
@@ -1080,7 +1077,7 @@ static int init_irq (ide_hwif_t *hwif)
#else
printk("%s at 0x%08lx on irq %d", hwif->name,
hwif->io_ports[IDE_DATA_OFFSET], hwif->irq);
-#endif /* __mc68000__ */
+#endif /* __mc68000__ && CONFIG_APUS */
if (match)
printk(" (%sed with %s)",
hwif->sharing_irq ? "shar" : "serializ", match->name);
diff --git a/trunk/drivers/ide/ide-proc.c b/trunk/drivers/ide/ide-proc.c
index bab88ca7f7ec..975c0ff0f438 100644
--- a/trunk/drivers/ide/ide-proc.c
+++ b/trunk/drivers/ide/ide-proc.c
@@ -65,7 +65,6 @@ static int proc_ide_read_imodel
case ide_4drives: name = "4drives"; break;
case ide_pmac: name = "mac-io"; break;
case ide_au1xxx: name = "au1xxx"; break;
- case ide_palm3710: name = "palm3710"; break;
case ide_etrax100: name = "etrax100"; break;
case ide_acorn: name = "acorn"; break;
default: name = "(unknown)"; break;
diff --git a/trunk/drivers/ide/ide-tape.c b/trunk/drivers/ide/ide-tape.c
index 49dd2e7bae7a..bf40d8c824ad 100644
--- a/trunk/drivers/ide/ide-tape.c
+++ b/trunk/drivers/ide/ide-tape.c
@@ -15,7 +15,7 @@
* Documentation/ide/ChangeLog.ide-tape.1995-2002
*/
-#define IDETAPE_VERSION "1.20"
+#define IDETAPE_VERSION "1.19"
#include
#include
@@ -39,70 +39,63 @@
#include
#include
-#include
-#include
-#include
+#include
+#include
+#include
#include
#include
-enum {
- /* output errors only */
- DBG_ERR = (1 << 0),
- /* output all sense key/asc */
- DBG_SENSE = (1 << 1),
- /* info regarding all chrdev-related procedures */
- DBG_CHRDEV = (1 << 2),
- /* all remaining procedures */
- DBG_PROCS = (1 << 3),
- /* buffer alloc info (pc_stack & rq_stack) */
- DBG_PCRQ_STACK = (1 << 4),
-};
-
-/* define to see debug info */
-#define IDETAPE_DEBUG_LOG 0
-
-#if IDETAPE_DEBUG_LOG
-#define debug_log(lvl, fmt, args...) \
-{ \
- if (tape->debug_mask & lvl) \
- printk(KERN_INFO "ide-tape: " fmt, ## args); \
-}
-#else
-#define debug_log(lvl, fmt, args...) do {} while (0)
-#endif
-
/**************************** Tunable parameters *****************************/
/*
- * Pipelined mode parameters.
+ * Pipelined mode parameters.
*
- * We try to use the minimum number of stages which is enough to keep the tape
- * constantly streaming. To accomplish that, we implement a feedback loop around
- * the maximum number of stages:
+ * We try to use the minimum number of stages which is enough to
+ * keep the tape constantly streaming. To accomplish that, we implement
+ * a feedback loop around the maximum number of stages:
*
- * We start from MIN maximum stages (we will not even use MIN stages if we don't
- * need them), increment it by RATE*(MAX-MIN) whenever we sense that the
- * pipeline is empty, until we reach the optimum value or until we reach MAX.
+ * We start from MIN maximum stages (we will not even use MIN stages
+ * if we don't need them), increment it by RATE*(MAX-MIN)
+ * whenever we sense that the pipeline is empty, until we reach
+ * the optimum value or until we reach MAX.
*
- * Setting the following parameter to 0 is illegal: the pipelined mode cannot be
- * disabled (idetape_calculate_speeds() divides by tape->max_stages.)
+ * Setting the following parameter to 0 is illegal: the pipelined mode
+ * cannot be disabled (calculate_speeds() divides by tape->max_stages.)
*/
#define IDETAPE_MIN_PIPELINE_STAGES 1
#define IDETAPE_MAX_PIPELINE_STAGES 400
#define IDETAPE_INCREASE_STAGES_RATE 20
/*
- * After each failed packet command we issue a request sense command and retry
- * the packet command IDETAPE_MAX_PC_RETRIES times.
+ * The following are used to debug the driver:
+ *
+ * Setting IDETAPE_DEBUG_LOG to 1 will log driver flow control.
*
- * Setting IDETAPE_MAX_PC_RETRIES to 0 will disable retries.
+ * Setting them to 0 will restore normal operation mode:
+ *
+ * 1. Disable logging normal successful operations.
+ * 2. Disable self-sanity checks.
+ * 3. Errors will still be logged, of course.
+ *
+ * All the #if DEBUG code will be removed some day, when the driver
+ * is verified to be stable enough. This will make it much more
+ * esthetic.
+ */
+#define IDETAPE_DEBUG_LOG 0
+
+/*
+ * After each failed packet command we issue a request sense command
+ * and retry the packet command IDETAPE_MAX_PC_RETRIES times.
+ *
+ * Setting IDETAPE_MAX_PC_RETRIES to 0 will disable retries.
*/
#define IDETAPE_MAX_PC_RETRIES 3
/*
- * With each packet command, we allocate a buffer of IDETAPE_PC_BUFFER_SIZE
- * bytes. This is used for several packet commands (Not for READ/WRITE commands)
+ * With each packet command, we allocate a buffer of
+ * IDETAPE_PC_BUFFER_SIZE bytes. This is used for several packet
+ * commands (Not for READ/WRITE commands).
*/
#define IDETAPE_PC_BUFFER_SIZE 256
@@ -121,39 +114,48 @@ enum {
#define IDETAPE_WAIT_CMD (900*HZ)
/*
- * The following parameter is used to select the point in the internal tape fifo
- * in which we will start to refill the buffer. Decreasing the following
- * parameter will improve the system's latency and interactive response, while
- * using a high value might improve system throughput.
+ * The following parameter is used to select the point in the internal
+ * tape fifo in which we will start to refill the buffer. Decreasing
+ * the following parameter will improve the system's latency and
+ * interactive response, while using a high value might improve system
+ * throughput.
*/
-#define IDETAPE_FIFO_THRESHOLD 2
+#define IDETAPE_FIFO_THRESHOLD 2
/*
- * DSC polling parameters.
+ * DSC polling parameters.
+ *
+ * Polling for DSC (a single bit in the status register) is a very
+ * important function in ide-tape. There are two cases in which we
+ * poll for DSC:
*
- * Polling for DSC (a single bit in the status register) is a very important
- * function in ide-tape. There are two cases in which we poll for DSC:
+ * 1. Before a read/write packet command, to ensure that we
+ * can transfer data from/to the tape's data buffers, without
+ * causing an actual media access. In case the tape is not
+ * ready yet, we take out our request from the device
+ * request queue, so that ide.c will service requests from
+ * the other device on the same interface meanwhile.
*
- * 1. Before a read/write packet command, to ensure that we can transfer data
- * from/to the tape's data buffers, without causing an actual media access.
- * In case the tape is not ready yet, we take out our request from the device
- * request queue, so that ide.c could service requests from the other device
- * on the same interface in the meantime.
+ * 2. After the successful initialization of a "media access
+ * packet command", which is a command which can take a long
+ * time to complete (it can be several seconds or even an hour).
*
- * 2. After the successful initialization of a "media access packet command",
- * which is a command that can take a long time to complete (the interval can
- * range from several seconds to even an hour). Again, we postpone our request
- * in the middle to free the bus for the other device. The polling frequency
- * here should be lower than the read/write frequency since those media access
- * commands are slow. We start from a "fast" frequency - IDETAPE_DSC_MA_FAST
- * (1 second), and if we don't receive DSC after IDETAPE_DSC_MA_THRESHOLD
- * (5 min), we switch it to a lower frequency - IDETAPE_DSC_MA_SLOW (1 min).
+ * Again, we postpone our request in the middle to free the bus
+ * for the other device. The polling frequency here should be
+ * lower than the read/write frequency since those media access
+ * commands are slow. We start from a "fast" frequency -
+ * IDETAPE_DSC_MA_FAST (one second), and if we don't receive DSC
+ * after IDETAPE_DSC_MA_THRESHOLD (5 minutes), we switch it to a
+ * lower frequency - IDETAPE_DSC_MA_SLOW (1 minute).
*
- * We also set a timeout for the timer, in case something goes wrong. The
- * timeout should be longer then the maximum execution time of a tape operation.
+ * We also set a timeout for the timer, in case something goes wrong.
+ * The timeout should be longer then the maximum execution time of a
+ * tape operation.
+ */
+
+/*
+ * DSC timings.
*/
-
-/* DSC timings. */
#define IDETAPE_DSC_RW_MIN 5*HZ/100 /* 50 msec */
#define IDETAPE_DSC_RW_MAX 40*HZ/100 /* 400 msec */
#define IDETAPE_DSC_RW_TIMEOUT 2*60*HZ /* 2 minutes */
@@ -164,15 +166,19 @@ enum {
/*************************** End of tunable parameters ***********************/
-/* Read/Write error simulation */
+/*
+ * Read/Write error simulation
+ */
#define SIMULATE_ERRORS 0
-/* tape directions */
-enum {
- IDETAPE_DIR_NONE = (1 << 0),
- IDETAPE_DIR_READ = (1 << 1),
- IDETAPE_DIR_WRITE = (1 << 2),
-};
+/*
+ * For general magnetic tape device compatibility.
+ */
+typedef enum {
+ idetape_direction_none,
+ idetape_direction_read,
+ idetape_direction_write
+} idetape_chrdev_direction_t;
struct idetape_bh {
u32 b_size;
@@ -181,32 +187,24 @@ struct idetape_bh {
char *b_data;
};
+/*
+ * Our view of a packet command.
+ */
typedef struct idetape_packet_command_s {
- /* Actual packet bytes */
- u8 c[12];
- /* On each retry, we increment retries */
- int retries;
- /* Error code */
- int error;
- /* Bytes to transfer */
- int request_transfer;
- /* Bytes actually transferred */
- int actually_transferred;
- /* Size of our data buffer */
- int buffer_size;
+ u8 c[12]; /* Actual packet bytes */
+ int retries; /* On each retry, we increment retries */
+ int error; /* Error code */
+ int request_transfer; /* Bytes to transfer */
+ int actually_transferred; /* Bytes actually transferred */
+ int buffer_size; /* Size of our data buffer */
struct idetape_bh *bh;
char *b_data;
int b_count;
- /* Data buffer */
- u8 *buffer;
- /* Pointer into the above buffer */
- u8 *current_position;
- /* Called when this packet command is completed */
- ide_startstop_t (*callback) (ide_drive_t *);
- /* Temporary buffer */
- u8 pc_buffer[IDETAPE_PC_BUFFER_SIZE];
- /* Status/Action bit flags: long for set_bit */
- unsigned long flags;
+ u8 *buffer; /* Data buffer */
+ u8 *current_position; /* Pointer into the above buffer */
+ ide_startstop_t (*callback) (ide_drive_t *); /* Called when this packet command is completed */
+ u8 pc_buffer[IDETAPE_PC_BUFFER_SIZE]; /* Temporary buffer */
+ unsigned long flags; /* Status/Action bit flags: long for set_bit */
} idetape_pc_t;
/*
@@ -225,7 +223,9 @@ typedef struct idetape_packet_command_s {
/* Data direction */
#define PC_WRITING 5
-/* A pipeline stage. */
+/*
+ * A pipeline stage.
+ */
typedef struct idetape_stage_s {
struct request rq; /* The corresponding request */
struct idetape_bh *bh; /* The data buffers */
@@ -233,8 +233,9 @@ typedef struct idetape_stage_s {
} idetape_stage_t;
/*
- * Most of our global data which we need to save even as we leave the driver due
- * to an interrupt or a timer event is stored in the struct defined below.
+ * Most of our global data which we need to save even as we leave the
+ * driver due to an interrupt or a timer event is stored in a variable
+ * of type idetape_tape_t, defined below.
*/
typedef struct ide_tape_obj {
ide_drive_t *drive;
@@ -270,14 +271,15 @@ typedef struct ide_tape_obj {
int rq_stack_index;
/*
- * DSC polling variables.
+ * DSC polling variables.
*
- * While polling for DSC we use postponed_rq to postpone the current
- * request so that ide.c will be able to service pending requests on the
- * other device. Note that at most we will have only one DSC (usually
- * data transfer) request in the device request queue. Additional
- * requests can be queued in our internal pipeline, but they will be
- * visible to ide.c only one at a time.
+ * While polling for DSC we use postponed_rq to postpone the
+ * current request so that ide.c will be able to service
+ * pending requests on the other device. Note that at most
+ * we will have only one DSC (usually data transfer) request
+ * in the device request queue. Additional requests can be
+ * queued in our internal pipeline, but they will be visible
+ * to ide.c only one at a time.
*/
struct request *postponed_rq;
/* The time in which we started polling for DSC */
@@ -285,57 +287,73 @@ typedef struct ide_tape_obj {
/* Timer used to poll for dsc */
struct timer_list dsc_timer;
/* Read/Write dsc polling frequency */
- unsigned long best_dsc_rw_freq;
- unsigned long dsc_poll_freq;
+ unsigned long best_dsc_rw_frequency;
+ /* The current polling frequency */
+ unsigned long dsc_polling_frequency;
+ /* Maximum waiting time */
unsigned long dsc_timeout;
- /* Read position information */
+ /*
+ * Read position information
+ */
u8 partition;
/* Current block */
- unsigned int first_frame;
+ unsigned int first_frame_position;
+ unsigned int last_frame_position;
+ unsigned int blocks_in_buffer;
- /* Last error information */
+ /*
+ * Last error information
+ */
u8 sense_key, asc, ascq;
- /* Character device operation */
+ /*
+ * Character device operation
+ */
unsigned int minor;
/* device name */
char name[4];
/* Current character device data transfer direction */
- u8 chrdev_dir;
+ idetape_chrdev_direction_t chrdev_direction;
- /* tape block size, usually 512 or 1024 bytes */
- unsigned short blk_size;
+ /*
+ * Device information
+ */
+ /* Usually 512 or 1024 bytes */
+ unsigned short tape_block_size;
int user_bs_factor;
/* Copy of the tape's Capabilities and Mechanical Page */
u8 caps[20];
/*
- * Active data transfer request parameters.
+ * Active data transfer request parameters.
+ *
+ * At most, there is only one ide-tape originated data transfer
+ * request in the device request queue. This allows ide.c to
+ * easily service requests from the other device when we
+ * postpone our active request. In the pipelined operation
+ * mode, we use our internal pipeline structure to hold
+ * more data requests.
*
- * At most, there is only one ide-tape originated data transfer request
- * in the device request queue. This allows ide.c to easily service
- * requests from the other device when we postpone our active request.
- * In the pipelined operation mode, we use our internal pipeline
- * structure to hold more data requests. The data buffer size is chosen
- * based on the tape's recommendation.
+ * The data buffer size is chosen based on the tape's
+ * recommendation.
*/
- /* ptr to the request which is waiting in the device request queue */
- struct request *active_data_rq;
- /* Data buffer size chosen based on the tape's recommendation */
+ /* Pointer to the request which is waiting in the device request queue */
+ struct request *active_data_request;
+ /* Data buffer size (chosen based on the tape's recommendation */
int stage_size;
idetape_stage_t *merge_stage;
int merge_stage_size;
struct idetape_bh *bh;
char *b_data;
int b_count;
-
+
/*
- * Pipeline parameters.
+ * Pipeline parameters.
*
- * To accomplish non-pipelined mode, we simply set the following
- * variables to zero (or NULL, where appropriate).
+ * To accomplish non-pipelined mode, we simply set the following
+ * variables to zero (or NULL, where appropriate).
*/
/* Number of currently used stages */
int nr_stages;
@@ -360,13 +378,20 @@ typedef struct ide_tape_obj {
/* Status/Action flags: long for set_bit */
unsigned long flags;
/* protects the ide-tape queue */
- spinlock_t lock;
+ spinlock_t spinlock;
- /* Measures average tape speed */
+ /*
+ * Measures average tape speed
+ */
unsigned long avg_time;
int avg_size;
int avg_speed;
+ char vendor_id[10];
+ char product_id[18];
+ char firmware_revision[6];
+ int firmware_revision_num;
+
/* the door is currently locked */
int door_locked;
/* the tape hardware is write protected */
@@ -375,9 +400,11 @@ typedef struct ide_tape_obj {
char write_prot;
/*
- * Limit the number of times a request can be postponed, to avoid an
- * infinite postpone deadlock.
+ * Limit the number of times a request can
+ * be postponed, to avoid an infinite postpone
+ * deadlock.
*/
+ /* request postpone count limit */
int postpone_cnt;
/*
@@ -392,19 +419,30 @@ typedef struct ide_tape_obj {
int tape_head;
int last_tape_head;
- /* Speed control at the tape buffers input/output */
+ /*
+ * Speed control at the tape buffers input/output
+ */
unsigned long insert_time;
int insert_size;
int insert_speed;
int max_insert_speed;
int measure_insert_time;
- /* Speed regulation negative feedback loop */
+ /*
+ * Measure tape still time, in milliseconds
+ */
+ unsigned long tape_still_time_begin;
+ int tape_still_time;
+
+ /*
+ * Speed regulation negative feedback loop
+ */
int speed_control;
int pipeline_head_speed;
int controlled_pipeline_head_speed;
int uncontrolled_pipeline_head_speed;
int controlled_last_pipeline_head;
+ int uncontrolled_last_pipeline_head;
unsigned long uncontrolled_pipeline_head_time;
unsigned long controlled_pipeline_head_time;
int controlled_previous_pipeline_head;
@@ -413,7 +451,18 @@ typedef struct ide_tape_obj {
unsigned long uncontrolled_previous_head_time;
int restart_speed_control_req;
- u32 debug_mask;
+ /*
+ * Debug_level determines amount of debugging output;
+ * can be changed using /proc/ide/hdx/settings
+ * 0 : almost no debugging output
+ * 1 : 0+output errors only
+ * 2 : 1+output all sensekey/asc
+ * 3 : 2+follow all chrdev related procedures
+ * 4 : 3+follow all procedures
+ * 5 : 4+include pc_stack rq_stack info
+ * 6 : 5+USE_COUNT updates
+ */
+ int debug_level;
} idetape_tape_t;
static DEFINE_MUTEX(idetape_ref_mutex);
@@ -446,7 +495,9 @@ static void ide_tape_put(struct ide_tape_obj *tape)
mutex_unlock(&idetape_ref_mutex);
}
-/* Tape door status */
+/*
+ * Tape door status
+ */
#define DOOR_UNLOCKED 0
#define DOOR_LOCKED 1
#define DOOR_EXPLICITLY_LOCKED 2
@@ -466,23 +517,30 @@ static void ide_tape_put(struct ide_tape_obj *tape)
/* 0 = no tape is loaded, so we don't rewind after ejecting */
#define IDETAPE_MEDIUM_PRESENT 9
-/* A define for the READ BUFFER command */
+/*
+ * Some defines for the READ BUFFER command
+ */
#define IDETAPE_RETRIEVE_FAULTY_BLOCK 6
-/* Some defines for the SPACE command */
+/*
+ * Some defines for the SPACE command
+ */
#define IDETAPE_SPACE_OVER_FILEMARK 1
#define IDETAPE_SPACE_TO_EOD 3
-/* Some defines for the LOAD UNLOAD command */
+/*
+ * Some defines for the LOAD UNLOAD command
+ */
#define IDETAPE_LU_LOAD_MASK 1
#define IDETAPE_LU_RETENSION_MASK 2
#define IDETAPE_LU_EOT_MASK 4
/*
- * Special requests for our block device strategy routine.
+ * Special requests for our block device strategy routine.
*
- * In order to service a character device command, we add special requests to
- * the tail of our block device request queue and wait for their completion.
+ * In order to service a character device command, we add special
+ * requests to the tail of our block device request queue and wait
+ * for their completion.
*/
enum {
@@ -493,20 +551,55 @@ enum {
REQ_IDETAPE_READ_BUFFER = (1 << 4),
};
-/* Error codes returned in rq->errors to the higher part of the driver. */
+/*
+ * Error codes which are returned in rq->errors to the higher part
+ * of the driver.
+ */
#define IDETAPE_ERROR_GENERAL 101
#define IDETAPE_ERROR_FILEMARK 102
#define IDETAPE_ERROR_EOD 103
+/*
+ * The following is used to format the general configuration word of
+ * the ATAPI IDENTIFY DEVICE command.
+ */
+struct idetape_id_gcw {
+ unsigned packet_size :2; /* Packet Size */
+ unsigned reserved234 :3; /* Reserved */
+ unsigned drq_type :2; /* Command packet DRQ type */
+ unsigned removable :1; /* Removable media */
+ unsigned device_type :5; /* Device type */
+ unsigned reserved13 :1; /* Reserved */
+ unsigned protocol :2; /* Protocol type */
+};
+
+/*
+ * READ POSITION packet command - Data Format (From Table 6-57)
+ */
+typedef struct {
+ unsigned reserved0_10 :2; /* Reserved */
+ unsigned bpu :1; /* Block Position Unknown */
+ unsigned reserved0_543 :3; /* Reserved */
+ unsigned eop :1; /* End Of Partition */
+ unsigned bop :1; /* Beginning Of Partition */
+ u8 partition; /* Partition Number */
+ u8 reserved2, reserved3; /* Reserved */
+ u32 first_block; /* First Block Location */
+ u32 last_block; /* Last Block Location (Optional) */
+ u8 reserved12; /* Reserved */
+ u8 blocks_in_buffer[3]; /* Blocks In Buffer - (Optional) */
+ u32 bytes_in_buffer; /* Bytes In Buffer (Optional) */
+} idetape_read_position_result_t;
+
/* Structures related to the SELECT SENSE / MODE SENSE packet commands. */
#define IDETAPE_BLOCK_DESCRIPTOR 0
#define IDETAPE_CAPABILITIES_PAGE 0x2a
/*
- * The variables below are used for the character device interface. Additional
- * state variables are defined in our ide_drive_t structure.
+ * The variables below are used for the character device interface.
+ * Additional state variables are defined in our ide_drive_t structure.
*/
-static struct ide_tape_obj *idetape_devs[MAX_HWIFS * MAX_DRIVES];
+static struct ide_tape_obj * idetape_devs[MAX_HWIFS * MAX_DRIVES];
#define ide_tape_f(file) ((file)->private_data)
@@ -522,18 +615,24 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i)
return tape;
}
+/*
+ * Function declarations
+ *
+ */
+static int idetape_chrdev_release (struct inode *inode, struct file *filp);
+static void idetape_write_release (ide_drive_t *drive, unsigned int minor);
+
/*
* Too bad. The drive wants to send us data which we are not ready to accept.
* Just throw it away.
*/
-static void idetape_discard_data(ide_drive_t *drive, unsigned int bcount)
+static void idetape_discard_data (ide_drive_t *drive, unsigned int bcount)
{
while (bcount--)
(void) HWIF(drive)->INB(IDE_DATA_REG);
}
-static void idetape_input_buffers(ide_drive_t *drive, idetape_pc_t *pc,
- unsigned int bcount)
+static void idetape_input_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsigned int bcount)
{
struct idetape_bh *bh = pc->bh;
int count;
@@ -545,11 +644,8 @@ static void idetape_input_buffers(ide_drive_t *drive, idetape_pc_t *pc,
idetape_discard_data(drive, bcount);
return;
}
- count = min(
- (unsigned int)(bh->b_size - atomic_read(&bh->b_count)),
- bcount);
- HWIF(drive)->atapi_input_bytes(drive, bh->b_data +
- atomic_read(&bh->b_count), count);
+ count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), bcount);
+ HWIF(drive)->atapi_input_bytes(drive, bh->b_data + atomic_read(&bh->b_count), count);
bcount -= count;
atomic_add(count, &bh->b_count);
if (atomic_read(&bh->b_count) == bh->b_size) {
@@ -561,16 +657,15 @@ static void idetape_input_buffers(ide_drive_t *drive, idetape_pc_t *pc,
pc->bh = bh;
}
-static void idetape_output_buffers(ide_drive_t *drive, idetape_pc_t *pc,
- unsigned int bcount)
+static void idetape_output_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsigned int bcount)
{
struct idetape_bh *bh = pc->bh;
int count;
while (bcount) {
if (bh == NULL) {
- printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
- __func__);
+ printk(KERN_ERR "ide-tape: bh == NULL in "
+ "idetape_output_buffers\n");
return;
}
count = min((unsigned int)pc->b_count, (unsigned int)bcount);
@@ -579,8 +674,7 @@ static void idetape_output_buffers(ide_drive_t *drive, idetape_pc_t *pc,
pc->b_data += count;
pc->b_count -= count;
if (!pc->b_count) {
- bh = bh->b_reqnext;
- pc->bh = bh;
+ pc->bh = bh = bh->b_reqnext;
if (bh) {
pc->b_data = bh->b_data;
pc->b_count = atomic_read(&bh->b_count);
@@ -589,7 +683,7 @@ static void idetape_output_buffers(ide_drive_t *drive, idetape_pc_t *pc,
}
}
-static void idetape_update_buffers(idetape_pc_t *pc)
+static void idetape_update_buffers (idetape_pc_t *pc)
{
struct idetape_bh *bh = pc->bh;
int count;
@@ -599,8 +693,8 @@ static void idetape_update_buffers(idetape_pc_t *pc)
return;
while (bcount) {
if (bh == NULL) {
- printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
- __func__);
+ printk(KERN_ERR "ide-tape: bh == NULL in "
+ "idetape_update_buffers\n");
return;
}
count = min((unsigned int)bh->b_size, (unsigned int)bcount);
@@ -618,14 +712,17 @@ static void idetape_update_buffers(idetape_pc_t *pc)
* driver. A storage space for a maximum of IDETAPE_PC_STACK packet
* commands is allocated at initialization time.
*/
-static idetape_pc_t *idetape_next_pc_storage(ide_drive_t *drive)
+static idetape_pc_t *idetape_next_pc_storage (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
- debug_log(DBG_PCRQ_STACK, "pc_stack_index=%d\n", tape->pc_stack_index);
-
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 5)
+ printk(KERN_INFO "ide-tape: pc_stack_index=%d\n",
+ tape->pc_stack_index);
+#endif /* IDETAPE_DEBUG_LOG */
if (tape->pc_stack_index == IDETAPE_PC_STACK)
- tape->pc_stack_index = 0;
+ tape->pc_stack_index=0;
return (&tape->pc_stack[tape->pc_stack_index++]);
}
@@ -634,26 +731,32 @@ static idetape_pc_t *idetape_next_pc_storage(ide_drive_t *drive)
* Since we queue packet commands in the request queue, we need to
* allocate a request, along with the allocation of a packet command.
*/
-
+
/**************************************************************
* *
* This should get fixed to use kmalloc(.., GFP_ATOMIC) *
* followed later on by kfree(). -ml *
* *
**************************************************************/
-
-static struct request *idetape_next_rq_storage(ide_drive_t *drive)
+
+static struct request *idetape_next_rq_storage (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
- debug_log(DBG_PCRQ_STACK, "rq_stack_index=%d\n", tape->rq_stack_index);
-
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 5)
+ printk(KERN_INFO "ide-tape: rq_stack_index=%d\n",
+ tape->rq_stack_index);
+#endif /* IDETAPE_DEBUG_LOG */
if (tape->rq_stack_index == IDETAPE_PC_STACK)
- tape->rq_stack_index = 0;
+ tape->rq_stack_index=0;
return (&tape->rq_stack[tape->rq_stack_index++]);
}
-static void idetape_init_pc(idetape_pc_t *pc)
+/*
+ * idetape_init_pc initializes a packet command.
+ */
+static void idetape_init_pc (idetape_pc_t *pc)
{
memset(pc->c, 0, 12);
pc->retries = 0;
@@ -677,14 +780,22 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
tape->sense_key = sense[2] & 0xF;
tape->asc = sense[12];
tape->ascq = sense[13];
-
- debug_log(DBG_ERR, "pc = %x, sense key = %x, asc = %x, ascq = %x\n",
- pc->c[0], tape->sense_key, tape->asc, tape->ascq);
+#if IDETAPE_DEBUG_LOG
+ /*
+ * Without debugging, we only log an error if we decided to give up
+ * retrying.
+ */
+ if (tape->debug_level >= 1)
+ printk(KERN_INFO "ide-tape: pc = %x, sense key = %x, "
+ "asc = %x, ascq = %x\n",
+ pc->c[0], tape->sense_key,
+ tape->asc, tape->ascq);
+#endif /* IDETAPE_DEBUG_LOG */
/* Correct pc->actually_transferred by asking the tape. */
if (test_bit(PC_DMA_ERROR, &pc->flags)) {
pc->actually_transferred = pc->request_transfer -
- tape->blk_size *
+ tape->tape_block_size *
be32_to_cpu(get_unaligned((u32 *)&sense[3]));
idetape_update_buffers(pc);
}
@@ -732,24 +843,50 @@ static void idetape_activate_next_stage(ide_drive_t *drive)
idetape_stage_t *stage = tape->next_stage;
struct request *rq = &stage->rq;
- debug_log(DBG_PROCS, "Enter %s\n", __func__);
-
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk(KERN_INFO "ide-tape: Reached idetape_active_next_stage\n");
+#endif /* IDETAPE_DEBUG_LOG */
if (stage == NULL) {
- printk(KERN_ERR "ide-tape: bug: Trying to activate a non"
- " existing stage\n");
+ printk(KERN_ERR "ide-tape: bug: Trying to activate a non existing stage\n");
return;
}
rq->rq_disk = tape->disk;
rq->buffer = NULL;
rq->special = (void *)stage->bh;
- tape->active_data_rq = rq;
+ tape->active_data_request = rq;
tape->active_stage = stage;
tape->next_stage = stage->next;
}
-/* Free a stage along with its related buffers completely. */
-static void __idetape_kfree_stage(idetape_stage_t *stage)
+/*
+ * idetape_increase_max_pipeline_stages is a part of the feedback
+ * loop which tries to find the optimum number of stages. In the
+ * feedback loop, we are starting from a minimum maximum number of
+ * stages, and if we sense that the pipeline is empty, we try to
+ * increase it, until we reach the user compile time memory limit.
+ */
+static void idetape_increase_max_pipeline_stages (ide_drive_t *drive)
+{
+ idetape_tape_t *tape = drive->driver_data;
+ int increase = (tape->max_pipeline - tape->min_pipeline) / 10;
+
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk (KERN_INFO "ide-tape: Reached idetape_increase_max_pipeline_stages\n");
+#endif /* IDETAPE_DEBUG_LOG */
+
+ tape->max_stages += max(increase, 1);
+ tape->max_stages = max(tape->max_stages, tape->min_pipeline);
+ tape->max_stages = min(tape->max_stages, tape->max_pipeline);
+}
+
+/*
+ * idetape_kfree_stage calls kfree to completely free a stage, along with
+ * its related buffers.
+ */
+static void __idetape_kfree_stage (idetape_stage_t *stage)
{
struct idetape_bh *prev_bh, *bh = stage->bh;
int size;
@@ -770,29 +907,30 @@ static void __idetape_kfree_stage(idetape_stage_t *stage)
kfree(stage);
}
-static void idetape_kfree_stage(idetape_tape_t *tape, idetape_stage_t *stage)
+static void idetape_kfree_stage (idetape_tape_t *tape, idetape_stage_t *stage)
{
__idetape_kfree_stage(stage);
}
/*
- * Remove tape->first_stage from the pipeline. The caller should avoid race
- * conditions.
+ * idetape_remove_stage_head removes tape->first_stage from the pipeline.
+ * The caller should avoid race conditions.
*/
-static void idetape_remove_stage_head(ide_drive_t *drive)
+static void idetape_remove_stage_head (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
idetape_stage_t *stage;
-
- debug_log(DBG_PROCS, "Enter %s\n", __func__);
-
+
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk(KERN_INFO "ide-tape: Reached idetape_remove_stage_head\n");
+#endif /* IDETAPE_DEBUG_LOG */
if (tape->first_stage == NULL) {
printk(KERN_ERR "ide-tape: bug: tape->first_stage is NULL\n");
return;
}
if (tape->active_stage == tape->first_stage) {
- printk(KERN_ERR "ide-tape: bug: Trying to free our active "
- "pipeline stage\n");
+ printk(KERN_ERR "ide-tape: bug: Trying to free our active pipeline stage\n");
return;
}
stage = tape->first_stage;
@@ -802,11 +940,9 @@ static void idetape_remove_stage_head(ide_drive_t *drive)
if (tape->first_stage == NULL) {
tape->last_stage = NULL;
if (tape->next_stage != NULL)
- printk(KERN_ERR "ide-tape: bug: tape->next_stage !="
- " NULL\n");
+ printk(KERN_ERR "ide-tape: bug: tape->next_stage != NULL\n");
if (tape->nr_stages)
- printk(KERN_ERR "ide-tape: bug: nr_stages should be 0 "
- "now\n");
+ printk(KERN_ERR "ide-tape: bug: nr_stages should be 0 now\n");
}
}
@@ -821,8 +957,10 @@ static void idetape_abort_pipeline(ide_drive_t *drive,
idetape_stage_t *stage = new_last_stage->next;
idetape_stage_t *nstage;
- debug_log(DBG_PROCS, "%s: Enter %s\n", tape->name, __func__);
-
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk(KERN_INFO "ide-tape: %s: idetape_abort_pipeline called\n", tape->name);
+#endif
while (stage) {
nstage = stage->next;
idetape_kfree_stage(tape, stage);
@@ -837,8 +975,8 @@ static void idetape_abort_pipeline(ide_drive_t *drive,
}
/*
- * Finish servicing a request and insert a pending pipeline request into the
- * main device queue.
+ * idetape_end_request is used to finish servicing a request, and to
+ * insert a pending pipeline request into the main device queue.
*/
static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
{
@@ -849,12 +987,15 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
int remove_stage = 0;
idetape_stage_t *active_stage;
- debug_log(DBG_PROCS, "Enter %s\n", __func__);
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk(KERN_INFO "ide-tape: Reached idetape_end_request\n");
+#endif /* IDETAPE_DEBUG_LOG */
switch (uptodate) {
- case 0: error = IDETAPE_ERROR_GENERAL; break;
- case 1: error = 0; break;
- default: error = uptodate;
+ case 0: error = IDETAPE_ERROR_GENERAL; break;
+ case 1: error = 0; break;
+ default: error = uptodate;
}
rq->errors = error;
if (error)
@@ -865,21 +1006,20 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
return 0;
}
- spin_lock_irqsave(&tape->lock, flags);
+ spin_lock_irqsave(&tape->spinlock, flags);
/* The request was a pipelined data transfer request */
- if (tape->active_data_rq == rq) {
+ if (tape->active_data_request == rq) {
active_stage = tape->active_stage;
tape->active_stage = NULL;
- tape->active_data_rq = NULL;
+ tape->active_data_request = NULL;
tape->nr_pending_stages--;
if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
remove_stage = 1;
if (error) {
set_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
if (error == IDETAPE_ERROR_EOD)
- idetape_abort_pipeline(drive,
- active_stage);
+ idetape_abort_pipeline(drive, active_stage);
}
} else if (rq->cmd[0] & REQ_IDETAPE_READ) {
if (error == IDETAPE_ERROR_EOD) {
@@ -890,57 +1030,48 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
if (tape->next_stage != NULL) {
idetape_activate_next_stage(drive);
- /* Insert the next request into the request queue. */
- (void)ide_do_drive_cmd(drive, tape->active_data_rq,
- ide_end);
- } else if (!error) {
/*
- * This is a part of the feedback loop which tries to
- * find the optimum number of stages. We are starting
- * from a minimum maximum number of stages, and if we
- * sense that the pipeline is empty, we try to increase
- * it, until we reach the user compile time memory
- * limit.
+ * Insert the next request into the request queue.
*/
- int i = (tape->max_pipeline - tape->min_pipeline) / 10;
-
- tape->max_stages += max(i, 1);
- tape->max_stages = max(tape->max_stages,
- tape->min_pipeline);
- tape->max_stages = min(tape->max_stages,
- tape->max_pipeline);
+ (void) ide_do_drive_cmd(drive, tape->active_data_request, ide_end);
+ } else if (!error) {
+ idetape_increase_max_pipeline_stages(drive);
}
}
ide_end_drive_cmd(drive, 0, 0);
+// blkdev_dequeue_request(rq);
+// drive->rq = NULL;
+// end_that_request_last(rq);
if (remove_stage)
idetape_remove_stage_head(drive);
- if (tape->active_data_rq == NULL)
+ if (tape->active_data_request == NULL)
clear_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
- spin_unlock_irqrestore(&tape->lock, flags);
+ spin_unlock_irqrestore(&tape->spinlock, flags);
return 0;
}
-static ide_startstop_t idetape_request_sense_callback(ide_drive_t *drive)
+static ide_startstop_t idetape_request_sense_callback (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
- debug_log(DBG_PROCS, "Enter %s\n", __func__);
-
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk(KERN_INFO "ide-tape: Reached idetape_request_sense_callback\n");
+#endif /* IDETAPE_DEBUG_LOG */
if (!tape->pc->error) {
idetape_analyze_error(drive, tape->pc->buffer);
idetape_end_request(drive, 1, 0);
} else {
- printk(KERN_ERR "ide-tape: Error in REQUEST SENSE itself - "
- "Aborting request!\n");
+ printk(KERN_ERR "ide-tape: Error in REQUEST SENSE itself - Aborting request!\n");
idetape_end_request(drive, 0, 0);
}
return ide_stopped;
}
-static void idetape_create_request_sense_cmd(idetape_pc_t *pc)
+static void idetape_create_request_sense_cmd (idetape_pc_t *pc)
{
- idetape_init_pc(pc);
+ idetape_init_pc(pc);
pc->c[0] = REQUEST_SENSE;
pc->c[4] = 20;
pc->request_transfer = 20;
@@ -955,22 +1086,25 @@ static void idetape_init_rq(struct request *rq, u8 cmd)
}
/*
- * Generate a new packet command request in front of the request queue, before
- * the current request, so that it will be processed immediately, on the next
- * pass through the driver. The function below is called from the request
- * handling part of the driver (the "bottom" part). Safe storage for the request
- * should be allocated with ide_tape_next_{pc,rq}_storage() prior to that.
+ * idetape_queue_pc_head generates a new packet command request in front
+ * of the request queue, before the current request, so that it will be
+ * processed immediately, on the next pass through the driver.
+ *
+ * idetape_queue_pc_head is called from the request handling part of
+ * the driver (the "bottom" part). Safe storage for the request should
+ * be allocated with idetape_next_pc_storage and idetape_next_rq_storage
+ * before calling idetape_queue_pc_head.
*
- * Memory for those requests is pre-allocated at initialization time, and is
- * limited to IDETAPE_PC_STACK requests. We assume that we have enough space for
- * the maximum possible number of inter-dependent packet commands.
+ * Memory for those requests is pre-allocated at initialization time, and
+ * is limited to IDETAPE_PC_STACK requests. We assume that we have enough
+ * space for the maximum possible number of inter-dependent packet commands.
*
- * The higher level of the driver - The ioctl handler and the character device
- * handling functions should queue request to the lower level part and wait for
- * their completion using idetape_queue_pc_tail or idetape_queue_rw_tail.
+ * The higher level of the driver - The ioctl handler and the character
+ * device handling functions should queue request to the lower level part
+ * and wait for their completion using idetape_queue_pc_tail or
+ * idetape_queue_rw_tail.
*/
-static void idetape_queue_pc_head(ide_drive_t *drive, idetape_pc_t *pc,
- struct request *rq)
+static void idetape_queue_pc_head (ide_drive_t *drive, idetape_pc_t *pc,struct request *rq)
{
struct ide_tape_obj *tape = drive->driver_data;
@@ -991,7 +1125,7 @@ static ide_startstop_t idetape_retry_pc (ide_drive_t *drive)
idetape_pc_t *pc;
struct request *rq;
- (void)ide_read_error(drive);
+ (void)drive->hwif->INB(IDE_ERROR_REG);
pc = idetape_next_pc_storage(drive);
rq = idetape_next_rq_storage(drive);
idetape_create_request_sense_cmd(pc);
@@ -1001,46 +1135,50 @@ static ide_startstop_t idetape_retry_pc (ide_drive_t *drive)
}
/*
- * Postpone the current request so that ide.c will be able to service requests
- * from another device on the same hwgroup while we are polling for DSC.
+ * idetape_postpone_request postpones the current request so that
+ * ide.c will be able to service requests from another device on
+ * the same hwgroup while we are polling for DSC.
*/
-static void idetape_postpone_request(ide_drive_t *drive)
+static void idetape_postpone_request (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
- debug_log(DBG_PROCS, "Enter %s\n", __func__);
-
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk(KERN_INFO "ide-tape: idetape_postpone_request\n");
+#endif
tape->postponed_rq = HWGROUP(drive)->rq;
- ide_stall_queue(drive, tape->dsc_poll_freq);
+ ide_stall_queue(drive, tape->dsc_polling_frequency);
}
-typedef void idetape_io_buf(ide_drive_t *, idetape_pc_t *, unsigned int);
-
/*
- * This is the usual interrupt handler which will be called during a packet
- * command. We will transfer some of the data (as requested by the drive) and
- * will re-point interrupt handler to us. When data transfer is finished, we
- * will act according to the algorithm described before
- * idetape_issue_pc.
+ * idetape_pc_intr is the usual interrupt handler which will be called
+ * during a packet command. We will transfer some of the data (as
+ * requested by the drive) and will re-point interrupt handler to us.
+ * When data transfer is finished, we will act according to the
+ * algorithm described before idetape_issue_packet_command.
+ *
*/
-static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t *pc = tape->pc;
- xfer_func_t *xferfunc;
- idetape_io_buf *iobuf;
unsigned int temp;
#if SIMULATE_ERRORS
- static int error_sim_count;
+ static int error_sim_count = 0;
#endif
u16 bcount;
u8 stat, ireason;
- debug_log(DBG_PROCS, "Enter %s - interrupt handler\n", __func__);
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk(KERN_INFO "ide-tape: Reached idetape_pc_intr "
+ "interrupt handler\n");
+#endif /* IDETAPE_DEBUG_LOG */
/* Clear the interrupt */
- stat = ide_read_status(drive);
+ stat = hwif->INB(IDE_STATUS_REG);
if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
if (hwif->ide_dma_end(drive) || (stat & ERR_STAT)) {
@@ -1070,16 +1208,20 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
pc->actually_transferred = pc->request_transfer;
idetape_update_buffers(pc);
}
- debug_log(DBG_PROCS, "DMA finished\n");
-
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk(KERN_INFO "ide-tape: DMA finished\n");
+#endif /* IDETAPE_DEBUG_LOG */
}
/* No more interrupts */
if ((stat & DRQ_STAT) == 0) {
- debug_log(DBG_SENSE, "Packet command completed, %d bytes"
- " transferred\n", pc->actually_transferred);
-
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 2)
+ printk(KERN_INFO "ide-tape: Packet command completed, %d bytes transferred\n", pc->actually_transferred);
+#endif /* IDETAPE_DEBUG_LOG */
clear_bit(PC_DMA_IN_PROGRESS, &pc->flags);
+
local_irq_enable();
#if SIMULATE_ERRORS
@@ -1094,16 +1236,19 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
stat &= ~ERR_STAT;
if ((stat & ERR_STAT) || test_bit(PC_DMA_ERROR, &pc->flags)) {
/* Error detected */
- debug_log(DBG_ERR, "%s: I/O error\n", tape->name);
-
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 1)
+ printk(KERN_INFO "ide-tape: %s: I/O error\n",
+ tape->name);
+#endif /* IDETAPE_DEBUG_LOG */
if (pc->c[0] == REQUEST_SENSE) {
- printk(KERN_ERR "ide-tape: I/O error in request"
- " sense command\n");
+ printk(KERN_ERR "ide-tape: I/O error in request sense command\n");
return ide_do_reset(drive);
}
- debug_log(DBG_ERR, "[cmd %x]: check condition\n",
- pc->c[0]);
-
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 1)
+ printk(KERN_INFO "ide-tape: [cmd %x]: check condition\n", pc->c[0]);
+#endif
/* Retry operation */
return idetape_retry_pc(drive);
}
@@ -1112,7 +1257,7 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
(stat & SEEK_STAT) == 0) {
/* Media access command */
tape->dsc_polling_start = jiffies;
- tape->dsc_poll_freq = IDETAPE_DSC_MA_FAST;
+ tape->dsc_polling_frequency = IDETAPE_DSC_MA_FAST;
tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT;
/* Allow ide.c to handle other requests */
idetape_postpone_request(drive);
@@ -1137,7 +1282,7 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
ireason = hwif->INB(IDE_IREASON_REG);
if (ireason & CD) {
- printk(KERN_ERR "ide-tape: CoD != 0 in %s\n", __func__);
+ printk(KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n");
return ide_do_reset(drive);
}
if (((ireason & IO) == IO) == test_bit(PC_WRITING, &pc->flags)) {
@@ -1153,76 +1298,86 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
temp = pc->actually_transferred + bcount;
if (temp > pc->request_transfer) {
if (temp > pc->buffer_size) {
- printk(KERN_ERR "ide-tape: The tape wants to "
- "send us more data than expected "
- "- discarding data\n");
+ printk(KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n");
idetape_discard_data(drive, bcount);
- ide_set_handler(drive, &idetape_pc_intr,
- IDETAPE_WAIT_CMD, NULL);
+ ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
return ide_started;
}
- debug_log(DBG_SENSE, "The tape wants to send us more "
- "data than expected - allowing transfer\n");
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 2)
+ printk(KERN_NOTICE "ide-tape: The tape wants to send us more data than expected - allowing transfer\n");
+#endif /* IDETAPE_DEBUG_LOG */
}
- iobuf = &idetape_input_buffers;
- xferfunc = hwif->atapi_input_bytes;
+ }
+ if (test_bit(PC_WRITING, &pc->flags)) {
+ if (pc->bh != NULL)
+ idetape_output_buffers(drive, pc, bcount);
+ else
+ /* Write the current buffer */
+ hwif->atapi_output_bytes(drive, pc->current_position,
+ bcount);
} else {
- iobuf = &idetape_output_buffers;
- xferfunc = hwif->atapi_output_bytes;
+ if (pc->bh != NULL)
+ idetape_input_buffers(drive, pc, bcount);
+ else
+ /* Read the current buffer */
+ hwif->atapi_input_bytes(drive, pc->current_position,
+ bcount);
}
-
- if (pc->bh)
- iobuf(drive, pc, bcount);
- else
- xferfunc(drive, pc->current_position, bcount);
-
/* Update the current position */
pc->actually_transferred += bcount;
pc->current_position += bcount;
-
- debug_log(DBG_SENSE, "[cmd %x] transferred %d bytes on that intr.\n",
- pc->c[0], bcount);
-
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 2)
+ printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes "
+ "on that interrupt\n", pc->c[0], bcount);
+#endif
/* And set the interrupt handler again */
ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
return ide_started;
}
/*
- * Packet Command Interface
+ * Packet Command Interface
+ *
+ * The current Packet Command is available in tape->pc, and will not
+ * change until we finish handling it. Each packet command is associated
+ * with a callback function that will be called when the command is
+ * finished.
*
- * The current Packet Command is available in tape->pc, and will not change
- * until we finish handling it. Each packet command is associated with a
- * callback function that will be called when the command is finished.
+ * The handling will be done in three stages:
*
- * The handling will be done in three stages:
+ * 1. idetape_issue_packet_command will send the packet command to the
+ * drive, and will set the interrupt handler to idetape_pc_intr.
*
- * 1. idetape_issue_pc will send the packet command to the drive, and will set
- * the interrupt handler to idetape_pc_intr.
+ * 2. On each interrupt, idetape_pc_intr will be called. This step
+ * will be repeated until the device signals us that no more
+ * interrupts will be issued.
*
- * 2. On each interrupt, idetape_pc_intr will be called. This step will be
- * repeated until the device signals us that no more interrupts will be issued.
+ * 3. ATAPI Tape media access commands have immediate status with a
+ * delayed process. In case of a successful initiation of a
+ * media access packet command, the DSC bit will be set when the
+ * actual execution of the command is finished.
+ * Since the tape drive will not issue an interrupt, we have to
+ * poll for this event. In this case, we define the request as
+ * "low priority request" by setting rq_status to
+ * IDETAPE_RQ_POSTPONED, set a timer to poll for DSC and exit
+ * the driver.
*
- * 3. ATAPI Tape media access commands have immediate status with a delayed
- * process. In case of a successful initiation of a media access packet command,
- * the DSC bit will be set when the actual execution of the command is finished.
- * Since the tape drive will not issue an interrupt, we have to poll for this
- * event. In this case, we define the request as "low priority request" by
- * setting rq_status to IDETAPE_RQ_POSTPONED, set a timer to poll for DSC and
- * exit the driver.
+ * ide.c will then give higher priority to requests which
+ * originate from the other device, until will change rq_status
+ * to RQ_ACTIVE.
*
- * ide.c will then give higher priority to requests which originate from the
- * other device, until will change rq_status to RQ_ACTIVE.
+ * 4. When the packet command is finished, it will be checked for errors.
*
- * 4. When the packet command is finished, it will be checked for errors.
+ * 5. In case an error was found, we queue a request sense packet
+ * command in front of the request queue and retry the operation
+ * up to IDETAPE_MAX_PC_RETRIES times.
*
- * 5. In case an error was found, we queue a request sense packet command in
- * front of the request queue and retry the operation up to
- * IDETAPE_MAX_PC_RETRIES times.
+ * 6. In case no error was found, or we decided to give up and not
+ * to retry again, the callback function will be called and then
+ * we will handle the next request.
*
- * 6. In case no error was found, or we decided to give up and not to retry
- * again, the callback function will be called and then we will handle the next
- * request.
*/
static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
{
@@ -1233,9 +1388,8 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
ide_startstop_t startstop;
u8 ireason;
- if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
- printk(KERN_ERR "ide-tape: Strange, packet command initiated "
- "yet DRQ isn't asserted\n");
+ if (ide_wait_stat(&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) {
+ printk(KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n");
return startstop;
}
ireason = hwif->INB(IDE_IREASON_REG);
@@ -1268,7 +1422,7 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
return ide_started;
}
-static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, idetape_pc_t *pc)
+static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape_pc_t *pc)
{
ide_hwif_t *hwif = drive->hwif;
idetape_tape_t *tape = drive->driver_data;
@@ -1289,9 +1443,9 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, idetape_pc_t *pc)
if (pc->retries > IDETAPE_MAX_PC_RETRIES ||
test_bit(PC_ABORT, &pc->flags)) {
/*
- * We will "abort" retrying a packet command in case legitimate
- * error code was received (crossing a filemark, or end of the
- * media, for example).
+ * We will "abort" retrying a packet command in case
+ * a legitimate error code was received (crossing a
+ * filemark, or end of the media, for example).
*/
if (!test_bit(PC_ABORT, &pc->flags)) {
if (!(pc->c[0] == TEST_UNIT_READY &&
@@ -1310,7 +1464,10 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, idetape_pc_t *pc)
tape->failed_pc = NULL;
return pc->callback(drive);
}
- debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 2)
+ printk(KERN_INFO "ide-tape: Retry number - %d, cmd = %02X\n", pc->retries, pc->c[0]);
+#endif /* IDETAPE_DEBUG_LOG */
pc->retries++;
/* We haven't transferred any data yet */
@@ -1342,24 +1499,31 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, idetape_pc_t *pc)
}
}
-static ide_startstop_t idetape_pc_callback(ide_drive_t *drive)
+/*
+ * General packet command callback function.
+ */
+static ide_startstop_t idetape_pc_callback (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
-
- debug_log(DBG_PROCS, "Enter %s\n", __func__);
+
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk(KERN_INFO "ide-tape: Reached idetape_pc_callback\n");
+#endif /* IDETAPE_DEBUG_LOG */
idetape_end_request(drive, tape->pc->error ? 0 : 1, 0);
return ide_stopped;
}
-/* A mode sense command is used to "sense" tape parameters. */
-static void idetape_create_mode_sense_cmd(idetape_pc_t *pc, u8 page_code)
+/*
+ * A mode sense command is used to "sense" tape parameters.
+ */
+static void idetape_create_mode_sense_cmd (idetape_pc_t *pc, u8 page_code)
{
idetape_init_pc(pc);
pc->c[0] = MODE_SENSE;
if (page_code != IDETAPE_BLOCK_DESCRIPTOR)
- /* DBD = 1 - Don't return block descriptors */
- pc->c[1] = 8;
+ pc->c[1] = 8; /* DBD = 1 - Don't return block descriptors */
pc->c[2] = page_code;
/*
* Changed pc->c[3] to 0 (255 will at best return unused info).
@@ -1369,8 +1533,7 @@ static void idetape_create_mode_sense_cmd(idetape_pc_t *pc, u8 page_code)
* and return an error when 255 is used.
*/
pc->c[3] = 0;
- /* We will just discard data in that case */
- pc->c[4] = 255;
+ pc->c[4] = 255; /* (We will just discard data in that case) */
if (page_code == IDETAPE_BLOCK_DESCRIPTOR)
pc->request_transfer = 12;
else if (page_code == IDETAPE_CAPABILITIES_PAGE)
@@ -1380,77 +1543,62 @@ static void idetape_create_mode_sense_cmd(idetape_pc_t *pc, u8 page_code)
pc->callback = &idetape_pc_callback;
}
-static void idetape_calculate_speeds(ide_drive_t *drive)
+static void calculate_speeds(ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
+ int full = 125, empty = 75;
- if (time_after(jiffies,
- tape->controlled_pipeline_head_time + 120 * HZ)) {
- tape->controlled_previous_pipeline_head =
- tape->controlled_last_pipeline_head;
- tape->controlled_previous_head_time =
- tape->controlled_pipeline_head_time;
+ if (time_after(jiffies, tape->controlled_pipeline_head_time + 120 * HZ)) {
+ tape->controlled_previous_pipeline_head = tape->controlled_last_pipeline_head;
+ tape->controlled_previous_head_time = tape->controlled_pipeline_head_time;
tape->controlled_last_pipeline_head = tape->pipeline_head;
tape->controlled_pipeline_head_time = jiffies;
}
if (time_after(jiffies, tape->controlled_pipeline_head_time + 60 * HZ))
- tape->controlled_pipeline_head_speed = (tape->pipeline_head -
- tape->controlled_last_pipeline_head) * 32 * HZ /
- (jiffies - tape->controlled_pipeline_head_time);
+ tape->controlled_pipeline_head_speed = (tape->pipeline_head - tape->controlled_last_pipeline_head) * 32 * HZ / (jiffies - tape->controlled_pipeline_head_time);
else if (time_after(jiffies, tape->controlled_previous_head_time))
- tape->controlled_pipeline_head_speed = (tape->pipeline_head -
- tape->controlled_previous_pipeline_head) * 32 *
- HZ / (jiffies - tape->controlled_previous_head_time);
+ tape->controlled_pipeline_head_speed = (tape->pipeline_head - tape->controlled_previous_pipeline_head) * 32 * HZ / (jiffies - tape->controlled_previous_head_time);
- if (tape->nr_pending_stages < tape->max_stages/*- 1 */) {
+ if (tape->nr_pending_stages < tape->max_stages /*- 1 */) {
/* -1 for read mode error recovery */
- if (time_after(jiffies, tape->uncontrolled_previous_head_time +
- 10 * HZ)) {
+ if (time_after(jiffies, tape->uncontrolled_previous_head_time + 10 * HZ)) {
tape->uncontrolled_pipeline_head_time = jiffies;
- tape->uncontrolled_pipeline_head_speed =
- (tape->pipeline_head -
- tape->uncontrolled_previous_pipeline_head) *
- 32 * HZ / (jiffies -
- tape->uncontrolled_previous_head_time);
+ tape->uncontrolled_pipeline_head_speed = (tape->pipeline_head - tape->uncontrolled_previous_pipeline_head) * 32 * HZ / (jiffies - tape->uncontrolled_previous_head_time);
}
} else {
tape->uncontrolled_previous_head_time = jiffies;
tape->uncontrolled_previous_pipeline_head = tape->pipeline_head;
- if (time_after(jiffies, tape->uncontrolled_pipeline_head_time +
- 30 * HZ))
+ if (time_after(jiffies, tape->uncontrolled_pipeline_head_time + 30 * HZ)) {
tape->uncontrolled_pipeline_head_time = jiffies;
-
+ }
}
- tape->pipeline_head_speed = max(tape->uncontrolled_pipeline_head_speed,
- tape->controlled_pipeline_head_speed);
-
- if (tape->speed_control == 1) {
+ tape->pipeline_head_speed = max(tape->uncontrolled_pipeline_head_speed, tape->controlled_pipeline_head_speed);
+ if (tape->speed_control == 0) {
+ tape->max_insert_speed = 5000;
+ } else if (tape->speed_control == 1) {
if (tape->nr_pending_stages >= tape->max_stages / 2)
tape->max_insert_speed = tape->pipeline_head_speed +
- (1100 - tape->pipeline_head_speed) * 2 *
- (tape->nr_pending_stages - tape->max_stages / 2)
- / tape->max_stages;
+ (1100 - tape->pipeline_head_speed) * 2 * (tape->nr_pending_stages - tape->max_stages / 2) / tape->max_stages;
else
tape->max_insert_speed = 500 +
- (tape->pipeline_head_speed - 500) * 2 *
- tape->nr_pending_stages / tape->max_stages;
-
+ (tape->pipeline_head_speed - 500) * 2 * tape->nr_pending_stages / tape->max_stages;
if (tape->nr_pending_stages >= tape->max_stages * 99 / 100)
tape->max_insert_speed = 5000;
+ } else if (tape->speed_control == 2) {
+ tape->max_insert_speed = tape->pipeline_head_speed * empty / 100 +
+ (tape->pipeline_head_speed * full / 100 - tape->pipeline_head_speed * empty / 100) * tape->nr_pending_stages / tape->max_stages;
} else
tape->max_insert_speed = tape->speed_control;
-
tape->max_insert_speed = max(tape->max_insert_speed, 500);
}
-static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
+static ide_startstop_t idetape_media_access_finished (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t *pc = tape->pc;
u8 stat;
- stat = ide_read_status(drive);
-
+ stat = drive->hwif->INB(IDE_STATUS_REG);
if (stat & SEEK_STAT) {
if (stat & ERR_STAT) {
/* Error detected */
@@ -1470,14 +1618,14 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
return pc->callback(drive);
}
-static ide_startstop_t idetape_rw_callback(ide_drive_t *drive)
+static ide_startstop_t idetape_rw_callback (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
struct request *rq = HWGROUP(drive)->rq;
- int blocks = tape->pc->actually_transferred / tape->blk_size;
+ int blocks = tape->pc->actually_transferred / tape->tape_block_size;
- tape->avg_size += blocks * tape->blk_size;
- tape->insert_size += blocks * tape->blk_size;
+ tape->avg_size += blocks * tape->tape_block_size;
+ tape->insert_size += blocks * tape->tape_block_size;
if (tape->insert_size > 1024 * 1024)
tape->measure_insert_time = 1;
if (tape->measure_insert_time) {
@@ -1486,17 +1634,19 @@ static ide_startstop_t idetape_rw_callback(ide_drive_t *drive)
tape->insert_size = 0;
}
if (time_after(jiffies, tape->insert_time))
- tape->insert_speed = tape->insert_size / 1024 * HZ /
- (jiffies - tape->insert_time);
+ tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time);
if (time_after_eq(jiffies, tape->avg_time + HZ)) {
- tape->avg_speed = tape->avg_size * HZ /
- (jiffies - tape->avg_time) / 1024;
+ tape->avg_speed = tape->avg_size * HZ / (jiffies - tape->avg_time) / 1024;
tape->avg_size = 0;
tape->avg_time = jiffies;
}
- debug_log(DBG_PROCS, "Enter %s\n", __func__);
- tape->first_frame += blocks;
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk(KERN_INFO "ide-tape: Reached idetape_rw_callback\n");
+#endif /* IDETAPE_DEBUG_LOG */
+
+ tape->first_frame_position += blocks;
rq->current_nr_sectors -= blocks;
if (!tape->pc->error)
@@ -1506,8 +1656,7 @@ static ide_startstop_t idetape_rw_callback(ide_drive_t *drive)
return ide_stopped;
}
-static void idetape_create_read_cmd(idetape_tape_t *tape, idetape_pc_t *pc,
- unsigned int length, struct idetape_bh *bh)
+static void idetape_create_read_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh)
{
idetape_init_pc(pc);
pc->c[0] = READ_6;
@@ -1517,14 +1666,12 @@ static void idetape_create_read_cmd(idetape_tape_t *tape, idetape_pc_t *pc,
pc->bh = bh;
atomic_set(&bh->b_count, 0);
pc->buffer = NULL;
- pc->buffer_size = length * tape->blk_size;
- pc->request_transfer = pc->buffer_size;
+ pc->request_transfer = pc->buffer_size = length * tape->tape_block_size;
if (pc->request_transfer == tape->stage_size)
set_bit(PC_DMA_RECOMMENDED, &pc->flags);
}
-static void idetape_create_read_buffer_cmd(idetape_tape_t *tape,
- idetape_pc_t *pc, struct idetape_bh *bh)
+static void idetape_create_read_buffer_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh)
{
int size = 32768;
struct idetape_bh *p = bh;
@@ -1542,12 +1689,10 @@ static void idetape_create_read_buffer_cmd(idetape_tape_t *tape,
atomic_set(&p->b_count, 0);
p = p->b_reqnext;
}
- pc->request_transfer = size;
- pc->buffer_size = size;
+ pc->request_transfer = pc->buffer_size = size;
}
-static void idetape_create_write_cmd(idetape_tape_t *tape, idetape_pc_t *pc,
- unsigned int length, struct idetape_bh *bh)
+static void idetape_create_write_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh)
{
idetape_init_pc(pc);
pc->c[0] = WRITE_6;
@@ -1559,12 +1704,14 @@ static void idetape_create_write_cmd(idetape_tape_t *tape, idetape_pc_t *pc,
pc->b_data = bh->b_data;
pc->b_count = atomic_read(&bh->b_count);
pc->buffer = NULL;
- pc->buffer_size = length * tape->blk_size;
- pc->request_transfer = pc->buffer_size;
+ pc->request_transfer = pc->buffer_size = length * tape->tape_block_size;
if (pc->request_transfer == tape->stage_size)
set_bit(PC_DMA_RECOMMENDED, &pc->flags);
}
+/*
+ * idetape_do_request is our request handling function.
+ */
static ide_startstop_t idetape_do_request(ide_drive_t *drive,
struct request *rq, sector_t block)
{
@@ -1573,22 +1720,30 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
struct request *postponed_rq = tape->postponed_rq;
u8 stat;
- debug_log(DBG_SENSE, "sector: %ld, nr_sectors: %ld,"
- " current_nr_sectors: %d\n",
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 2)
+ printk(KERN_INFO "ide-tape: sector: %ld, "
+ "nr_sectors: %ld, current_nr_sectors: %d\n",
rq->sector, rq->nr_sectors, rq->current_nr_sectors);
+#endif /* IDETAPE_DEBUG_LOG */
if (!blk_special_request(rq)) {
- /* We do not support buffer cache originated requests. */
+ /*
+ * We do not support buffer cache originated requests.
+ */
printk(KERN_NOTICE "ide-tape: %s: Unsupported request in "
"request queue (%d)\n", drive->name, rq->cmd_type);
ide_end_request(drive, 0, 0);
return ide_stopped;
}
- /* Retry a failed packet command */
- if (tape->failed_pc && tape->pc->c[0] == REQUEST_SENSE)
- return idetape_issue_pc(drive, tape->failed_pc);
-
+ /*
+ * Retry a failed packet command
+ */
+ if (tape->failed_pc != NULL &&
+ tape->pc->c[0] == REQUEST_SENSE) {
+ return idetape_issue_packet_command(drive, tape->failed_pc);
+ }
if (postponed_rq != NULL)
if (rq != postponed_rq) {
printk(KERN_ERR "ide-tape: ide-tape.c bug - "
@@ -1603,7 +1758,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
* If the tape is still busy, postpone our request and service
* the other device meanwhile.
*/
- stat = ide_read_status(drive);
+ stat = drive->hwif->INB(IDE_STATUS_REG);
if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2))
set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
@@ -1613,15 +1768,16 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
drive->post_reset = 0;
}
+ if (tape->tape_still_time > 100 && tape->tape_still_time < 200)
+ tape->measure_insert_time = 1;
if (time_after(jiffies, tape->insert_time))
- tape->insert_speed = tape->insert_size / 1024 * HZ /
- (jiffies - tape->insert_time);
- idetape_calculate_speeds(drive);
+ tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time);
+ calculate_speeds(drive);
if (!test_and_clear_bit(IDETAPE_IGNORE_DSC, &tape->flags) &&
(stat & SEEK_STAT) == 0) {
if (postponed_rq == NULL) {
tape->dsc_polling_start = jiffies;
- tape->dsc_poll_freq = tape->best_dsc_rw_freq;
+ tape->dsc_polling_frequency = tape->best_dsc_rw_frequency;
tape->dsc_timeout = jiffies + IDETAPE_DSC_RW_TIMEOUT;
} else if (time_after(jiffies, tape->dsc_timeout)) {
printk(KERN_ERR "ide-tape: %s: DSC timeout\n",
@@ -1632,10 +1788,8 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
} else {
return ide_do_reset(drive);
}
- } else if (time_after(jiffies,
- tape->dsc_polling_start +
- IDETAPE_DSC_MA_THRESHOLD))
- tape->dsc_poll_freq = IDETAPE_DSC_MA_SLOW;
+ } else if (time_after(jiffies, tape->dsc_polling_start + IDETAPE_DSC_MA_THRESHOLD))
+ tape->dsc_polling_frequency = IDETAPE_DSC_MA_SLOW;
idetape_postpone_request(drive);
return ide_stopped;
}
@@ -1643,23 +1797,20 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
tape->buffer_head++;
tape->postpone_cnt = 0;
pc = idetape_next_pc_storage(drive);
- idetape_create_read_cmd(tape, pc, rq->current_nr_sectors,
- (struct idetape_bh *)rq->special);
+ idetape_create_read_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special);
goto out;
}
if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
tape->buffer_head++;
tape->postpone_cnt = 0;
pc = idetape_next_pc_storage(drive);
- idetape_create_write_cmd(tape, pc, rq->current_nr_sectors,
- (struct idetape_bh *)rq->special);
+ idetape_create_write_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special);
goto out;
}
if (rq->cmd[0] & REQ_IDETAPE_READ_BUFFER) {
tape->postpone_cnt = 0;
pc = idetape_next_pc_storage(drive);
- idetape_create_read_buffer_cmd(tape, pc,
- (struct idetape_bh *)rq->special);
+ idetape_create_read_buffer_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special);
goto out;
}
if (rq->cmd[0] & REQ_IDETAPE_PC1) {
@@ -1674,51 +1825,49 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
}
BUG();
out:
- return idetape_issue_pc(drive, pc);
+ return idetape_issue_packet_command(drive, pc);
}
-/* Pipeline related functions */
-static inline int idetape_pipeline_active(idetape_tape_t *tape)
+/*
+ * Pipeline related functions
+ */
+static inline int idetape_pipeline_active (idetape_tape_t *tape)
{
int rc1, rc2;
rc1 = test_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
- rc2 = (tape->active_data_rq != NULL);
+ rc2 = (tape->active_data_request != NULL);
return rc1;
}
/*
- * The function below uses __get_free_page to allocate a pipeline stage, along
- * with all the necessary small buffers which together make a buffer of size
- * tape->stage_size (or a bit more). We attempt to combine sequential pages as
- * much as possible.
+ * idetape_kmalloc_stage uses __get_free_page to allocate a pipeline
+ * stage, along with all the necessary small buffers which together make
+ * a buffer of size tape->stage_size (or a bit more). We attempt to
+ * combine sequential pages as much as possible.
*
- * It returns a pointer to the new allocated stage, or NULL if we can't (or
- * don't want to) allocate a stage.
+ * Returns a pointer to the new allocated stage, or NULL if we
+ * can't (or don't want to) allocate a stage.
*
- * Pipeline stages are optional and are used to increase performance. If we
- * can't allocate them, we'll manage without them.
+ * Pipeline stages are optional and are used to increase performance.
+ * If we can't allocate them, we'll manage without them.
*/
-static idetape_stage_t *__idetape_kmalloc_stage(idetape_tape_t *tape, int full,
- int clear)
+static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full, int clear)
{
idetape_stage_t *stage;
struct idetape_bh *prev_bh, *bh;
int pages = tape->pages_per_stage;
char *b_data = NULL;
- stage = kmalloc(sizeof(idetape_stage_t), GFP_KERNEL);
- if (!stage)
+ if ((stage = kmalloc(sizeof (idetape_stage_t),GFP_KERNEL)) == NULL)
return NULL;
stage->next = NULL;
- stage->bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
- bh = stage->bh;
+ bh = stage->bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
if (bh == NULL)
goto abort;
bh->b_reqnext = NULL;
- bh->b_data = (char *) __get_free_page(GFP_KERNEL);
- if (!bh->b_data)
+ if ((bh->b_data = (char *) __get_free_page (GFP_KERNEL)) == NULL)
goto abort;
if (clear)
memset(bh->b_data, 0, PAGE_SIZE);
@@ -1726,8 +1875,7 @@ static idetape_stage_t *__idetape_kmalloc_stage(idetape_tape_t *tape, int full,
atomic_set(&bh->b_count, full ? bh->b_size : 0);
while (--pages) {
- b_data = (char *) __get_free_page(GFP_KERNEL);
- if (!b_data)
+ if ((b_data = (char *) __get_free_page (GFP_KERNEL)) == NULL)
goto abort;
if (clear)
memset(b_data, 0, PAGE_SIZE);
@@ -1745,8 +1893,7 @@ static idetape_stage_t *__idetape_kmalloc_stage(idetape_tape_t *tape, int full,
continue;
}
prev_bh = bh;
- bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
- if (!bh) {
+ if ((bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL)) == NULL) {
free_page((unsigned long) b_data);
goto abort;
}
@@ -1765,11 +1912,14 @@ static idetape_stage_t *__idetape_kmalloc_stage(idetape_tape_t *tape, int full,
return NULL;
}
-static idetape_stage_t *idetape_kmalloc_stage(idetape_tape_t *tape)
+static idetape_stage_t *idetape_kmalloc_stage (idetape_tape_t *tape)
{
idetape_stage_t *cache_stage = tape->cache_stage;
- debug_log(DBG_PROCS, "Enter %s\n", __func__);
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk(KERN_INFO "ide-tape: Reached idetape_kmalloc_stage\n");
+#endif /* IDETAPE_DEBUG_LOG */
if (tape->nr_stages >= tape->max_stages)
return NULL;
@@ -1780,8 +1930,7 @@ static idetape_stage_t *idetape_kmalloc_stage(idetape_tape_t *tape)
return __idetape_kmalloc_stage(tape, 0, 0);
}
-static int idetape_copy_stage_from_user(idetape_tape_t *tape,
- idetape_stage_t *stage, const char __user *buf, int n)
+static int idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char __user *buf, int n)
{
struct idetape_bh *bh = tape->bh;
int count;
@@ -1789,15 +1938,12 @@ static int idetape_copy_stage_from_user(idetape_tape_t *tape,
while (n) {
if (bh == NULL) {
- printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
- __func__);
+ printk(KERN_ERR "ide-tape: bh == NULL in "
+ "idetape_copy_stage_from_user\n");
return 1;
}
- count = min((unsigned int)
- (bh->b_size - atomic_read(&bh->b_count)),
- (unsigned int)n);
- if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf,
- count))
+ count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), (unsigned int)n);
+ if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count))
ret = 1;
n -= count;
atomic_add(count, &bh->b_count);
@@ -1812,8 +1958,7 @@ static int idetape_copy_stage_from_user(idetape_tape_t *tape,
return ret;
}
-static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf,
- idetape_stage_t *stage, int n)
+static int idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, idetape_stage_t *stage, int n)
{
struct idetape_bh *bh = tape->bh;
int count;
@@ -1821,8 +1966,8 @@ static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf,
while (n) {
if (bh == NULL) {
- printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
- __func__);
+ printk(KERN_ERR "ide-tape: bh == NULL in "
+ "idetape_copy_stage_to_user\n");
return 1;
}
count = min(tape->b_count, n);
@@ -1833,8 +1978,7 @@ static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf,
tape->b_count -= count;
buf += count;
if (!tape->b_count) {
- bh = bh->b_reqnext;
- tape->bh = bh;
+ tape->bh = bh = bh->b_reqnext;
if (bh) {
tape->b_data = bh->b_data;
tape->b_count = atomic_read(&bh->b_count);
@@ -1844,12 +1988,12 @@ static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf,
return ret;
}
-static void idetape_init_merge_stage(idetape_tape_t *tape)
+static void idetape_init_merge_stage (idetape_tape_t *tape)
{
struct idetape_bh *bh = tape->merge_stage->bh;
-
+
tape->bh = bh;
- if (tape->chrdev_dir == IDETAPE_DIR_WRITE)
+ if (tape->chrdev_direction == idetape_direction_write)
atomic_set(&bh->b_count, 0);
else {
tape->b_data = bh->b_data;
@@ -1857,7 +2001,7 @@ static void idetape_init_merge_stage(idetape_tape_t *tape)
}
}
-static void idetape_switch_buffers(idetape_tape_t *tape, idetape_stage_t *stage)
+static void idetape_switch_buffers (idetape_tape_t *tape, idetape_stage_t *stage)
{
struct idetape_bh *tmp;
@@ -1867,76 +2011,87 @@ static void idetape_switch_buffers(idetape_tape_t *tape, idetape_stage_t *stage)
idetape_init_merge_stage(tape);
}
-/* Add a new stage at the end of the pipeline. */
-static void idetape_add_stage_tail(ide_drive_t *drive, idetape_stage_t *stage)
+/*
+ * idetape_add_stage_tail adds a new stage at the end of the pipeline.
+ */
+static void idetape_add_stage_tail (ide_drive_t *drive,idetape_stage_t *stage)
{
idetape_tape_t *tape = drive->driver_data;
unsigned long flags;
-
- debug_log(DBG_PROCS, "Enter %s\n", __func__);
-
- spin_lock_irqsave(&tape->lock, flags);
+
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk (KERN_INFO "ide-tape: Reached idetape_add_stage_tail\n");
+#endif /* IDETAPE_DEBUG_LOG */
+ spin_lock_irqsave(&tape->spinlock, flags);
stage->next = NULL;
if (tape->last_stage != NULL)
- tape->last_stage->next = stage;
+ tape->last_stage->next=stage;
else
- tape->first_stage = stage;
- tape->next_stage = stage;
+ tape->first_stage = tape->next_stage=stage;
tape->last_stage = stage;
if (tape->next_stage == NULL)
tape->next_stage = tape->last_stage;
tape->nr_stages++;
tape->nr_pending_stages++;
- spin_unlock_irqrestore(&tape->lock, flags);
+ spin_unlock_irqrestore(&tape->spinlock, flags);
}
-/* Install a completion in a pending request and sleep until it is serviced. The
- * caller should ensure that the request will not be serviced before we install
- * the completion (usually by disabling interrupts).
+/*
+ * idetape_wait_for_request installs a completion in a pending request
+ * and sleeps until it is serviced.
+ *
+ * The caller should ensure that the request will not be serviced
+ * before we install the completion (usually by disabling interrupts).
*/
-static void idetape_wait_for_request(ide_drive_t *drive, struct request *rq)
+static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq)
{
DECLARE_COMPLETION_ONSTACK(wait);
idetape_tape_t *tape = drive->driver_data;
if (rq == NULL || !blk_special_request(rq)) {
- printk(KERN_ERR "ide-tape: bug: Trying to sleep on non-valid"
- " request\n");
+ printk (KERN_ERR "ide-tape: bug: Trying to sleep on non-valid request\n");
return;
}
rq->end_io_data = &wait;
rq->end_io = blk_end_sync_rq;
- spin_unlock_irq(&tape->lock);
+ spin_unlock_irq(&tape->spinlock);
wait_for_completion(&wait);
/* The stage and its struct request have been deallocated */
- spin_lock_irq(&tape->lock);
+ spin_lock_irq(&tape->spinlock);
}
-static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive)
+static ide_startstop_t idetape_read_position_callback (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
- u8 *readpos = tape->pc->buffer;
-
- debug_log(DBG_PROCS, "Enter %s\n", __func__);
+ idetape_read_position_result_t *result;
+
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk(KERN_INFO "ide-tape: Reached idetape_read_position_callback\n");
+#endif /* IDETAPE_DEBUG_LOG */
if (!tape->pc->error) {
- debug_log(DBG_SENSE, "BOP - %s\n",
- (readpos[0] & 0x80) ? "Yes" : "No");
- debug_log(DBG_SENSE, "EOP - %s\n",
- (readpos[0] & 0x40) ? "Yes" : "No");
-
- if (readpos[0] & 0x4) {
- printk(KERN_INFO "ide-tape: Block location is unknown"
- "to the tape\n");
+ result = (idetape_read_position_result_t *) tape->pc->buffer;
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 2)
+ printk(KERN_INFO "ide-tape: BOP - %s\n",result->bop ? "Yes":"No");
+ if (tape->debug_level >= 2)
+ printk(KERN_INFO "ide-tape: EOP - %s\n",result->eop ? "Yes":"No");
+#endif /* IDETAPE_DEBUG_LOG */
+ if (result->bpu) {
+ printk(KERN_INFO "ide-tape: Block location is unknown to the tape\n");
clear_bit(IDETAPE_ADDRESS_VALID, &tape->flags);
idetape_end_request(drive, 0, 0);
} else {
- debug_log(DBG_SENSE, "Block Location - %u\n",
- be32_to_cpu(*(u32 *)&readpos[4]));
-
- tape->partition = readpos[1];
- tape->first_frame =
- be32_to_cpu(*(u32 *)&readpos[4]);
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 2)
+ printk(KERN_INFO "ide-tape: Block Location - %u\n", ntohl(result->first_block));
+#endif /* IDETAPE_DEBUG_LOG */
+ tape->partition = result->partition;
+ tape->first_frame_position = ntohl(result->first_block);
+ tape->last_frame_position = ntohl(result->last_block);
+ tape->blocks_in_buffer = result->blocks_in_buffer[2];
set_bit(IDETAPE_ADDRESS_VALID, &tape->flags);
idetape_end_request(drive, 1, 0);
}
@@ -1947,11 +2102,14 @@ static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive)
}
/*
- * Write a filemark if write_filemark=1. Flush the device buffers without
- * writing a filemark otherwise.
+ * idetape_create_write_filemark_cmd will:
+ *
+ * 1. Write a filemark if write_filemark=1.
+ * 2. Flush the device buffers without writing a filemark
+ * if write_filemark=0.
+ *
*/
-static void idetape_create_write_filemark_cmd(ide_drive_t *drive,
- idetape_pc_t *pc, int write_filemark)
+static void idetape_create_write_filemark_cmd (ide_drive_t *drive, idetape_pc_t *pc,int write_filemark)
{
idetape_init_pc(pc);
pc->c[0] = WRITE_FILEMARKS;
@@ -1968,19 +2126,26 @@ static void idetape_create_test_unit_ready_cmd(idetape_pc_t *pc)
}
/*
- * We add a special packet command request to the tail of the request queue, and
- * wait for it to be serviced. This is not to be called from within the request
- * handling part of the driver! We allocate here data on the stack and it is
- * valid until the request is finished. This is not the case for the bottom part
- * of the driver, where we are always leaving the functions to wait for an
- * interrupt or a timer event.
+ * idetape_queue_pc_tail is based on the following functions:
+ *
+ * ide_do_drive_cmd from ide.c
+ * cdrom_queue_request and cdrom_queue_packet_command from ide-cd.c
*
- * From the bottom part of the driver, we should allocate safe memory using
- * idetape_next_pc_storage() and ide_tape_next_rq_storage(), and add the request
- * to the request list without waiting for it to be serviced! In that case, we
- * usually use idetape_queue_pc_head().
+ * We add a special packet command request to the tail of the request
+ * queue, and wait for it to be serviced.
+ *
+ * This is not to be called from within the request handling part
+ * of the driver ! We allocate here data in the stack, and it is valid
+ * until the request is finished. This is not the case for the bottom
+ * part of the driver, where we are always leaving the functions to wait
+ * for an interrupt or a timer event.
+ *
+ * From the bottom part of the driver, we should allocate safe memory
+ * using idetape_next_pc_storage and idetape_next_rq_storage, and add
+ * the request to the request list without waiting for it to be serviced !
+ * In that case, we usually use idetape_queue_pc_head.
*/
-static int __idetape_queue_pc_tail(ide_drive_t *drive, idetape_pc_t *pc)
+static int __idetape_queue_pc_tail (ide_drive_t *drive, idetape_pc_t *pc)
{
struct ide_tape_obj *tape = drive->driver_data;
struct request rq;
@@ -1991,8 +2156,7 @@ static int __idetape_queue_pc_tail(ide_drive_t *drive, idetape_pc_t *pc)
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
-static void idetape_create_load_unload_cmd(ide_drive_t *drive, idetape_pc_t *pc,
- int cmd)
+static void idetape_create_load_unload_cmd (ide_drive_t *drive, idetape_pc_t *pc,int cmd)
{
idetape_init_pc(pc);
pc->c[0] = START_STOP;
@@ -2007,7 +2171,9 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
idetape_pc_t pc;
int load_attempted = 0;
- /* Wait for the tape to become ready */
+ /*
+ * Wait for the tape to become ready
+ */
set_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags);
timeout += jiffies;
while (time_before(jiffies, timeout)) {
@@ -2015,12 +2181,10 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
if (!__idetape_queue_pc_tail(drive, &pc))
return 0;
if ((tape->sense_key == 2 && tape->asc == 4 && tape->ascq == 2)
- || (tape->asc == 0x3A)) {
- /* no media */
+ || (tape->asc == 0x3A)) { /* no media */
if (load_attempted)
return -ENOMEDIUM;
- idetape_create_load_unload_cmd(drive, &pc,
- IDETAPE_LU_LOAD_MASK);
+ idetape_create_load_unload_cmd(drive, &pc, IDETAPE_LU_LOAD_MASK);
__idetape_queue_pc_tail(drive, &pc);
load_attempted = 1;
/* not about to be ready */
@@ -2032,25 +2196,24 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
return -EIO;
}
-static int idetape_queue_pc_tail(ide_drive_t *drive, idetape_pc_t *pc)
+static int idetape_queue_pc_tail (ide_drive_t *drive,idetape_pc_t *pc)
{
return __idetape_queue_pc_tail(drive, pc);
}
-static int idetape_flush_tape_buffers(ide_drive_t *drive)
+static int idetape_flush_tape_buffers (ide_drive_t *drive)
{
idetape_pc_t pc;
int rc;
idetape_create_write_filemark_cmd(drive, &pc, 0);
- rc = idetape_queue_pc_tail(drive, &pc);
- if (rc)
+ if ((rc = idetape_queue_pc_tail(drive, &pc)))
return rc;
idetape_wait_ready(drive, 60 * 5 * HZ);
return 0;
}
-static void idetape_create_read_position_cmd(idetape_pc_t *pc)
+static void idetape_create_read_position_cmd (idetape_pc_t *pc)
{
idetape_init_pc(pc);
pc->c[0] = READ_POSITION;
@@ -2058,23 +2221,25 @@ static void idetape_create_read_position_cmd(idetape_pc_t *pc)
pc->callback = &idetape_read_position_callback;
}
-static int idetape_read_position(ide_drive_t *drive)
+static int idetape_read_position (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t pc;
int position;
- debug_log(DBG_PROCS, "Enter %s\n", __func__);
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk(KERN_INFO "ide-tape: Reached idetape_read_position\n");
+#endif /* IDETAPE_DEBUG_LOG */
idetape_create_read_position_cmd(&pc);
if (idetape_queue_pc_tail(drive, &pc))
return -1;
- position = tape->first_frame;
+ position = tape->first_frame_position;
return position;
}
-static void idetape_create_locate_cmd(ide_drive_t *drive, idetape_pc_t *pc,
- unsigned int block, u8 partition, int skip)
+static void idetape_create_locate_cmd (ide_drive_t *drive, idetape_pc_t *pc, unsigned int block, u8 partition, int skip)
{
idetape_init_pc(pc);
pc->c[0] = POSITION_TO_ELEMENT;
@@ -2085,8 +2250,7 @@ static void idetape_create_locate_cmd(ide_drive_t *drive, idetape_pc_t *pc,
pc->callback = &idetape_pc_callback;
}
-static int idetape_create_prevent_cmd(ide_drive_t *drive, idetape_pc_t *pc,
- int prevent)
+static int idetape_create_prevent_cmd (ide_drive_t *drive, idetape_pc_t *pc, int prevent)
{
idetape_tape_t *tape = drive->driver_data;
@@ -2101,17 +2265,17 @@ static int idetape_create_prevent_cmd(ide_drive_t *drive, idetape_pc_t *pc,
return 1;
}
-static int __idetape_discard_read_pipeline(ide_drive_t *drive)
+static int __idetape_discard_read_pipeline (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
unsigned long flags;
int cnt;
- if (tape->chrdev_dir != IDETAPE_DIR_READ)
+ if (tape->chrdev_direction != idetape_direction_read)
return 0;
/* Remove merge stage. */
- cnt = tape->merge_stage_size / tape->blk_size;
+ cnt = tape->merge_stage_size / tape->tape_block_size;
if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags))
++cnt; /* Filemarks count as 1 sector */
tape->merge_stage_size = 0;
@@ -2122,22 +2286,22 @@ static int __idetape_discard_read_pipeline(ide_drive_t *drive)
/* Clear pipeline flags. */
clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
- tape->chrdev_dir = IDETAPE_DIR_NONE;
+ tape->chrdev_direction = idetape_direction_none;
/* Remove pipeline stages. */
if (tape->first_stage == NULL)
return 0;
- spin_lock_irqsave(&tape->lock, flags);
+ spin_lock_irqsave(&tape->spinlock, flags);
tape->next_stage = NULL;
if (idetape_pipeline_active(tape))
- idetape_wait_for_request(drive, tape->active_data_rq);
- spin_unlock_irqrestore(&tape->lock, flags);
+ idetape_wait_for_request(drive, tape->active_data_request);
+ spin_unlock_irqrestore(&tape->spinlock, flags);
while (tape->first_stage != NULL) {
struct request *rq_ptr = &tape->first_stage->rq;
- cnt += rq_ptr->nr_sectors - rq_ptr->current_nr_sectors;
+ cnt += rq_ptr->nr_sectors - rq_ptr->current_nr_sectors;
if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK)
++cnt;
idetape_remove_stage_head(drive);
@@ -2148,19 +2312,21 @@ static int __idetape_discard_read_pipeline(ide_drive_t *drive)
}
/*
- * Position the tape to the requested block using the LOCATE packet command.
- * A READ POSITION command is then issued to check where we are positioned. Like
- * all higher level operations, we queue the commands at the tail of the request
- * queue and wait for their completion.
+ * idetape_position_tape positions the tape to the requested block
+ * using the LOCATE packet command. A READ POSITION command is then
+ * issued to check where we are positioned.
+ *
+ * Like all higher level operations, we queue the commands at the tail
+ * of the request queue and wait for their completion.
+ *
*/
-static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
- u8 partition, int skip)
+static int idetape_position_tape (ide_drive_t *drive, unsigned int block, u8 partition, int skip)
{
idetape_tape_t *tape = drive->driver_data;
int retval;
idetape_pc_t pc;
- if (tape->chrdev_dir == IDETAPE_DIR_READ)
+ if (tape->chrdev_direction == idetape_direction_read)
__idetape_discard_read_pipeline(drive);
idetape_wait_ready(drive, 60 * 5 * HZ);
idetape_create_locate_cmd(drive, &pc, block, partition, skip);
@@ -2172,8 +2338,7 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
return (idetape_queue_pc_tail(drive, &pc));
}
-static void idetape_discard_read_pipeline(ide_drive_t *drive,
- int restore_position)
+static void idetape_discard_read_pipeline (ide_drive_t *drive, int restore_position)
{
idetape_tape_t *tape = drive->driver_data;
int cnt;
@@ -2184,37 +2349,35 @@ static void idetape_discard_read_pipeline(ide_drive_t *drive,
position = idetape_read_position(drive);
seek = position > cnt ? position - cnt : 0;
if (idetape_position_tape(drive, seek, 0, 0)) {
- printk(KERN_INFO "ide-tape: %s: position_tape failed in"
- " discard_pipeline()\n", tape->name);
+ printk(KERN_INFO "ide-tape: %s: position_tape failed in discard_pipeline()\n", tape->name);
return;
}
}
}
/*
- * Generate a read/write request for the block device interface and wait for it
- * to be serviced.
+ * idetape_queue_rw_tail generates a read/write request for the block
+ * device interface and wait for it to be serviced.
*/
-static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks,
- struct idetape_bh *bh)
+static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks, struct idetape_bh *bh)
{
idetape_tape_t *tape = drive->driver_data;
struct request rq;
- debug_log(DBG_SENSE, "%s: cmd=%d\n", __func__, cmd);
-
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 2)
+ printk(KERN_INFO "ide-tape: idetape_queue_rw_tail: cmd=%d\n",cmd);
+#endif /* IDETAPE_DEBUG_LOG */
if (idetape_pipeline_active(tape)) {
- printk(KERN_ERR "ide-tape: bug: the pipeline is active in %s\n",
- __func__);
+ printk(KERN_ERR "ide-tape: bug: the pipeline is active in idetape_queue_rw_tail\n");
return (0);
}
idetape_init_rq(&rq, cmd);
rq.rq_disk = tape->disk;
rq.special = (void *)bh;
- rq.sector = tape->first_frame;
- rq.nr_sectors = blocks;
- rq.current_nr_sectors = blocks;
+ rq.sector = tape->first_frame_position;
+ rq.nr_sectors = rq.current_nr_sectors = blocks;
(void) ide_do_drive_cmd(drive, &rq, ide_wait);
if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0)
@@ -2224,11 +2387,14 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks,
idetape_init_merge_stage(tape);
if (rq.errors == IDETAPE_ERROR_GENERAL)
return -EIO;
- return (tape->blk_size * (blocks-rq.current_nr_sectors));
+ return (tape->tape_block_size * (blocks-rq.current_nr_sectors));
}
-/* start servicing the pipeline stages, starting from tape->next_stage. */
-static void idetape_plug_pipeline(ide_drive_t *drive)
+/*
+ * idetape_insert_pipeline_into_queue is used to start servicing the
+ * pipeline stages, starting from tape->next_stage.
+ */
+static void idetape_insert_pipeline_into_queue (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
@@ -2237,20 +2403,19 @@ static void idetape_plug_pipeline(ide_drive_t *drive)
if (!idetape_pipeline_active(tape)) {
set_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
idetape_activate_next_stage(drive);
- (void) ide_do_drive_cmd(drive, tape->active_data_rq, ide_end);
+ (void) ide_do_drive_cmd(drive, tape->active_data_request, ide_end);
}
}
-static void idetape_create_inquiry_cmd(idetape_pc_t *pc)
+static void idetape_create_inquiry_cmd (idetape_pc_t *pc)
{
idetape_init_pc(pc);
pc->c[0] = INQUIRY;
- pc->c[4] = 254;
- pc->request_transfer = 254;
+ pc->c[4] = pc->request_transfer = 254;
pc->callback = &idetape_pc_callback;
}
-static void idetape_create_rewind_cmd(ide_drive_t *drive, idetape_pc_t *pc)
+static void idetape_create_rewind_cmd (ide_drive_t *drive, idetape_pc_t *pc)
{
idetape_init_pc(pc);
pc->c[0] = REZERO_UNIT;
@@ -2258,7 +2423,7 @@ static void idetape_create_rewind_cmd(ide_drive_t *drive, idetape_pc_t *pc)
pc->callback = &idetape_pc_callback;
}
-static void idetape_create_erase_cmd(idetape_pc_t *pc)
+static void idetape_create_erase_cmd (idetape_pc_t *pc)
{
idetape_init_pc(pc);
pc->c[0] = ERASE;
@@ -2267,7 +2432,7 @@ static void idetape_create_erase_cmd(idetape_pc_t *pc)
pc->callback = &idetape_pc_callback;
}
-static void idetape_create_space_cmd(idetape_pc_t *pc, int count, u8 cmd)
+static void idetape_create_space_cmd (idetape_pc_t *pc,int count, u8 cmd)
{
idetape_init_pc(pc);
pc->c[0] = SPACE;
@@ -2277,87 +2442,89 @@ static void idetape_create_space_cmd(idetape_pc_t *pc, int count, u8 cmd)
pc->callback = &idetape_pc_callback;
}
-static void idetape_wait_first_stage(ide_drive_t *drive)
+static void idetape_wait_first_stage (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
unsigned long flags;
if (tape->first_stage == NULL)
return;
- spin_lock_irqsave(&tape->lock, flags);
+ spin_lock_irqsave(&tape->spinlock, flags);
if (tape->active_stage == tape->first_stage)
- idetape_wait_for_request(drive, tape->active_data_rq);
- spin_unlock_irqrestore(&tape->lock, flags);
+ idetape_wait_for_request(drive, tape->active_data_request);
+ spin_unlock_irqrestore(&tape->spinlock, flags);
}
/*
- * Try to add a character device originated write request to our pipeline. In
- * case we don't succeed, we revert to non-pipelined operation mode for this
- * request. In order to accomplish that, we
+ * idetape_add_chrdev_write_request tries to add a character device
+ * originated write request to our pipeline. In case we don't succeed,
+ * we revert to non-pipelined operation mode for this request.
*
- * 1. Try to allocate a new pipeline stage.
- * 2. If we can't, wait for more and more requests to be serviced and try again
- * each time.
- * 3. If we still can't allocate a stage, fallback to non-pipelined operation
- * mode for this request.
+ * 1. Try to allocate a new pipeline stage.
+ * 2. If we can't, wait for more and more requests to be serviced
+ * and try again each time.
+ * 3. If we still can't allocate a stage, fallback to
+ * non-pipelined operation mode for this request.
*/
-static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks)
+static int idetape_add_chrdev_write_request (ide_drive_t *drive, int blocks)
{
idetape_tape_t *tape = drive->driver_data;
idetape_stage_t *new_stage;
unsigned long flags;
struct request *rq;
- debug_log(DBG_CHRDEV, "Enter %s\n", __func__);
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 3)
+ printk(KERN_INFO "ide-tape: Reached idetape_add_chrdev_write_request\n");
+#endif /* IDETAPE_DEBUG_LOG */
- /* Attempt to allocate a new stage. Beware possible race conditions. */
+ /*
+ * Attempt to allocate a new stage.
+ * Pay special attention to possible race conditions.
+ */
while ((new_stage = idetape_kmalloc_stage(tape)) == NULL) {
- spin_lock_irqsave(&tape->lock, flags);
+ spin_lock_irqsave(&tape->spinlock, flags);
if (idetape_pipeline_active(tape)) {
- idetape_wait_for_request(drive, tape->active_data_rq);
- spin_unlock_irqrestore(&tape->lock, flags);
+ idetape_wait_for_request(drive, tape->active_data_request);
+ spin_unlock_irqrestore(&tape->spinlock, flags);
} else {
- spin_unlock_irqrestore(&tape->lock, flags);
- idetape_plug_pipeline(drive);
+ spin_unlock_irqrestore(&tape->spinlock, flags);
+ idetape_insert_pipeline_into_queue(drive);
if (idetape_pipeline_active(tape))
continue;
/*
- * The machine is short on memory. Fallback to non-
- * pipelined operation mode for this request.
+ * Linux is short on memory. Fallback to
+ * non-pipelined operation mode for this request.
*/
- return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE,
- blocks, tape->merge_stage->bh);
+ return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks, tape->merge_stage->bh);
}
}
rq = &new_stage->rq;
idetape_init_rq(rq, REQ_IDETAPE_WRITE);
/* Doesn't actually matter - We always assume sequential access */
- rq->sector = tape->first_frame;
- rq->current_nr_sectors = blocks;
- rq->nr_sectors = blocks;
+ rq->sector = tape->first_frame_position;
+ rq->nr_sectors = rq->current_nr_sectors = blocks;
idetape_switch_buffers(tape, new_stage);
idetape_add_stage_tail(drive, new_stage);
tape->pipeline_head++;
- idetape_calculate_speeds(drive);
+ calculate_speeds(drive);
/*
- * Estimate whether the tape has stopped writing by checking if our
- * write pipeline is currently empty. If we are not writing anymore,
- * wait for the pipeline to be almost completely full (90%) before
- * starting to service requests, so that we will be able to keep up with
- * the higher speeds of the tape.
+ * Estimate whether the tape has stopped writing by checking
+ * if our write pipeline is currently empty. If we are not
+ * writing anymore, wait for the pipeline to be full enough
+ * (90%) before starting to service requests, so that we will
+ * be able to keep up with the higher speeds of the tape.
*/
if (!idetape_pipeline_active(tape)) {
if (tape->nr_stages >= tape->max_stages * 9 / 10 ||
- tape->nr_stages >= tape->max_stages -
- tape->uncontrolled_pipeline_head_speed * 3 * 1024 /
- tape->blk_size) {
+ tape->nr_stages >= tape->max_stages - tape->uncontrolled_pipeline_head_speed * 3 * 1024 / tape->tape_block_size) {
tape->measure_insert_time = 1;
tape->insert_time = jiffies;
tape->insert_size = 0;
tape->insert_speed = 0;
- idetape_plug_pipeline(drive);
+ idetape_insert_pipeline_into_queue(drive);
}
}
if (test_and_clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags))
@@ -2367,32 +2534,31 @@ static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks)
}
/*
- * Wait until all pending pipeline requests are serviced. Typically called on
- * device close.
+ * idetape_wait_for_pipeline will wait until all pending pipeline
+ * requests are serviced. Typically called on device close.
*/
-static void idetape_wait_for_pipeline(ide_drive_t *drive)
+static void idetape_wait_for_pipeline (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
unsigned long flags;
while (tape->next_stage || idetape_pipeline_active(tape)) {
- idetape_plug_pipeline(drive);
- spin_lock_irqsave(&tape->lock, flags);
+ idetape_insert_pipeline_into_queue(drive);
+ spin_lock_irqsave(&tape->spinlock, flags);
if (idetape_pipeline_active(tape))
- idetape_wait_for_request(drive, tape->active_data_rq);
- spin_unlock_irqrestore(&tape->lock, flags);
+ idetape_wait_for_request(drive, tape->active_data_request);
+ spin_unlock_irqrestore(&tape->spinlock, flags);
}
}
-static void idetape_empty_write_pipeline(ide_drive_t *drive)
+static void idetape_empty_write_pipeline (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
int blocks, min;
struct idetape_bh *bh;
- if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
- printk(KERN_ERR "ide-tape: bug: Trying to empty write pipeline,"
- " but we are not writing.\n");
+ if (tape->chrdev_direction != idetape_direction_write) {
+ printk(KERN_ERR "ide-tape: bug: Trying to empty write pipeline, but we are not writing.\n");
return;
}
if (tape->merge_stage_size > tape->stage_size) {
@@ -2400,13 +2566,12 @@ static void idetape_empty_write_pipeline(ide_drive_t *drive)
tape->merge_stage_size = tape->stage_size;
}
if (tape->merge_stage_size) {
- blocks = tape->merge_stage_size / tape->blk_size;
- if (tape->merge_stage_size % tape->blk_size) {
+ blocks = tape->merge_stage_size / tape->tape_block_size;
+ if (tape->merge_stage_size % tape->tape_block_size) {
unsigned int i;
blocks++;
- i = tape->blk_size - tape->merge_stage_size %
- tape->blk_size;
+ i = tape->tape_block_size - tape->merge_stage_size % tape->tape_block_size;
bh = tape->bh->b_reqnext;
while (bh) {
atomic_set(&bh->b_count, 0);
@@ -2415,14 +2580,12 @@ static void idetape_empty_write_pipeline(ide_drive_t *drive)
bh = tape->bh;
while (i) {
if (bh == NULL) {
- printk(KERN_INFO "ide-tape: bug,"
- " bh NULL\n");
+
+ printk(KERN_INFO "ide-tape: bug, bh NULL\n");
break;
}
- min = min(i, (unsigned int)(bh->b_size -
- atomic_read(&bh->b_count)));
- memset(bh->b_data + atomic_read(&bh->b_count),
- 0, min);
+ min = min(i, (unsigned int)(bh->b_size - atomic_read(&bh->b_count)));
+ memset(bh->b_data + atomic_read(&bh->b_count), 0, min);
atomic_add(min, &bh->b_count);
i -= min;
bh = bh->b_reqnext;
@@ -2437,13 +2600,13 @@ static void idetape_empty_write_pipeline(ide_drive_t *drive)
tape->merge_stage = NULL;
}
clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
- tape->chrdev_dir = IDETAPE_DIR_NONE;
+ tape->chrdev_direction = idetape_direction_none;
/*
- * On the next backup, perform the feedback loop again. (I don't want to
- * keep sense information between backups, as some systems are
- * constantly on, and the system load can be totally different on the
- * next backup).
+ * On the next backup, perform the feedback loop again.
+ * (I don't want to keep sense information between backups,
+ * as some systems are constantly on, and the system load
+ * can be totally different on the next backup).
*/
tape->max_stages = tape->min_pipeline;
if (tape->first_stage != NULL ||
@@ -2458,25 +2621,21 @@ static void idetape_empty_write_pipeline(ide_drive_t *drive)
}
}
-static void idetape_restart_speed_control(ide_drive_t *drive)
+static void idetape_restart_speed_control (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
tape->restart_speed_control_req = 0;
tape->pipeline_head = 0;
- tape->controlled_last_pipeline_head = 0;
- tape->controlled_previous_pipeline_head = 0;
- tape->uncontrolled_previous_pipeline_head = 0;
- tape->controlled_pipeline_head_speed = 5000;
- tape->pipeline_head_speed = 5000;
+ tape->controlled_last_pipeline_head = tape->uncontrolled_last_pipeline_head = 0;
+ tape->controlled_previous_pipeline_head = tape->uncontrolled_previous_pipeline_head = 0;
+ tape->pipeline_head_speed = tape->controlled_pipeline_head_speed = 5000;
tape->uncontrolled_pipeline_head_speed = 0;
- tape->controlled_pipeline_head_time =
- tape->uncontrolled_pipeline_head_time = jiffies;
- tape->controlled_previous_head_time =
- tape->uncontrolled_previous_head_time = jiffies;
+ tape->controlled_pipeline_head_time = tape->uncontrolled_pipeline_head_time = jiffies;
+ tape->controlled_previous_head_time = tape->uncontrolled_previous_head_time = jiffies;
}
-static int idetape_init_read(ide_drive_t *drive, int max_stages)
+static int idetape_initiate_read (ide_drive_t *drive, int max_stages)
{
idetape_tape_t *tape = drive->driver_data;
idetape_stage_t *new_stage;
@@ -2485,35 +2644,32 @@ static int idetape_init_read(ide_drive_t *drive, int max_stages)
u16 blocks = *(u16 *)&tape->caps[12];
/* Initialize read operation */
- if (tape->chrdev_dir != IDETAPE_DIR_READ) {
- if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
+ if (tape->chrdev_direction != idetape_direction_read) {
+ if (tape->chrdev_direction == idetape_direction_write) {
idetape_empty_write_pipeline(drive);
idetape_flush_tape_buffers(drive);
}
if (tape->merge_stage || tape->merge_stage_size) {
- printk(KERN_ERR "ide-tape: merge_stage_size should be"
- " 0 now\n");
+ printk (KERN_ERR "ide-tape: merge_stage_size should be 0 now\n");
tape->merge_stage_size = 0;
}
- tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0);
- if (!tape->merge_stage)
+ if ((tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0)) == NULL)
return -ENOMEM;
- tape->chrdev_dir = IDETAPE_DIR_READ;
+ tape->chrdev_direction = idetape_direction_read;
/*
- * Issue a read 0 command to ensure that DSC handshake is
- * switched from completion mode to buffer available mode.
- * No point in issuing this if DSC overlap isn't supported, some
- * drives (Seagate STT3401A) will return an error.
+ * Issue a read 0 command to ensure that DSC handshake
+ * is switched from completion mode to buffer available
+ * mode.
+ * No point in issuing this if DSC overlap isn't supported,
+ * some drives (Seagate STT3401A) will return an error.
*/
if (drive->dsc_overlap) {
- bytes_read = idetape_queue_rw_tail(drive,
- REQ_IDETAPE_READ, 0,
- tape->merge_stage->bh);
+ bytes_read = idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, 0, tape->merge_stage->bh);
if (bytes_read < 0) {
__idetape_kfree_stage(tape->merge_stage);
tape->merge_stage = NULL;
- tape->chrdev_dir = IDETAPE_DIR_NONE;
+ tape->chrdev_direction = idetape_direction_none;
return bytes_read;
}
}
@@ -2521,9 +2677,8 @@ static int idetape_init_read(ide_drive_t *drive, int max_stages)
if (tape->restart_speed_control_req)
idetape_restart_speed_control(drive);
idetape_init_rq(&rq, REQ_IDETAPE_READ);
- rq.sector = tape->first_frame;
- rq.nr_sectors = blocks;
- rq.current_nr_sectors = blocks;
+ rq.sector = tape->first_frame_position;
+ rq.nr_sectors = rq.current_nr_sectors = blocks;
if (!test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags) &&
tape->nr_stages < max_stages) {
new_stage = idetape_kmalloc_stage(tape);
@@ -2541,43 +2696,50 @@ static int idetape_init_read(ide_drive_t *drive, int max_stages)
tape->insert_time = jiffies;
tape->insert_size = 0;
tape->insert_speed = 0;
- idetape_plug_pipeline(drive);
+ idetape_insert_pipeline_into_queue(drive);
}
}
return 0;
}
/*
- * Called from idetape_chrdev_read() to service a character device read request
- * and add read-ahead requests to our pipeline.
+ * idetape_add_chrdev_read_request is called from idetape_chrdev_read
+ * to service a character device read request and add read-ahead
+ * requests to our pipeline.
*/
-static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks)
+static int idetape_add_chrdev_read_request (ide_drive_t *drive,int blocks)
{
idetape_tape_t *tape = drive->driver_data;
unsigned long flags;
struct request *rq_ptr;
int bytes_read;
- debug_log(DBG_PROCS, "Enter %s, %d blocks\n", __func__, blocks);
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk(KERN_INFO "ide-tape: Reached idetape_add_chrdev_read_request, %d blocks\n", blocks);
+#endif /* IDETAPE_DEBUG_LOG */
- /* If we are at a filemark, return a read length of 0 */
+ /*
+ * If we are at a filemark, return a read length of 0
+ */
if (test_bit(IDETAPE_FILEMARK, &tape->flags))
return 0;
- /* Wait for the next block to reach the head of the pipeline. */
- idetape_init_read(drive, tape->max_stages);
+ /*
+ * Wait for the next block to be available at the head
+ * of the pipeline
+ */
+ idetape_initiate_read(drive, tape->max_stages);
if (tape->first_stage == NULL) {
if (test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags))
return 0;
- return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks,
- tape->merge_stage->bh);
+ return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks, tape->merge_stage->bh);
}
idetape_wait_first_stage(drive);
rq_ptr = &tape->first_stage->rq;
- bytes_read = tape->blk_size * (rq_ptr->nr_sectors -
- rq_ptr->current_nr_sectors);
- rq_ptr->nr_sectors = 0;
- rq_ptr->current_nr_sectors = 0;
+ bytes_read = tape->tape_block_size * (rq_ptr->nr_sectors - rq_ptr->current_nr_sectors);
+ rq_ptr->nr_sectors = rq_ptr->current_nr_sectors = 0;
+
if (rq_ptr->errors == IDETAPE_ERROR_EOD)
return 0;
@@ -2585,46 +2747,43 @@ static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks)
idetape_switch_buffers(tape, tape->first_stage);
if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK)
set_bit(IDETAPE_FILEMARK, &tape->flags);
- spin_lock_irqsave(&tape->lock, flags);
+ spin_lock_irqsave(&tape->spinlock, flags);
idetape_remove_stage_head(drive);
- spin_unlock_irqrestore(&tape->lock, flags);
+ spin_unlock_irqrestore(&tape->spinlock, flags);
tape->pipeline_head++;
- idetape_calculate_speeds(drive);
+ calculate_speeds(drive);
}
- if (bytes_read > blocks * tape->blk_size) {
- printk(KERN_ERR "ide-tape: bug: trying to return more bytes"
- " than requested\n");
- bytes_read = blocks * tape->blk_size;
+ if (bytes_read > blocks * tape->tape_block_size) {
+ printk(KERN_ERR "ide-tape: bug: trying to return more bytes than requested\n");
+ bytes_read = blocks * tape->tape_block_size;
}
return (bytes_read);
}
-static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
+static void idetape_pad_zeros (ide_drive_t *drive, int bcount)
{
idetape_tape_t *tape = drive->driver_data;
struct idetape_bh *bh;
int blocks;
-
+
while (bcount) {
unsigned int count;
bh = tape->merge_stage->bh;
count = min(tape->stage_size, bcount);
bcount -= count;
- blocks = count / tape->blk_size;
+ blocks = count / tape->tape_block_size;
while (count) {
- atomic_set(&bh->b_count,
- min(count, (unsigned int)bh->b_size));
+ atomic_set(&bh->b_count, min(count, (unsigned int)bh->b_size));
memset(bh->b_data, 0, atomic_read(&bh->b_count));
count -= atomic_read(&bh->b_count);
bh = bh->b_reqnext;
}
- idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks,
- tape->merge_stage->bh);
+ idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks, tape->merge_stage->bh);
}
}
-static int idetape_pipeline_size(ide_drive_t *drive)
+static int idetape_pipeline_size (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
idetape_stage_t *stage;
@@ -2635,10 +2794,9 @@ static int idetape_pipeline_size(ide_drive_t *drive)
stage = tape->first_stage;
while (stage != NULL) {
rq = &stage->rq;
- size += tape->blk_size * (rq->nr_sectors -
- rq->current_nr_sectors);
+ size += tape->tape_block_size * (rq->nr_sectors-rq->current_nr_sectors);
if (rq->errors == IDETAPE_ERROR_FILEMARK)
- size += tape->blk_size;
+ size += tape->tape_block_size;
stage = stage->next;
}
size += tape->merge_stage_size;
@@ -2646,18 +2804,20 @@ static int idetape_pipeline_size(ide_drive_t *drive)
}
/*
- * Rewinds the tape to the Beginning Of the current Partition (BOP). We
- * currently support only one partition.
- */
-static int idetape_rewind_tape(ide_drive_t *drive)
+ * Rewinds the tape to the Beginning Of the current Partition (BOP).
+ *
+ * We currently support only one partition.
+ */
+static int idetape_rewind_tape (ide_drive_t *drive)
{
int retval;
idetape_pc_t pc;
- idetape_tape_t *tape;
- tape = drive->driver_data;
-
- debug_log(DBG_SENSE, "Enter %s\n", __func__);
-
+#if IDETAPE_DEBUG_LOG
+ idetape_tape_t *tape = drive->driver_data;
+ if (tape->debug_level >= 2)
+ printk(KERN_INFO "ide-tape: Reached idetape_rewind_tape\n");
+#endif /* IDETAPE_DEBUG_LOG */
+
idetape_create_rewind_cmd(drive, &pc);
retval = idetape_queue_pc_tail(drive, &pc);
if (retval)
@@ -2670,9 +2830,14 @@ static int idetape_rewind_tape(ide_drive_t *drive)
return 0;
}
-/* mtio.h compatible commands should be issued to the chrdev interface. */
-static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd,
- unsigned long arg)
+/*
+ * Our special ide-tape ioctl's.
+ *
+ * Currently there aren't any ioctl's.
+ * mtio.h compatible commands should be issued to the character device
+ * interface.
+ */
+static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd, unsigned long arg)
{
idetape_tape_t *tape = drive->driver_data;
void __user *argp = (void __user *)arg;
@@ -2683,41 +2848,44 @@ static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd,
int nr_stages;
} config;
- debug_log(DBG_PROCS, "Enter %s\n", __func__);
-
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk(KERN_INFO "ide-tape: Reached idetape_blkdev_ioctl\n");
+#endif /* IDETAPE_DEBUG_LOG */
switch (cmd) {
- case 0x0340:
- if (copy_from_user(&config, argp, sizeof(config)))
- return -EFAULT;
- tape->best_dsc_rw_freq = config.dsc_rw_frequency;
- tape->max_stages = config.nr_stages;
- break;
- case 0x0350:
- config.dsc_rw_frequency = (int) tape->best_dsc_rw_freq;
- config.nr_stages = tape->max_stages;
- if (copy_to_user(argp, &config, sizeof(config)))
- return -EFAULT;
- break;
- default:
- return -EIO;
+ case 0x0340:
+ if (copy_from_user(&config, argp, sizeof(config)))
+ return -EFAULT;
+ tape->best_dsc_rw_frequency = config.dsc_rw_frequency;
+ tape->max_stages = config.nr_stages;
+ break;
+ case 0x0350:
+ config.dsc_rw_frequency = (int) tape->best_dsc_rw_frequency;
+ config.nr_stages = tape->max_stages;
+ if (copy_to_user(argp, &config, sizeof(config)))
+ return -EFAULT;
+ break;
+ default:
+ return -EIO;
}
return 0;
}
/*
- * The function below is now a bit more complicated than just passing the
- * command to the tape since we may have crossed some filemarks during our
- * pipelined read-ahead mode. As a minor side effect, the pipeline enables us to
- * support MTFSFM when the filemark is in our internal pipeline even if the tape
- * doesn't support spacing over filemarks in the reverse direction.
+ * idetape_space_over_filemarks is now a bit more complicated than just
+ * passing the command to the tape since we may have crossed some
+ * filemarks during our pipelined read-ahead mode.
+ *
+ * As a minor side effect, the pipeline enables us to support MTFSFM when
+ * the filemark is in our internal pipeline even if the tape doesn't
+ * support spacing over filemarks in the reverse direction.
*/
-static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
- int mt_count)
+static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_count)
{
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t pc;
unsigned long flags;
- int retval, count = 0;
+ int retval,count=0;
int sprev = !!(tape->caps[4] & 0x20);
if (mt_count == 0)
@@ -2725,11 +2893,14 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
if (MTBSF == mt_op || MTBSFM == mt_op) {
if (!sprev)
return -EIO;
- mt_count = -mt_count;
+ mt_count = - mt_count;
}
- if (tape->chrdev_dir == IDETAPE_DIR_READ) {
- /* its a read-ahead buffer, scan it for crossed filemarks. */
+ if (tape->chrdev_direction == idetape_direction_read) {
+ /*
+ * We have a read-ahead buffer. Scan it for crossed
+ * filemarks.
+ */
tape->merge_stage_size = 0;
if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags))
++count;
@@ -2739,27 +2910,24 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
set_bit(IDETAPE_FILEMARK, &tape->flags);
return 0;
}
- spin_lock_irqsave(&tape->lock, flags);
+ spin_lock_irqsave(&tape->spinlock, flags);
if (tape->first_stage == tape->active_stage) {
/*
- * We have reached the active stage in the read
- * pipeline. There is no point in allowing the
- * drive to continue reading any farther, so we
- * stop the pipeline.
+ * We have reached the active stage in the read pipeline.
+ * There is no point in allowing the drive to continue
+ * reading any farther, so we stop the pipeline.
*
- * This section should be moved to a separate
- * subroutine because similar operations are
- * done in __idetape_discard_read_pipeline(),
- * for example.
+ * This section should be moved to a separate subroutine,
+ * because a similar function is performed in
+ * __idetape_discard_read_pipeline(), for example.
*/
tape->next_stage = NULL;
- spin_unlock_irqrestore(&tape->lock, flags);
+ spin_unlock_irqrestore(&tape->spinlock, flags);
idetape_wait_first_stage(drive);
tape->next_stage = tape->first_stage->next;
} else
- spin_unlock_irqrestore(&tape->lock, flags);
- if (tape->first_stage->rq.errors ==
- IDETAPE_ERROR_FILEMARK)
+ spin_unlock_irqrestore(&tape->spinlock, flags);
+ if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK)
++count;
idetape_remove_stage_head(drive);
}
@@ -2767,74 +2935,73 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
}
/*
- * The filemark was not found in our internal pipeline; now we can issue
- * the space command.
+ * The filemark was not found in our internal pipeline.
+ * Now we can issue the space command.
*/
switch (mt_op) {
- case MTFSF:
- case MTBSF:
- idetape_create_space_cmd(&pc, mt_count - count,
- IDETAPE_SPACE_OVER_FILEMARK);
- return idetape_queue_pc_tail(drive, &pc);
- case MTFSFM:
- case MTBSFM:
- if (!sprev)
- return -EIO;
- retval = idetape_space_over_filemarks(drive, MTFSF,
- mt_count - count);
- if (retval)
- return retval;
- count = (MTBSFM == mt_op ? 1 : -1);
- return idetape_space_over_filemarks(drive, MTFSF, count);
- default:
- printk(KERN_ERR "ide-tape: MTIO operation %d not supported\n",
- mt_op);
- return -EIO;
+ case MTFSF:
+ case MTBSF:
+ idetape_create_space_cmd(&pc,mt_count-count,IDETAPE_SPACE_OVER_FILEMARK);
+ return (idetape_queue_pc_tail(drive, &pc));
+ case MTFSFM:
+ case MTBSFM:
+ if (!sprev)
+ return (-EIO);
+ retval = idetape_space_over_filemarks(drive, MTFSF, mt_count-count);
+ if (retval) return (retval);
+ count = (MTBSFM == mt_op ? 1 : -1);
+ return (idetape_space_over_filemarks(drive, MTFSF, count));
+ default:
+ printk(KERN_ERR "ide-tape: MTIO operation %d not supported\n",mt_op);
+ return (-EIO);
}
}
+
/*
- * Our character device read / write functions.
+ * Our character device read / write functions.
*
- * The tape is optimized to maximize throughput when it is transferring an
- * integral number of the "continuous transfer limit", which is a parameter of
- * the specific tape (26kB on my particular tape, 32kB for Onstream).
+ * The tape is optimized to maximize throughput when it is transferring
+ * an integral number of the "continuous transfer limit", which is
+ * a parameter of the specific tape (26 KB on my particular tape).
+ * (32 kB for Onstream)
*
- * As of version 1.3 of the driver, the character device provides an abstract
- * continuous view of the media - any mix of block sizes (even 1 byte) on the
- * same backup/restore procedure is supported. The driver will internally
- * convert the requests to the recommended transfer unit, so that an unmatch
- * between the user's block size to the recommended size will only result in a
- * (slightly) increased driver overhead, but will no longer hit performance.
- * This is not applicable to Onstream.
+ * As of version 1.3 of the driver, the character device provides an
+ * abstract continuous view of the media - any mix of block sizes (even 1
+ * byte) on the same backup/restore procedure is supported. The driver
+ * will internally convert the requests to the recommended transfer unit,
+ * so that an unmatch between the user's block size to the recommended
+ * size will only result in a (slightly) increased driver overhead, but
+ * will no longer hit performance.
+ * This is not applicable to Onstream.
*/
-static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
+static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
{
struct ide_tape_obj *tape = ide_tape_f(file);
ide_drive_t *drive = tape->drive;
- ssize_t bytes_read, temp, actually_read = 0, rc;
+ ssize_t bytes_read,temp, actually_read = 0, rc;
ssize_t ret = 0;
u16 ctl = *(u16 *)&tape->caps[12];
- debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count);
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 3)
+ printk(KERN_INFO "ide-tape: Reached idetape_chrdev_read, count %Zd\n", count);
+#endif /* IDETAPE_DEBUG_LOG */
- if (tape->chrdev_dir != IDETAPE_DIR_READ) {
+ if (tape->chrdev_direction != idetape_direction_read) {
if (test_bit(IDETAPE_DETECT_BS, &tape->flags))
- if (count > tape->blk_size &&
- (count % tape->blk_size) == 0)
- tape->user_bs_factor = count / tape->blk_size;
+ if (count > tape->tape_block_size &&
+ (count % tape->tape_block_size) == 0)
+ tape->user_bs_factor = count / tape->tape_block_size;
}
- rc = idetape_init_read(drive, tape->max_stages);
- if (rc < 0)
+ if ((rc = idetape_initiate_read(drive, tape->max_stages)) < 0)
return rc;
if (count == 0)
return (0);
if (tape->merge_stage_size) {
- actually_read = min((unsigned int)(tape->merge_stage_size),
- (unsigned int)count);
- if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage,
- actually_read))
+ actually_read = min((unsigned int)(tape->merge_stage_size), (unsigned int)count);
+ if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, actually_read))
ret = -EFAULT;
buf += actually_read;
tape->merge_stage_size -= actually_read;
@@ -2844,8 +3011,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
bytes_read = idetape_add_chrdev_read_request(drive, ctl);
if (bytes_read <= 0)
goto finish;
- if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage,
- bytes_read))
+ if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read))
ret = -EFAULT;
buf += bytes_read;
count -= bytes_read;
@@ -2856,24 +3022,25 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
if (bytes_read <= 0)
goto finish;
temp = min((unsigned long)count, (unsigned long)bytes_read);
- if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage,
- temp))
+ if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, temp))
ret = -EFAULT;
actually_read += temp;
tape->merge_stage_size = bytes_read-temp;
}
finish:
if (!actually_read && test_bit(IDETAPE_FILEMARK, &tape->flags)) {
- debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name);
-
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 2)
+ printk(KERN_INFO "ide-tape: %s: spacing over filemark\n", tape->name);
+#endif
idetape_space_over_filemarks(drive, MTFSF, 1);
return 0;
}
- return ret ? ret : actually_read;
+ return (ret) ? ret : actually_read;
}
-static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
+static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
struct ide_tape_obj *tape = ide_tape_f(file);
@@ -2886,37 +3053,39 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
if (tape->write_prot)
return -EACCES;
- debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count);
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 3)
+ printk(KERN_INFO "ide-tape: Reached idetape_chrdev_write, "
+ "count %Zd\n", count);
+#endif /* IDETAPE_DEBUG_LOG */
/* Initialize write operation */
- if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
- if (tape->chrdev_dir == IDETAPE_DIR_READ)
+ if (tape->chrdev_direction != idetape_direction_write) {
+ if (tape->chrdev_direction == idetape_direction_read)
idetape_discard_read_pipeline(drive, 1);
if (tape->merge_stage || tape->merge_stage_size) {
printk(KERN_ERR "ide-tape: merge_stage_size "
"should be 0 now\n");
tape->merge_stage_size = 0;
}
- tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0);
- if (!tape->merge_stage)
+ if ((tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0)) == NULL)
return -ENOMEM;
- tape->chrdev_dir = IDETAPE_DIR_WRITE;
+ tape->chrdev_direction = idetape_direction_write;
idetape_init_merge_stage(tape);
/*
- * Issue a write 0 command to ensure that DSC handshake is
- * switched from completion mode to buffer available mode. No
- * point in issuing this if DSC overlap isn't supported, some
- * drives (Seagate STT3401A) will return an error.
+ * Issue a write 0 command to ensure that DSC handshake
+ * is switched from completion mode to buffer available
+ * mode.
+ * No point in issuing this if DSC overlap isn't supported,
+ * some drives (Seagate STT3401A) will return an error.
*/
if (drive->dsc_overlap) {
- ssize_t retval = idetape_queue_rw_tail(drive,
- REQ_IDETAPE_WRITE, 0,
- tape->merge_stage->bh);
+ ssize_t retval = idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 0, tape->merge_stage->bh);
if (retval < 0) {
__idetape_kfree_stage(tape->merge_stage);
tape->merge_stage = NULL;
- tape->chrdev_dir = IDETAPE_DIR_NONE;
+ tape->chrdev_direction = idetape_direction_none;
return retval;
}
}
@@ -2927,14 +3096,11 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
idetape_restart_speed_control(drive);
if (tape->merge_stage_size) {
if (tape->merge_stage_size >= tape->stage_size) {
- printk(KERN_ERR "ide-tape: bug: merge buf too big\n");
+ printk(KERN_ERR "ide-tape: bug: merge buffer too big\n");
tape->merge_stage_size = 0;
}
- actually_written = min((unsigned int)
- (tape->stage_size - tape->merge_stage_size),
- (unsigned int)count);
- if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf,
- actually_written))
+ actually_written = min((unsigned int)(tape->stage_size - tape->merge_stage_size), (unsigned int)count);
+ if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written))
ret = -EFAULT;
buf += actually_written;
tape->merge_stage_size += actually_written;
@@ -2950,8 +3116,7 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
}
while (count >= tape->stage_size) {
ssize_t retval;
- if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf,
- tape->stage_size))
+ if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, tape->stage_size))
ret = -EFAULT;
buf += tape->stage_size;
count -= tape->stage_size;
@@ -2962,15 +3127,14 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
}
if (count) {
actually_written += count;
- if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf,
- count))
+ if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, count))
ret = -EFAULT;
tape->merge_stage_size += count;
}
- return ret ? ret : actually_written;
+ return (ret) ? ret : actually_written;
}
-static int idetape_write_filemark(ide_drive_t *drive)
+static int idetape_write_filemark (ide_drive_t *drive)
{
idetape_pc_t pc;
@@ -3001,117 +3165,113 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
{
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t pc;
- int i, retval;
-
- debug_log(DBG_ERR, "Handling MTIOCTOP ioctl: mt_op=%d, mt_count=%d\n",
- mt_op, mt_count);
+ int i,retval;
- /* Commands which need our pipelined read-ahead stages. */
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 1)
+ printk(KERN_INFO "ide-tape: Handling MTIOCTOP ioctl: "
+ "mt_op=%d, mt_count=%d\n", mt_op, mt_count);
+#endif /* IDETAPE_DEBUG_LOG */
+ /*
+ * Commands which need our pipelined read-ahead stages.
+ */
switch (mt_op) {
- case MTFSF:
- case MTFSFM:
- case MTBSF:
- case MTBSFM:
- if (!mt_count)
- return 0;
- return idetape_space_over_filemarks(drive, mt_op, mt_count);
- default:
- break;
+ case MTFSF:
+ case MTFSFM:
+ case MTBSF:
+ case MTBSFM:
+ if (!mt_count)
+ return (0);
+ return (idetape_space_over_filemarks(drive,mt_op,mt_count));
+ default:
+ break;
}
-
switch (mt_op) {
- case MTWEOF:
- if (tape->write_prot)
- return -EACCES;
- idetape_discard_read_pipeline(drive, 1);
- for (i = 0; i < mt_count; i++) {
- retval = idetape_write_filemark(drive);
- if (retval)
- return retval;
- }
- return 0;
- case MTREW:
- idetape_discard_read_pipeline(drive, 0);
- if (idetape_rewind_tape(drive))
- return -EIO;
- return 0;
- case MTLOAD:
- idetape_discard_read_pipeline(drive, 0);
- idetape_create_load_unload_cmd(drive, &pc,
- IDETAPE_LU_LOAD_MASK);
- return idetape_queue_pc_tail(drive, &pc);
- case MTUNLOAD:
- case MTOFFL:
- /*
- * If door is locked, attempt to unlock before
- * attempting to eject.
- */
- if (tape->door_locked) {
- if (idetape_create_prevent_cmd(drive, &pc, 0))
- if (!idetape_queue_pc_tail(drive, &pc))
- tape->door_locked = DOOR_UNLOCKED;
- }
- idetape_discard_read_pipeline(drive, 0);
- idetape_create_load_unload_cmd(drive, &pc,
- !IDETAPE_LU_LOAD_MASK);
- retval = idetape_queue_pc_tail(drive, &pc);
- if (!retval)
- clear_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags);
- return retval;
- case MTNOP:
- idetape_discard_read_pipeline(drive, 0);
- return idetape_flush_tape_buffers(drive);
- case MTRETEN:
- idetape_discard_read_pipeline(drive, 0);
- idetape_create_load_unload_cmd(drive, &pc,
- IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK);
- return idetape_queue_pc_tail(drive, &pc);
- case MTEOM:
- idetape_create_space_cmd(&pc, 0, IDETAPE_SPACE_TO_EOD);
- return idetape_queue_pc_tail(drive, &pc);
- case MTERASE:
- (void)idetape_rewind_tape(drive);
- idetape_create_erase_cmd(&pc);
- return idetape_queue_pc_tail(drive, &pc);
- case MTSETBLK:
- if (mt_count) {
- if (mt_count < tape->blk_size ||
- mt_count % tape->blk_size)
+ case MTWEOF:
+ if (tape->write_prot)
+ return -EACCES;
+ idetape_discard_read_pipeline(drive, 1);
+ for (i = 0; i < mt_count; i++) {
+ retval = idetape_write_filemark(drive);
+ if (retval)
+ return retval;
+ }
+ return (0);
+ case MTREW:
+ idetape_discard_read_pipeline(drive, 0);
+ if (idetape_rewind_tape(drive))
return -EIO;
- tape->user_bs_factor = mt_count / tape->blk_size;
- clear_bit(IDETAPE_DETECT_BS, &tape->flags);
- } else
- set_bit(IDETAPE_DETECT_BS, &tape->flags);
- return 0;
- case MTSEEK:
- idetape_discard_read_pipeline(drive, 0);
- return idetape_position_tape(drive,
- mt_count * tape->user_bs_factor, tape->partition, 0);
- case MTSETPART:
- idetape_discard_read_pipeline(drive, 0);
- return idetape_position_tape(drive, 0, mt_count, 0);
- case MTFSR:
- case MTBSR:
- case MTLOCK:
- if (!idetape_create_prevent_cmd(drive, &pc, 1))
return 0;
- retval = idetape_queue_pc_tail(drive, &pc);
- if (retval)
+ case MTLOAD:
+ idetape_discard_read_pipeline(drive, 0);
+ idetape_create_load_unload_cmd(drive, &pc, IDETAPE_LU_LOAD_MASK);
+ return (idetape_queue_pc_tail(drive, &pc));
+ case MTUNLOAD:
+ case MTOFFL:
+ /*
+ * If door is locked, attempt to unlock before
+ * attempting to eject.
+ */
+ if (tape->door_locked) {
+ if (idetape_create_prevent_cmd(drive, &pc, 0))
+ if (!idetape_queue_pc_tail(drive, &pc))
+ tape->door_locked = DOOR_UNLOCKED;
+ }
+ idetape_discard_read_pipeline(drive, 0);
+ idetape_create_load_unload_cmd(drive, &pc,!IDETAPE_LU_LOAD_MASK);
+ retval = idetape_queue_pc_tail(drive, &pc);
+ if (!retval)
+ clear_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags);
return retval;
- tape->door_locked = DOOR_EXPLICITLY_LOCKED;
- return 0;
- case MTUNLOCK:
- if (!idetape_create_prevent_cmd(drive, &pc, 0))
+ case MTNOP:
+ idetape_discard_read_pipeline(drive, 0);
+ return (idetape_flush_tape_buffers(drive));
+ case MTRETEN:
+ idetape_discard_read_pipeline(drive, 0);
+ idetape_create_load_unload_cmd(drive, &pc,IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK);
+ return (idetape_queue_pc_tail(drive, &pc));
+ case MTEOM:
+ idetape_create_space_cmd(&pc, 0, IDETAPE_SPACE_TO_EOD);
+ return (idetape_queue_pc_tail(drive, &pc));
+ case MTERASE:
+ (void) idetape_rewind_tape(drive);
+ idetape_create_erase_cmd(&pc);
+ return (idetape_queue_pc_tail(drive, &pc));
+ case MTSETBLK:
+ if (mt_count) {
+ if (mt_count < tape->tape_block_size || mt_count % tape->tape_block_size)
+ return -EIO;
+ tape->user_bs_factor = mt_count / tape->tape_block_size;
+ clear_bit(IDETAPE_DETECT_BS, &tape->flags);
+ } else
+ set_bit(IDETAPE_DETECT_BS, &tape->flags);
return 0;
- retval = idetape_queue_pc_tail(drive, &pc);
- if (retval)
- return retval;
- tape->door_locked = DOOR_UNLOCKED;
- return 0;
- default:
- printk(KERN_ERR "ide-tape: MTIO operation %d not supported\n",
- mt_op);
- return -EIO;
+ case MTSEEK:
+ idetape_discard_read_pipeline(drive, 0);
+ return idetape_position_tape(drive, mt_count * tape->user_bs_factor, tape->partition, 0);
+ case MTSETPART:
+ idetape_discard_read_pipeline(drive, 0);
+ return (idetape_position_tape(drive, 0, mt_count, 0));
+ case MTFSR:
+ case MTBSR:
+ case MTLOCK:
+ if (!idetape_create_prevent_cmd(drive, &pc, 1))
+ return 0;
+ retval = idetape_queue_pc_tail(drive, &pc);
+ if (retval) return retval;
+ tape->door_locked = DOOR_EXPLICITLY_LOCKED;
+ return 0;
+ case MTUNLOCK:
+ if (!idetape_create_prevent_cmd(drive, &pc, 0))
+ return 0;
+ retval = idetape_queue_pc_tail(drive, &pc);
+ if (retval) return retval;
+ tape->door_locked = DOOR_UNLOCKED;
+ return 0;
+ default:
+ printk(KERN_ERR "ide-tape: MTIO operation %d not "
+ "supported\n", mt_op);
+ return (-EIO);
}
}
@@ -3128,51 +3288,50 @@ static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
struct mtop mtop;
struct mtget mtget;
struct mtpos mtpos;
- int block_offset = 0, position = tape->first_frame;
+ int block_offset = 0, position = tape->first_frame_position;
void __user *argp = (void __user *)arg;
- debug_log(DBG_CHRDEV, "Enter %s, cmd=%u\n", __func__, cmd);
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 3)
+ printk(KERN_INFO "ide-tape: Reached idetape_chrdev_ioctl, "
+ "cmd=%u\n", cmd);
+#endif /* IDETAPE_DEBUG_LOG */
tape->restart_speed_control_req = 1;
- if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
+ if (tape->chrdev_direction == idetape_direction_write) {
idetape_empty_write_pipeline(drive);
idetape_flush_tape_buffers(drive);
}
if (cmd == MTIOCGET || cmd == MTIOCPOS) {
- block_offset = idetape_pipeline_size(drive) /
- (tape->blk_size * tape->user_bs_factor);
- position = idetape_read_position(drive);
- if (position < 0)
+ block_offset = idetape_pipeline_size(drive) / (tape->tape_block_size * tape->user_bs_factor);
+ if ((position = idetape_read_position(drive)) < 0)
return -EIO;
}
switch (cmd) {
- case MTIOCTOP:
- if (copy_from_user(&mtop, argp, sizeof(struct mtop)))
- return -EFAULT;
- return idetape_mtioctop(drive, mtop.mt_op, mtop.mt_count);
- case MTIOCGET:
- memset(&mtget, 0, sizeof(struct mtget));
- mtget.mt_type = MT_ISSCSI2;
- mtget.mt_blkno = position / tape->user_bs_factor - block_offset;
- mtget.mt_dsreg =
- ((tape->blk_size * tape->user_bs_factor)
- << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK;
-
- if (tape->drv_write_prot)
- mtget.mt_gstat |= GMT_WR_PROT(0xffffffff);
-
- if (copy_to_user(argp, &mtget, sizeof(struct mtget)))
- return -EFAULT;
- return 0;
- case MTIOCPOS:
- mtpos.mt_blkno = position / tape->user_bs_factor - block_offset;
- if (copy_to_user(argp, &mtpos, sizeof(struct mtpos)))
- return -EFAULT;
- return 0;
- default:
- if (tape->chrdev_dir == IDETAPE_DIR_READ)
- idetape_discard_read_pipeline(drive, 1);
- return idetape_blkdev_ioctl(drive, cmd, arg);
+ case MTIOCTOP:
+ if (copy_from_user(&mtop, argp, sizeof (struct mtop)))
+ return -EFAULT;
+ return (idetape_mtioctop(drive,mtop.mt_op,mtop.mt_count));
+ case MTIOCGET:
+ memset(&mtget, 0, sizeof (struct mtget));
+ mtget.mt_type = MT_ISSCSI2;
+ mtget.mt_blkno = position / tape->user_bs_factor - block_offset;
+ mtget.mt_dsreg = ((tape->tape_block_size * tape->user_bs_factor) << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK;
+ if (tape->drv_write_prot) {
+ mtget.mt_gstat |= GMT_WR_PROT(0xffffffff);
+ }
+ if (copy_to_user(argp, &mtget, sizeof(struct mtget)))
+ return -EFAULT;
+ return 0;
+ case MTIOCPOS:
+ mtpos.mt_blkno = position / tape->user_bs_factor - block_offset;
+ if (copy_to_user(argp, &mtpos, sizeof(struct mtpos)))
+ return -EFAULT;
+ return 0;
+ default:
+ if (tape->chrdev_direction == idetape_direction_read)
+ idetape_discard_read_pipeline(drive, 1);
+ return idetape_blkdev_ioctl(drive, cmd, arg);
}
}
@@ -3188,20 +3347,23 @@ static void ide_tape_get_bsize_from_bdesc(ide_drive_t *drive)
idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR);
if (idetape_queue_pc_tail(drive, &pc)) {
printk(KERN_ERR "ide-tape: Can't get block descriptor\n");
- if (tape->blk_size == 0) {
+ if (tape->tape_block_size == 0) {
printk(KERN_WARNING "ide-tape: Cannot deal with zero "
"block size, assuming 32k\n");
- tape->blk_size = 32768;
+ tape->tape_block_size = 32768;
}
return;
}
- tape->blk_size = (pc.buffer[4 + 5] << 16) +
+ tape->tape_block_size = (pc.buffer[4 + 5] << 16) +
(pc.buffer[4 + 6] << 8) +
pc.buffer[4 + 7];
tape->drv_write_prot = (pc.buffer[2] & 0x80) >> 7;
}
-static int idetape_chrdev_open(struct inode *inode, struct file *filp)
+/*
+ * Our character device open function.
+ */
+static int idetape_chrdev_open (struct inode *inode, struct file *filp)
{
unsigned int minor = iminor(inode), i = minor & ~0xc0;
ide_drive_t *drive;
@@ -3209,15 +3371,6 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
idetape_pc_t pc;
int retval;
- if (i >= MAX_HWIFS * MAX_DRIVES)
- return -ENXIO;
-
- tape = ide_tape_chrdev_get(i);
- if (!tape)
- return -ENXIO;
-
- debug_log(DBG_CHRDEV, "Enter %s\n", __func__);
-
/*
* We really want to do nonseekable_open(inode, filp); here, but some
* versions of tar incorrectly call lseek on tapes and bail out if that
@@ -3225,6 +3378,16 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
*/
filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
+#if IDETAPE_DEBUG_LOG
+ printk(KERN_INFO "ide-tape: Reached idetape_chrdev_open\n");
+#endif /* IDETAPE_DEBUG_LOG */
+
+ if (i >= MAX_HWIFS * MAX_DRIVES)
+ return -ENXIO;
+
+ if (!(tape = ide_tape_chrdev_get(i)))
+ return -ENXIO;
+
drive = tape->drive;
filp->private_data = tape;
@@ -3245,7 +3408,7 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
if (!test_bit(IDETAPE_ADDRESS_VALID, &tape->flags))
(void)idetape_rewind_tape(drive);
- if (tape->chrdev_dir != IDETAPE_DIR_READ)
+ if (tape->chrdev_direction != idetape_direction_read)
clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
/* Read block size and write protect status from drive. */
@@ -3267,8 +3430,10 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
}
}
- /* Lock the tape drive door so user can't eject. */
- if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
+ /*
+ * Lock the tape drive door so user can't eject.
+ */
+ if (tape->chrdev_direction == idetape_direction_none) {
if (idetape_create_prevent_cmd(drive, &pc, 1)) {
if (!idetape_queue_pc_tail(drive, &pc)) {
if (tape->door_locked != DOOR_EXPLICITLY_LOCKED)
@@ -3285,15 +3450,14 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
return retval;
}
-static void idetape_write_release(ide_drive_t *drive, unsigned int minor)
+static void idetape_write_release (ide_drive_t *drive, unsigned int minor)
{
idetape_tape_t *tape = drive->driver_data;
idetape_empty_write_pipeline(drive);
tape->merge_stage = __idetape_kmalloc_stage(tape, 1, 0);
if (tape->merge_stage != NULL) {
- idetape_pad_zeros(drive, tape->blk_size *
- (tape->user_bs_factor - 1));
+ idetape_pad_zeros(drive, tape->tape_block_size * (tape->user_bs_factor - 1));
__idetape_kfree_stage(tape->merge_stage);
tape->merge_stage = NULL;
}
@@ -3302,7 +3466,10 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor)
idetape_flush_tape_buffers(drive);
}
-static int idetape_chrdev_release(struct inode *inode, struct file *filp)
+/*
+ * Our character device release function.
+ */
+static int idetape_chrdev_release (struct inode *inode, struct file *filp)
{
struct ide_tape_obj *tape = ide_tape_f(filp);
ide_drive_t *drive = tape->drive;
@@ -3311,12 +3478,14 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
lock_kernel();
tape = drive->driver_data;
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 3)
+ printk(KERN_INFO "ide-tape: Reached idetape_chrdev_release\n");
+#endif /* IDETAPE_DEBUG_LOG */
- debug_log(DBG_CHRDEV, "Enter %s\n", __func__);
-
- if (tape->chrdev_dir == IDETAPE_DIR_WRITE)
+ if (tape->chrdev_direction == idetape_direction_write)
idetape_write_release(drive, minor);
- if (tape->chrdev_dir == IDETAPE_DIR_READ) {
+ if (tape->chrdev_direction == idetape_direction_read) {
if (minor < 128)
idetape_discard_read_pipeline(drive, 1);
else
@@ -3328,7 +3497,7 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
}
if (minor < 128 && test_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags))
(void) idetape_rewind_tape(drive);
- if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
+ if (tape->chrdev_direction == idetape_direction_none) {
if (tape->door_locked == DOOR_LOCKED) {
if (idetape_create_prevent_cmd(drive, &pc, 0)) {
if (!idetape_queue_pc_tail(drive, &pc))
@@ -3343,39 +3512,37 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
}
/*
- * check the contents of the ATAPI IDENTIFY command results. We return:
+ * idetape_identify_device is called to check the contents of the
+ * ATAPI IDENTIFY command results. We return:
*
- * 1 - If the tape can be supported by us, based on the information we have so
- * far.
+ * 1 If the tape can be supported by us, based on the information
+ * we have so far.
*
- * 0 - If this tape driver is not currently supported by us.
+ * 0 If this tape driver is not currently supported by us.
*/
-static int idetape_identify_device(ide_drive_t *drive)
+static int idetape_identify_device (ide_drive_t *drive)
{
- u8 gcw[2], protocol, device_type, removable, packet_size;
+ struct idetape_id_gcw gcw;
+ struct hd_driveid *id = drive->id;
if (drive->id_read == 0)
return 1;
- *((unsigned short *) &gcw) = drive->id->config;
-
- protocol = (gcw[1] & 0xC0) >> 6;
- device_type = gcw[1] & 0x1F;
- removable = !!(gcw[0] & 0x80);
- packet_size = gcw[0] & 0x3;
+ *((unsigned short *) &gcw) = id->config;
/* Check that we can support this device */
- if (protocol != 2)
+
+ if (gcw.protocol != 2)
printk(KERN_ERR "ide-tape: Protocol (0x%02x) is not ATAPI\n",
- protocol);
- else if (device_type != 1)
+ gcw.protocol);
+ else if (gcw.device_type != 1)
printk(KERN_ERR "ide-tape: Device type (0x%02x) is not set "
- "to tape\n", device_type);
- else if (!removable)
+ "to tape\n", gcw.device_type);
+ else if (!gcw.removable)
printk(KERN_ERR "ide-tape: The removable flag is not set\n");
- else if (packet_size != 0) {
- printk(KERN_ERR "ide-tape: Packet size (0x%02x) is not 12"
- " bytes\n", packet_size);
+ else if (gcw.packet_size != 0) {
+ printk(KERN_ERR "ide-tape: Packet size (0x%02x) is not 12 "
+ "bytes long\n", gcw.packet_size);
} else
return 1;
return 0;
@@ -3383,9 +3550,9 @@ static int idetape_identify_device(ide_drive_t *drive)
static void idetape_get_inquiry_results(ide_drive_t *drive)
{
+ char *r;
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t pc;
- char fw_rev[6], vendor_id[10], product_id[18];
idetape_create_inquiry_cmd(&pc);
if (idetape_queue_pc_tail(drive, &pc)) {
@@ -3393,23 +3560,27 @@ static void idetape_get_inquiry_results(ide_drive_t *drive)
tape->name);
return;
}
- memcpy(vendor_id, &pc.buffer[8], 8);
- memcpy(product_id, &pc.buffer[16], 16);
- memcpy(fw_rev, &pc.buffer[32], 4);
-
- ide_fixstring(vendor_id, 10, 0);
- ide_fixstring(product_id, 18, 0);
- ide_fixstring(fw_rev, 6, 0);
-
+ memcpy(tape->vendor_id, &pc.buffer[8], 8);
+ memcpy(tape->product_id, &pc.buffer[16], 16);
+ memcpy(tape->firmware_revision, &pc.buffer[32], 4);
+
+ ide_fixstring(tape->vendor_id, 10, 0);
+ ide_fixstring(tape->product_id, 18, 0);
+ ide_fixstring(tape->firmware_revision, 6, 0);
+ r = tape->firmware_revision;
+ if (*(r + 1) == '.')
+ tape->firmware_revision_num = (*r - '0') * 100 +
+ (*(r + 2) - '0') * 10 + *(r + 3) - '0';
printk(KERN_INFO "ide-tape: %s <-> %s: %s %s rev %s\n",
- drive->name, tape->name, vendor_id, product_id, fw_rev);
+ drive->name, tape->name, tape->vendor_id,
+ tape->product_id, tape->firmware_revision);
}
/*
* Ask the tape about its various parameters. In particular, we will adjust our
* data transfer buffer size to the recommended value as returned by the tape.
*/
-static void idetape_get_mode_sense_results(ide_drive_t *drive)
+static void idetape_get_mode_sense_results (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t pc;
@@ -3420,7 +3591,7 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive)
if (idetape_queue_pc_tail(drive, &pc)) {
printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming"
" some default values\n");
- tape->blk_size = 512;
+ tape->tape_block_size = 512;
put_unaligned(52, (u16 *)&tape->caps[12]);
put_unaligned(540, (u16 *)&tape->caps[14]);
put_unaligned(6*52, (u16 *)&tape->caps[16]);
@@ -3450,75 +3621,62 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive)
memcpy(&tape->caps, caps, 20);
if (caps[7] & 0x02)
- tape->blk_size = 512;
+ tape->tape_block_size = 512;
else if (caps[7] & 0x04)
- tape->blk_size = 1024;
+ tape->tape_block_size = 1024;
}
#ifdef CONFIG_IDE_PROC_FS
-static void idetape_add_settings(ide_drive_t *drive)
+static void idetape_add_settings (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
+/*
+ * drive setting name read/write data type min max mul_factor div_factor data pointer set function
+ */
ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff,
1, 2, (u16 *)&tape->caps[16], NULL);
- ide_add_setting(drive, "pipeline_min", SETTING_RW, TYPE_INT, 1, 0xffff,
- tape->stage_size / 1024, 1, &tape->min_pipeline, NULL);
- ide_add_setting(drive, "pipeline", SETTING_RW, TYPE_INT, 1, 0xffff,
- tape->stage_size / 1024, 1, &tape->max_stages, NULL);
- ide_add_setting(drive, "pipeline_max", SETTING_RW, TYPE_INT, 1, 0xffff,
- tape->stage_size / 1024, 1, &tape->max_pipeline, NULL);
- ide_add_setting(drive, "pipeline_used", SETTING_READ, TYPE_INT, 0,
- 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages,
- NULL);
- ide_add_setting(drive, "pipeline_pending", SETTING_READ, TYPE_INT, 0,
- 0xffff, tape->stage_size / 1024, 1,
- &tape->nr_pending_stages, NULL);
+ ide_add_setting(drive, "pipeline_min", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL);
+ ide_add_setting(drive, "pipeline", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL);
+ ide_add_setting(drive, "pipeline_max", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL);
+ ide_add_setting(drive, "pipeline_used", SETTING_READ, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages, NULL);
+ ide_add_setting(drive, "pipeline_pending", SETTING_READ, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_pending_stages, NULL);
ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff,
1, 1, (u16 *)&tape->caps[14], NULL);
- ide_add_setting(drive, "stage", SETTING_READ, TYPE_INT, 0, 0xffff, 1,
- 1024, &tape->stage_size, NULL);
- ide_add_setting(drive, "tdsc", SETTING_RW, TYPE_INT, IDETAPE_DSC_RW_MIN,
- IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_freq,
- NULL);
- ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1,
- 1, &drive->dsc_overlap, NULL);
- ide_add_setting(drive, "pipeline_head_speed_c", SETTING_READ, TYPE_INT,
- 0, 0xffff, 1, 1, &tape->controlled_pipeline_head_speed,
- NULL);
- ide_add_setting(drive, "pipeline_head_speed_u", SETTING_READ, TYPE_INT,
- 0, 0xffff, 1, 1,
- &tape->uncontrolled_pipeline_head_speed, NULL);
- ide_add_setting(drive, "avg_speed", SETTING_READ, TYPE_INT, 0, 0xffff,
- 1, 1, &tape->avg_speed, NULL);
- ide_add_setting(drive, "debug_mask", SETTING_RW, TYPE_INT, 0, 0xffff, 1,
- 1, &tape->debug_mask, NULL);
+ ide_add_setting(drive, "stage", SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1024, &tape->stage_size, NULL);
+ ide_add_setting(drive, "tdsc", SETTING_RW, TYPE_INT, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_frequency, NULL);
+ ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL);
+ ide_add_setting(drive, "pipeline_head_speed_c",SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->controlled_pipeline_head_speed, NULL);
+ ide_add_setting(drive, "pipeline_head_speed_u",SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->uncontrolled_pipeline_head_speed,NULL);
+ ide_add_setting(drive, "avg_speed", SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->avg_speed, NULL);
+ ide_add_setting(drive, "debug_level", SETTING_RW, TYPE_INT, 0, 0xffff, 1, 1, &tape->debug_level, NULL);
}
#else
static inline void idetape_add_settings(ide_drive_t *drive) { ; }
#endif
/*
- * The function below is called to:
+ * ide_setup is called to:
*
- * 1. Initialize our various state variables.
- * 2. Ask the tape for its capabilities.
- * 3. Allocate a buffer which will be used for data transfer. The buffer size
- * is chosen based on the recommendation which we received in step 2.
+ * 1. Initialize our various state variables.
+ * 2. Ask the tape for its capabilities.
+ * 3. Allocate a buffer which will be used for data
+ * transfer. The buffer size is chosen based on
+ * the recommendation which we received in step (2).
*
- * Note that at this point ide.c already assigned us an irq, so that we can
- * queue requests here and wait for their completion.
+ * Note that at this point ide.c already assigned us an irq, so that
+ * we can queue requests here and wait for their completion.
*/
-static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
+static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
{
unsigned long t1, tmid, tn, t;
int speed;
+ struct idetape_id_gcw gcw;
int stage_size;
- u8 gcw[2];
struct sysinfo si;
u16 *ctl = (u16 *)&tape->caps[12];
- spin_lock_init(&tape->lock);
+ spin_lock_init(&tape->spinlock);
drive->dsc_overlap = 1;
if (drive->hwif->host_flags & IDE_HFLAG_NO_DSC) {
printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n",
@@ -3532,29 +3690,25 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
tape->name[0] = 'h';
tape->name[1] = 't';
tape->name[2] = '0' + minor;
- tape->chrdev_dir = IDETAPE_DIR_NONE;
+ tape->chrdev_direction = idetape_direction_none;
tape->pc = tape->pc_stack;
tape->max_insert_speed = 10000;
tape->speed_control = 1;
*((unsigned short *) &gcw) = drive->id->config;
-
- /* Command packet DRQ type */
- if (((gcw[0] & 0x60) >> 5) == 1)
+ if (gcw.drq_type == 1)
set_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags);
- tape->min_pipeline = 10;
- tape->max_pipeline = 10;
- tape->max_stages = 10;
-
+ tape->min_pipeline = tape->max_pipeline = tape->max_stages = 10;
+
idetape_get_inquiry_results(drive);
idetape_get_mode_sense_results(drive);
ide_tape_get_bsize_from_bdesc(drive);
tape->user_bs_factor = 1;
- tape->stage_size = *ctl * tape->blk_size;
+ tape->stage_size = *ctl * tape->tape_block_size;
while (tape->stage_size > 0xffff) {
printk(KERN_NOTICE "ide-tape: decreasing stage size\n");
*ctl /= 2;
- tape->stage_size = *ctl * tape->blk_size;
+ tape->stage_size = *ctl * tape->tape_block_size;
}
stage_size = tape->stage_size;
tape->pages_per_stage = stage_size / PAGE_SIZE;
@@ -3568,22 +3722,17 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
tape->max_stages = speed * 1000 * 10 / tape->stage_size;
- /* Limit memory use for pipeline to 10% of physical memory */
+ /*
+ * Limit memory use for pipeline to 10% of physical memory
+ */
si_meminfo(&si);
- if (tape->max_stages * tape->stage_size >
- si.totalram * si.mem_unit / 10)
- tape->max_stages =
- si.totalram * si.mem_unit / (10 * tape->stage_size);
-
+ if (tape->max_stages * tape->stage_size > si.totalram * si.mem_unit / 10)
+ tape->max_stages = si.totalram * si.mem_unit / (10 * tape->stage_size);
tape->max_stages = min(tape->max_stages, IDETAPE_MAX_PIPELINE_STAGES);
tape->min_pipeline = min(tape->max_stages, IDETAPE_MIN_PIPELINE_STAGES);
- tape->max_pipeline =
- min(tape->max_stages * 2, IDETAPE_MAX_PIPELINE_STAGES);
- if (tape->max_stages == 0) {
- tape->max_stages = 1;
- tape->min_pipeline = 1;
- tape->max_pipeline = 1;
- }
+ tape->max_pipeline = min(tape->max_stages * 2, IDETAPE_MAX_PIPELINE_STAGES);
+ if (tape->max_stages == 0)
+ tape->max_stages = tape->min_pipeline = tape->max_pipeline = 1;
t1 = (tape->stage_size * HZ) / (speed * 1000);
tmid = (*(u16 *)&tape->caps[16] * 32 * HZ) / (speed * 125);
@@ -3595,19 +3744,17 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
t = t1;
/*
- * Ensure that the number we got makes sense; limit it within
- * IDETAPE_DSC_RW_MIN and IDETAPE_DSC_RW_MAX.
+ * Ensure that the number we got makes sense; limit
+ * it within IDETAPE_DSC_RW_MIN and IDETAPE_DSC_RW_MAX.
*/
- tape->best_dsc_rw_freq = max_t(unsigned long,
- min_t(unsigned long, t, IDETAPE_DSC_RW_MAX),
- IDETAPE_DSC_RW_MIN);
+ tape->best_dsc_rw_frequency = max_t(unsigned long, min_t(unsigned long, t, IDETAPE_DSC_RW_MAX), IDETAPE_DSC_RW_MIN);
printk(KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, "
"%dkB pipeline, %lums tDSC%s\n",
drive->name, tape->name, *(u16 *)&tape->caps[14],
(*(u16 *)&tape->caps[16] * 512) / tape->stage_size,
tape->stage_size / 1024,
tape->max_stages * tape->stage_size / 1024,
- tape->best_dsc_rw_freq * 1000 / HZ,
+ tape->best_dsc_rw_frequency * 1000 / HZ,
drive->using_dma ? ", DMA":"");
idetape_add_settings(drive);
@@ -3635,8 +3782,7 @@ static void ide_tape_release(struct kref *kref)
drive->dsc_overlap = 0;
drive->driver_data = NULL;
device_destroy(idetape_sysfs_class, MKDEV(IDETAPE_MAJOR, tape->minor));
- device_destroy(idetape_sysfs_class,
- MKDEV(IDETAPE_MAJOR, tape->minor + 128));
+ device_destroy(idetape_sysfs_class, MKDEV(IDETAPE_MAJOR, tape->minor + 128));
idetape_devs[tape->minor] = NULL;
g->private_data = NULL;
put_disk(g);
@@ -3685,7 +3831,9 @@ static ide_driver_t idetape_driver = {
#endif
};
-/* Our character device supporting functions, passed to register_chrdev. */
+/*
+ * Our character device supporting functions, passed to register_chrdev.
+ */
static const struct file_operations idetape_fops = {
.owner = THIS_MODULE,
.read = idetape_chrdev_read,
@@ -3700,8 +3848,7 @@ static int idetape_open(struct inode *inode, struct file *filp)
struct gendisk *disk = inode->i_bdev->bd_disk;
struct ide_tape_obj *tape;
- tape = ide_tape_get(disk);
- if (!tape)
+ if (!(tape = ide_tape_get(disk)))
return -ENXIO;
return 0;
@@ -3748,20 +3895,21 @@ static int ide_tape_probe(ide_drive_t *drive)
goto failed;
if (drive->media != ide_tape)
goto failed;
- if (!idetape_identify_device(drive)) {
- printk(KERN_ERR "ide-tape: %s: not supported by this version of"
- " the driver\n", drive->name);
+ if (!idetape_identify_device (drive)) {
+ printk(KERN_ERR "ide-tape: %s: not supported by this version of ide-tape\n", drive->name);
goto failed;
}
if (drive->scsi) {
- printk(KERN_INFO "ide-tape: passing drive %s to ide-scsi"
- " emulation.\n", drive->name);
+ printk("ide-tape: passing drive %s to ide-scsi emulation.\n", drive->name);
goto failed;
}
- tape = kzalloc(sizeof(idetape_tape_t), GFP_KERNEL);
+ if (strstr(drive->id->model, "OnStream DI-")) {
+ printk(KERN_WARNING "ide-tape: Use drive %s with ide-scsi emulation and osst.\n", drive->name);
+ printk(KERN_WARNING "ide-tape: OnStream support will be removed soon from ide-tape!\n");
+ }
+ tape = kzalloc(sizeof (idetape_tape_t), GFP_KERNEL);
if (tape == NULL) {
- printk(KERN_ERR "ide-tape: %s: Can't allocate a tape struct\n",
- drive->name);
+ printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name);
goto failed;
}
@@ -3807,7 +3955,10 @@ static int ide_tape_probe(ide_drive_t *drive)
return -ENODEV;
}
-static void __exit idetape_exit(void)
+MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver");
+MODULE_LICENSE("GPL");
+
+static void __exit idetape_exit (void)
{
driver_unregister(&idetape_driver.gen_driver);
class_destroy(idetape_sysfs_class);
@@ -3826,8 +3977,7 @@ static int __init idetape_init(void)
}
if (register_chrdev(IDETAPE_MAJOR, "ht", &idetape_fops)) {
- printk(KERN_ERR "ide-tape: Failed to register chrdev"
- " interface\n");
+ printk(KERN_ERR "ide-tape: Failed to register character device interface\n");
error = -EBUSY;
goto out_free_class;
}
@@ -3850,5 +4000,3 @@ MODULE_ALIAS("ide:*m-tape*");
module_init(idetape_init);
module_exit(idetape_exit);
MODULE_ALIAS_CHARDEV_MAJOR(IDETAPE_MAJOR);
-MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver");
-MODULE_LICENSE("GPL");
diff --git a/trunk/drivers/ide/ide-taskfile.c b/trunk/drivers/ide/ide-taskfile.c
index 0518a2e948cf..4e1da1c78cb5 100644
--- a/trunk/drivers/ide/ide-taskfile.c
+++ b/trunk/drivers/ide/ide-taskfile.c
@@ -189,11 +189,12 @@ EXPORT_SYMBOL_GPL(do_rw_taskfile);
*/
static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
{
- u8 stat = ide_read_status(drive);
+ ide_hwif_t *hwif = HWIF(drive);
+ u8 stat;
- if (OK_STAT(stat, READY_STAT, BAD_STAT))
+ if (OK_STAT(stat = hwif->INB(IDE_STATUS_REG),READY_STAT,BAD_STAT)) {
drive->mult_count = drive->mult_req;
- else {
+ } else {
drive->mult_req = drive->mult_count = 0;
drive->special.b.recalibrate = 1;
(void) ide_dump_status(drive, "set_multmode", stat);
@@ -206,10 +207,11 @@ static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
*/
static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
{
+ ide_hwif_t *hwif = HWIF(drive);
int retries = 5;
u8 stat;
- while (((stat = ide_read_status(drive)) & BUSY_STAT) && retries--)
+ while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
udelay(10);
if (OK_STAT(stat, READY_STAT, BAD_STAT))
@@ -228,9 +230,10 @@ static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
*/
static ide_startstop_t recal_intr(ide_drive_t *drive)
{
- u8 stat = ide_read_status(drive);
+ ide_hwif_t *hwif = HWIF(drive);
+ u8 stat;
- if (!OK_STAT(stat, READY_STAT, BAD_STAT))
+ if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), READY_STAT, BAD_STAT))
return ide_error(drive, "recal_intr", stat);
return ide_stopped;
}
@@ -241,23 +244,23 @@ static ide_startstop_t recal_intr(ide_drive_t *drive)
static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
{
ide_task_t *args = HWGROUP(drive)->rq->special;
+ ide_hwif_t *hwif = HWIF(drive);
u8 stat;
local_irq_enable_in_hardirq();
- stat = ide_read_status(drive);
-
- if (!OK_STAT(stat, READY_STAT, BAD_STAT))
+ if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG),READY_STAT,BAD_STAT)) {
return ide_error(drive, "task_no_data_intr", stat);
/* calls ide_end_drive_cmd */
-
+ }
if (args)
- ide_end_drive_cmd(drive, stat, ide_read_error(drive));
+ ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG));
return ide_stopped;
}
static u8 wait_drive_not_busy(ide_drive_t *drive)
{
+ ide_hwif_t *hwif = HWIF(drive);
int retries;
u8 stat;
@@ -266,9 +269,7 @@ static u8 wait_drive_not_busy(ide_drive_t *drive)
* This can take up to 10 usec, but we will wait max 1 ms.
*/
for (retries = 0; retries < 100; retries++) {
- stat = ide_read_status(drive);
-
- if (stat & BUSY_STAT)
+ if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT)
udelay(10);
else
break;
@@ -407,7 +408,7 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
{
if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
- u8 err = ide_read_error(drive);
+ u8 err = drive->hwif->INB(IDE_ERROR_REG);
ide_end_drive_cmd(drive, stat, err);
return;
@@ -429,7 +430,7 @@ static ide_startstop_t task_in_intr(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
struct request *rq = HWGROUP(drive)->rq;
- u8 stat = ide_read_status(drive);
+ u8 stat = hwif->INB(IDE_STATUS_REG);
/* new way for dealing with premature shared PCI interrupts */
if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) {
@@ -464,7 +465,7 @@ static ide_startstop_t task_out_intr (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
struct request *rq = HWGROUP(drive)->rq;
- u8 stat = ide_read_status(drive);
+ u8 stat = hwif->INB(IDE_STATUS_REG);
if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
return task_error(drive, rq, __FUNCTION__, stat);
diff --git a/trunk/drivers/ide/ide.c b/trunk/drivers/ide/ide.c
index ad0e9955f73c..ac6136001615 100644
--- a/trunk/drivers/ide/ide.c
+++ b/trunk/drivers/ide/ide.c
@@ -618,6 +618,60 @@ void ide_unregister(unsigned int index, int init_default, int restore)
EXPORT_SYMBOL(ide_unregister);
+
+/**
+ * ide_setup_ports - set up IDE interface ports
+ * @hw: register descriptions
+ * @base: base register
+ * @offsets: table of register offsets
+ * @ctrl: control register
+ * @ack_irq: IRQ ack
+ * @irq: interrupt lie
+ *
+ * Setup hw_regs_t structure described by parameters. You
+ * may set up the hw structure yourself OR use this routine to
+ * do it for you. This is basically a helper
+ *
+ */
+
+void ide_setup_ports ( hw_regs_t *hw,
+ unsigned long base, int *offsets,
+ unsigned long ctrl, unsigned long intr,
+ ide_ack_intr_t *ack_intr,
+/*
+ * ide_io_ops_t *iops,
+ */
+ int irq)
+{
+ int i;
+
+ memset(hw, 0, sizeof(hw_regs_t));
+ for (i = 0; i < IDE_NR_PORTS; i++) {
+ if (offsets[i] == -1) {
+ switch(i) {
+ case IDE_CONTROL_OFFSET:
+ hw->io_ports[i] = ctrl;
+ break;
+#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
+ case IDE_IRQ_OFFSET:
+ hw->io_ports[i] = intr;
+ break;
+#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
+ default:
+ hw->io_ports[i] = 0;
+ break;
+ }
+ } else {
+ hw->io_ports[i] = base + offsets[i];
+ }
+ }
+ hw->irq = irq;
+ hw->ack_intr = ack_intr;
+/*
+ * hw->iops = iops;
+ */
+}
+
void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
{
memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports));
diff --git a/trunk/drivers/ide/legacy/buddha.c b/trunk/drivers/ide/legacy/buddha.c
index 50ffa871d5e9..8bdb79da17e8 100644
--- a/trunk/drivers/ide/legacy/buddha.c
+++ b/trunk/drivers/ide/legacy/buddha.c
@@ -56,11 +56,31 @@ static u_int xsurf_bases[XSURF_NUM_HWIFS] __initdata = {
XSURF_BASE1, XSURF_BASE2
};
+
/*
* Offsets from one of the above bases
*/
+#define BUDDHA_DATA 0x00
+#define BUDDHA_ERROR 0x06 /* see err-bits */
+#define BUDDHA_NSECTOR 0x0a /* nr of sectors to read/write */
+#define BUDDHA_SECTOR 0x0e /* starting sector */
+#define BUDDHA_LCYL 0x12 /* starting cylinder */
+#define BUDDHA_HCYL 0x16 /* high byte of starting cyl */
+#define BUDDHA_SELECT 0x1a /* 101dhhhh , d=drive, hhhh=head */
+#define BUDDHA_STATUS 0x1e /* see status-bits */
#define BUDDHA_CONTROL 0x11a
+#define XSURF_CONTROL -1 /* X-Surf has no CS1* (Control/AltStat) */
+
+static int buddha_offsets[IDE_NR_PORTS] __initdata = {
+ BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL,
+ BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, BUDDHA_CONTROL, -1
+};
+
+static int xsurf_offsets[IDE_NR_PORTS] __initdata = {
+ BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL,
+ BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, XSURF_CONTROL, -1
+};
/*
* Other registers
@@ -120,26 +140,6 @@ static int xsurf_ack_intr(ide_hwif_t *hwif)
return 1;
}
-static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base,
- unsigned long ctl, unsigned long irq_port,
- ide_ack_intr_t *ack_intr)
-{
- int i;
-
- memset(hw, 0, sizeof(*hw));
-
- hw->io_ports[IDE_DATA_OFFSET] = base;
-
- for (i = 1; i < 8; i++)
- hw->io_ports[i] = base + 2 + i * 4;
-
- hw->io_ports[IDE_CONTROL_OFFSET] = ctl;
- hw->io_ports[IDE_IRQ_OFFSET] = irq_port;
-
- hw->irq = IRQ_AMIGA_PORTS;
- hw->ack_intr = ack_intr;
-}
-
/*
* Probe for a Buddha or Catweasel IDE interface
*/
@@ -202,24 +202,22 @@ static int __init buddha_init(void)
printk(KERN_INFO "ide: %s IDE controller\n",
buddha_board_name[type]);
- for (i = 0; i < buddha_num_hwifs; i++) {
- unsigned long base, ctl, irq_port;
- ide_ack_intr_t *ack_intr;
-
- if (type != BOARD_XSURF) {
- base = buddha_board + buddha_bases[i];
- ctl = base + BUDDHA_CONTROL;
- irq_port = buddha_board + buddha_irqports[i];
- ack_intr = buddha_ack_intr;
+ for(i=0;iio_ports[IDE_DATA_OFFSET] = ATA_HD_BASE;
-
- for (i = 1; i < 8; i++)
- hw->io_ports[i] = ATA_HD_BASE + 1 + i * 4;
-
- hw->io_ports[IDE_CONTROL_OFFSET] = ATA_HD_CONTROL;
-
- hw->irq = IRQ_MFP_IDE;
- hw->ack_intr = NULL;
-}
/*
* Probe for a Falcon IDE interface
@@ -66,15 +64,16 @@ static void __init falconide_setup_ports(hw_regs_t *hw)
static int __init falconide_init(void)
{
+ if (MACH_IS_ATARI && ATARIHW_PRESENT(IDE)) {
hw_regs_t hw;
ide_hwif_t *hwif;
- if (!MACH_IS_ATARI || !ATARIHW_PRESENT(IDE))
- return 0;
-
printk(KERN_INFO "ide: Falcon IDE controller\n");
- falconide_setup_ports(&hw);
+ ide_setup_ports(&hw, ATA_HD_BASE, falconide_offsets,
+ 0, 0, NULL,
+// falconide_iops,
+ IRQ_MFP_IDE);
hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
if (hwif) {
@@ -86,8 +85,9 @@ static int __init falconide_init(void)
ide_device_add(idx, NULL);
}
+ }
- return 0;
+ return 0;
}
module_init(falconide_init);
diff --git a/trunk/drivers/ide/legacy/gayle.c b/trunk/drivers/ide/legacy/gayle.c
index 9d3851d27677..fc29ce75aff1 100644
--- a/trunk/drivers/ide/legacy/gayle.c
+++ b/trunk/drivers/ide/legacy/gayle.c
@@ -34,8 +34,22 @@
* Offsets from one of the above bases
*/
+#define GAYLE_DATA 0x00
+#define GAYLE_ERROR 0x06 /* see err-bits */
+#define GAYLE_NSECTOR 0x0a /* nr of sectors to read/write */
+#define GAYLE_SECTOR 0x0e /* starting sector */
+#define GAYLE_LCYL 0x12 /* starting cylinder */
+#define GAYLE_HCYL 0x16 /* high byte of starting cyl */
+#define GAYLE_SELECT 0x1a /* 101dhhhh , d=drive, hhhh=head */
+#define GAYLE_STATUS 0x1e /* see status-bits */
#define GAYLE_CONTROL 0x101a
+static int gayle_offsets[IDE_NR_PORTS] __initdata = {
+ GAYLE_DATA, GAYLE_ERROR, GAYLE_NSECTOR, GAYLE_SECTOR, GAYLE_LCYL,
+ GAYLE_HCYL, GAYLE_SELECT, GAYLE_STATUS, -1, -1
+};
+
+
/*
* These are at different offsets from the base
*/
@@ -92,26 +106,6 @@ static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
return 1;
}
-static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base,
- unsigned long ctl, unsigned long irq_port,
- ide_ack_intr_t *ack_intr);
-{
- int i;
-
- memset(hw, 0, sizeof(*hw));
-
- hw->io_ports[IDE_DATA_OFFSET] = base;
-
- for (i = 1; i < 8; i++)
- hw->io_ports[i] = base + 2 + i * 4;
-
- hw->io_ports[IDE_CONTROL_OFFSET] = ctl;
- hw->io_ports[IDE_IRQ_OFFSET] = irq_port;
-
- hw->irq = IRQ_AMIGA_PORTS;
- hw->ack_intr = ack_intr;
-}
-
/*
* Probe for a Gayle IDE interface (and optionally for an IDE doubler)
*/
@@ -173,7 +167,10 @@ static int __init gayle_init(void)
base = (unsigned long)ZTWO_VADDR(phys_base);
ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;
- gayle_setup_ports(&hw, base, ctrlport, irqport, ack_intr);
+ ide_setup_ports(&hw, base, gayle_offsets,
+ ctrlport, irqport, ack_intr,
+// &gayle_iops,
+ IRQ_AMIGA_PORTS);
hwif = ide_find_port(base);
if (hwif) {
diff --git a/trunk/drivers/ide/legacy/hd.c b/trunk/drivers/ide/legacy/hd.c
index 0b0d86731927..8e05d88e81ba 100644
--- a/trunk/drivers/ide/legacy/hd.c
+++ b/trunk/drivers/ide/legacy/hd.c
@@ -421,14 +421,11 @@ static void bad_rw_intr(void)
static inline int wait_DRQ(void)
{
- int retries;
- int stat;
+ int retries = 100000, stat;
- for (retries = 0; retries < 100000; retries++) {
- stat = inb_p(HD_STATUS);
- if (stat & DRQ_STAT)
+ while (--retries > 0)
+ if ((stat = inb_p(HD_STATUS)) & DRQ_STAT)
return 0;
- }
dump_status("wait_DRQ", stat);
return -1;
}
diff --git a/trunk/drivers/ide/legacy/macide.c b/trunk/drivers/ide/legacy/macide.c
index a61e60737dc7..06df8df857a3 100644
--- a/trunk/drivers/ide/legacy/macide.c
+++ b/trunk/drivers/ide/legacy/macide.c
@@ -31,6 +31,14 @@
* These match MkLinux so they should be correct.
*/
+#define IDE_DATA 0x00
+#define IDE_ERROR 0x04 /* see err-bits */
+#define IDE_NSECTOR 0x08 /* nr of sectors to read/write */
+#define IDE_SECTOR 0x0c /* starting sector */
+#define IDE_LCYL 0x10 /* starting cylinder */
+#define IDE_HCYL 0x14 /* high byte of starting cyl */
+#define IDE_SELECT 0x18 /* 101dhhhh , d=drive, hhhh=head */
+#define IDE_STATUS 0x1c /* see status-bits */
#define IDE_CONTROL 0x38 /* control/altstatus */
/*
@@ -55,6 +63,11 @@
volatile unsigned char *ide_ifr = (unsigned char *) (IDE_BASE + IDE_IFR);
+static int macide_offsets[IDE_NR_PORTS] = {
+ IDE_DATA, IDE_ERROR, IDE_NSECTOR, IDE_SECTOR, IDE_LCYL,
+ IDE_HCYL, IDE_SELECT, IDE_STATUS, IDE_CONTROL
+};
+
int macide_ack_intr(ide_hwif_t* hwif)
{
if (*ide_ifr & 0x20) {
@@ -64,22 +77,6 @@ int macide_ack_intr(ide_hwif_t* hwif)
return 0;
}
-static void __init macide_setup_ports(hw_regs_t *hw, unsigned long base,
- int irq, ide_ack_intr_t *ack_intr)
-{
- int i;
-
- memset(hw, 0, sizeof(*hw));
-
- for (i = 0; i < 8; i++)
- hw->io_ports[i] = base + i * 4;
-
- hw->io_ports[IDE_CONTROL_OFFSET] = IDE_CONTROL;
-
- hw->irq = irq;
- hw->ack_intr = ack_intr;
-}
-
static const char *mac_ide_name[] =
{ "Quadra", "Powerbook", "Powerbook Baboon" };
@@ -89,27 +86,27 @@ static const char *mac_ide_name[] =
static int __init macide_init(void)
{
- ide_hwif_t *hwif;
- ide_ack_intr_t *ack_intr;
- unsigned long base;
- int irq;
hw_regs_t hw;
+ ide_hwif_t *hwif;
switch (macintosh_config->ide_type) {
case MAC_IDE_QUADRA:
- base = IDE_BASE;
- ack_intr = macide_ack_intr;
- irq = IRQ_NUBUS_F;
+ ide_setup_ports(&hw, IDE_BASE, macide_offsets,
+ 0, 0, macide_ack_intr,
+// quadra_ide_iops,
+ IRQ_NUBUS_F);
break;
case MAC_IDE_PB:
- base = IDE_BASE;
- ack_intr = macide_ack_intr;
- irq = IRQ_NUBUS_C;
+ ide_setup_ports(&hw, IDE_BASE, macide_offsets,
+ 0, 0, macide_ack_intr,
+// macide_pb_iops,
+ IRQ_NUBUS_C);
break;
case MAC_IDE_BABOON:
- base = BABOON_BASE;
- ack_intr = NULL;
- irq = IRQ_BABOON_1;
+ ide_setup_ports(&hw, BABOON_BASE, macide_offsets,
+ 0, 0, NULL,
+// macide_baboon_iops,
+ IRQ_BABOON_1);
break;
default:
return -ENODEV;
@@ -118,8 +115,6 @@ static int __init macide_init(void)
printk(KERN_INFO "ide: Macintosh %s IDE controller\n",
mac_ide_name[macintosh_config->ide_type - 1]);
- macide_setup_ports(&hw, base, irq, ack_intr);
-
hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
if (hwif) {
u8 index = hwif->index;
diff --git a/trunk/drivers/ide/legacy/q40ide.c b/trunk/drivers/ide/legacy/q40ide.c
index 1381b91bc316..2f0b34d892a1 100644
--- a/trunk/drivers/ide/legacy/q40ide.c
+++ b/trunk/drivers/ide/legacy/q40ide.c
@@ -66,12 +66,16 @@ static int q40ide_default_irq(unsigned long base)
/*
- * Addresses are pretranslated for Q40 ISA access.
+ * This is very similar to ide_setup_ports except that addresses
+ * are pretranslated for q40 ISA access
*/
void q40_ide_setup_ports ( hw_regs_t *hw,
unsigned long base, int *offsets,
unsigned long ctrl, unsigned long intr,
ide_ack_intr_t *ack_intr,
+/*
+ * ide_io_ops_t *iops,
+ */
int irq)
{
int i;
@@ -88,6 +92,9 @@ void q40_ide_setup_ports ( hw_regs_t *hw,
hw->irq = irq;
hw->ack_intr = ack_intr;
+/*
+ * hw->iops = iops;
+ */
}
diff --git a/trunk/drivers/ide/pci/Makefile b/trunk/drivers/ide/pci/Makefile
index 02e6ee7d751d..94803253e8af 100644
--- a/trunk/drivers/ide/pci/Makefile
+++ b/trunk/drivers/ide/pci/Makefile
@@ -34,8 +34,7 @@ obj-$(CONFIG_BLK_DEV_TRM290) += trm290.o
obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o
# Must appear at the end of the block
-obj-$(CONFIG_BLK_DEV_GENERIC) += ide-pci-generic.o
-ide-pci-generic-y += generic.o
+obj-$(CONFIG_BLK_DEV_GENERIC) += generic.o
ifeq ($(CONFIG_BLK_DEV_CMD640), m)
obj-m += cmd640.o
diff --git a/trunk/drivers/ide/pci/generic.c b/trunk/drivers/ide/pci/generic.c
index 7fd83a9d4dee..9262a9174b4e 100644
--- a/trunk/drivers/ide/pci/generic.c
+++ b/trunk/drivers/ide/pci/generic.c
@@ -29,6 +29,19 @@
static int ide_generic_all; /* Set to claim all devices */
+/*
+ * the module_param_named() was added for the modular case
+ * the __setup() is left as compatibility for existing setups
+ */
+#ifndef MODULE
+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;
+}
+const __setup("all-generic-ide", ide_generic_all_on);
+#endif
module_param_named(all_generic_ide, ide_generic_all, bool, 0444);
MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers.");
diff --git a/trunk/drivers/ide/pci/siimage.c b/trunk/drivers/ide/pci/siimage.c
index cc4be9621bc0..ef5b39fa042b 100644
--- a/trunk/drivers/ide/pci/siimage.c
+++ b/trunk/drivers/ide/pci/siimage.c
@@ -704,6 +704,9 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
hwif->sata_scr[SATA_STATUS_OFFSET] = base + 0x104;
hwif->sata_scr[SATA_ERROR_OFFSET] = base + 0x108;
hwif->sata_scr[SATA_CONTROL_OFFSET] = base + 0x100;
+ hwif->sata_misc[SATA_MISC_OFFSET] = base + 0x140;
+ hwif->sata_misc[SATA_PHY_OFFSET] = base + 0x144;
+ hwif->sata_misc[SATA_IEN_OFFSET] = base + 0x148;
}
memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
diff --git a/trunk/drivers/input/touchscreen/h3600_ts_input.c b/trunk/drivers/input/touchscreen/h3600_ts_input.c
index 28ae15ed12c5..2ae6c6016a86 100644
--- a/trunk/drivers/input/touchscreen/h3600_ts_input.c
+++ b/trunk/drivers/input/touchscreen/h3600_ts_input.c
@@ -109,7 +109,7 @@ struct h3600_dev {
static irqreturn_t action_button_handler(int irq, void *dev_id)
{
int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1;
- struct input_dev *dev = dev_id;
+ struct input_dev *dev = (struct input_dev *) dev_id;
input_report_key(dev, KEY_ENTER, down);
input_sync(dev);
@@ -120,7 +120,7 @@ static irqreturn_t action_button_handler(int irq, void *dev_id)
static irqreturn_t npower_button_handler(int irq, void *dev_id)
{
int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1;
- struct input_dev *dev = dev_id;
+ struct input_dev *dev = (struct input_dev *) dev_id;
/*
* This interrupt is only called when we release the key. So we have
diff --git a/trunk/drivers/isdn/act2000/module.c b/trunk/drivers/isdn/act2000/module.c
index 8325022e2bed..ee2b0b9f8f46 100644
--- a/trunk/drivers/isdn/act2000/module.c
+++ b/trunk/drivers/isdn/act2000/module.c
@@ -310,7 +310,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c)
}
break;
case ISDN_CMD_DIAL:
- if (!(card->flags & ACT2000_FLAGS_RUNNING))
+ if (!card->flags & ACT2000_FLAGS_RUNNING)
return -ENODEV;
if (!(chan = find_channel(card, c->arg & 0x0f)))
break;
@@ -339,7 +339,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c)
}
return ret;
case ISDN_CMD_ACCEPTD:
- if (!(card->flags & ACT2000_FLAGS_RUNNING))
+ if (!card->flags & ACT2000_FLAGS_RUNNING)
return -ENODEV;
if (!(chan = find_channel(card, c->arg & 0x0f)))
break;
@@ -347,11 +347,11 @@ act2000_command(act2000_card * card, isdn_ctrl * c)
actcapi_select_b2_protocol_req(card, chan);
return 0;
case ISDN_CMD_ACCEPTB:
- if (!(card->flags & ACT2000_FLAGS_RUNNING))
+ if (!card->flags & ACT2000_FLAGS_RUNNING)
return -ENODEV;
return 0;
case ISDN_CMD_HANGUP:
- if (!(card->flags & ACT2000_FLAGS_RUNNING))
+ if (!card->flags & ACT2000_FLAGS_RUNNING)
return -ENODEV;
if (!(chan = find_channel(card, c->arg & 0x0f)))
break;
@@ -366,7 +366,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c)
}
return 0;
case ISDN_CMD_SETEAZ:
- if (!(card->flags & ACT2000_FLAGS_RUNNING))
+ if (!card->flags & ACT2000_FLAGS_RUNNING)
return -ENODEV;
if (!(chan = find_channel(card, c->arg & 0x0f)))
break;
@@ -386,7 +386,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c)
actcapi_listen_req(card);
return 0;
case ISDN_CMD_CLREAZ:
- if (!(card->flags & ACT2000_FLAGS_RUNNING))
+ if (!card->flags & ACT2000_FLAGS_RUNNING)
return -ENODEV;
if (!(chan = find_channel(card, c->arg & 0x0f)))
break;
@@ -394,14 +394,14 @@ act2000_command(act2000_card * card, isdn_ctrl * c)
actcapi_listen_req(card);
return 0;
case ISDN_CMD_SETL2:
- if (!(card->flags & ACT2000_FLAGS_RUNNING))
+ if (!card->flags & ACT2000_FLAGS_RUNNING)
return -ENODEV;
if (!(chan = find_channel(card, c->arg & 0x0f)))
break;
chan->l2prot = (c->arg >> 8);
return 0;
case ISDN_CMD_SETL3:
- if (!(card->flags & ACT2000_FLAGS_RUNNING))
+ if (!card->flags & ACT2000_FLAGS_RUNNING)
return -ENODEV;
if ((c->arg >> 8) != ISDN_PROTO_L3_TRANS) {
printk(KERN_WARNING "L3 protocol unknown\n");
@@ -524,7 +524,7 @@ if_writecmd(const u_char __user *buf, int len, int id, int channel)
act2000_card *card = act2000_findcard(id);
if (card) {
- if (!(card->flags & ACT2000_FLAGS_RUNNING))
+ if (!card->flags & ACT2000_FLAGS_RUNNING)
return -ENODEV;
return (len);
}
@@ -539,7 +539,7 @@ if_readstatus(u_char __user * buf, int len, int id, int channel)
act2000_card *card = act2000_findcard(id);
if (card) {
- if (!(card->flags & ACT2000_FLAGS_RUNNING))
+ if (!card->flags & ACT2000_FLAGS_RUNNING)
return -ENODEV;
return (act2000_readstatus(buf, len, card));
}
@@ -554,7 +554,7 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb)
act2000_card *card = act2000_findcard(id);
if (card) {
- if (!(card->flags & ACT2000_FLAGS_RUNNING))
+ if (!card->flags & ACT2000_FLAGS_RUNNING)
return -ENODEV;
return (act2000_sendbuf(card, channel, ack, skb));
}
diff --git a/trunk/drivers/isdn/gigaset/asyncdata.c b/trunk/drivers/isdn/gigaset/asyncdata.c
index 091deb9d1c47..00a3be5b862b 100644
--- a/trunk/drivers/isdn/gigaset/asyncdata.c
+++ b/trunk/drivers/isdn/gigaset/asyncdata.c
@@ -350,8 +350,8 @@ void gigaset_m10x_input(struct inbuf_t *inbuf)
unsigned char *src, c;
int procbytes;
- head = inbuf->head;
- tail = inbuf->tail;
+ head = atomic_read(&inbuf->head);
+ tail = atomic_read(&inbuf->tail);
gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
if (head != tail) {
@@ -361,7 +361,7 @@ void gigaset_m10x_input(struct inbuf_t *inbuf)
gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
while (numbytes) {
- if (cs->mstate == MS_LOCKED) {
+ if (atomic_read(&cs->mstate) == MS_LOCKED) {
procbytes = lock_loop(src, numbytes, inbuf);
src += procbytes;
numbytes -= procbytes;
@@ -436,7 +436,7 @@ void gigaset_m10x_input(struct inbuf_t *inbuf)
}
gig_dbg(DEBUG_INTR, "setting head to %u", head);
- inbuf->head = head;
+ atomic_set(&inbuf->head, head);
}
}
EXPORT_SYMBOL_GPL(gigaset_m10x_input);
diff --git a/trunk/drivers/isdn/gigaset/bas-gigaset.c b/trunk/drivers/isdn/gigaset/bas-gigaset.c
index 5255b5e20e13..af7648274b38 100644
--- a/trunk/drivers/isdn/gigaset/bas-gigaset.c
+++ b/trunk/drivers/isdn/gigaset/bas-gigaset.c
@@ -73,14 +73,6 @@ static int gigaset_probe(struct usb_interface *interface,
/* Function will be called if the device is unplugged */
static void gigaset_disconnect(struct usb_interface *interface);
-/* functions called before/after suspend */
-static int gigaset_suspend(struct usb_interface *intf, pm_message_t message);
-static int gigaset_resume(struct usb_interface *intf);
-
-/* functions called before/after device reset */
-static int gigaset_pre_reset(struct usb_interface *intf);
-static int gigaset_post_reset(struct usb_interface *intf);
-
static int atread_submit(struct cardstate *, int);
static void stopurbs(struct bas_bc_state *);
static int req_submit(struct bc_state *, int, int, int);
@@ -113,9 +105,8 @@ struct bas_cardstate {
unsigned char int_in_buf[3];
spinlock_t lock; /* locks all following */
- int basstate; /* bitmap (BS_*) */
+ atomic_t basstate; /* bitmap (BS_*) */
int pending; /* uncompleted base request */
- wait_queue_head_t waitqueue;
int rcvbuf_size; /* size of AT receive buffer */
/* 0: no receive in progress */
int retry_cmd_in; /* receive req retry count */
@@ -130,10 +121,10 @@ struct bas_cardstate {
#define BS_ATTIMER 0x020 /* waiting for HD_READY_SEND_ATDATA */
#define BS_ATRDPEND 0x040 /* urb_cmd_in in use */
#define BS_ATWRPEND 0x080 /* urb_cmd_out in use */
-#define BS_SUSPEND 0x100 /* USB port suspended */
static struct gigaset_driver *driver = NULL;
+static struct cardstate *cardstate = NULL;
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver gigaset_usb_driver = {
@@ -141,11 +132,6 @@ static struct usb_driver gigaset_usb_driver = {
.probe = gigaset_probe,
.disconnect = gigaset_disconnect,
.id_table = gigaset_table,
- .suspend = gigaset_suspend,
- .resume = gigaset_resume,
- .reset_resume = gigaset_post_reset,
- .pre_reset = gigaset_pre_reset,
- .post_reset = gigaset_post_reset,
};
/* get message text for usb_submit_urb return code
@@ -262,12 +248,12 @@ static inline void dump_urb(enum debuglevel level, const char *tag,
if (urb) {
gig_dbg(level,
" dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, "
- "hcpriv=0x%08lx, transfer_flags=0x%x,",
+ "status=%d, hcpriv=0x%08lx, transfer_flags=0x%x,",
(unsigned long) urb->dev,
usb_pipetype_str(urb->pipe),
usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe),
usb_pipein(urb->pipe) ? "in" : "out",
- (unsigned long) urb->hcpriv,
+ urb->status, (unsigned long) urb->hcpriv,
urb->transfer_flags);
gig_dbg(level,
" transfer_buffer=0x%08lx[%d], actual_length=%d, "
@@ -369,27 +355,27 @@ static void check_pending(struct bas_cardstate *ucs)
case 0:
break;
case HD_OPEN_ATCHANNEL:
- if (ucs->basstate & BS_ATOPEN)
+ if (atomic_read(&ucs->basstate) & BS_ATOPEN)
ucs->pending = 0;
break;
case HD_OPEN_B1CHANNEL:
- if (ucs->basstate & BS_B1OPEN)
+ if (atomic_read(&ucs->basstate) & BS_B1OPEN)
ucs->pending = 0;
break;
case HD_OPEN_B2CHANNEL:
- if (ucs->basstate & BS_B2OPEN)
+ if (atomic_read(&ucs->basstate) & BS_B2OPEN)
ucs->pending = 0;
break;
case HD_CLOSE_ATCHANNEL:
- if (!(ucs->basstate & BS_ATOPEN))
+ if (!(atomic_read(&ucs->basstate) & BS_ATOPEN))
ucs->pending = 0;
break;
case HD_CLOSE_B1CHANNEL:
- if (!(ucs->basstate & BS_B1OPEN))
+ if (!(atomic_read(&ucs->basstate) & BS_B1OPEN))
ucs->pending = 0;
break;
case HD_CLOSE_B2CHANNEL:
- if (!(ucs->basstate & BS_B2OPEN))
+ if (!(atomic_read(&ucs->basstate) & BS_B2OPEN))
ucs->pending = 0;
break;
case HD_DEVICE_INIT_ACK: /* no reply expected */
@@ -455,8 +441,8 @@ inline static int update_basstate(struct bas_cardstate *ucs,
int state;
spin_lock_irqsave(&ucs->lock, flags);
- state = ucs->basstate;
- ucs->basstate = (state & ~clear) | set;
+ state = atomic_read(&ucs->basstate);
+ atomic_set(&ucs->basstate, (state & ~clear) | set);
spin_unlock_irqrestore(&ucs->lock, flags);
return state;
}
@@ -473,13 +459,11 @@ static void read_ctrl_callback(struct urb *urb)
struct inbuf_t *inbuf = urb->context;
struct cardstate *cs = inbuf->cs;
struct bas_cardstate *ucs = cs->hw.bas;
- int status = urb->status;
int have_data = 0;
unsigned numbytes;
int rc;
update_basstate(ucs, 0, BS_ATRDPEND);
- wake_up(&ucs->waitqueue);
if (!ucs->rcvbuf_size) {
dev_warn(cs->dev, "%s: no receive in progress\n", __func__);
@@ -488,7 +472,7 @@ static void read_ctrl_callback(struct urb *urb)
del_timer(&ucs->timer_cmd_in);
- switch (status) {
+ switch (urb->status) {
case 0: /* normal completion */
numbytes = urb->actual_length;
if (unlikely(numbytes != ucs->rcvbuf_size)) {
@@ -522,12 +506,12 @@ static void read_ctrl_callback(struct urb *urb)
case -ESHUTDOWN: /* device shut down */
/* no action necessary */
gig_dbg(DEBUG_USBREQ, "%s: %s",
- __func__, get_usb_statmsg(status));
+ __func__, get_usb_statmsg(urb->status));
break;
default: /* severe trouble */
dev_warn(cs->dev, "control read: %s\n",
- get_usb_statmsg(status));
+ get_usb_statmsg(urb->status));
if (ucs->retry_cmd_in++ < BAS_RETRY) {
dev_notice(cs->dev, "control read: retry %d\n",
ucs->retry_cmd_in);
@@ -566,28 +550,17 @@ static void read_ctrl_callback(struct urb *urb)
static int atread_submit(struct cardstate *cs, int timeout)
{
struct bas_cardstate *ucs = cs->hw.bas;
- int basstate;
int ret;
gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)",
ucs->rcvbuf_size);
- basstate = update_basstate(ucs, BS_ATRDPEND, 0);
- if (basstate & BS_ATRDPEND) {
+ if (update_basstate(ucs, BS_ATRDPEND, 0) & BS_ATRDPEND) {
dev_err(cs->dev,
"could not submit HD_READ_ATMESSAGE: URB busy\n");
return -EBUSY;
}
- if (basstate & BS_SUSPEND) {
- dev_notice(cs->dev,
- "HD_READ_ATMESSAGE not submitted, "
- "suspend in progress\n");
- update_basstate(ucs, 0, BS_ATRDPEND);
- /* treat like disconnect */
- return -ENODEV;
- }
-
ucs->dr_cmd_in.bRequestType = IN_VENDOR_REQ;
ucs->dr_cmd_in.bRequest = HD_READ_ATMESSAGE;
ucs->dr_cmd_in.wValue = 0;
@@ -628,13 +601,12 @@ static void read_int_callback(struct urb *urb)
struct cardstate *cs = urb->context;
struct bas_cardstate *ucs = cs->hw.bas;
struct bc_state *bcs;
- int status = urb->status;
unsigned long flags;
int rc;
unsigned l;
int channel;
- switch (status) {
+ switch (urb->status) {
case 0: /* success */
break;
case -ENOENT: /* cancelled */
@@ -642,7 +614,7 @@ static void read_int_callback(struct urb *urb)
case -EINPROGRESS: /* pending */
/* ignore silently */
gig_dbg(DEBUG_USBREQ, "%s: %s",
- __func__, get_usb_statmsg(status));
+ __func__, get_usb_statmsg(urb->status));
return;
case -ENODEV: /* device removed */
case -ESHUTDOWN: /* device shut down */
@@ -651,7 +623,7 @@ static void read_int_callback(struct urb *urb)
return;
default: /* severe trouble */
dev_warn(cs->dev, "interrupt read: %s\n",
- get_usb_statmsg(status));
+ get_usb_statmsg(urb->status));
//FIXME corrective action? resubmission always ok?
goto resubmit;
}
@@ -773,7 +745,6 @@ static void read_int_callback(struct urb *urb)
}
check_pending(ucs);
- wake_up(&ucs->waitqueue);
resubmit:
rc = usb_submit_urb(urb, GFP_ATOMIC);
@@ -795,18 +766,17 @@ static void read_iso_callback(struct urb *urb)
{
struct bc_state *bcs;
struct bas_bc_state *ubc;
- int status = urb->status;
unsigned long flags;
int i, rc;
/* status codes not worth bothering the tasklet with */
- if (unlikely(status == -ENOENT ||
- status == -ECONNRESET ||
- status == -EINPROGRESS ||
- status == -ENODEV ||
- status == -ESHUTDOWN)) {
+ if (unlikely(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -EINPROGRESS ||
+ urb->status == -ENODEV ||
+ urb->status == -ESHUTDOWN)) {
gig_dbg(DEBUG_ISO, "%s: %s",
- __func__, get_usb_statmsg(status));
+ __func__, get_usb_statmsg(urb->status));
return;
}
@@ -817,11 +787,10 @@ static void read_iso_callback(struct urb *urb)
if (likely(ubc->isoindone == NULL)) {
/* pass URB to tasklet */
ubc->isoindone = urb;
- ubc->isoinstatus = status;
tasklet_schedule(&ubc->rcvd_tasklet);
} else {
/* tasklet still busy, drop data and resubmit URB */
- ubc->loststatus = status;
+ ubc->loststatus = urb->status;
for (i = 0; i < BAS_NUMFRAMES; i++) {
ubc->isoinlost += urb->iso_frame_desc[i].actual_length;
if (unlikely(urb->iso_frame_desc[i].status != 0 &&
@@ -831,7 +800,7 @@ static void read_iso_callback(struct urb *urb)
urb->iso_frame_desc[i].status = 0;
urb->iso_frame_desc[i].actual_length = 0;
}
- if (likely(ubc->running)) {
+ if (likely(atomic_read(&ubc->running))) {
/* urb->dev is clobbered by USB subsystem */
urb->dev = bcs->cs->hw.bas->udev;
urb->transfer_flags = URB_ISO_ASAP;
@@ -862,24 +831,22 @@ static void write_iso_callback(struct urb *urb)
{
struct isow_urbctx_t *ucx;
struct bas_bc_state *ubc;
- int status = urb->status;
unsigned long flags;
/* status codes not worth bothering the tasklet with */
- if (unlikely(status == -ENOENT ||
- status == -ECONNRESET ||
- status == -EINPROGRESS ||
- status == -ENODEV ||
- status == -ESHUTDOWN)) {
+ if (unlikely(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -EINPROGRESS ||
+ urb->status == -ENODEV ||
+ urb->status == -ESHUTDOWN)) {
gig_dbg(DEBUG_ISO, "%s: %s",
- __func__, get_usb_statmsg(status));
+ __func__, get_usb_statmsg(urb->status));
return;
}
/* pass URB context to tasklet */
ucx = urb->context;
ubc = ucx->bcs->hw.bas;
- ucx->status = status;
spin_lock_irqsave(&ubc->isooutlock, flags);
ubc->isooutovfl = ubc->isooutdone;
@@ -908,7 +875,7 @@ static int starturbs(struct bc_state *bcs)
bcs->inputstate |= INS_flag_hunt;
/* submit all isochronous input URBs */
- ubc->running = 1;
+ atomic_set(&ubc->running, 1);
for (k = 0; k < BAS_INURBS; k++) {
urb = ubc->isoinurbs[k];
if (!urb) {
@@ -965,15 +932,15 @@ static int starturbs(struct bc_state *bcs)
ubc->isoouturbs[k].limit = -1;
}
- /* keep one URB free, submit the others */
- for (k = 0; k < BAS_OUTURBS-1; ++k) {
+ /* submit two URBs, keep third one */
+ for (k = 0; k < 2; ++k) {
dump_urb(DEBUG_ISO, "Initial isoc write", urb);
rc = usb_submit_urb(ubc->isoouturbs[k].urb, GFP_ATOMIC);
if (rc != 0)
goto error;
}
dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb);
- ubc->isooutfree = &ubc->isoouturbs[BAS_OUTURBS-1];
+ ubc->isooutfree = &ubc->isoouturbs[2];
ubc->isooutdone = ubc->isooutovfl = NULL;
return 0;
error:
@@ -991,7 +958,7 @@ static void stopurbs(struct bas_bc_state *ubc)
{
int k, rc;
- ubc->running = 0;
+ atomic_set(&ubc->running, 0);
for (k = 0; k < BAS_INURBS; ++k) {
rc = usb_unlink_urb(ubc->isoinurbs[k]);
@@ -1067,7 +1034,7 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
}
break;
}
- ucx->limit = ubc->isooutbuf->nextread;
+ ucx->limit = atomic_read(&ubc->isooutbuf->nextread);
ifd->status = 0;
ifd->actual_length = 0;
}
@@ -1103,7 +1070,6 @@ static void write_iso_tasklet(unsigned long data)
struct cardstate *cs = bcs->cs;
struct isow_urbctx_t *done, *next, *ovfl;
struct urb *urb;
- int status;
struct usb_iso_packet_descriptor *ifd;
int offset;
unsigned long flags;
@@ -1114,7 +1080,7 @@ static void write_iso_tasklet(unsigned long data)
/* loop while completed URBs arrive in time */
for (;;) {
- if (unlikely(!(ubc->running))) {
+ if (unlikely(!(atomic_read(&ubc->running)))) {
gig_dbg(DEBUG_ISO, "%s: not running", __func__);
return;
}
@@ -1160,8 +1126,7 @@ static void write_iso_tasklet(unsigned long data)
/* process completed URB */
urb = done->urb;
- status = done->status;
- switch (status) {
+ switch (urb->status) {
case -EXDEV: /* partial completion */
gig_dbg(DEBUG_ISO, "%s: URB partially completed",
__func__);
@@ -1214,12 +1179,12 @@ static void write_iso_tasklet(unsigned long data)
break;
default: /* severe trouble */
dev_warn(cs->dev, "isochronous write: %s\n",
- get_usb_statmsg(status));
+ get_usb_statmsg(urb->status));
}
/* mark the write buffer area covered by this URB as free */
if (done->limit >= 0)
- ubc->isooutbuf->read = done->limit;
+ atomic_set(&ubc->isooutbuf->read, done->limit);
/* mark URB as free */
spin_lock_irqsave(&ubc->isooutlock, flags);
@@ -1268,7 +1233,6 @@ static void read_iso_tasklet(unsigned long data)
struct bas_bc_state *ubc = bcs->hw.bas;
struct cardstate *cs = bcs->cs;
struct urb *urb;
- int status;
char *rcvbuf;
unsigned long flags;
int totleft, numbytes, offset, frame, rc;
@@ -1281,7 +1245,6 @@ static void read_iso_tasklet(unsigned long data)
spin_unlock_irqrestore(&ubc->isoinlock, flags);
return;
}
- status = ubc->isoinstatus;
ubc->isoindone = NULL;
if (unlikely(ubc->loststatus != -EINPROGRESS)) {
dev_warn(cs->dev,
@@ -1293,15 +1256,15 @@ static void read_iso_tasklet(unsigned long data)
}
spin_unlock_irqrestore(&ubc->isoinlock, flags);
- if (unlikely(!(ubc->running))) {
+ if (unlikely(!(atomic_read(&ubc->running)))) {
gig_dbg(DEBUG_ISO,
"%s: channel not running, "
"dropped URB with status: %s",
- __func__, get_usb_statmsg(status));
+ __func__, get_usb_statmsg(urb->status));
return;
}
- switch (status) {
+ switch (urb->status) {
case 0: /* normal completion */
break;
case -EXDEV: /* inspect individual frames
@@ -1313,7 +1276,7 @@ static void read_iso_tasklet(unsigned long data)
case -ECONNRESET:
case -EINPROGRESS:
gig_dbg(DEBUG_ISO, "%s: %s",
- __func__, get_usb_statmsg(status));
+ __func__, get_usb_statmsg(urb->status));
continue; /* -> skip */
case -EPIPE:
dev_err(cs->dev, "isochronous read stalled\n");
@@ -1321,7 +1284,7 @@ static void read_iso_tasklet(unsigned long data)
continue; /* -> skip */
default: /* severe trouble */
dev_warn(cs->dev, "isochronous read: %s\n",
- get_usb_statmsg(status));
+ get_usb_statmsg(urb->status));
goto error;
}
@@ -1443,8 +1406,6 @@ static void req_timeout(unsigned long data)
dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n",
pending);
}
-
- wake_up(&ucs->waitqueue);
}
/* write_ctrl_callback
@@ -1457,12 +1418,11 @@ static void req_timeout(unsigned long data)
static void write_ctrl_callback(struct urb *urb)
{
struct bas_cardstate *ucs = urb->context;
- int status = urb->status;
int rc;
unsigned long flags;
/* check status */
- switch (status) {
+ switch (urb->status) {
case 0: /* normal completion */
spin_lock_irqsave(&ucs->lock, flags);
switch (ucs->pending) {
@@ -1481,22 +1441,20 @@ static void write_ctrl_callback(struct urb *urb)
case -ESHUTDOWN: /* device shut down */
/* ignore silently */
gig_dbg(DEBUG_USBREQ, "%s: %s",
- __func__, get_usb_statmsg(status));
+ __func__, get_usb_statmsg(urb->status));
break;
default: /* any failure */
- /* don't retry if suspend requested */
- if (++ucs->retry_ctrl > BAS_RETRY ||
- (ucs->basstate & BS_SUSPEND)) {
+ if (++ucs->retry_ctrl > BAS_RETRY) {
dev_err(&ucs->interface->dev,
"control request 0x%02x failed: %s\n",
ucs->dr_ctrl.bRequest,
- get_usb_statmsg(status));
+ get_usb_statmsg(urb->status));
break; /* give up */
}
dev_notice(&ucs->interface->dev,
"control request 0x%02x: %s, retry %d\n",
- ucs->dr_ctrl.bRequest, get_usb_statmsg(status),
+ ucs->dr_ctrl.bRequest, get_usb_statmsg(urb->status),
ucs->retry_ctrl);
/* urb->dev is clobbered by USB subsystem */
urb->dev = ucs->udev;
@@ -1516,7 +1474,6 @@ static void write_ctrl_callback(struct urb *urb)
del_timer(&ucs->timer_ctrl);
ucs->pending = 0;
spin_unlock_irqrestore(&ucs->lock, flags);
- wake_up(&ucs->waitqueue);
}
/* req_submit
@@ -1591,46 +1548,37 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout)
*/
static int gigaset_init_bchannel(struct bc_state *bcs)
{
- struct cardstate *cs = bcs->cs;
int req, ret;
unsigned long flags;
- spin_lock_irqsave(&cs->lock, flags);
- if (unlikely(!cs->connected)) {
+ spin_lock_irqsave(&bcs->cs->lock, flags);
+ if (unlikely(!bcs->cs->connected)) {
gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
- spin_unlock_irqrestore(&cs->lock, flags);
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
return -ENODEV;
}
- if (cs->hw.bas->basstate & BS_SUSPEND) {
- dev_notice(cs->dev,
- "not starting isochronous I/O, "
- "suspend in progress\n");
- spin_unlock_irqrestore(&cs->lock, flags);
- return -EHOSTUNREACH;
- }
-
if ((ret = starturbs(bcs)) < 0) {
- dev_err(cs->dev,
+ dev_err(bcs->cs->dev,
"could not start isochronous I/O for channel B%d: %s\n",
bcs->channel + 1,
ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret));
if (ret != -ENODEV)
error_hangup(bcs);
- spin_unlock_irqrestore(&cs->lock, flags);
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
return ret;
}
req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL;
if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) {
- dev_err(cs->dev, "could not open channel B%d\n",
+ dev_err(bcs->cs->dev, "could not open channel B%d\n",
bcs->channel + 1);
stopurbs(bcs->hw.bas);
if (ret != -ENODEV)
error_hangup(bcs);
}
- spin_unlock_irqrestore(&cs->lock, flags);
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
return ret;
}
@@ -1646,20 +1594,20 @@ static int gigaset_init_bchannel(struct bc_state *bcs)
*/
static int gigaset_close_bchannel(struct bc_state *bcs)
{
- struct cardstate *cs = bcs->cs;
int req, ret;
unsigned long flags;
- spin_lock_irqsave(&cs->lock, flags);
- if (unlikely(!cs->connected)) {
- spin_unlock_irqrestore(&cs->lock, flags);
+ spin_lock_irqsave(&bcs->cs->lock, flags);
+ if (unlikely(!bcs->cs->connected)) {
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
return -ENODEV;
}
- if (!(cs->hw.bas->basstate & (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) {
+ if (!(atomic_read(&bcs->cs->hw.bas->basstate) &
+ (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) {
/* channel not running: just signal common.c */
- spin_unlock_irqrestore(&cs->lock, flags);
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
gigaset_bchannel_down(bcs);
return 0;
}
@@ -1667,10 +1615,10 @@ static int gigaset_close_bchannel(struct bc_state *bcs)
/* channel running: tell device to close it */
req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL;
if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0)
- dev_err(cs->dev, "closing channel B%d failed\n",
+ dev_err(bcs->cs->dev, "closing channel B%d failed\n",
bcs->channel + 1);
- spin_unlock_irqrestore(&cs->lock, flags);
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
return ret;
}
@@ -1717,14 +1665,12 @@ static void write_command_callback(struct urb *urb)
{
struct cardstate *cs = urb->context;
struct bas_cardstate *ucs = cs->hw.bas;
- int status = urb->status;
unsigned long flags;
update_basstate(ucs, 0, BS_ATWRPEND);
- wake_up(&ucs->waitqueue);
/* check status */
- switch (status) {
+ switch (urb->status) {
case 0: /* normal completion */
break;
case -ENOENT: /* cancelled */
@@ -1734,33 +1680,26 @@ static void write_command_callback(struct urb *urb)
case -ESHUTDOWN: /* device shut down */
/* ignore silently */
gig_dbg(DEBUG_USBREQ, "%s: %s",
- __func__, get_usb_statmsg(status));
+ __func__, get_usb_statmsg(urb->status));
return;
default: /* any failure */
if (++ucs->retry_cmd_out > BAS_RETRY) {
dev_warn(cs->dev,
"command write: %s, "
"giving up after %d retries\n",
- get_usb_statmsg(status),
+ get_usb_statmsg(urb->status),
ucs->retry_cmd_out);
break;
}
- if (ucs->basstate & BS_SUSPEND) {
- dev_warn(cs->dev,
- "command write: %s, "
- "won't retry - suspend requested\n",
- get_usb_statmsg(status));
- break;
- }
if (cs->cmdbuf == NULL) {
dev_warn(cs->dev,
"command write: %s, "
"cannot retry - cmdbuf gone\n",
- get_usb_statmsg(status));
+ get_usb_statmsg(urb->status));
break;
}
dev_notice(cs->dev, "command write: %s, retry %d\n",
- get_usb_statmsg(status), ucs->retry_cmd_out);
+ get_usb_statmsg(urb->status), ucs->retry_cmd_out);
if (atwrite_submit(cs, cs->cmdbuf->buf, cs->cmdbuf->len) >= 0)
/* resubmitted - bypass regular exit block */
return;
@@ -1860,14 +1799,8 @@ static int start_cbsend(struct cardstate *cs)
int rc;
int retval = 0;
- /* check if suspend requested */
- if (ucs->basstate & BS_SUSPEND) {
- gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "suspending");
- return -EHOSTUNREACH;
- }
-
/* check if AT channel is open */
- if (!(ucs->basstate & BS_ATOPEN)) {
+ if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) {
gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open");
rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT);
if (rc < 0) {
@@ -1883,7 +1816,8 @@ static int start_cbsend(struct cardstate *cs)
/* try to send first command in queue */
spin_lock_irqsave(&cs->cmdlock, flags);
- while ((cb = cs->cmdbuf) != NULL && (ucs->basstate & BS_ATREADY)) {
+ while ((cb = cs->cmdbuf) != NULL &&
+ atomic_read(&ucs->basstate) & BS_ATREADY) {
ucs->retry_cmd_out = 0;
rc = atwrite_submit(cs, cb->buf, cb->len);
if (unlikely(rc)) {
@@ -1921,7 +1855,7 @@ static int gigaset_write_cmd(struct cardstate *cs,
unsigned long flags;
int rc;
- gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
+ gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
DEBUG_TRANSCMD : DEBUG_LOCKCMD,
"CMD Transmit", len, buf);
@@ -2036,7 +1970,7 @@ static int gigaset_freebcshw(struct bc_state *bcs)
return 0;
/* kill URBs and tasklets before freeing - better safe than sorry */
- ubc->running = 0;
+ atomic_set(&ubc->running, 0);
gig_dbg(DEBUG_INIT, "%s: killing iso URBs", __func__);
for (i = 0; i < BAS_OUTURBS; ++i) {
usb_kill_urb(ubc->isoouturbs[i].urb);
@@ -2071,7 +2005,7 @@ static int gigaset_initbcshw(struct bc_state *bcs)
return 0;
}
- ubc->running = 0;
+ atomic_set(&ubc->running, 0);
atomic_set(&ubc->corrbytes, 0);
spin_lock_init(&ubc->isooutlock);
for (i = 0; i < BAS_OUTURBS; ++i) {
@@ -2116,7 +2050,7 @@ static void gigaset_reinitbcshw(struct bc_state *bcs)
{
struct bas_bc_state *ubc = bcs->hw.bas;
- bcs->hw.bas->running = 0;
+ atomic_set(&bcs->hw.bas->running, 0);
atomic_set(&bcs->hw.bas->corrbytes, 0);
bcs->hw.bas->numsub = 0;
spin_lock_init(&ubc->isooutlock);
@@ -2147,11 +2081,10 @@ static int gigaset_initcshw(struct cardstate *cs)
spin_lock_init(&ucs->lock);
ucs->pending = 0;
- ucs->basstate = 0;
+ atomic_set(&ucs->basstate, 0);
init_timer(&ucs->timer_ctrl);
init_timer(&ucs->timer_atrdy);
init_timer(&ucs->timer_cmd_in);
- init_waitqueue_head(&ucs->waitqueue);
return 1;
}
@@ -2169,7 +2102,7 @@ static void freeurbs(struct cardstate *cs)
int i, j;
gig_dbg(DEBUG_INIT, "%s: killing URBs", __func__);
- for (j = 0; j < BAS_CHANNELS; ++j) {
+ for (j = 0; j < 2; ++j) {
ubc = cs->bcs[j].hw.bas;
for (i = 0; i < BAS_OUTURBS; ++i) {
usb_kill_urb(ubc->isoouturbs[i].urb);
@@ -2246,11 +2179,11 @@ static int gigaset_probe(struct usb_interface *interface,
__func__, le16_to_cpu(udev->descriptor.idVendor),
le16_to_cpu(udev->descriptor.idProduct));
- /* allocate memory for our device state and intialize it */
- cs = gigaset_initcs(driver, BAS_CHANNELS, 0, 0, cidmode,
- GIGASET_MODULENAME);
- if (!cs)
+ cs = gigaset_getunassignedcs(driver);
+ if (!cs) {
+ dev_err(&udev->dev, "no free cardstate\n");
return -ENODEV;
+ }
ucs = cs->hw.bas;
/* save off device structure ptrs for later use */
@@ -2270,7 +2203,7 @@ static int gigaset_probe(struct usb_interface *interface,
!(ucs->urb_ctrl = usb_alloc_urb(0, GFP_KERNEL)))
goto allocerr;
- for (j = 0; j < BAS_CHANNELS; ++j) {
+ for (j = 0; j < 2; ++j) {
ubc = cs->bcs[j].hw.bas;
for (i = 0; i < BAS_OUTURBS; ++i)
if (!(ubc->isoouturbs[i].urb =
@@ -2304,7 +2237,7 @@ static int gigaset_probe(struct usb_interface *interface,
/* tell common part that the device is ready */
if (startmode == SM_LOCKED)
- cs->mstate = MS_LOCKED;
+ atomic_set(&cs->mstate, MS_LOCKED);
/* save address of controller structure */
usb_set_intfdata(interface, cs);
@@ -2319,7 +2252,7 @@ static int gigaset_probe(struct usb_interface *interface,
error:
freeurbs(cs);
usb_set_intfdata(interface, NULL);
- gigaset_freecs(cs);
+ gigaset_unassign(cs);
return -ENODEV;
}
@@ -2339,10 +2272,11 @@ static void gigaset_disconnect(struct usb_interface *interface)
dev_info(cs->dev, "disconnecting Gigaset base\n");
/* mark base as not ready, all channels disconnected */
- ucs->basstate = 0;
+ atomic_set(&ucs->basstate, 0);
/* tell LL all channels are down */
- for (j = 0; j < BAS_CHANNELS; ++j)
+ //FIXME shouldn't gigaset_stop() do this?
+ for (j = 0; j < 2; ++j)
gigaset_bchannel_down(cs->bcs + j);
/* stop driver (common part) */
@@ -2361,113 +2295,9 @@ static void gigaset_disconnect(struct usb_interface *interface)
ucs->interface = NULL;
ucs->udev = NULL;
cs->dev = NULL;
- gigaset_freecs(cs);
+ gigaset_unassign(cs);
}
-/* gigaset_suspend
- * This function is called before the USB connection is suspended.
- */
-static int gigaset_suspend(struct usb_interface *intf, pm_message_t message)
-{
- struct cardstate *cs = usb_get_intfdata(intf);
- struct bas_cardstate *ucs = cs->hw.bas;
- int rc;
-
- /* set suspend flag; this stops AT command/response traffic */
- if (update_basstate(ucs, BS_SUSPEND, 0) & BS_SUSPEND) {
- gig_dbg(DEBUG_SUSPEND, "already suspended");
- return 0;
- }
-
- /* wait a bit for blocking conditions to go away */
- rc = wait_event_timeout(ucs->waitqueue,
- !(ucs->basstate &
- (BS_B1OPEN|BS_B2OPEN|BS_ATRDPEND|BS_ATWRPEND)),
- BAS_TIMEOUT*HZ/10);
- gig_dbg(DEBUG_SUSPEND, "wait_event_timeout() -> %d", rc);
-
- /* check for conditions preventing suspend */
- if (ucs->basstate & (BS_B1OPEN|BS_B2OPEN|BS_ATRDPEND|BS_ATWRPEND)) {
- dev_warn(cs->dev, "cannot suspend:\n");
- if (ucs->basstate & BS_B1OPEN)
- dev_warn(cs->dev, " B channel 1 open\n");
- if (ucs->basstate & BS_B2OPEN)
- dev_warn(cs->dev, " B channel 2 open\n");
- if (ucs->basstate & BS_ATRDPEND)
- dev_warn(cs->dev, " receiving AT reply\n");
- if (ucs->basstate & BS_ATWRPEND)
- dev_warn(cs->dev, " sending AT command\n");
- update_basstate(ucs, 0, BS_SUSPEND);
- return -EBUSY;
- }
-
- /* close AT channel if open */
- if (ucs->basstate & BS_ATOPEN) {
- gig_dbg(DEBUG_SUSPEND, "closing AT channel");
- rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, 0);
- if (rc) {
- update_basstate(ucs, 0, BS_SUSPEND);
- return rc;
- }
- wait_event_timeout(ucs->waitqueue, !ucs->pending,
- BAS_TIMEOUT*HZ/10);
- /* in case of timeout, proceed anyway */
- }
-
- /* kill all URBs and timers that might still be pending */
- usb_kill_urb(ucs->urb_ctrl);
- usb_kill_urb(ucs->urb_int_in);
- del_timer_sync(&ucs->timer_ctrl);
-
- gig_dbg(DEBUG_SUSPEND, "suspend complete");
- return 0;
-}
-
-/* gigaset_resume
- * This function is called after the USB connection has been resumed.
- */
-static int gigaset_resume(struct usb_interface *intf)
-{
- struct cardstate *cs = usb_get_intfdata(intf);
- struct bas_cardstate *ucs = cs->hw.bas;
- int rc;
-
- /* resubmit interrupt URB for spontaneous messages from base */
- rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL);
- if (rc) {
- dev_err(cs->dev, "could not resubmit interrupt URB: %s\n",
- get_usb_rcmsg(rc));
- return rc;
- }
-
- /* clear suspend flag to reallow activity */
- update_basstate(ucs, 0, BS_SUSPEND);
-
- gig_dbg(DEBUG_SUSPEND, "resume complete");
- return 0;
-}
-
-/* gigaset_pre_reset
- * This function is called before the USB connection is reset.
- */
-static int gigaset_pre_reset(struct usb_interface *intf)
-{
- /* handle just like suspend */
- return gigaset_suspend(intf, PMSG_ON);
-}
-
-/* gigaset_post_reset
- * This function is called after the USB connection has been reset.
- */
-static int gigaset_post_reset(struct usb_interface *intf)
-{
- /* FIXME: send HD_DEVICE_INIT_ACK? */
-
- /* resume operations */
- return gigaset_resume(intf);
-}
-
-
static const struct gigaset_ops gigops = {
gigaset_write_cmd,
gigaset_write_room,
@@ -2500,6 +2330,12 @@ static int __init bas_gigaset_init(void)
&gigops, THIS_MODULE)) == NULL)
goto error;
+ /* allocate memory for our device state and intialize it */
+ cardstate = gigaset_initcs(driver, 2, 0, 0, cidmode,
+ GIGASET_MODULENAME);
+ if (!cardstate)
+ goto error;
+
/* register this driver with the USB subsystem */
result = usb_register(&gigaset_usb_driver);
if (result < 0) {
@@ -2511,7 +2347,9 @@ static int __init bas_gigaset_init(void)
info(DRIVER_DESC);
return 0;
-error:
+error: if (cardstate)
+ gigaset_freecs(cardstate);
+ cardstate = NULL;
if (driver)
gigaset_freedriver(driver);
driver = NULL;
@@ -2523,50 +2361,43 @@ static int __init bas_gigaset_init(void)
*/
static void __exit bas_gigaset_exit(void)
{
- struct bas_cardstate *ucs;
- int i;
+ struct bas_cardstate *ucs = cardstate->hw.bas;
gigaset_blockdriver(driver); /* => probe will fail
* => no gigaset_start any more
*/
- /* stop all connected devices */
- for (i = 0; i < driver->minors; i++) {
- if (gigaset_shutdown(driver->cs + i) < 0)
- continue; /* no device */
- /* from now on, no isdn callback should be possible */
-
- /* close all still open channels */
- ucs = driver->cs[i].hw.bas;
- if (ucs->basstate & BS_B1OPEN) {
- gig_dbg(DEBUG_INIT, "closing B1 channel");
- usb_control_msg(ucs->udev,
- usb_sndctrlpipe(ucs->udev, 0),
- HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ,
- 0, 0, NULL, 0, BAS_TIMEOUT);
- }
- if (ucs->basstate & BS_B2OPEN) {
- gig_dbg(DEBUG_INIT, "closing B2 channel");
- usb_control_msg(ucs->udev,
- usb_sndctrlpipe(ucs->udev, 0),
- HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ,
- 0, 0, NULL, 0, BAS_TIMEOUT);
- }
- if (ucs->basstate & BS_ATOPEN) {
- gig_dbg(DEBUG_INIT, "closing AT channel");
- usb_control_msg(ucs->udev,
- usb_sndctrlpipe(ucs->udev, 0),
- HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ,
- 0, 0, NULL, 0, BAS_TIMEOUT);
- }
- ucs->basstate = 0;
+ gigaset_shutdown(cardstate);
+ /* from now on, no isdn callback should be possible */
+
+ /* close all still open channels */
+ if (atomic_read(&ucs->basstate) & BS_B1OPEN) {
+ gig_dbg(DEBUG_INIT, "closing B1 channel");
+ usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0),
+ HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, 0, 0,
+ NULL, 0, BAS_TIMEOUT);
+ }
+ if (atomic_read(&ucs->basstate) & BS_B2OPEN) {
+ gig_dbg(DEBUG_INIT, "closing B2 channel");
+ usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0),
+ HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, 0, 0,
+ NULL, 0, BAS_TIMEOUT);
+ }
+ if (atomic_read(&ucs->basstate) & BS_ATOPEN) {
+ gig_dbg(DEBUG_INIT, "closing AT channel");
+ usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0),
+ HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, 0, 0,
+ NULL, 0, BAS_TIMEOUT);
}
+ atomic_set(&ucs->basstate, 0);
/* deregister this driver with the USB subsystem */
usb_deregister(&gigaset_usb_driver);
/* this will call the disconnect-callback */
/* from now on, no disconnect/probe callback should be running */
+ gigaset_freecs(cardstate);
+ cardstate = NULL;
gigaset_freedriver(driver);
driver = NULL;
}
diff --git a/trunk/drivers/isdn/gigaset/common.c b/trunk/drivers/isdn/gigaset/common.c
index aacedec4986f..acd417197d03 100644
--- a/trunk/drivers/isdn/gigaset/common.c
+++ b/trunk/drivers/isdn/gigaset/common.c
@@ -31,6 +31,7 @@ MODULE_PARM_DESC(debug, "debug level");
/* driver state flags */
#define VALID_MINOR 0x01
#define VALID_ID 0x02
+#define ASSIGNED 0x04
void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
size_t len, const unsigned char *buf)
@@ -177,7 +178,7 @@ int gigaset_get_channel(struct bc_state *bcs)
unsigned long flags;
spin_lock_irqsave(&bcs->cs->lock, flags);
- if (bcs->use_count || !try_module_get(bcs->cs->driver->owner)) {
+ if (bcs->use_count) {
gig_dbg(DEBUG_ANY, "could not allocate channel %d",
bcs->channel);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
@@ -202,7 +203,6 @@ void gigaset_free_channel(struct bc_state *bcs)
}
--bcs->use_count;
bcs->busy = 0;
- module_put(bcs->cs->driver->owner);
gig_dbg(DEBUG_ANY, "freed channel %d", bcs->channel);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
}
@@ -356,28 +356,31 @@ static struct cardstate *alloc_cs(struct gigaset_driver *drv)
{
unsigned long flags;
unsigned i;
- struct cardstate *cs;
struct cardstate *ret = NULL;
spin_lock_irqsave(&drv->lock, flags);
- if (drv->blocked)
- goto exit;
for (i = 0; i < drv->minors; ++i) {
- cs = drv->cs + i;
- if (!(cs->flags & VALID_MINOR)) {
- cs->flags = VALID_MINOR;
- ret = cs;
+ if (!(drv->flags[i] & VALID_MINOR)) {
+ if (try_module_get(drv->owner)) {
+ drv->flags[i] = VALID_MINOR;
+ ret = drv->cs + i;
+ }
break;
}
}
-exit:
spin_unlock_irqrestore(&drv->lock, flags);
return ret;
}
static void free_cs(struct cardstate *cs)
{
- cs->flags = 0;
+ unsigned long flags;
+ struct gigaset_driver *drv = cs->driver;
+ spin_lock_irqsave(&drv->lock, flags);
+ if (drv->flags[cs->minor_index] & VALID_MINOR)
+ module_put(drv->owner);
+ drv->flags[cs->minor_index] = 0;
+ spin_unlock_irqrestore(&drv->lock, flags);
}
static void make_valid(struct cardstate *cs, unsigned mask)
@@ -385,7 +388,7 @@ static void make_valid(struct cardstate *cs, unsigned mask)
unsigned long flags;
struct gigaset_driver *drv = cs->driver;
spin_lock_irqsave(&drv->lock, flags);
- cs->flags |= mask;
+ drv->flags[cs->minor_index] |= mask;
spin_unlock_irqrestore(&drv->lock, flags);
}
@@ -394,7 +397,7 @@ static void make_invalid(struct cardstate *cs, unsigned mask)
unsigned long flags;
struct gigaset_driver *drv = cs->driver;
spin_lock_irqsave(&drv->lock, flags);
- cs->flags &= ~mask;
+ drv->flags[cs->minor_index] &= ~mask;
spin_unlock_irqrestore(&drv->lock, flags);
}
@@ -498,11 +501,11 @@ static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs,
struct cardstate *cs, int inputstate)
/* inbuf->read must be allocated before! */
{
- inbuf->head = 0;
- inbuf->tail = 0;
+ atomic_set(&inbuf->head, 0);
+ atomic_set(&inbuf->tail, 0);
inbuf->cs = cs;
inbuf->bcs = bcs; /*base driver: NULL*/
- inbuf->rcvbuf = NULL;
+ inbuf->rcvbuf = NULL; //FIXME
inbuf->inputstate = inputstate;
}
@@ -518,8 +521,8 @@ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
return 0;
bytesleft = numbytes;
- tail = inbuf->tail;
- head = inbuf->head;
+ tail = atomic_read(&inbuf->tail);
+ head = atomic_read(&inbuf->head);
gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
while (bytesleft) {
@@ -543,7 +546,7 @@ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
src += n;
}
gig_dbg(DEBUG_INTR, "setting tail to %u", tail);
- inbuf->tail = tail;
+ atomic_set(&inbuf->tail, tail);
return numbytes != bytesleft;
}
EXPORT_SYMBOL_GPL(gigaset_fill_inbuf);
@@ -665,7 +668,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
tasklet_init(&cs->event_tasklet, &gigaset_handle_event,
(unsigned long) cs);
- cs->commands_pending = 0;
+ atomic_set(&cs->commands_pending, 0);
cs->cur_at_seq = 0;
cs->gotfwver = -1;
cs->open_count = 0;
@@ -685,8 +688,8 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
init_waitqueue_head(&cs->waitqueue);
cs->waiting = 0;
- cs->mode = M_UNKNOWN;
- cs->mstate = MS_UNINITIALIZED;
+ atomic_set(&cs->mode, M_UNKNOWN);
+ atomic_set(&cs->mstate, MS_UNINITIALIZED);
for (i = 0; i < channels; ++i) {
gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i);
@@ -803,8 +806,8 @@ static void cleanup_cs(struct cardstate *cs)
spin_lock_irqsave(&cs->lock, flags);
- cs->mode = M_UNKNOWN;
- cs->mstate = MS_UNINITIALIZED;
+ atomic_set(&cs->mode, M_UNKNOWN);
+ atomic_set(&cs->mstate, MS_UNINITIALIZED);
clear_at_state(&cs->at_state);
dealloc_at_states(cs);
@@ -814,8 +817,8 @@ static void cleanup_cs(struct cardstate *cs)
kfree(cs->inbuf->rcvbuf);
cs->inbuf->rcvbuf = NULL;
cs->inbuf->inputstate = INS_command;
- cs->inbuf->head = 0;
- cs->inbuf->tail = 0;
+ atomic_set(&cs->inbuf->head, 0);
+ atomic_set(&cs->inbuf->tail, 0);
cb = cs->cmdbuf;
while (cb) {
@@ -829,7 +832,7 @@ static void cleanup_cs(struct cardstate *cs)
cs->gotfwver = -1;
cs->dle = 0;
cs->cur_at_seq = 0;
- cs->commands_pending = 0;
+ atomic_set(&cs->commands_pending, 0);
cs->cbytes = 0;
spin_unlock_irqrestore(&cs->lock, flags);
@@ -859,7 +862,7 @@ int gigaset_start(struct cardstate *cs)
cs->connected = 1;
spin_unlock_irqrestore(&cs->lock, flags);
- if (cs->mstate != MS_LOCKED) {
+ if (atomic_read(&cs->mstate) != MS_LOCKED) {
cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS);
cs->ops->baud_rate(cs, B115200);
cs->ops->set_line_ctrl(cs, CS8);
@@ -890,17 +893,10 @@ int gigaset_start(struct cardstate *cs)
}
EXPORT_SYMBOL_GPL(gigaset_start);
-/* gigaset_shutdown
- * check if a device is associated to the cardstate structure and stop it
- * return value: 0 if ok, -1 if no device was associated
- */
-int gigaset_shutdown(struct cardstate *cs)
+void gigaset_shutdown(struct cardstate *cs)
{
mutex_lock(&cs->mutex);
- if (!(cs->flags & VALID_MINOR))
- return -1;
-
cs->waiting = 1;
if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) {
@@ -917,7 +913,6 @@ int gigaset_shutdown(struct cardstate *cs)
exit:
mutex_unlock(&cs->mutex);
- return 0;
}
EXPORT_SYMBOL_GPL(gigaset_shutdown);
@@ -959,11 +954,13 @@ struct cardstate *gigaset_get_cs_by_id(int id)
list_for_each_entry(drv, &drivers, list) {
spin_lock(&drv->lock);
for (i = 0; i < drv->minors; ++i) {
- cs = drv->cs + i;
- if ((cs->flags & VALID_ID) && cs->myid == id) {
- ret = cs;
- break;
+ if (drv->flags[i] & VALID_ID) {
+ cs = drv->cs + i;
+ if (cs->myid == id)
+ ret = cs;
}
+ if (ret)
+ break;
}
spin_unlock(&drv->lock);
if (ret)
@@ -986,9 +983,10 @@ void gigaset_debugdrivers(void)
spin_lock(&drv->lock);
for (i = 0; i < drv->minors; ++i) {
gig_dbg(DEBUG_DRIVER, " index %u", i);
+ gig_dbg(DEBUG_DRIVER, " flags 0x%02x",
+ drv->flags[i]);
cs = drv->cs + i;
gig_dbg(DEBUG_DRIVER, " cardstate %p", cs);
- gig_dbg(DEBUG_DRIVER, " flags 0x%02x", cs->flags);
gig_dbg(DEBUG_DRIVER, " minor_index %u",
cs->minor_index);
gig_dbg(DEBUG_DRIVER, " driver %p", cs->driver);
@@ -1012,7 +1010,7 @@ static struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
continue;
index = minor - drv->minor;
spin_lock(&drv->lock);
- if (drv->cs[index].flags & VALID_MINOR)
+ if (drv->flags[index] & VALID_MINOR)
ret = drv->cs + index;
spin_unlock(&drv->lock);
if (ret)
@@ -1040,6 +1038,7 @@ void gigaset_freedriver(struct gigaset_driver *drv)
gigaset_if_freedriver(drv);
kfree(drv->cs);
+ kfree(drv->flags);
kfree(drv);
}
EXPORT_SYMBOL_GPL(gigaset_freedriver);
@@ -1081,8 +1080,12 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
if (!drv->cs)
goto error;
+ drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL);
+ if (!drv->flags)
+ goto error;
+
for (i = 0; i < minors; ++i) {
- drv->cs[i].flags = 0;
+ drv->flags[i] = 0;
drv->cs[i].driver = drv;
drv->cs[i].ops = drv->ops;
drv->cs[i].minor_index = i;
@@ -1103,9 +1106,53 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
}
EXPORT_SYMBOL_GPL(gigaset_initdriver);
+/* For drivers without fixed assignment device<->cardstate (usb) */
+struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv)
+{
+ unsigned long flags;
+ struct cardstate *cs = NULL;
+ unsigned i;
+
+ spin_lock_irqsave(&drv->lock, flags);
+ if (drv->blocked)
+ goto exit;
+ for (i = 0; i < drv->minors; ++i) {
+ if ((drv->flags[i] & VALID_MINOR) &&
+ !(drv->flags[i] & ASSIGNED)) {
+ drv->flags[i] |= ASSIGNED;
+ cs = drv->cs + i;
+ break;
+ }
+ }
+exit:
+ spin_unlock_irqrestore(&drv->lock, flags);
+ return cs;
+}
+EXPORT_SYMBOL_GPL(gigaset_getunassignedcs);
+
+void gigaset_unassign(struct cardstate *cs)
+{
+ unsigned long flags;
+ unsigned *minor_flags;
+ struct gigaset_driver *drv;
+
+ if (!cs)
+ return;
+ drv = cs->driver;
+ spin_lock_irqsave(&drv->lock, flags);
+ minor_flags = drv->flags + cs->minor_index;
+ if (*minor_flags & VALID_MINOR)
+ *minor_flags &= ~ASSIGNED;
+ spin_unlock_irqrestore(&drv->lock, flags);
+}
+EXPORT_SYMBOL_GPL(gigaset_unassign);
+
void gigaset_blockdriver(struct gigaset_driver *drv)
{
+ unsigned long flags;
+ spin_lock_irqsave(&drv->lock, flags);
drv->blocked = 1;
+ spin_unlock_irqrestore(&drv->lock, flags);
}
EXPORT_SYMBOL_GPL(gigaset_blockdriver);
diff --git a/trunk/drivers/isdn/gigaset/ev-layer.c b/trunk/drivers/isdn/gigaset/ev-layer.c
index 5cbf64d850ee..cec1ef342fcc 100644
--- a/trunk/drivers/isdn/gigaset/ev-layer.c
+++ b/trunk/drivers/isdn/gigaset/ev-layer.c
@@ -735,7 +735,7 @@ static void disconnect(struct at_state_t **at_state_p)
/* revert to selected idle mode */
if (!cs->cidmode) {
cs->at_state.pending_commands |= PC_UMMODE;
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1); //FIXME
gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
}
spin_unlock_irqrestore(&cs->lock, flags);
@@ -793,15 +793,15 @@ static void init_failed(struct cardstate *cs, int mode)
struct at_state_t *at_state;
cs->at_state.pending_commands &= ~PC_INIT;
- cs->mode = mode;
- cs->mstate = MS_UNINITIALIZED;
+ atomic_set(&cs->mode, mode);
+ atomic_set(&cs->mstate, MS_UNINITIALIZED);
gigaset_free_channels(cs);
for (i = 0; i < cs->channels; ++i) {
at_state = &cs->bcs[i].at_state;
if (at_state->pending_commands & PC_CID) {
at_state->pending_commands &= ~PC_CID;
at_state->pending_commands |= PC_NOCID;
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1);
}
}
}
@@ -812,11 +812,11 @@ static void schedule_init(struct cardstate *cs, int state)
gig_dbg(DEBUG_CMD, "not scheduling PC_INIT again");
return;
}
- cs->mstate = state;
- cs->mode = M_UNKNOWN;
+ atomic_set(&cs->mstate, state);
+ atomic_set(&cs->mode, M_UNKNOWN);
gigaset_block_channels(cs);
cs->at_state.pending_commands |= PC_INIT;
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1);
gig_dbg(DEBUG_CMD, "Scheduling PC_INIT");
}
@@ -953,13 +953,13 @@ static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_ind
at_state->pending_commands |= PC_CID;
gig_dbg(DEBUG_CMD, "Scheduling PC_CID");
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1);
return;
error:
at_state->pending_commands |= PC_NOCID;
gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID");
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1);
return;
}
@@ -973,12 +973,12 @@ static void start_accept(struct at_state_t *at_state)
if (retval == 0) {
at_state->pending_commands |= PC_ACCEPT;
gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT");
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1);
} else {
- /* error reset */
+ //FIXME
at_state->pending_commands |= PC_HUP;
gig_dbg(DEBUG_CMD, "Scheduling PC_HUP");
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1);
}
}
@@ -986,7 +986,7 @@ static void do_start(struct cardstate *cs)
{
gigaset_free_channels(cs);
- if (cs->mstate != MS_LOCKED)
+ if (atomic_read(&cs->mstate) != MS_LOCKED)
schedule_init(cs, MS_INIT);
cs->isdn_up = 1;
@@ -1000,9 +1000,9 @@ static void do_start(struct cardstate *cs)
static void finish_shutdown(struct cardstate *cs)
{
- if (cs->mstate != MS_LOCKED) {
- cs->mstate = MS_UNINITIALIZED;
- cs->mode = M_UNKNOWN;
+ if (atomic_read(&cs->mstate) != MS_LOCKED) {
+ atomic_set(&cs->mstate, MS_UNINITIALIZED);
+ atomic_set(&cs->mode, M_UNKNOWN);
}
/* Tell the LL that the device is not available .. */
@@ -1022,10 +1022,10 @@ static void do_shutdown(struct cardstate *cs)
{
gigaset_block_channels(cs);
- if (cs->mstate == MS_READY) {
- cs->mstate = MS_SHUTDOWN;
+ if (atomic_read(&cs->mstate) == MS_READY) {
+ atomic_set(&cs->mstate, MS_SHUTDOWN);
cs->at_state.pending_commands |= PC_SHUTDOWN;
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1);
gig_dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN");
} else
finish_shutdown(cs);
@@ -1120,7 +1120,7 @@ static void handle_icall(struct cardstate *cs, struct bc_state *bcs,
* In fact it doesn't.
*/
at_state->pending_commands |= PC_HUP;
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1);
break;
}
}
@@ -1130,7 +1130,7 @@ static int do_lock(struct cardstate *cs)
int mode;
int i;
- switch (cs->mstate) {
+ switch (atomic_read(&cs->mstate)) {
case MS_UNINITIALIZED:
case MS_READY:
if (cs->cur_at_seq || !list_empty(&cs->temp_at_states) ||
@@ -1152,20 +1152,20 @@ static int do_lock(struct cardstate *cs)
return -EBUSY;
}
- mode = cs->mode;
- cs->mstate = MS_LOCKED;
- cs->mode = M_UNKNOWN;
+ mode = atomic_read(&cs->mode);
+ atomic_set(&cs->mstate, MS_LOCKED);
+ atomic_set(&cs->mode, M_UNKNOWN);
return mode;
}
static int do_unlock(struct cardstate *cs)
{
- if (cs->mstate != MS_LOCKED)
+ if (atomic_read(&cs->mstate) != MS_LOCKED)
return -EINVAL;
- cs->mstate = MS_UNINITIALIZED;
- cs->mode = M_UNKNOWN;
+ atomic_set(&cs->mstate, MS_UNINITIALIZED);
+ atomic_set(&cs->mode, M_UNKNOWN);
gigaset_free_channels(cs);
if (cs->connected)
schedule_init(cs, MS_INIT);
@@ -1198,17 +1198,17 @@ static void do_action(int action, struct cardstate *cs,
case ACT_INIT:
cs->at_state.pending_commands &= ~PC_INIT;
cs->cur_at_seq = SEQ_NONE;
- cs->mode = M_UNIMODEM;
+ atomic_set(&cs->mode, M_UNIMODEM);
spin_lock_irqsave(&cs->lock, flags);
if (!cs->cidmode) {
spin_unlock_irqrestore(&cs->lock, flags);
gigaset_free_channels(cs);
- cs->mstate = MS_READY;
+ atomic_set(&cs->mstate, MS_READY);
break;
}
spin_unlock_irqrestore(&cs->lock, flags);
cs->at_state.pending_commands |= PC_CIDMODE;
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1);
gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
break;
case ACT_FAILINIT:
@@ -1234,20 +1234,22 @@ static void do_action(int action, struct cardstate *cs,
| INS_command;
break;
case ACT_CMODESET:
- if (cs->mstate == MS_INIT || cs->mstate == MS_RECOVER) {
+ if (atomic_read(&cs->mstate) == MS_INIT ||
+ atomic_read(&cs->mstate) == MS_RECOVER) {
gigaset_free_channels(cs);
- cs->mstate = MS_READY;
+ atomic_set(&cs->mstate, MS_READY);
}
- cs->mode = M_CID;
+ atomic_set(&cs->mode, M_CID);
cs->cur_at_seq = SEQ_NONE;
break;
case ACT_UMODESET:
- cs->mode = M_UNIMODEM;
+ atomic_set(&cs->mode, M_UNIMODEM);
cs->cur_at_seq = SEQ_NONE;
break;
case ACT_FAILCMODE:
cs->cur_at_seq = SEQ_NONE;
- if (cs->mstate == MS_INIT || cs->mstate == MS_RECOVER) {
+ if (atomic_read(&cs->mstate) == MS_INIT ||
+ atomic_read(&cs->mstate) == MS_RECOVER) {
init_failed(cs, M_UNKNOWN);
break;
}
@@ -1305,7 +1307,7 @@ static void do_action(int action, struct cardstate *cs,
case ACT_CONNECT:
if (cs->onechannel) {
at_state->pending_commands |= PC_DLE1;
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1);
break;
}
bcs->chstate |= CHS_D_UP;
@@ -1331,7 +1333,7 @@ static void do_action(int action, struct cardstate *cs,
* DLE only used for M10x with one B channel.
*/
at_state->pending_commands |= PC_DLE0;
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1);
} else
disconnect(p_at_state);
break;
@@ -1367,7 +1369,7 @@ static void do_action(int action, struct cardstate *cs,
"Could not enter DLE mode. Trying to hang up.\n");
channel = cs->curchannel;
cs->bcs[channel].at_state.pending_commands |= PC_HUP;
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1);
break;
case ACT_CID: /* got cid; start dialing */
@@ -1377,7 +1379,7 @@ static void do_action(int action, struct cardstate *cs,
cs->bcs[channel].at_state.cid = ev->parameter;
cs->bcs[channel].at_state.pending_commands |=
PC_DIAL;
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1);
break;
}
/* fall through */
@@ -1409,14 +1411,14 @@ static void do_action(int action, struct cardstate *cs,
case ACT_ABORTDIAL: /* error/timeout during dial preparation */
cs->cur_at_seq = SEQ_NONE;
at_state->pending_commands |= PC_HUP;
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1);
break;
case ACT_REMOTEREJECT: /* DISCONNECT_IND after dialling */
case ACT_CONNTIMEOUT: /* timeout waiting for ZSAU=ACTIVE */
case ACT_REMOTEHUP: /* DISCONNECT_IND with established connection */
at_state->pending_commands |= PC_HUP;
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1);
break;
case ACT_GETSTRING: /* warning: RING, ZDLE, ...
are not handled properly anymore */
@@ -1513,7 +1515,7 @@ static void do_action(int action, struct cardstate *cs,
break;
case ACT_HUP:
at_state->pending_commands |= PC_HUP;
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1);
gig_dbg(DEBUG_CMD, "Scheduling PC_HUP");
break;
@@ -1556,7 +1558,7 @@ static void do_action(int action, struct cardstate *cs,
cs->at_state.pending_commands |= PC_UMMODE;
gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
}
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1);
}
spin_unlock_irqrestore(&cs->lock, flags);
cs->waiting = 0;
@@ -1739,7 +1741,7 @@ static void process_command_flags(struct cardstate *cs)
int sequence;
unsigned long flags;
- cs->commands_pending = 0;
+ atomic_set(&cs->commands_pending, 0);
if (cs->cur_at_seq) {
gig_dbg(DEBUG_CMD, "not searching scheduled commands: busy");
@@ -1777,7 +1779,7 @@ static void process_command_flags(struct cardstate *cs)
~(PC_DLE1 | PC_ACCEPT | PC_DIAL);
if (at_state->cid > 0)
at_state->pending_commands |= PC_HUP;
- if (cs->mstate == MS_RECOVER) {
+ if (atomic_read(&cs->mstate) == MS_RECOVER) {
if (at_state->pending_commands & PC_CID) {
at_state->pending_commands |= PC_NOCID;
at_state->pending_commands &= ~PC_CID;
@@ -1791,7 +1793,7 @@ static void process_command_flags(struct cardstate *cs)
if (cs->at_state.pending_commands == PC_UMMODE
&& !cs->cidmode
&& list_empty(&cs->temp_at_states)
- && cs->mode == M_CID) {
+ && atomic_read(&cs->mode) == M_CID) {
sequence = SEQ_UMMODE;
at_state = &cs->at_state;
for (i = 0; i < cs->channels; ++i) {
@@ -1858,7 +1860,7 @@ static void process_command_flags(struct cardstate *cs)
}
if (cs->at_state.pending_commands & PC_CIDMODE) {
cs->at_state.pending_commands &= ~PC_CIDMODE;
- if (cs->mode == M_UNIMODEM) {
+ if (atomic_read(&cs->mode) == M_UNIMODEM) {
cs->retry_count = 1;
schedule_sequence(cs, &cs->at_state, SEQ_CIDMODE);
return;
@@ -1884,11 +1886,11 @@ static void process_command_flags(struct cardstate *cs)
return;
}
if (bcs->at_state.pending_commands & PC_CID) {
- switch (cs->mode) {
+ switch (atomic_read(&cs->mode)) {
case M_UNIMODEM:
cs->at_state.pending_commands |= PC_CIDMODE;
gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
- cs->commands_pending = 1;
+ atomic_set(&cs->commands_pending, 1);
return;
#ifdef GIG_MAYINITONDIAL
case M_UNKNOWN:
@@ -1924,7 +1926,7 @@ static void process_events(struct cardstate *cs)
for (i = 0; i < 2 * MAX_EVENTS; ++i) {
tail = cs->ev_tail;
if (tail == head) {
- if (!check_flags && !cs->commands_pending)
+ if (!check_flags && !atomic_read(&cs->commands_pending))
break;
check_flags = 0;
spin_unlock_irqrestore(&cs->ev_lock, flags);
@@ -1932,7 +1934,7 @@ static void process_events(struct cardstate *cs)
spin_lock_irqsave(&cs->ev_lock, flags);
tail = cs->ev_tail;
if (tail == head) {
- if (!cs->commands_pending)
+ if (!atomic_read(&cs->commands_pending))
break;
continue;
}
@@ -1969,7 +1971,7 @@ void gigaset_handle_event(unsigned long data)
struct cardstate *cs = (struct cardstate *) data;
/* handle incoming data on control/common channel */
- if (cs->inbuf->head != cs->inbuf->tail) {
+ if (atomic_read(&cs->inbuf->head) != atomic_read(&cs->inbuf->tail)) {
gig_dbg(DEBUG_INTR, "processing new data");
cs->ops->handle_input(cs->inbuf);
}
diff --git a/trunk/drivers/isdn/gigaset/gigaset.h b/trunk/drivers/isdn/gigaset/gigaset.h
index f365993161fc..02bdaf22d7ea 100644
--- a/trunk/drivers/isdn/gigaset/gigaset.h
+++ b/trunk/drivers/isdn/gigaset/gigaset.h
@@ -70,13 +70,22 @@
extern int gigaset_debuglevel; /* "needs" cast to (enum debuglevel) */
-/* debug flags, combine by adding/bitwise OR */
+/* any combination of these can be given with the 'debug=' parameter to insmod,
+ * e.g. 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and
+ * DEBUG_INTR.
+ */
enum debuglevel {
- DEBUG_INTR = 0x00008, /* interrupt processing */
+ DEBUG_REG = 0x0002, /* serial port I/O register operations */
+ DEBUG_OPEN = 0x0004, /* open/close serial port */
+ DEBUG_INTR = 0x0008, /* interrupt processing */
+ DEBUG_INTR_DUMP = 0x0010, /* Activating hexdump debug output on
+ interrupt requests, not available as
+ run-time option */
DEBUG_CMD = 0x00020, /* sent/received LL commands */
DEBUG_STREAM = 0x00040, /* application data stream I/O events */
DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */
DEBUG_LLDATA = 0x00100, /* sent/received LL data */
+ DEBUG_INTR_0 = 0x00200, /* serial port interrupt processing */
DEBUG_DRIVER = 0x00400, /* driver structure */
DEBUG_HDLC = 0x00800, /* M10x HDLC processing */
DEBUG_WRITE = 0x01000, /* M105 data write */
@@ -84,7 +93,7 @@ enum debuglevel {
DEBUG_MCMD = 0x04000, /* COMMANDS THAT ARE SENT VERY OFTEN */
DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data
structures */
- DEBUG_SUSPEND = 0x10000, /* suspend/resume processing */
+ DEBUG_LOCK = 0x10000, /* semaphore operations */
DEBUG_OUTPUT = 0x20000, /* output to device */
DEBUG_ISO = 0x40000, /* isochronous transfers */
DEBUG_IF = 0x80000, /* character device operations */
@@ -182,9 +191,6 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
#define HD_OPEN_ATCHANNEL (0x28) // 3070
#define HD_CLOSE_ATCHANNEL (0x29) // 3070
-/* number of B channels supported by base driver */
-#define BAS_CHANNELS 2
-
/* USB frames for isochronous transfer */
#define BAS_FRAMETIME 1 /* number of milliseconds between frames */
#define BAS_NUMFRAMES 8 /* number of frames per URB */
@@ -307,7 +313,7 @@ struct inbuf_t {
struct bc_state *bcs;
struct cardstate *cs;
int inputstate;
- int head, tail;
+ atomic_t head, tail;
unsigned char data[RBUFSIZE];
};
@@ -329,9 +335,9 @@ struct inbuf_t {
* are also filled with that value
*/
struct isowbuf_t {
- int read;
- int nextread;
- int write;
+ atomic_t read;
+ atomic_t nextread;
+ atomic_t write;
atomic_t writesem;
int wbits;
unsigned char data[BAS_OUTBUFSIZE + BAS_OUTBUFPAD];
@@ -344,13 +350,11 @@ struct isowbuf_t {
* - urb: pointer to the URB itself
* - bcs: pointer to the B Channel control structure
* - limit: end of write buffer area covered by this URB
- * - status: URB completion status
*/
struct isow_urbctx_t {
struct urb *urb;
struct bc_state *bcs;
int limit;
- int status;
};
/* AT state structure
@@ -435,15 +439,14 @@ struct cardstate {
unsigned minor_index;
struct device *dev;
struct device *tty_dev;
- unsigned flags;
const struct gigaset_ops *ops;
/* Stuff to handle communication */
wait_queue_head_t waitqueue;
int waiting;
- int mode; /* see M_XXXX */
- int mstate; /* Modem state: see MS_XXXX */
+ atomic_t mode; /* see M_XXXX */
+ atomic_t mstate; /* Modem state: see MS_XXXX */
/* only changed by the event layer */
int cmd_result;
@@ -500,7 +503,7 @@ struct cardstate {
processed */
int curchannel; /* channel those commands are meant
for */
- int commands_pending; /* flag(s) in xxx.commands_pending have
+ atomic_t commands_pending; /* flag(s) in xxx.commands_pending have
been set */
struct tasklet_struct event_tasklet;
/* tasklet for serializing AT commands.
@@ -540,6 +543,7 @@ struct gigaset_driver {
unsigned minor;
unsigned minors;
struct cardstate *cs;
+ unsigned *flags;
int blocked;
const struct gigaset_ops *ops;
@@ -555,7 +559,7 @@ struct cmdbuf_t {
struct bas_bc_state {
/* isochronous output state */
- int running;
+ atomic_t running;
atomic_t corrbytes;
spinlock_t isooutlock;
struct isow_urbctx_t isoouturbs[BAS_OUTURBS];
@@ -570,7 +574,6 @@ struct bas_bc_state {
struct urb *isoinurbs[BAS_INURBS];
unsigned char isoinbuf[BAS_INBUFSIZE * BAS_INURBS];
struct urb *isoindone; /* completed isoc read URB */
- int isoinstatus; /* status of completed URB */
int loststatus; /* status of dropped URB */
unsigned isoinlost; /* number of bytes lost */
/* state of bit unstuffing algorithm
@@ -767,6 +770,10 @@ void gigaset_freedriver(struct gigaset_driver *drv);
void gigaset_debugdrivers(void);
struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty);
struct cardstate *gigaset_get_cs_by_id(int id);
+
+/* For drivers without fixed assignment device<->cardstate (usb) */
+struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv);
+void gigaset_unassign(struct cardstate *cs);
void gigaset_blockdriver(struct gigaset_driver *drv);
/* Allocate and initialize card state. Calls hardware dependent
@@ -785,7 +792,7 @@ int gigaset_start(struct cardstate *cs);
void gigaset_stop(struct cardstate *cs);
/* Tell common.c that the driver is being unloaded. */
-int gigaset_shutdown(struct cardstate *cs);
+void gigaset_shutdown(struct cardstate *cs);
/* Tell common.c that an skb has been sent. */
void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb);
diff --git a/trunk/drivers/isdn/gigaset/interface.c b/trunk/drivers/isdn/gigaset/interface.c
index af195b07c191..eb50f3dab5f7 100644
--- a/trunk/drivers/isdn/gigaset/interface.c
+++ b/trunk/drivers/isdn/gigaset/interface.c
@@ -28,11 +28,12 @@ static int if_lock(struct cardstate *cs, int *arg)
return -EINVAL;
if (cmd < 0) {
- *arg = cs->mstate == MS_LOCKED;
+ *arg = atomic_read(&cs->mstate) == MS_LOCKED; //FIXME remove?
return 0;
}
- if (!cmd && cs->mstate == MS_LOCKED && cs->connected) {
+ if (!cmd && atomic_read(&cs->mstate) == MS_LOCKED
+ && cs->connected) {
cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS);
cs->ops->baud_rate(cs, B115200);
cs->ops->set_line_ctrl(cs, CS8);
@@ -103,7 +104,7 @@ static int if_config(struct cardstate *cs, int *arg)
if (*arg != 1)
return -EINVAL;
- if (cs->mstate != MS_LOCKED)
+ if (atomic_read(&cs->mstate) != MS_LOCKED)
return -EBUSY;
if (!cs->connected) {
@@ -161,7 +162,7 @@ static int if_open(struct tty_struct *tty, struct file *filp)
tty->driver_data = NULL;
cs = gigaset_get_cs_by_tty(tty);
- if (!cs || !try_module_get(cs->driver->owner))
+ if (!cs)
return -ENODEV;
if (mutex_lock_interruptible(&cs->mutex))
@@ -207,8 +208,6 @@ static void if_close(struct tty_struct *tty, struct file *filp)
}
mutex_unlock(&cs->mutex);
-
- module_put(cs->driver->owner);
}
static int if_ioctl(struct tty_struct *tty, struct file *file,
@@ -365,7 +364,7 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count)
if (!cs->open_count)
warn("%s: device not opened", __func__);
- else if (cs->mstate != MS_LOCKED) {
+ else if (atomic_read(&cs->mstate) != MS_LOCKED) {
warn("can't write to unlocked device");
retval = -EBUSY;
} else if (!cs->connected) {
@@ -399,9 +398,9 @@ static int if_write_room(struct tty_struct *tty)
if (!cs->open_count)
warn("%s: device not opened", __func__);
- else if (cs->mstate != MS_LOCKED) {
+ else if (atomic_read(&cs->mstate) != MS_LOCKED) {
warn("can't write to unlocked device");
- retval = -EBUSY;
+ retval = -EBUSY; //FIXME
} else if (!cs->connected) {
gig_dbg(DEBUG_ANY, "can't write to unplugged device");
retval = -EBUSY; //FIXME
@@ -431,7 +430,7 @@ static int if_chars_in_buffer(struct tty_struct *tty)
if (!cs->open_count)
warn("%s: device not opened", __func__);
- else if (cs->mstate != MS_LOCKED) {
+ else if (atomic_read(&cs->mstate) != MS_LOCKED) {
warn("can't write to unlocked device");
retval = -EBUSY;
} else if (!cs->connected) {
diff --git a/trunk/drivers/isdn/gigaset/isocdata.c b/trunk/drivers/isdn/gigaset/isocdata.c
index e30a7773f93c..e0505f238807 100644
--- a/trunk/drivers/isdn/gigaset/isocdata.c
+++ b/trunk/drivers/isdn/gigaset/isocdata.c
@@ -23,9 +23,9 @@
*/
void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle)
{
- iwb->read = 0;
- iwb->nextread = 0;
- iwb->write = 0;
+ atomic_set(&iwb->read, 0);
+ atomic_set(&iwb->nextread, 0);
+ atomic_set(&iwb->write, 0);
atomic_set(&iwb->writesem, 1);
iwb->wbits = 0;
iwb->idle = idle;
@@ -39,8 +39,8 @@ static inline int isowbuf_freebytes(struct isowbuf_t *iwb)
{
int read, write, freebytes;
- read = iwb->read;
- write = iwb->write;
+ read = atomic_read(&iwb->read);
+ write = atomic_read(&iwb->write);
if ((freebytes = read - write) > 0) {
/* no wraparound: need padding space within regular area */
return freebytes - BAS_OUTBUFPAD;
@@ -62,7 +62,7 @@ static inline int isowbuf_poscmp(struct isowbuf_t *iwb, int a, int b)
int read;
if (a == b)
return 0;
- read = iwb->read;
+ read = atomic_read(&iwb->read);
if (a < b) {
if (a < read && read <= b)
return +1;
@@ -91,18 +91,18 @@ static inline int isowbuf_startwrite(struct isowbuf_t *iwb)
#ifdef CONFIG_GIGASET_DEBUG
gig_dbg(DEBUG_ISO,
"%s: acquired iso write semaphore, data[write]=%02x, nbits=%d",
- __func__, iwb->data[iwb->write], iwb->wbits);
+ __func__, iwb->data[atomic_read(&iwb->write)], iwb->wbits);
#endif
return 1;
}
/* finish writing
- * release the write semaphore
+ * release the write semaphore and update the maximum buffer fill level
* returns the current write position
*/
static inline int isowbuf_donewrite(struct isowbuf_t *iwb)
{
- int write = iwb->write;
+ int write = atomic_read(&iwb->write);
atomic_inc(&iwb->writesem);
return write;
}
@@ -116,7 +116,7 @@ static inline int isowbuf_donewrite(struct isowbuf_t *iwb)
*/
static inline void isowbuf_putbits(struct isowbuf_t *iwb, u32 data, int nbits)
{
- int write = iwb->write;
+ int write = atomic_read(&iwb->write);
data <<= iwb->wbits;
data |= iwb->data[write];
nbits += iwb->wbits;
@@ -128,7 +128,7 @@ static inline void isowbuf_putbits(struct isowbuf_t *iwb, u32 data, int nbits)
}
iwb->wbits = nbits;
iwb->data[write] = data & 0xff;
- iwb->write = write;
+ atomic_set(&iwb->write, write);
}
/* put final flag on HDLC bitstream
@@ -142,7 +142,7 @@ static inline void isowbuf_putflag(struct isowbuf_t *iwb)
/* add two flags, thus reliably covering one byte */
isowbuf_putbits(iwb, 0x7e7e, 8);
/* recover the idle flag byte */
- write = iwb->write;
+ write = atomic_read(&iwb->write);
iwb->idle = iwb->data[write];
gig_dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle);
/* mask extraneous bits in buffer */
@@ -160,8 +160,8 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
int read, write, limit, src, dst;
unsigned char pbyte;
- read = iwb->nextread;
- write = iwb->write;
+ read = atomic_read(&iwb->nextread);
+ write = atomic_read(&iwb->write);
if (likely(read == write)) {
/* return idle frame */
return read < BAS_OUTBUFPAD ?
@@ -176,7 +176,7 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
err("invalid size %d", size);
return -EINVAL;
}
- src = iwb->read;
+ src = atomic_read(&iwb->read);
if (unlikely(limit > BAS_OUTBUFSIZE + BAS_OUTBUFPAD ||
(read < src && limit >= src))) {
err("isoc write buffer frame reservation violated");
@@ -191,8 +191,7 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
if (!isowbuf_startwrite(iwb))
return -EBUSY;
/* write position could have changed */
- write = iwb->write;
- if (limit >= write) {
+ if (limit >= (write = atomic_read(&iwb->write))) {
pbyte = iwb->data[write]; /* save
partial byte */
limit = write + BAS_OUTBUFPAD;
@@ -214,7 +213,7 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
__func__, pbyte, limit);
iwb->data[limit] = pbyte; /* restore
partial byte */
- iwb->write = limit;
+ atomic_set(&iwb->write, limit);
}
isowbuf_donewrite(iwb);
}
@@ -234,7 +233,7 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
limit = src;
}
}
- iwb->nextread = limit;
+ atomic_set(&iwb->nextread, limit);
return read;
}
@@ -478,7 +477,7 @@ static inline int trans_buildframe(struct isowbuf_t *iwb,
unsigned char c;
if (unlikely(count <= 0))
- return iwb->write;
+ return atomic_read(&iwb->write); /* better ideas? */
if (isowbuf_freebytes(iwb) < count ||
!isowbuf_startwrite(iwb)) {
@@ -487,13 +486,13 @@ static inline int trans_buildframe(struct isowbuf_t *iwb,
}
gig_dbg(DEBUG_STREAM, "put %d bytes", count);
- write = iwb->write;
+ write = atomic_read(&iwb->write);
do {
c = bitrev8(*in++);
iwb->data[write++] = c;
write %= BAS_OUTBUFSIZE;
} while (--count > 0);
- iwb->write = write;
+ atomic_set(&iwb->write, write);
iwb->idle = c;
return isowbuf_donewrite(iwb);
@@ -948,8 +947,8 @@ void gigaset_isoc_input(struct inbuf_t *inbuf)
unsigned tail, head, numbytes;
unsigned char *src;
- head = inbuf->head;
- while (head != (tail = inbuf->tail)) {
+ head = atomic_read(&inbuf->head);
+ while (head != (tail = atomic_read(&inbuf->tail))) {
gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
if (head > tail)
tail = RBUFSIZE;
@@ -957,7 +956,7 @@ void gigaset_isoc_input(struct inbuf_t *inbuf)
numbytes = tail - head;
gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
- if (cs->mstate == MS_LOCKED) {
+ if (atomic_read(&cs->mstate) == MS_LOCKED) {
gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
numbytes, src);
gigaset_if_receive(inbuf->cs, src, numbytes);
@@ -971,7 +970,7 @@ void gigaset_isoc_input(struct inbuf_t *inbuf)
if (head == RBUFSIZE)
head = 0;
gig_dbg(DEBUG_INTR, "setting head to %u", head);
- inbuf->head = head;
+ atomic_set(&inbuf->head, head);
}
}
diff --git a/trunk/drivers/isdn/gigaset/ser-gigaset.c b/trunk/drivers/isdn/gigaset/ser-gigaset.c
index fceeb1d57682..ea44302e6e7e 100644
--- a/trunk/drivers/isdn/gigaset/ser-gigaset.c
+++ b/trunk/drivers/isdn/gigaset/ser-gigaset.c
@@ -17,7 +17,6 @@
#include
#include
#include
-#include
/* Version Information */
#define DRIVER_AUTHOR "Tilman Schmidt"
@@ -49,7 +48,7 @@ struct ser_cardstate {
struct platform_device dev;
struct tty_struct *tty;
atomic_t refcnt;
- struct completion dead_cmp;
+ struct mutex dead_mutex;
};
static struct platform_driver device_driver = {
@@ -241,7 +240,7 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
struct cmdbuf_t *cb;
unsigned long flags;
- gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
+ gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
DEBUG_TRANSCMD : DEBUG_LOCKCMD,
"CMD Transmit", len, buf);
@@ -499,7 +498,7 @@ static struct cardstate *cs_get(struct tty_struct *tty)
static void cs_put(struct cardstate *cs)
{
if (atomic_dec_and_test(&cs->hw.ser->refcnt))
- complete(&cs->hw.ser->dead_cmp);
+ mutex_unlock(&cs->hw.ser->dead_mutex);
}
/*
@@ -528,8 +527,8 @@ gigaset_tty_open(struct tty_struct *tty)
cs->dev = &cs->hw.ser->dev.dev;
cs->hw.ser->tty = tty;
+ mutex_init(&cs->hw.ser->dead_mutex);
atomic_set(&cs->hw.ser->refcnt, 1);
- init_completion(&cs->hw.ser->dead_cmp);
tty->disc_data = cs;
@@ -537,13 +536,14 @@ gigaset_tty_open(struct tty_struct *tty)
* startup system and notify the LL that we are ready to run
*/
if (startmode == SM_LOCKED)
- cs->mstate = MS_LOCKED;
+ atomic_set(&cs->mstate, MS_LOCKED);
if (!gigaset_start(cs)) {
tasklet_kill(&cs->write_tasklet);
goto error;
}
gig_dbg(DEBUG_INIT, "Startup of HLL done");
+ mutex_lock(&cs->hw.ser->dead_mutex);
return 0;
error:
@@ -577,7 +577,7 @@ gigaset_tty_close(struct tty_struct *tty)
else {
/* wait for running methods to finish */
if (!atomic_dec_and_test(&cs->hw.ser->refcnt))
- wait_for_completion(&cs->hw.ser->dead_cmp);
+ mutex_lock(&cs->hw.ser->dead_mutex);
}
/* stop operations */
@@ -714,8 +714,8 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf,
return;
}
- tail = inbuf->tail;
- head = inbuf->head;
+ tail = atomic_read(&inbuf->tail);
+ head = atomic_read(&inbuf->head);
gig_dbg(DEBUG_INTR, "buffer state: %u -> %u, receive %u bytes",
head, tail, count);
@@ -742,7 +742,7 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf,
}
gig_dbg(DEBUG_INTR, "setting tail to %u", tail);
- inbuf->tail = tail;
+ atomic_set(&inbuf->tail, tail);
/* Everything was received .. Push data into handler */
gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
diff --git a/trunk/drivers/isdn/gigaset/usb-gigaset.c b/trunk/drivers/isdn/gigaset/usb-gigaset.c
index 77d20ab0cd4d..ca4bee173cfb 100644
--- a/trunk/drivers/isdn/gigaset/usb-gigaset.c
+++ b/trunk/drivers/isdn/gigaset/usb-gigaset.c
@@ -104,17 +104,12 @@ MODULE_DEVICE_TABLE(usb, gigaset_table);
* flags per packet.
*/
-/* functions called if a device of this driver is connected/disconnected */
static int gigaset_probe(struct usb_interface *interface,
const struct usb_device_id *id);
static void gigaset_disconnect(struct usb_interface *interface);
-/* functions called before/after suspend */
-static int gigaset_suspend(struct usb_interface *intf, pm_message_t message);
-static int gigaset_resume(struct usb_interface *intf);
-static int gigaset_pre_reset(struct usb_interface *intf);
-
static struct gigaset_driver *driver = NULL;
+static struct cardstate *cardstate = NULL;
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver gigaset_usb_driver = {
@@ -122,17 +117,12 @@ static struct usb_driver gigaset_usb_driver = {
.probe = gigaset_probe,
.disconnect = gigaset_disconnect,
.id_table = gigaset_table,
- .suspend = gigaset_suspend,
- .resume = gigaset_resume,
- .reset_resume = gigaset_resume,
- .pre_reset = gigaset_pre_reset,
- .post_reset = gigaset_resume,
};
struct usb_cardstate {
struct usb_device *udev; /* usb device pointer */
struct usb_interface *interface; /* interface for this device */
- int busy; /* bulk output in progress */
+ atomic_t busy; /* bulk output in progress */
/* Output buffer */
unsigned char *bulk_out_buffer;
@@ -324,7 +314,7 @@ static void gigaset_modem_fill(unsigned long data)
gig_dbg(DEBUG_OUTPUT, "modem_fill");
- if (cs->hw.usb->busy) {
+ if (atomic_read(&cs->hw.usb->busy)) {
gig_dbg(DEBUG_OUTPUT, "modem_fill: busy");
return;
}
@@ -371,13 +361,18 @@ static void gigaset_read_int_callback(struct urb *urb)
{
struct inbuf_t *inbuf = urb->context;
struct cardstate *cs = inbuf->cs;
- int status = urb->status;
+ int resubmit = 0;
int r;
unsigned numbytes;
unsigned char *src;
unsigned long flags;
- if (!status) {
+ if (!urb->status) {
+ if (!cs->connected) {
+ err("%s: disconnected", __func__); /* should never happen */
+ return;
+ }
+
numbytes = urb->actual_length;
if (numbytes) {
@@ -394,26 +389,28 @@ static void gigaset_read_int_callback(struct urb *urb)
}
} else
gig_dbg(DEBUG_INTR, "Received zero block length");
+ resubmit = 1;
} else {
/* The urb might have been killed. */
- gig_dbg(DEBUG_ANY, "%s - nonzero status received: %d",
- __func__, status);
- if (status == -ENOENT || status == -ESHUTDOWN)
- /* killed or endpoint shutdown: don't resubmit */
- return;
+ gig_dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d",
+ __func__, urb->status);
+ if (urb->status != -ENOENT) { /* not killed */
+ if (!cs->connected) {
+ err("%s: disconnected", __func__); /* should never happen */
+ return;
+ }
+ resubmit = 1;
+ }
}
- /* resubmit URB */
- spin_lock_irqsave(&cs->lock, flags);
- if (!cs->connected) {
+ if (resubmit) {
+ spin_lock_irqsave(&cs->lock, flags);
+ r = cs->connected ? usb_submit_urb(urb, GFP_ATOMIC) : -ENODEV;
spin_unlock_irqrestore(&cs->lock, flags);
- err("%s: disconnected", __func__);
- return;
+ if (r)
+ dev_err(cs->dev, "error %d when resubmitting urb.\n",
+ -r);
}
- r = usb_submit_urb(urb, GFP_ATOMIC);
- spin_unlock_irqrestore(&cs->lock, flags);
- if (r)
- dev_err(cs->dev, "error %d resubmitting URB\n", -r);
}
@@ -421,28 +418,19 @@ static void gigaset_read_int_callback(struct urb *urb)
static void gigaset_write_bulk_callback(struct urb *urb)
{
struct cardstate *cs = urb->context;
- int status = urb->status;
unsigned long flags;
- switch (status) {
- case 0: /* normal completion */
- break;
- case -ENOENT: /* killed */
- gig_dbg(DEBUG_ANY, "%s: killed", __func__);
- cs->hw.usb->busy = 0;
- return;
- default:
+ if (urb->status)
dev_err(cs->dev, "bulk transfer failed (status %d)\n",
- -status);
+ -urb->status);
/* That's all we can do. Communication problems
are handled by timeouts or network protocols. */
- }
spin_lock_irqsave(&cs->lock, flags);
if (!cs->connected) {
err("%s: not connected", __func__);
} else {
- cs->hw.usb->busy = 0;
+ atomic_set(&cs->hw.usb->busy, 0);
tasklet_schedule(&cs->write_tasklet);
}
spin_unlock_irqrestore(&cs->lock, flags);
@@ -490,14 +478,14 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
cb->offset += count;
cb->len -= count;
- ucs->busy = 1;
+ atomic_set(&ucs->busy, 1);
spin_lock_irqsave(&cs->lock, flags);
status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : -ENODEV;
spin_unlock_irqrestore(&cs->lock, flags);
if (status) {
- ucs->busy = 0;
+ atomic_set(&ucs->busy, 0);
err("could not submit urb (error %d)\n",
-status);
cb->len = 0; /* skip urb => remove cb+wakeup
@@ -516,7 +504,7 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
struct cmdbuf_t *cb;
unsigned long flags;
- gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
+ gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
DEBUG_TRANSCMD : DEBUG_LOCKCMD,
"CMD Transmit", len, buf);
@@ -653,7 +641,7 @@ static int write_modem(struct cardstate *cs)
count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size);
skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count);
skb_pull(bcs->tx_skb, count);
- ucs->busy = 1;
+ atomic_set(&ucs->busy, 1);
gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count);
spin_lock_irqsave(&cs->lock, flags);
@@ -671,7 +659,7 @@ static int write_modem(struct cardstate *cs)
if (ret) {
err("could not submit urb (error %d)\n", -ret);
- ucs->busy = 0;
+ atomic_set(&ucs->busy, 0);
}
if (!bcs->tx_skb->len) {
@@ -692,44 +680,53 @@ static int gigaset_probe(struct usb_interface *interface,
{
int retval;
struct usb_device *udev = interface_to_usbdev(interface);
- struct usb_host_interface *hostif = interface->cur_altsetting;
+ unsigned int ifnum;
+ struct usb_host_interface *hostif;
struct cardstate *cs = NULL;
struct usb_cardstate *ucs = NULL;
struct usb_endpoint_descriptor *endpoint;
int buffer_size;
+ int alt;
- gig_dbg(DEBUG_ANY, "%s: Check if device matches ...", __func__);
+ gig_dbg(DEBUG_ANY,
+ "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
+ __func__, le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
+
+ retval = -ENODEV; //FIXME
/* See if the device offered us matches what we can accept */
if ((le16_to_cpu(udev->descriptor.idVendor) != USB_M105_VENDOR_ID) ||
- (le16_to_cpu(udev->descriptor.idProduct) != USB_M105_PRODUCT_ID)) {
- gig_dbg(DEBUG_ANY, "device ID (0x%x, 0x%x) not for me - skip",
- le16_to_cpu(udev->descriptor.idVendor),
- le16_to_cpu(udev->descriptor.idProduct));
+ (le16_to_cpu(udev->descriptor.idProduct) != USB_M105_PRODUCT_ID))
return -ENODEV;
- }
- if (hostif->desc.bInterfaceNumber != 0) {
- gig_dbg(DEBUG_ANY, "interface %d not for me - skip",
- hostif->desc.bInterfaceNumber);
- return -ENODEV;
- }
- if (hostif->desc.bAlternateSetting != 0) {
- dev_notice(&udev->dev, "unsupported altsetting %d - skip",
- hostif->desc.bAlternateSetting);
+
+ /* this starts to become ascii art... */
+ hostif = interface->cur_altsetting;
+ alt = hostif->desc.bAlternateSetting;
+ ifnum = hostif->desc.bInterfaceNumber; // FIXME ?
+
+ if (alt != 0 || ifnum != 0) {
+ dev_warn(&udev->dev, "ifnum %d, alt %d\n", ifnum, alt);
return -ENODEV;
}
+
+ /* Reject application specific intefaces
+ *
+ */
if (hostif->desc.bInterfaceClass != 255) {
- dev_notice(&udev->dev, "unsupported interface class %d - skip",
- hostif->desc.bInterfaceClass);
+ dev_info(&udev->dev,
+ "%s: Device matched but iface_desc[%d]->bInterfaceClass==%d!\n",
+ __func__, ifnum, hostif->desc.bInterfaceClass);
return -ENODEV;
}
dev_info(&udev->dev, "%s: Device matched ... !\n", __func__);
- /* allocate memory for our device state and intialize it */
- cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME);
- if (!cs)
+ cs = gigaset_getunassignedcs(driver);
+ if (!cs) {
+ dev_warn(&udev->dev, "no free cardstate\n");
return -ENODEV;
+ }
ucs = cs->hw.usb;
/* save off device structure ptrs for later use */
@@ -762,7 +759,7 @@ static int gigaset_probe(struct usb_interface *interface,
endpoint = &hostif->endpoint[1].desc;
- ucs->busy = 0;
+ atomic_set(&ucs->busy, 0);
ucs->read_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!ucs->read_urb) {
@@ -795,7 +792,7 @@ static int gigaset_probe(struct usb_interface *interface,
/* tell common part that the device is ready */
if (startmode == SM_LOCKED)
- cs->mstate = MS_LOCKED;
+ atomic_set(&cs->mstate, MS_LOCKED);
if (!gigaset_start(cs)) {
tasklet_kill(&cs->write_tasklet);
@@ -816,7 +813,7 @@ static int gigaset_probe(struct usb_interface *interface,
usb_put_dev(ucs->udev);
ucs->udev = NULL;
ucs->interface = NULL;
- gigaset_freecs(cs);
+ gigaset_unassign(cs);
return retval;
}
@@ -827,9 +824,6 @@ static void gigaset_disconnect(struct usb_interface *interface)
cs = usb_get_intfdata(interface);
ucs = cs->hw.usb;
-
- dev_info(cs->dev, "disconnecting Gigaset USB adapter\n");
-
usb_kill_urb(ucs->read_urb);
gigaset_stop(cs);
@@ -837,7 +831,7 @@ static void gigaset_disconnect(struct usb_interface *interface)
usb_set_intfdata(interface, NULL);
tasklet_kill(&cs->write_tasklet);
- usb_kill_urb(ucs->bulk_out_urb);
+ usb_kill_urb(ucs->bulk_out_urb); /* FIXME: only if active? */
kfree(ucs->bulk_out_buffer);
usb_free_urb(ucs->bulk_out_urb);
@@ -850,53 +844,7 @@ static void gigaset_disconnect(struct usb_interface *interface)
ucs->interface = NULL;
ucs->udev = NULL;
cs->dev = NULL;
- gigaset_freecs(cs);
-}
-
-/* gigaset_suspend
- * This function is called before the USB connection is suspended or reset.
- */
-static int gigaset_suspend(struct usb_interface *intf, pm_message_t message)
-{
- struct cardstate *cs = usb_get_intfdata(intf);
-
- /* stop activity */
- cs->connected = 0; /* prevent rescheduling */
- usb_kill_urb(cs->hw.usb->read_urb);
- tasklet_kill(&cs->write_tasklet);
- usb_kill_urb(cs->hw.usb->bulk_out_urb);
-
- gig_dbg(DEBUG_SUSPEND, "suspend complete");
- return 0;
-}
-
-/* gigaset_resume
- * This function is called after the USB connection has been resumed or reset.
- */
-static int gigaset_resume(struct usb_interface *intf)
-{
- struct cardstate *cs = usb_get_intfdata(intf);
- int rc;
-
- /* resubmit interrupt URB */
- cs->connected = 1;
- rc = usb_submit_urb(cs->hw.usb->read_urb, GFP_KERNEL);
- if (rc) {
- dev_err(cs->dev, "Could not submit read URB (error %d)\n", -rc);
- return rc;
- }
-
- gig_dbg(DEBUG_SUSPEND, "resume complete");
- return 0;
-}
-
-/* gigaset_pre_reset
- * This function is called before the USB connection is reset.
- */
-static int gigaset_pre_reset(struct usb_interface *intf)
-{
- /* same as suspend */
- return gigaset_suspend(intf, PMSG_ON);
+ gigaset_unassign(cs);
}
static const struct gigaset_ops ops = {
@@ -932,6 +880,11 @@ static int __init usb_gigaset_init(void)
&ops, THIS_MODULE)) == NULL)
goto error;
+ /* allocate memory for our device state and intialize it */
+ cardstate = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME);
+ if (!cardstate)
+ goto error;
+
/* register this driver with the USB subsystem */
result = usb_register(&gigaset_usb_driver);
if (result < 0) {
@@ -944,7 +897,9 @@ static int __init usb_gigaset_init(void)
info(DRIVER_DESC);
return 0;
-error:
+error: if (cardstate)
+ gigaset_freecs(cardstate);
+ cardstate = NULL;
if (driver)
gigaset_freedriver(driver);
driver = NULL;
@@ -958,16 +913,11 @@ static int __init usb_gigaset_init(void)
*/
static void __exit usb_gigaset_exit(void)
{
- int i;
-
gigaset_blockdriver(driver); /* => probe will fail
* => no gigaset_start any more
*/
- /* stop all connected devices */
- for (i = 0; i < driver->minors; i++)
- gigaset_shutdown(driver->cs + i);
-
+ gigaset_shutdown(cardstate);
/* from now on, no isdn callback should be possible */
/* deregister this driver with the USB subsystem */
@@ -975,6 +925,8 @@ static void __exit usb_gigaset_exit(void)
/* this will call the disconnect-callback */
/* from now on, no disconnect/probe callback should be running */
+ gigaset_freecs(cardstate);
+ cardstate = NULL;
gigaset_freedriver(driver);
driver = NULL;
}
diff --git a/trunk/drivers/isdn/hardware/eicon/debug.c b/trunk/drivers/isdn/hardware/eicon/debug.c
index 84318ec8d13e..0db9cc661e28 100644
--- a/trunk/drivers/isdn/hardware/eicon/debug.c
+++ b/trunk/drivers/isdn/hardware/eicon/debug.c
@@ -1188,7 +1188,7 @@ int SuperTraceASSIGN (void* AdapterHandle, byte* data) {
if ((features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) &&
(features[0] & DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA)) {
- dword uninitialized_var(rx_dma_magic);
+ dword rx_dma_magic;
if ((pC->dma_handle = diva_get_dma_descriptor (pC->request, &rx_dma_magic)) >= 0) {
pC->xbuffer[0] = LLI;
pC->xbuffer[1] = 8;
diff --git a/trunk/drivers/isdn/hardware/eicon/diva.c b/trunk/drivers/isdn/hardware/eicon/diva.c
index 1403a5458e68..ffa2afa77c2f 100644
--- a/trunk/drivers/isdn/hardware/eicon/diva.c
+++ b/trunk/drivers/isdn/hardware/eicon/diva.c
@@ -515,11 +515,12 @@ diva_xdi_read(void *adapter, void *os_handle, void __user *dst,
irqreturn_t diva_os_irq_wrapper(int irq, void *context)
{
- diva_os_xdi_adapter_t *a = context;
+ diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) context;
diva_xdi_clear_interrupts_proc_t clear_int_proc;
- if (!a || !a->xdi_adapter.diva_isr_handler)
+ if (!a || !a->xdi_adapter.diva_isr_handler) {
return IRQ_NONE;
+ }
if ((clear_int_proc = a->clear_interrupts_proc)) {
(*clear_int_proc) (a);
diff --git a/trunk/drivers/isdn/hardware/eicon/message.c b/trunk/drivers/isdn/hardware/eicon/message.c
index 1ff98e7eb794..b9177ca4369a 100644
--- a/trunk/drivers/isdn/hardware/eicon/message.c
+++ b/trunk/drivers/isdn/hardware/eicon/message.c
@@ -9027,7 +9027,7 @@ static byte AddInfo(byte **add_i,
/* facility is a nested structure */
/* FTY can be more than once */
- if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
+ if(esc_chi[0] && !(esc_chi[esc_chi[0]])&0x7f )
{
add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
}
diff --git a/trunk/drivers/isdn/hisax/avm_pci.c b/trunk/drivers/isdn/hisax/avm_pci.c
index 0f1db1f669b2..035d158779df 100644
--- a/trunk/drivers/isdn/hisax/avm_pci.c
+++ b/trunk/drivers/isdn/hisax/avm_pci.c
@@ -263,7 +263,11 @@ hdlc_empty_fifo(struct BCState *bcs, int count)
outl(idx, cs->hw.avm.cfg_reg + 4);
while (cnt < count) {
#ifdef __powerpc__
+#ifdef CONFIG_APUS
+ *ptr++ = in_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE));
+#else
*ptr++ = in_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE));
+#endif /* CONFIG_APUS */
#else
*ptr++ = inl(cs->hw.avm.isac);
#endif /* __powerpc__ */
@@ -324,7 +328,11 @@ hdlc_fill_fifo(struct BCState *bcs)
if (cs->subtyp == AVM_FRITZ_PCI) {
while (cnthw.avm.isac +_IO_BASE), *ptr++);
+#else
out_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE), *ptr++);
+#endif /* CONFIG_APUS */
#else
outl(*ptr++, cs->hw.avm.isac);
#endif /* __powerpc__ */
diff --git a/trunk/drivers/isdn/i4l/isdn_tty.c b/trunk/drivers/isdn/i4l/isdn_tty.c
index 133eb18e65cc..9cb6e5021adb 100644
--- a/trunk/drivers/isdn/i4l/isdn_tty.c
+++ b/trunk/drivers/isdn/i4l/isdn_tty.c
@@ -1917,6 +1917,7 @@ isdn_tty_modem_init(void)
info->owner = THIS_MODULE;
#endif
spin_lock_init(&info->readlock);
+ init_MUTEX(&info->write_sem);
sprintf(info->last_cause, "0000");
sprintf(info->last_num, "none");
info->last_dir = 0;
diff --git a/trunk/drivers/isdn/i4l/isdn_ttyfax.c b/trunk/drivers/isdn/i4l/isdn_ttyfax.c
index f93de4a30355..a943d078bacc 100644
--- a/trunk/drivers/isdn/i4l/isdn_ttyfax.c
+++ b/trunk/drivers/isdn/i4l/isdn_ttyfax.c
@@ -834,7 +834,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
char *rp = &f->resolution;
p[0] += 2;
- if (!(info->faxonline & 1)) /* not outgoing connection */
+ if (!info->faxonline & 1) /* not outgoing connection */
PARSE_ERROR1;
for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 4); i++) {
diff --git a/trunk/drivers/isdn/icn/icn.c b/trunk/drivers/isdn/icn/icn.c
index bf7997abc4ac..82d957bde299 100644
--- a/trunk/drivers/isdn/icn/icn.c
+++ b/trunk/drivers/isdn/icn/icn.c
@@ -1302,7 +1302,7 @@ icn_command(isdn_ctrl * c, icn_card * card)
}
break;
case ISDN_CMD_DIAL:
- if (!(card->flags & ICN_FLAGS_RUNNING))
+ if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
if (card->leased)
break;
@@ -1328,7 +1328,7 @@ icn_command(isdn_ctrl * c, icn_card * card)
}
break;
case ISDN_CMD_ACCEPTD:
- if (!(card->flags & ICN_FLAGS_RUNNING))
+ if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
if (c->arg < ICN_BCH) {
a = c->arg + 1;
@@ -1348,7 +1348,7 @@ icn_command(isdn_ctrl * c, icn_card * card)
}
break;
case ISDN_CMD_ACCEPTB:
- if (!(card->flags & ICN_FLAGS_RUNNING))
+ if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
if (c->arg < ICN_BCH) {
a = c->arg + 1;
@@ -1366,7 +1366,7 @@ icn_command(isdn_ctrl * c, icn_card * card)
}
break;
case ISDN_CMD_HANGUP:
- if (!(card->flags & ICN_FLAGS_RUNNING))
+ if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
if (c->arg < ICN_BCH) {
a = c->arg + 1;
@@ -1375,7 +1375,7 @@ icn_command(isdn_ctrl * c, icn_card * card)
}
break;
case ISDN_CMD_SETEAZ:
- if (!(card->flags & ICN_FLAGS_RUNNING))
+ if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
if (card->leased)
break;
@@ -1391,7 +1391,7 @@ icn_command(isdn_ctrl * c, icn_card * card)
}
break;
case ISDN_CMD_CLREAZ:
- if (!(card->flags & ICN_FLAGS_RUNNING))
+ if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
if (card->leased)
break;
@@ -1405,7 +1405,7 @@ icn_command(isdn_ctrl * c, icn_card * card)
}
break;
case ISDN_CMD_SETL2:
- if (!(card->flags & ICN_FLAGS_RUNNING))
+ if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
if ((c->arg & 255) < ICN_BCH) {
a = c->arg;
@@ -1424,7 +1424,7 @@ icn_command(isdn_ctrl * c, icn_card * card)
}
break;
case ISDN_CMD_SETL3:
- if (!(card->flags & ICN_FLAGS_RUNNING))
+ if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
return 0;
default:
@@ -1471,7 +1471,7 @@ if_writecmd(const u_char __user *buf, int len, int id, int channel)
icn_card *card = icn_findcard(id);
if (card) {
- if (!(card->flags & ICN_FLAGS_RUNNING))
+ if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
return (icn_writecmd(buf, len, 1, card));
}
@@ -1486,7 +1486,7 @@ if_readstatus(u_char __user *buf, int len, int id, int channel)
icn_card *card = icn_findcard(id);
if (card) {
- if (!(card->flags & ICN_FLAGS_RUNNING))
+ if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
return (icn_readstatus(buf, len, card));
}
@@ -1501,7 +1501,7 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb)
icn_card *card = icn_findcard(id);
if (card) {
- if (!(card->flags & ICN_FLAGS_RUNNING))
+ if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
return (icn_sendbuf(channel, ack, skb, card));
}
diff --git a/trunk/drivers/isdn/isdnloop/isdnloop.c b/trunk/drivers/isdn/isdnloop/isdnloop.c
index 655ef9a3f4df..bb92e3cd9334 100644
--- a/trunk/drivers/isdn/isdnloop/isdnloop.c
+++ b/trunk/drivers/isdn/isdnloop/isdnloop.c
@@ -1184,7 +1184,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card)
}
break;
case ISDN_CMD_DIAL:
- if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
+ if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
return -ENODEV;
if (card->leased)
break;
@@ -1210,7 +1210,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card)
}
break;
case ISDN_CMD_ACCEPTD:
- if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
+ if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
return -ENODEV;
if (c->arg < ISDNLOOP_BCH) {
a = c->arg + 1;
@@ -1238,7 +1238,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card)
}
break;
case ISDN_CMD_ACCEPTB:
- if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
+ if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
return -ENODEV;
if (c->arg < ISDNLOOP_BCH) {
a = c->arg + 1;
@@ -1264,7 +1264,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card)
i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
break;
case ISDN_CMD_HANGUP:
- if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
+ if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
return -ENODEV;
if (c->arg < ISDNLOOP_BCH) {
a = c->arg + 1;
@@ -1273,7 +1273,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card)
}
break;
case ISDN_CMD_SETEAZ:
- if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
+ if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
return -ENODEV;
if (card->leased)
break;
@@ -1303,7 +1303,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card)
}
break;
case ISDN_CMD_SETL2:
- if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
+ if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
return -ENODEV;
if ((c->arg & 255) < ISDNLOOP_BCH) {
a = c->arg;
@@ -1395,7 +1395,7 @@ if_readstatus(u_char __user *buf, int len, int id, int channel)
isdnloop_card *card = isdnloop_findcard(id);
if (card) {
- if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
+ if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
return -ENODEV;
return (isdnloop_readstatus(buf, len, card));
}
@@ -1410,7 +1410,7 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb)
isdnloop_card *card = isdnloop_findcard(id);
if (card) {
- if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
+ if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
return -ENODEV;
/* ack request stored in skb scratch area */
*(skb->head) = ack;
diff --git a/trunk/drivers/macintosh/mediabay.c b/trunk/drivers/macintosh/mediabay.c
index 936788272a5f..de9ebbfbf122 100644
--- a/trunk/drivers/macintosh/mediabay.c
+++ b/trunk/drivers/macintosh/mediabay.c
@@ -78,14 +78,12 @@ struct media_bay_info {
int cached_gpio;
int sleeping;
struct semaphore lock;
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
+#ifdef CONFIG_BLK_DEV_IDE
void __iomem *cd_base;
+ int cd_index;
int cd_irq;
int cd_retry;
#endif
-#if defined(CONFIG_BLK_DEV_IDE_PMAC) || defined(CONFIG_MAC_FLOPPY)
- int cd_index;
-#endif
};
#define MAX_BAYS 2
@@ -93,7 +91,7 @@ struct media_bay_info {
static struct media_bay_info media_bays[MAX_BAYS];
int media_bay_count = 0;
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
+#ifdef CONFIG_BLK_DEV_IDE
/* check the busy bit in the media-bay ide interface
(assumes the media-bay contains an ide device) */
#define MB_IDE_READY(i) ((readb(media_bays[i].cd_base + 0x70) & 0x80) == 0)
@@ -403,7 +401,7 @@ static void poll_media_bay(struct media_bay_info* bay)
set_mb_power(bay, id != MB_NO);
bay->content_id = id;
if (id == MB_NO) {
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
+#ifdef CONFIG_BLK_DEV_IDE
bay->cd_retry = 0;
#endif
printk(KERN_INFO "media bay %d is empty\n", bay->index);
@@ -416,9 +414,9 @@ static void poll_media_bay(struct media_bay_info* bay)
}
}
-#ifdef CONFIG_MAC_FLOPPY
int check_media_bay(struct device_node *which_bay, int what)
{
+#ifdef CONFIG_BLK_DEV_IDE
int i;
for (i=0; istate = mb_resetting;
MBDBG("mediabay%d: waiting reset (kind:%d)\n", i, bay->content_id);
break;
+
case mb_resetting:
if (bay->content_id != MB_CD) {
MBDBG("mediabay%d: bay is up (kind:%d)\n", i, bay->content_id);
bay->state = mb_up;
break;
}
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
+#ifdef CONFIG_BLK_DEV_IDE
MBDBG("mediabay%d: waiting IDE reset (kind:%d)\n", i, bay->content_id);
bay->ops->un_reset_ide(bay);
bay->timer = msecs_to_jiffies(MB_IDE_WAIT);
@@ -535,14 +536,16 @@ static void media_bay_step(int i)
#else
printk(KERN_DEBUG "media-bay %d is ide (not compiled in kernel)\n", i);
set_mb_power(bay, 0);
-#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+#endif /* CONFIG_BLK_DEV_IDE */
break;
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
+
+#ifdef CONFIG_BLK_DEV_IDE
case mb_ide_resetting:
bay->timer = msecs_to_jiffies(MB_IDE_TIMEOUT);
bay->state = mb_ide_waiting;
MBDBG("mediabay%d: waiting IDE ready (kind:%d)\n", i, bay->content_id);
break;
+
case mb_ide_waiting:
if (bay->cd_base == NULL) {
bay->timer = 0;
@@ -584,10 +587,11 @@ static void media_bay_step(int i)
bay->timer = 0;
}
break;
-#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+#endif /* CONFIG_BLK_DEV_IDE */
+
case mb_powering_down:
bay->state = mb_empty;
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
+#ifdef CONFIG_BLK_DEV_IDE
if (bay->cd_index >= 0) {
printk(KERN_DEBUG "Unregistering mb %d ide, index:%d\n", i,
bay->cd_index);
@@ -603,7 +607,7 @@ static void media_bay_step(int i)
bay->content_id = MB_NO;
}
}
-#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+#endif /* CONFIG_BLK_DEV_IDE */
MBDBG("mediabay%d: end of power down\n", i);
break;
}
@@ -735,7 +739,7 @@ static int media_bay_resume(struct macio_dev *mdev)
bay->last_value = bay->content_id;
bay->value_count = msecs_to_jiffies(MB_STABLE_DELAY);
bay->timer = msecs_to_jiffies(MB_POWER_DELAY);
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
+#ifdef CONFIG_BLK_DEV_IDE
bay->cd_retry = 0;
#endif
do {
@@ -825,7 +829,7 @@ static int __init media_bay_init(void)
for (i=0; iflags)
|| test_bit(Faulty, &rdev->flags))
continue;
@@ -261,7 +261,7 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
struct list_head *tmp;
mddev_t *mddev = bitmap->mddev;
- rdev_for_each(rdev, tmp, mddev)
+ ITERATE_RDEV(mddev, rdev, tmp)
if (test_bit(In_sync, &rdev->flags)
&& !test_bit(Faulty, &rdev->flags)) {
int size = PAGE_SIZE;
@@ -1348,38 +1348,14 @@ void bitmap_close_sync(struct bitmap *bitmap)
*/
sector_t sector = 0;
int blocks;
- if (!bitmap)
- return;
+ if (!bitmap) return;
while (sector < bitmap->mddev->resync_max_sectors) {
bitmap_end_sync(bitmap, sector, &blocks, 0);
- sector += blocks;
- }
-}
-
-void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector)
-{
- sector_t s = 0;
- int blocks;
-
- if (!bitmap)
- return;
- if (sector == 0) {
- bitmap->last_end_sync = jiffies;
- return;
- }
- if (time_before(jiffies, (bitmap->last_end_sync
- + bitmap->daemon_sleep * HZ)))
- return;
- wait_event(bitmap->mddev->recovery_wait,
- atomic_read(&bitmap->mddev->recovery_active) == 0);
-
- sector &= ~((1ULL << CHUNK_BLOCK_SHIFT(bitmap)) - 1);
- s = 0;
- while (s < sector && s < bitmap->mddev->resync_max_sectors) {
- bitmap_end_sync(bitmap, s, &blocks, 0);
- s += blocks;
+/*
+ if (sector < 500) printk("bitmap_close_sync: sec %llu blks %d\n",
+ (unsigned long long)sector, blocks);
+*/ sector += blocks;
}
- bitmap->last_end_sync = jiffies;
}
static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed)
@@ -1589,4 +1565,3 @@ EXPORT_SYMBOL(bitmap_start_sync);
EXPORT_SYMBOL(bitmap_end_sync);
EXPORT_SYMBOL(bitmap_unplug);
EXPORT_SYMBOL(bitmap_close_sync);
-EXPORT_SYMBOL(bitmap_cond_end_sync);
diff --git a/trunk/drivers/md/faulty.c b/trunk/drivers/md/faulty.c
index d107ddceefcd..cf2ddce34118 100644
--- a/trunk/drivers/md/faulty.c
+++ b/trunk/drivers/md/faulty.c
@@ -294,7 +294,7 @@ static int run(mddev_t *mddev)
}
conf->nfaults = 0;
- rdev_for_each(rdev, tmp, mddev)
+ ITERATE_RDEV(mddev, rdev, tmp)
conf->rdev = rdev;
mddev->array_size = mddev->size;
diff --git a/trunk/drivers/md/linear.c b/trunk/drivers/md/linear.c
index 0b8511776b3e..3dac1cfb8189 100644
--- a/trunk/drivers/md/linear.c
+++ b/trunk/drivers/md/linear.c
@@ -122,7 +122,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
cnt = 0;
conf->array_size = 0;
- rdev_for_each(rdev, tmp, mddev) {
+ ITERATE_RDEV(mddev,rdev,tmp) {
int j = rdev->raid_disk;
dev_info_t *disk = conf->disks + j;
diff --git a/trunk/drivers/md/md.c b/trunk/drivers/md/md.c
index 5fc326d3970e..c28a120b4161 100644
--- a/trunk/drivers/md/md.c
+++ b/trunk/drivers/md/md.c
@@ -195,7 +195,7 @@ static DEFINE_SPINLOCK(all_mddevs_lock);
* Any code which breaks out of this loop while own
* a reference to the current mddev and must mddev_put it.
*/
-#define for_each_mddev(mddev,tmp) \
+#define ITERATE_MDDEV(mddev,tmp) \
\
for (({ spin_lock(&all_mddevs_lock); \
tmp = all_mddevs.next; \
@@ -275,7 +275,6 @@ static mddev_t * mddev_find(dev_t unit)
spin_lock_init(&new->write_lock);
init_waitqueue_head(&new->sb_wait);
new->reshape_position = MaxSector;
- new->resync_max = MaxSector;
new->queue = blk_alloc_queue(GFP_KERNEL);
if (!new->queue) {
@@ -311,7 +310,7 @@ static mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr)
mdk_rdev_t * rdev;
struct list_head *tmp;
- rdev_for_each(rdev, tmp, mddev) {
+ ITERATE_RDEV(mddev,rdev,tmp) {
if (rdev->desc_nr == nr)
return rdev;
}
@@ -323,7 +322,7 @@ static mdk_rdev_t * find_rdev(mddev_t * mddev, dev_t dev)
struct list_head *tmp;
mdk_rdev_t *rdev;
- rdev_for_each(rdev, tmp, mddev) {
+ ITERATE_RDEV(mddev,rdev,tmp) {
if (rdev->bdev->bd_dev == dev)
return rdev;
}
@@ -774,16 +773,12 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
__u64 ev1 = md_event(sb);
rdev->raid_disk = -1;
- clear_bit(Faulty, &rdev->flags);
- clear_bit(In_sync, &rdev->flags);
- clear_bit(WriteMostly, &rdev->flags);
- clear_bit(BarriersNotsupp, &rdev->flags);
-
+ rdev->flags = 0;
if (mddev->raid_disks == 0) {
mddev->major_version = 0;
mddev->minor_version = sb->minor_version;
mddev->patch_version = sb->patch_version;
- mddev->external = 0;
+ mddev->persistent = ! sb->not_persistent;
mddev->chunk_size = sb->chunk_size;
mddev->ctime = sb->ctime;
mddev->utime = sb->utime;
@@ -909,7 +904,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
sb->size = mddev->size;
sb->raid_disks = mddev->raid_disks;
sb->md_minor = mddev->md_minor;
- sb->not_persistent = 0;
+ sb->not_persistent = !mddev->persistent;
sb->utime = mddev->utime;
sb->state = 0;
sb->events_hi = (mddev->events>>32);
@@ -943,7 +938,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
sb->state |= (1<disks[0].state = (1<raid_disk >= 0 && test_bit(In_sync, &rdev2->flags)
@@ -1158,15 +1153,11 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
__u64 ev1 = le64_to_cpu(sb->events);
rdev->raid_disk = -1;
- clear_bit(Faulty, &rdev->flags);
- clear_bit(In_sync, &rdev->flags);
- clear_bit(WriteMostly, &rdev->flags);
- clear_bit(BarriersNotsupp, &rdev->flags);
-
+ rdev->flags = 0;
if (mddev->raid_disks == 0) {
mddev->major_version = 1;
mddev->patch_version = 0;
- mddev->external = 0;
+ mddev->persistent = 1;
mddev->chunk_size = le32_to_cpu(sb->chunksize) << 9;
mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1);
mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1);
@@ -1295,7 +1286,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
}
max_dev = 0;
- rdev_for_each(rdev2, tmp, mddev)
+ ITERATE_RDEV(mddev,rdev2,tmp)
if (rdev2->desc_nr+1 > max_dev)
max_dev = rdev2->desc_nr+1;
@@ -1304,7 +1295,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
for (i=0; idev_roles[i] = cpu_to_le16(0xfffe);
- rdev_for_each(rdev2, tmp, mddev) {
+ ITERATE_RDEV(mddev,rdev2,tmp) {
i = rdev2->desc_nr;
if (test_bit(Faulty, &rdev2->flags))
sb->dev_roles[i] = cpu_to_le16(0xfffe);
@@ -1342,8 +1333,8 @@ static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2)
struct list_head *tmp, *tmp2;
mdk_rdev_t *rdev, *rdev2;
- rdev_for_each(rdev, tmp, mddev1)
- rdev_for_each(rdev2, tmp2, mddev2)
+ ITERATE_RDEV(mddev1,rdev,tmp)
+ ITERATE_RDEV(mddev2, rdev2, tmp2)
if (rdev->bdev->bd_contains ==
rdev2->bdev->bd_contains)
return 1;
@@ -1410,7 +1401,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
goto fail;
}
list_add(&rdev->same_set, &mddev->disks);
- bd_claim_by_disk(rdev->bdev, rdev->bdev->bd_holder, mddev->gendisk);
+ bd_claim_by_disk(rdev->bdev, rdev, mddev->gendisk);
return 0;
fail:
@@ -1419,11 +1410,10 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
return err;
}
-static void md_delayed_delete(struct work_struct *ws)
+static void delayed_delete(struct work_struct *ws)
{
mdk_rdev_t *rdev = container_of(ws, mdk_rdev_t, del_work);
kobject_del(&rdev->kobj);
- kobject_put(&rdev->kobj);
}
static void unbind_rdev_from_array(mdk_rdev_t * rdev)
@@ -1442,8 +1432,7 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev)
/* We need to delay this, otherwise we can deadlock when
* writing to 'remove' to "dev/state"
*/
- INIT_WORK(&rdev->del_work, md_delayed_delete);
- kobject_get(&rdev->kobj);
+ INIT_WORK(&rdev->del_work, delayed_delete);
schedule_work(&rdev->del_work);
}
@@ -1452,7 +1441,7 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev)
* otherwise reused by a RAID array (or any other kernel
* subsystem), by bd_claiming the device.
*/
-static int lock_rdev(mdk_rdev_t *rdev, dev_t dev, int shared)
+static int lock_rdev(mdk_rdev_t *rdev, dev_t dev)
{
int err = 0;
struct block_device *bdev;
@@ -1464,15 +1453,13 @@ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev, int shared)
__bdevname(dev, b));
return PTR_ERR(bdev);
}
- err = bd_claim(bdev, shared ? (mdk_rdev_t *)lock_rdev : rdev);
+ err = bd_claim(bdev, rdev);
if (err) {
printk(KERN_ERR "md: could not bd_claim %s.\n",
bdevname(bdev, b));
blkdev_put(bdev);
return err;
}
- if (!shared)
- set_bit(AllReserved, &rdev->flags);
rdev->bdev = bdev;
return err;
}
@@ -1516,7 +1503,7 @@ static void export_array(mddev_t *mddev)
struct list_head *tmp;
mdk_rdev_t *rdev;
- rdev_for_each(rdev, tmp, mddev) {
+ ITERATE_RDEV(mddev,rdev,tmp) {
if (!rdev->mddev) {
MD_BUG();
continue;
@@ -1594,17 +1581,17 @@ static void md_print_devices(void)
printk("md: **********************************\n");
printk("md: * *\n");
printk("md: **********************************\n");
- for_each_mddev(mddev, tmp) {
+ ITERATE_MDDEV(mddev,tmp) {
if (mddev->bitmap)
bitmap_print_sb(mddev->bitmap);
else
printk("%s: ", mdname(mddev));
- rdev_for_each(rdev, tmp2, mddev)
+ ITERATE_RDEV(mddev,rdev,tmp2)
printk("<%s>", bdevname(rdev->bdev,b));
printk("\n");
- rdev_for_each(rdev, tmp2, mddev)
+ ITERATE_RDEV(mddev,rdev,tmp2)
print_rdev(rdev);
}
printk("md: **********************************\n");
@@ -1623,7 +1610,7 @@ static void sync_sbs(mddev_t * mddev, int nospares)
mdk_rdev_t *rdev;
struct list_head *tmp;
- rdev_for_each(rdev, tmp, mddev) {
+ ITERATE_RDEV(mddev,rdev,tmp) {
if (rdev->sb_events == mddev->events ||
(nospares &&
rdev->raid_disk < 0 &&
@@ -1709,20 +1696,18 @@ static void md_update_sb(mddev_t * mddev, int force_change)
MD_BUG();
mddev->events --;
}
+ sync_sbs(mddev, nospares);
/*
* do not write anything to disk if using
* nonpersistent superblocks
*/
if (!mddev->persistent) {
- if (!mddev->external)
- clear_bit(MD_CHANGE_PENDING, &mddev->flags);
-
+ clear_bit(MD_CHANGE_PENDING, &mddev->flags);
spin_unlock_irq(&mddev->write_lock);
wake_up(&mddev->sb_wait);
return;
}
- sync_sbs(mddev, nospares);
spin_unlock_irq(&mddev->write_lock);
dprintk(KERN_INFO
@@ -1730,7 +1715,7 @@ static void md_update_sb(mddev_t * mddev, int force_change)
mdname(mddev),mddev->in_sync);
bitmap_update_sb(mddev->bitmap);
- rdev_for_each(rdev, tmp, mddev) {
+ ITERATE_RDEV(mddev,rdev,tmp) {
char b[BDEVNAME_SIZE];
dprintk(KERN_INFO "md: ");
if (rdev->sb_loaded != 1)
@@ -1800,7 +1785,7 @@ static ssize_t
state_show(mdk_rdev_t *rdev, char *page)
{
char *sep = "";
- size_t len = 0;
+ int len=0;
if (test_bit(Faulty, &rdev->flags)) {
len+= sprintf(page+len, "%sfaulty",sep);
@@ -1902,45 +1887,20 @@ static ssize_t
slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
{
char *e;
- int err;
- char nm[20];
int slot = simple_strtoul(buf, &e, 10);
if (strncmp(buf, "none", 4)==0)
slot = -1;
else if (e==buf || (*e && *e!= '\n'))
return -EINVAL;
- if (rdev->mddev->pers) {
- /* Setting 'slot' on an active array requires also
- * updating the 'rd%d' link, and communicating
- * with the personality with ->hot_*_disk.
- * For now we only support removing
- * failed/spare devices. This normally happens automatically,
- * but not when the metadata is externally managed.
- */
- if (slot != -1)
- return -EBUSY;
- if (rdev->raid_disk == -1)
- return -EEXIST;
- /* personality does all needed checks */
- if (rdev->mddev->pers->hot_add_disk == NULL)
- return -EINVAL;
- err = rdev->mddev->pers->
- hot_remove_disk(rdev->mddev, rdev->raid_disk);
- if (err)
- return err;
- sprintf(nm, "rd%d", rdev->raid_disk);
- sysfs_remove_link(&rdev->mddev->kobj, nm);
- set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery);
- md_wakeup_thread(rdev->mddev->thread);
- } else {
- if (slot >= rdev->mddev->raid_disks)
- return -ENOSPC;
- rdev->raid_disk = slot;
- /* assume it is working */
- clear_bit(Faulty, &rdev->flags);
- clear_bit(WriteMostly, &rdev->flags);
- set_bit(In_sync, &rdev->flags);
- }
+ if (rdev->mddev->pers)
+ /* Cannot set slot in active array (yet) */
+ return -EBUSY;
+ if (slot >= rdev->mddev->raid_disks)
+ return -ENOSPC;
+ rdev->raid_disk = slot;
+ /* assume it is working */
+ rdev->flags = 0;
+ set_bit(In_sync, &rdev->flags);
return len;
}
@@ -1963,10 +1923,6 @@ offset_store(mdk_rdev_t *rdev, const char *buf, size_t len)
return -EINVAL;
if (rdev->mddev->pers)
return -EBUSY;
- if (rdev->size && rdev->mddev->external)
- /* Must set offset before size, so overlap checks
- * can be sane */
- return -EBUSY;
rdev->data_offset = offset;
return len;
}
@@ -1980,69 +1936,16 @@ rdev_size_show(mdk_rdev_t *rdev, char *page)
return sprintf(page, "%llu\n", (unsigned long long)rdev->size);
}
-static int overlaps(sector_t s1, sector_t l1, sector_t s2, sector_t l2)
-{
- /* check if two start/length pairs overlap */
- if (s1+l1 <= s2)
- return 0;
- if (s2+l2 <= s1)
- return 0;
- return 1;
-}
-
static ssize_t
rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
{
char *e;
unsigned long long size = simple_strtoull(buf, &e, 10);
- unsigned long long oldsize = rdev->size;
if (e==buf || (*e && *e != '\n'))
return -EINVAL;
if (rdev->mddev->pers)
return -EBUSY;
rdev->size = size;
- if (size > oldsize && rdev->mddev->external) {
- /* need to check that all other rdevs with the same ->bdev
- * do not overlap. We need to unlock the mddev to avoid
- * a deadlock. We have already changed rdev->size, and if
- * we have to change it back, we will have the lock again.
- */
- mddev_t *mddev;
- int overlap = 0;
- struct list_head *tmp, *tmp2;
-
- mddev_unlock(rdev->mddev);
- for_each_mddev(mddev, tmp) {
- mdk_rdev_t *rdev2;
-
- mddev_lock(mddev);
- rdev_for_each(rdev2, tmp2, mddev)
- if (test_bit(AllReserved, &rdev2->flags) ||
- (rdev->bdev == rdev2->bdev &&
- rdev != rdev2 &&
- overlaps(rdev->data_offset, rdev->size,
- rdev2->data_offset, rdev2->size))) {
- overlap = 1;
- break;
- }
- mddev_unlock(mddev);
- if (overlap) {
- mddev_put(mddev);
- break;
- }
- }
- mddev_lock(rdev->mddev);
- if (overlap) {
- /* Someone else could have slipped in a size
- * change here, but doing so is just silly.
- * We put oldsize back because we *know* it is
- * safe, and trust userspace not to race with
- * itself
- */
- rdev->size = oldsize;
- return -EBUSY;
- }
- }
if (size < rdev->mddev->size || rdev->mddev->size == 0)
rdev->mddev->size = size;
return len;
@@ -2077,18 +1980,12 @@ rdev_attr_store(struct kobject *kobj, struct attribute *attr,
{
struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr);
mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj);
- int rv;
if (!entry->store)
return -EIO;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- rv = mddev_lock(rdev->mddev);
- if (!rv) {
- rv = entry->store(rdev, page, length);
- mddev_unlock(rdev->mddev);
- }
- return rv;
+ return entry->store(rdev, page, length);
}
static void rdev_free(struct kobject *ko)
@@ -2132,7 +2029,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
if ((err = alloc_disk_sb(rdev)))
goto abort_free;
- err = lock_rdev(rdev, newdev, super_format == -2);
+ err = lock_rdev(rdev, newdev);
if (err)
goto abort_free;
@@ -2202,7 +2099,7 @@ static void analyze_sbs(mddev_t * mddev)
char b[BDEVNAME_SIZE];
freshest = NULL;
- rdev_for_each(rdev, tmp, mddev)
+ ITERATE_RDEV(mddev,rdev,tmp)
switch (super_types[mddev->major_version].
load_super(rdev, freshest, mddev->minor_version)) {
case 1:
@@ -2223,7 +2120,7 @@ static void analyze_sbs(mddev_t * mddev)
validate_super(mddev, freshest);
i = 0;
- rdev_for_each(rdev, tmp, mddev) {
+ ITERATE_RDEV(mddev,rdev,tmp) {
if (rdev != freshest)
if (super_types[mddev->major_version].
validate_super(mddev, rdev)) {
@@ -2318,7 +2215,7 @@ level_show(mddev_t *mddev, char *page)
static ssize_t
level_store(mddev_t *mddev, const char *buf, size_t len)
{
- ssize_t rv = len;
+ int rv = len;
if (mddev->pers)
return -EBUSY;
if (len == 0)
@@ -2528,8 +2425,6 @@ array_state_show(mddev_t *mddev, char *page)
case 0:
if (mddev->in_sync)
st = clean;
- else if (test_bit(MD_CHANGE_CLEAN, &mddev->flags))
- st = write_pending;
else if (mddev->safemode)
st = active_idle;
else
@@ -2560,9 +2455,11 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
break;
case clear:
/* stopping an active array */
- if (atomic_read(&mddev->active) > 1)
- return -EBUSY;
- err = do_md_stop(mddev, 0);
+ if (mddev->pers) {
+ if (atomic_read(&mddev->active) > 1)
+ return -EBUSY;
+ err = do_md_stop(mddev, 0);
+ }
break;
case inactive:
/* stopping an active array */
@@ -2570,8 +2467,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
if (atomic_read(&mddev->active) > 1)
return -EBUSY;
err = do_md_stop(mddev, 2);
- } else
- err = 0; /* already inactive */
+ }
break;
case suspended:
break; /* not supported yet */
@@ -2599,15 +2495,9 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
restart_array(mddev);
spin_lock_irq(&mddev->write_lock);
if (atomic_read(&mddev->writes_pending) == 0) {
- if (mddev->in_sync == 0) {
- mddev->in_sync = 1;
- if (mddev->persistent)
- set_bit(MD_CHANGE_CLEAN,
- &mddev->flags);
- }
- err = 0;
- } else
- err = -EBUSY;
+ mddev->in_sync = 1;
+ set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+ }
spin_unlock_irq(&mddev->write_lock);
} else {
mddev->ro = 0;
@@ -2618,8 +2508,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
case active:
if (mddev->pers) {
restart_array(mddev);
- if (mddev->external)
- clear_bit(MD_CHANGE_CLEAN, &mddev->flags);
+ clear_bit(MD_CHANGE_CLEAN, &mddev->flags);
wake_up(&mddev->sb_wait);
err = 0;
} else {
@@ -2685,9 +2574,7 @@ new_dev_store(mddev_t *mddev, const char *buf, size_t len)
if (err < 0)
goto out;
}
- } else if (mddev->external)
- rdev = md_import_device(dev, -2, -1);
- else
+ } else
rdev = md_import_device(dev, -1, -1);
if (IS_ERR(rdev))
@@ -2772,9 +2659,7 @@ __ATTR(component_size, S_IRUGO|S_IWUSR, size_show, size_store);
/* Metdata version.
- * This is one of
- * 'none' for arrays with no metadata (good luck...)
- * 'external' for arrays with externally managed metadata,
+ * This is either 'none' for arrays with externally managed metadata,
* or N.M for internally known formats
*/
static ssize_t
@@ -2783,8 +2668,6 @@ metadata_show(mddev_t *mddev, char *page)
if (mddev->persistent)
return sprintf(page, "%d.%d\n",
mddev->major_version, mddev->minor_version);
- else if (mddev->external)
- return sprintf(page, "external:%s\n", mddev->metadata_type);
else
return sprintf(page, "none\n");
}
@@ -2799,21 +2682,6 @@ metadata_store(mddev_t *mddev, const char *buf, size_t len)
if (cmd_match(buf, "none")) {
mddev->persistent = 0;
- mddev->external = 0;
- mddev->major_version = 0;
- mddev->minor_version = 90;
- return len;
- }
- if (strncmp(buf, "external:", 9) == 0) {
- size_t namelen = len-9;
- if (namelen >= sizeof(mddev->metadata_type))
- namelen = sizeof(mddev->metadata_type)-1;
- strncpy(mddev->metadata_type, buf+9, namelen);
- mddev->metadata_type[namelen] = 0;
- if (namelen && mddev->metadata_type[namelen-1] == '\n')
- mddev->metadata_type[--namelen] = 0;
- mddev->persistent = 0;
- mddev->external = 1;
mddev->major_version = 0;
mddev->minor_version = 90;
return len;
@@ -2830,7 +2698,6 @@ metadata_store(mddev_t *mddev, const char *buf, size_t len)
mddev->major_version = major;
mddev->minor_version = minor;
mddev->persistent = 1;
- mddev->external = 0;
return len;
}
@@ -2997,43 +2864,6 @@ sync_completed_show(mddev_t *mddev, char *page)
static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed);
-static ssize_t
-max_sync_show(mddev_t *mddev, char *page)
-{
- if (mddev->resync_max == MaxSector)
- return sprintf(page, "max\n");
- else
- return sprintf(page, "%llu\n",
- (unsigned long long)mddev->resync_max);
-}
-static ssize_t
-max_sync_store(mddev_t *mddev, const char *buf, size_t len)
-{
- if (strncmp(buf, "max", 3) == 0)
- mddev->resync_max = MaxSector;
- else {
- char *ep;
- unsigned long long max = simple_strtoull(buf, &ep, 10);
- if (ep == buf || (*ep != 0 && *ep != '\n'))
- return -EINVAL;
- if (max < mddev->resync_max &&
- test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
- return -EBUSY;
-
- /* Must be a multiple of chunk_size */
- if (mddev->chunk_size) {
- if (max & (sector_t)((mddev->chunk_size>>9)-1))
- return -EINVAL;
- }
- mddev->resync_max = max;
- }
- wake_up(&mddev->recovery_wait);
- return len;
-}
-
-static struct md_sysfs_entry md_max_sync =
-__ATTR(sync_max, S_IRUGO|S_IWUSR, max_sync_show, max_sync_store);
-
static ssize_t
suspend_lo_show(mddev_t *mddev, char *page)
{
@@ -3144,7 +2974,6 @@ static struct attribute *md_redundancy_attrs[] = {
&md_sync_max.attr,
&md_sync_speed.attr,
&md_sync_completed.attr,
- &md_max_sync.attr,
&md_suspend_lo.attr,
&md_suspend_hi.attr,
&md_bitmap.attr,
@@ -3289,11 +3118,8 @@ static int do_md_run(mddev_t * mddev)
/*
* Analyze all RAID superblock(s)
*/
- if (!mddev->raid_disks) {
- if (!mddev->persistent)
- return -EINVAL;
+ if (!mddev->raid_disks)
analyze_sbs(mddev);
- }
chunk_size = mddev->chunk_size;
@@ -3317,7 +3143,7 @@ static int do_md_run(mddev_t * mddev)
}
/* devices must have minimum size of one chunk */
- rdev_for_each(rdev, tmp, mddev) {
+ ITERATE_RDEV(mddev,rdev,tmp) {
if (test_bit(Faulty, &rdev->flags))
continue;
if (rdev->size < chunk_size / 1024) {
@@ -3344,7 +3170,7 @@ static int do_md_run(mddev_t * mddev)
* the only valid external interface is through the md
* device.
*/
- rdev_for_each(rdev, tmp, mddev) {
+ ITERATE_RDEV(mddev,rdev,tmp) {
if (test_bit(Faulty, &rdev->flags))
continue;
sync_blockdev(rdev->bdev);
@@ -3410,8 +3236,8 @@ static int do_md_run(mddev_t * mddev)
mdk_rdev_t *rdev2;
struct list_head *tmp2;
int warned = 0;
- rdev_for_each(rdev, tmp, mddev) {
- rdev_for_each(rdev2, tmp2, mddev) {
+ ITERATE_RDEV(mddev, rdev, tmp) {
+ ITERATE_RDEV(mddev, rdev2, tmp2) {
if (rdev < rdev2 &&
rdev->bdev->bd_contains ==
rdev2->bdev->bd_contains) {
@@ -3471,7 +3297,7 @@ static int do_md_run(mddev_t * mddev)
mddev->safemode_delay = (200 * HZ)/1000 +1; /* 200 msec delay */
mddev->in_sync = 1;
- rdev_for_each(rdev, tmp, mddev)
+ ITERATE_RDEV(mddev,rdev,tmp)
if (rdev->raid_disk >= 0) {
char nm[20];
sprintf(nm, "rd%d", rdev->raid_disk);
@@ -3504,7 +3330,7 @@ static int do_md_run(mddev_t * mddev)
if (mddev->degraded && !mddev->sync_thread) {
struct list_head *rtmp;
int spares = 0;
- rdev_for_each(rdev, rtmp, mddev)
+ ITERATE_RDEV(mddev,rdev,rtmp)
if (rdev->raid_disk >= 0 &&
!test_bit(In_sync, &rdev->flags) &&
!test_bit(Faulty, &rdev->flags))
@@ -3681,14 +3507,14 @@ static int do_md_stop(mddev_t * mddev, int mode)
}
mddev->bitmap_offset = 0;
- rdev_for_each(rdev, tmp, mddev)
+ ITERATE_RDEV(mddev,rdev,tmp)
if (rdev->raid_disk >= 0) {
char nm[20];
sprintf(nm, "rd%d", rdev->raid_disk);
sysfs_remove_link(&mddev->kobj, nm);
}
- /* make sure all md_delayed_delete calls have finished */
+ /* make sure all delayed_delete calls have finished */
flush_scheduled_work();
export_array(mddev);
@@ -3697,10 +3523,7 @@ static int do_md_stop(mddev_t * mddev, int mode)
mddev->size = 0;
mddev->raid_disks = 0;
mddev->recovery_cp = 0;
- mddev->resync_max = MaxSector;
mddev->reshape_position = MaxSector;
- mddev->external = 0;
- mddev->persistent = 0;
} else if (mddev->pers)
printk(KERN_INFO "md: %s switched to read-only mode.\n",
@@ -3723,7 +3546,7 @@ static void autorun_array(mddev_t *mddev)
printk(KERN_INFO "md: running: ");
- rdev_for_each(rdev, tmp, mddev) {
+ ITERATE_RDEV(mddev,rdev,tmp) {
char b[BDEVNAME_SIZE];
printk("<%s>", bdevname(rdev->bdev,b));
}
@@ -3766,7 +3589,7 @@ static void autorun_devices(int part)
printk(KERN_INFO "md: considering %s ...\n",
bdevname(rdev0->bdev,b));
INIT_LIST_HEAD(&candidates);
- rdev_for_each_list(rdev, tmp, pending_raid_disks)
+ ITERATE_RDEV_PENDING(rdev,tmp)
if (super_90_load(rdev, rdev0, 0) >= 0) {
printk(KERN_INFO "md: adding %s ...\n",
bdevname(rdev->bdev,b));
@@ -3809,8 +3632,7 @@ static void autorun_devices(int part)
mddev_unlock(mddev);
} else {
printk(KERN_INFO "md: created %s\n", mdname(mddev));
- mddev->persistent = 1;
- rdev_for_each_list(rdev, tmp, candidates) {
+ ITERATE_RDEV_GENERIC(candidates,rdev,tmp) {
list_del_init(&rdev->same_set);
if (bind_rdev_to_array(rdev, mddev))
export_rdev(rdev);
@@ -3821,7 +3643,7 @@ static void autorun_devices(int part)
/* on success, candidates will be empty, on error
* it won't...
*/
- rdev_for_each_list(rdev, tmp, candidates)
+ ITERATE_RDEV_GENERIC(candidates,rdev,tmp)
export_rdev(rdev);
mddev_put(mddev);
}
@@ -3851,7 +3673,7 @@ static int get_array_info(mddev_t * mddev, void __user * arg)
struct list_head *tmp;
nr=working=active=failed=spare=0;
- rdev_for_each(rdev, tmp, mddev) {
+ ITERATE_RDEV(mddev,rdev,tmp) {
nr++;
if (test_bit(Faulty, &rdev->flags))
failed++;
@@ -4097,6 +3919,8 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
else
rdev->raid_disk = -1;
+ rdev->flags = 0;
+
if (rdev->raid_disk < mddev->raid_disks)
if (info->state & (1<flags);
@@ -4341,15 +4165,13 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
else
mddev->recovery_cp = 0;
mddev->persistent = ! info->not_persistent;
- mddev->external = 0;
mddev->layout = info->layout;
mddev->chunk_size = info->chunk_size;
mddev->max_disks = MD_SB_DISKS;
- if (mddev->persistent)
- mddev->flags = 0;
+ mddev->flags = 0;
set_bit(MD_CHANGE_DEVS, &mddev->flags);
mddev->default_bitmap_offset = MD_SB_BYTES >> 9;
@@ -4391,7 +4213,7 @@ static int update_size(mddev_t *mddev, unsigned long size)
*/
if (mddev->sync_thread)
return -EBUSY;
- rdev_for_each(rdev, tmp, mddev) {
+ ITERATE_RDEV(mddev,rdev,tmp) {
sector_t avail;
avail = rdev->size * 2;
@@ -4649,10 +4471,9 @@ static int md_ioctl(struct inode *inode, struct file *file,
*/
/* if we are not initialised yet, only ADD_NEW_DISK, STOP_ARRAY,
* RUN_ARRAY, and GET_ and SET_BITMAP_FILE are allowed */
- if ((!mddev->raid_disks && !mddev->external)
- && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY
- && cmd != RUN_ARRAY && cmd != SET_BITMAP_FILE
- && cmd != GET_BITMAP_FILE) {
+ if (!mddev->raid_disks && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY
+ && cmd != RUN_ARRAY && cmd != SET_BITMAP_FILE
+ && cmd != GET_BITMAP_FILE) {
err = -ENODEV;
goto abort_unlock;
}
@@ -4936,7 +4757,7 @@ static void status_unused(struct seq_file *seq)
seq_printf(seq, "unused devices: ");
- rdev_for_each_list(rdev, tmp, pending_raid_disks) {
+ ITERATE_RDEV_PENDING(rdev,tmp) {
char b[BDEVNAME_SIZE];
i++;
seq_printf(seq, "%s ",
@@ -5132,7 +4953,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
}
size = 0;
- rdev_for_each(rdev, tmp2, mddev) {
+ ITERATE_RDEV(mddev,rdev,tmp2) {
char b[BDEVNAME_SIZE];
seq_printf(seq, " %s[%d]",
bdevname(rdev->bdev,b), rdev->desc_nr);
@@ -5161,10 +4982,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
mddev->major_version,
mddev->minor_version);
}
- } else if (mddev->external)
- seq_printf(seq, " super external:%s",
- mddev->metadata_type);
- else
+ } else
seq_printf(seq, " super non-persistent");
if (mddev->pers) {
@@ -5288,7 +5106,7 @@ static int is_mddev_idle(mddev_t *mddev)
long curr_events;
idle = 1;
- rdev_for_each(rdev, tmp, mddev) {
+ ITERATE_RDEV(mddev,rdev,tmp) {
struct gendisk *disk = rdev->bdev->bd_contains->bd_disk;
curr_events = disk_stat_read(disk, sectors[0]) +
disk_stat_read(disk, sectors[1]) -
@@ -5465,7 +5283,7 @@ void md_do_sync(mddev_t *mddev)
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
goto skip;
}
- for_each_mddev(mddev2, tmp) {
+ ITERATE_MDDEV(mddev2,tmp) {
if (mddev2 == mddev)
continue;
if (mddev2->curr_resync &&
@@ -5515,7 +5333,7 @@ void md_do_sync(mddev_t *mddev)
/* recovery follows the physical size of devices */
max_sectors = mddev->size << 1;
j = MaxSector;
- rdev_for_each(rdev, rtmp, mddev)
+ ITERATE_RDEV(mddev,rdev,rtmp)
if (rdev->raid_disk >= 0 &&
!test_bit(Faulty, &rdev->flags) &&
!test_bit(In_sync, &rdev->flags) &&
@@ -5563,16 +5381,8 @@ void md_do_sync(mddev_t *mddev)
sector_t sectors;
skipped = 0;
- if (j >= mddev->resync_max) {
- sysfs_notify(&mddev->kobj, NULL, "sync_completed");
- wait_event(mddev->recovery_wait,
- mddev->resync_max > j
- || kthread_should_stop());
- }
- if (kthread_should_stop())
- goto interrupted;
sectors = mddev->pers->sync_request(mddev, j, &skipped,
- currspeed < speed_min(mddev));
+ currspeed < speed_min(mddev));
if (sectors == 0) {
set_bit(MD_RECOVERY_ERR, &mddev->recovery);
goto out;
@@ -5614,9 +5424,15 @@ void md_do_sync(mddev_t *mddev)
}
- if (kthread_should_stop())
- goto interrupted;
-
+ if (kthread_should_stop()) {
+ /*
+ * got a signal, exit.
+ */
+ printk(KERN_INFO
+ "md: md_do_sync() got signal ... exiting\n");
+ set_bit(MD_RECOVERY_INTR, &mddev->recovery);
+ goto out;
+ }
/*
* this loop exits only if either when we are slower than
@@ -5668,7 +5484,7 @@ void md_do_sync(mddev_t *mddev)
} else {
if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery))
mddev->curr_resync = MaxSector;
- rdev_for_each(rdev, rtmp, mddev)
+ ITERATE_RDEV(mddev,rdev,rtmp)
if (rdev->raid_disk >= 0 &&
!test_bit(Faulty, &rdev->flags) &&
!test_bit(In_sync, &rdev->flags) &&
@@ -5680,22 +5496,9 @@ void md_do_sync(mddev_t *mddev)
skip:
mddev->curr_resync = 0;
- mddev->resync_max = MaxSector;
- sysfs_notify(&mddev->kobj, NULL, "sync_completed");
wake_up(&resync_wait);
set_bit(MD_RECOVERY_DONE, &mddev->recovery);
md_wakeup_thread(mddev->thread);
- return;
-
- interrupted:
- /*
- * got a signal, exit.
- */
- printk(KERN_INFO
- "md: md_do_sync() got signal ... exiting\n");
- set_bit(MD_RECOVERY_INTR, &mddev->recovery);
- goto out;
-
}
EXPORT_SYMBOL_GPL(md_do_sync);
@@ -5706,9 +5509,8 @@ static int remove_and_add_spares(mddev_t *mddev)
struct list_head *rtmp;
int spares = 0;
- rdev_for_each(rdev, rtmp, mddev)
+ ITERATE_RDEV(mddev,rdev,rtmp)
if (rdev->raid_disk >= 0 &&
- !mddev->external &&
(test_bit(Faulty, &rdev->flags) ||
! test_bit(In_sync, &rdev->flags)) &&
atomic_read(&rdev->nr_pending)==0) {
@@ -5722,7 +5524,7 @@ static int remove_and_add_spares(mddev_t *mddev)
}
if (mddev->degraded) {
- rdev_for_each(rdev, rtmp, mddev)
+ ITERATE_RDEV(mddev,rdev,rtmp)
if (rdev->raid_disk < 0
&& !test_bit(Faulty, &rdev->flags)) {
rdev->recovery_offset = 0;
@@ -5787,7 +5589,7 @@ void md_check_recovery(mddev_t *mddev)
}
if ( ! (
- (mddev->flags && !mddev->external) ||
+ mddev->flags ||
test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
(mddev->safemode == 1) ||
@@ -5803,8 +5605,7 @@ void md_check_recovery(mddev_t *mddev)
if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
!mddev->in_sync && mddev->recovery_cp == MaxSector) {
mddev->in_sync = 1;
- if (mddev->persistent)
- set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+ set_bit(MD_CHANGE_CLEAN, &mddev->flags);
}
if (mddev->safemode == 1)
mddev->safemode = 0;
@@ -5836,7 +5637,7 @@ void md_check_recovery(mddev_t *mddev)
* information must be scrapped
*/
if (!mddev->degraded)
- rdev_for_each(rdev, rtmp, mddev)
+ ITERATE_RDEV(mddev,rdev,rtmp)
rdev->saved_raid_disk = -1;
mddev->recovery = 0;
@@ -5913,7 +5714,7 @@ static int md_notify_reboot(struct notifier_block *this,
printk(KERN_INFO "md: stopping all md devices.\n");
- for_each_mddev(mddev, tmp)
+ ITERATE_MDDEV(mddev,tmp)
if (mddev_trylock(mddev)) {
do_md_stop (mddev, 1);
mddev_unlock(mddev);
@@ -6047,7 +5848,7 @@ static __exit void md_exit(void)
unregister_reboot_notifier(&md_notifier);
unregister_sysctl_table(raid_table_header);
remove_proc_entry("mdstat", NULL);
- for_each_mddev(mddev, tmp) {
+ ITERATE_MDDEV(mddev,tmp) {
struct gendisk *disk = mddev->gendisk;
if (!disk)
continue;
diff --git a/trunk/drivers/md/mktables.c b/trunk/drivers/md/mktables.c
index b61d5767aae7..adef299908cf 100644
--- a/trunk/drivers/md/mktables.c
+++ b/trunk/drivers/md/mktables.c
@@ -1,10 +1,13 @@
-/* -*- linux-c -*- ------------------------------------------------------- *
+#ident "$Id: mktables.c,v 1.2 2002/12/12 22:41:27 hpa Exp $"
+/* ----------------------------------------------------------------------- *
*
- * Copyright 2002-2007 H. Peter Anvin - All Rights Reserved
+ * Copyright 2002 H. Peter Anvin - All Rights Reserved
*
- * This file is part of the Linux kernel, and is made available under
- * the terms of the GNU General Public License version 2 or (at your
- * option) any later version; incorporated herein by reference.
+ * 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, Inc., 53 Temple Place Ste 330,
+ * Bostom MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
*
* ----------------------------------------------------------------------- */
@@ -23,98 +26,100 @@
static uint8_t gfmul(uint8_t a, uint8_t b)
{
- uint8_t v = 0;
-
- while (b) {
- if (b & 1)
- v ^= a;
- a = (a << 1) ^ (a & 0x80 ? 0x1d : 0);
- b >>= 1;
- }
-
- return v;
+ uint8_t v = 0;
+
+ while ( b ) {
+ if ( b & 1 ) v ^= a;
+ a = (a << 1) ^ (a & 0x80 ? 0x1d : 0);
+ b >>= 1;
+ }
+ return v;
}
static uint8_t gfpow(uint8_t a, int b)
{
- uint8_t v = 1;
-
- b %= 255;
- if (b < 0)
- b += 255;
-
- while (b) {
- if (b & 1)
- v = gfmul(v, a);
- a = gfmul(a, a);
- b >>= 1;
- }
-
- return v;
+ uint8_t v = 1;
+
+ b %= 255;
+ if ( b < 0 )
+ b += 255;
+
+ while ( b ) {
+ if ( b & 1 ) v = gfmul(v,a);
+ a = gfmul(a,a);
+ b >>= 1;
+ }
+ return v;
}
int main(int argc, char *argv[])
{
- int i, j, k;
- uint8_t v;
- uint8_t exptbl[256], invtbl[256];
-
- printf("#include \"raid6.h\"\n");
-
- /* Compute multiplication table */
- printf("\nconst u8 __attribute__((aligned(256)))\n"
- "raid6_gfmul[256][256] =\n"
- "{\n");
- for (i = 0; i < 256; i++) {
- printf("\t{\n");
- for (j = 0; j < 256; j += 8) {
- printf("\t\t");
- for (k = 0; k < 8; k++)
- printf("0x%02x,%c", gfmul(i, j + k),
- (k == 7) ? '\n' : ' ');
- }
- printf("\t},\n");
- }
- printf("};\n");
-
- /* Compute power-of-2 table (exponent) */
- v = 1;
- printf("\nconst u8 __attribute__((aligned(256)))\n"
- "raid6_gfexp[256] =\n" "{\n");
- for (i = 0; i < 256; i += 8) {
- printf("\t");
- for (j = 0; j < 8; j++) {
- exptbl[i + j] = v;
- printf("0x%02x,%c", v, (j == 7) ? '\n' : ' ');
- v = gfmul(v, 2);
- if (v == 1)
- v = 0; /* For entry 255, not a real entry */
- }
- }
- printf("};\n");
-
- /* Compute inverse table x^-1 == x^254 */
- printf("\nconst u8 __attribute__((aligned(256)))\n"
- "raid6_gfinv[256] =\n" "{\n");
- for (i = 0; i < 256; i += 8) {
- printf("\t");
- for (j = 0; j < 8; j++) {
- invtbl[i + j] = v = gfpow(i + j, 254);
- printf("0x%02x,%c", v, (j == 7) ? '\n' : ' ');
- }
- }
- printf("};\n");
-
- /* Compute inv(2^x + 1) (exponent-xor-inverse) table */
- printf("\nconst u8 __attribute__((aligned(256)))\n"
- "raid6_gfexi[256] =\n" "{\n");
- for (i = 0; i < 256; i += 8) {
- printf("\t");
- for (j = 0; j < 8; j++)
- printf("0x%02x,%c", invtbl[exptbl[i + j] ^ 1],
- (j == 7) ? '\n' : ' ');
- }
- printf("};\n");
-
- return 0;
+ int i, j, k;
+ uint8_t v;
+ uint8_t exptbl[256], invtbl[256];
+
+ printf("#include \"raid6.h\"\n");
+
+ /* Compute multiplication table */
+ printf("\nconst u8 __attribute__((aligned(256)))\n"
+ "raid6_gfmul[256][256] =\n"
+ "{\n");
+ for ( i = 0 ; i < 256 ; i++ ) {
+ printf("\t{\n");
+ for ( j = 0 ; j < 256 ; j += 8 ) {
+ printf("\t\t");
+ for ( k = 0 ; k < 8 ; k++ ) {
+ printf("0x%02x, ", gfmul(i,j+k));
+ }
+ printf("\n");
+ }
+ printf("\t},\n");
+ }
+ printf("};\n");
+
+ /* Compute power-of-2 table (exponent) */
+ v = 1;
+ printf("\nconst u8 __attribute__((aligned(256)))\n"
+ "raid6_gfexp[256] =\n"
+ "{\n");
+ for ( i = 0 ; i < 256 ; i += 8 ) {
+ printf("\t");
+ for ( j = 0 ; j < 8 ; j++ ) {
+ exptbl[i+j] = v;
+ printf("0x%02x, ", v);
+ v = gfmul(v,2);
+ if ( v == 1 ) v = 0; /* For entry 255, not a real entry */
+ }
+ printf("\n");
+ }
+ printf("};\n");
+
+ /* Compute inverse table x^-1 == x^254 */
+ printf("\nconst u8 __attribute__((aligned(256)))\n"
+ "raid6_gfinv[256] =\n"
+ "{\n");
+ for ( i = 0 ; i < 256 ; i += 8 ) {
+ printf("\t");
+ for ( j = 0 ; j < 8 ; j++ ) {
+ invtbl[i+j] = v = gfpow(i+j,254);
+ printf("0x%02x, ", v);
+ }
+ printf("\n");
+ }
+ printf("};\n");
+
+ /* Compute inv(2^x + 1) (exponent-xor-inverse) table */
+ printf("\nconst u8 __attribute__((aligned(256)))\n"
+ "raid6_gfexi[256] =\n"
+ "{\n");
+ for ( i = 0 ; i < 256 ; i += 8 ) {
+ printf("\t");
+ for ( j = 0 ; j < 8 ; j++ ) {
+ printf("0x%02x, ", invtbl[exptbl[i+j]^1]);
+ }
+ printf("\n");
+ }
+ printf("};\n\n");
+
+ return 0;
}
diff --git a/trunk/drivers/md/multipath.c b/trunk/drivers/md/multipath.c
index 3f299d835a2b..eb631ebed686 100644
--- a/trunk/drivers/md/multipath.c
+++ b/trunk/drivers/md/multipath.c
@@ -436,7 +436,7 @@ static int multipath_run (mddev_t *mddev)
}
conf->working_disks = 0;
- rdev_for_each(rdev, tmp, mddev) {
+ ITERATE_RDEV(mddev,rdev,tmp) {
disk_idx = rdev->raid_disk;
if (disk_idx < 0 ||
disk_idx >= mddev->raid_disks)
diff --git a/trunk/drivers/md/raid0.c b/trunk/drivers/md/raid0.c
index 818b48284096..f8e591708d1f 100644
--- a/trunk/drivers/md/raid0.c
+++ b/trunk/drivers/md/raid0.c
@@ -72,11 +72,11 @@ static int create_strip_zones (mddev_t *mddev)
*/
conf->nr_strip_zones = 0;
- rdev_for_each(rdev1, tmp1, mddev) {
+ ITERATE_RDEV(mddev,rdev1,tmp1) {
printk("raid0: looking at %s\n",
bdevname(rdev1->bdev,b));
c = 0;
- rdev_for_each(rdev2, tmp2, mddev) {
+ ITERATE_RDEV(mddev,rdev2,tmp2) {
printk("raid0: comparing %s(%llu)",
bdevname(rdev1->bdev,b),
(unsigned long long)rdev1->size);
@@ -124,7 +124,7 @@ static int create_strip_zones (mddev_t *mddev)
cnt = 0;
smallest = NULL;
zone->dev = conf->devlist;
- rdev_for_each(rdev1, tmp1, mddev) {
+ ITERATE_RDEV(mddev, rdev1, tmp1) {
int j = rdev1->raid_disk;
if (j < 0 || j >= mddev->raid_disks) {
@@ -293,7 +293,7 @@ static int raid0_run (mddev_t *mddev)
/* calculate array device size */
mddev->array_size = 0;
- rdev_for_each(rdev, tmp, mddev)
+ ITERATE_RDEV(mddev,rdev,tmp)
mddev->array_size += rdev->size;
printk("raid0 : md_size is %llu blocks.\n",
diff --git a/trunk/drivers/md/raid1.c b/trunk/drivers/md/raid1.c
index 5c7fef091cec..4a69c416e045 100644
--- a/trunk/drivers/md/raid1.c
+++ b/trunk/drivers/md/raid1.c
@@ -1684,7 +1684,6 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
if (!go_faster && conf->nr_waiting)
msleep_interruptible(1000);
- bitmap_cond_end_sync(mddev->bitmap, sector_nr);
raise_barrier(conf);
conf->next_resync = sector_nr;
@@ -1767,8 +1766,6 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
return rv;
}
- if (max_sector > mddev->resync_max)
- max_sector = mddev->resync_max; /* Don't do IO beyond here */
nr_sectors = 0;
sync_blocks = 0;
do {
@@ -1887,7 +1884,7 @@ static int run(mddev_t *mddev)
if (!conf->r1bio_pool)
goto out_no_mem;
- rdev_for_each(rdev, tmp, mddev) {
+ ITERATE_RDEV(mddev, rdev, tmp) {
disk_idx = rdev->raid_disk;
if (disk_idx >= mddev->raid_disks
|| disk_idx < 0)
diff --git a/trunk/drivers/md/raid10.c b/trunk/drivers/md/raid10.c
index 017f58113c33..5cdcc9386200 100644
--- a/trunk/drivers/md/raid10.c
+++ b/trunk/drivers/md/raid10.c
@@ -1657,9 +1657,6 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
return (max_sector - sector_nr) + sectors_skipped;
}
- if (max_sector > mddev->resync_max)
- max_sector = mddev->resync_max; /* Don't do IO beyond here */
-
/* make sure whole request will fit in a chunk - if chunks
* are meaningful
*/
@@ -1673,8 +1670,6 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
if (!go_faster && conf->nr_waiting)
msleep_interruptible(1000);
- bitmap_cond_end_sync(mddev->bitmap, sector_nr);
-
/* Again, very different code for resync and recovery.
* Both must result in an r10bio with a list of bios that
* have bi_end_io, bi_sector, bi_bdev set,
@@ -2026,7 +2021,7 @@ static int run(mddev_t *mddev)
goto out_free_conf;
}
- rdev_for_each(rdev, tmp, mddev) {
+ ITERATE_RDEV(mddev, rdev, tmp) {
disk_idx = rdev->raid_disk;
if (disk_idx >= mddev->raid_disks
|| disk_idx < 0)
diff --git a/trunk/drivers/md/raid5.c b/trunk/drivers/md/raid5.c
index 2d6f1a51359c..e8c8157b02fc 100644
--- a/trunk/drivers/md/raid5.c
+++ b/trunk/drivers/md/raid5.c
@@ -3159,8 +3159,7 @@ static void raid5_activate_delayed(raid5_conf_t *conf)
atomic_inc(&conf->preread_active_stripes);
list_add_tail(&sh->lru, &conf->handle_list);
}
- } else
- blk_plug_device(conf->mddev->queue);
+ }
}
static void activate_bit_delay(raid5_conf_t *conf)
@@ -3550,8 +3549,7 @@ static int make_request(struct request_queue *q, struct bio * bi)
goto retry;
}
finish_wait(&conf->wait_for_overlap, &w);
- set_bit(STRIPE_HANDLE, &sh->state);
- clear_bit(STRIPE_DELAYED, &sh->state);
+ handle_stripe(sh, NULL);
release_stripe(sh);
} else {
/* cannot get stripe for read-ahead, just give-up */
@@ -3700,25 +3698,6 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
release_stripe(sh);
first_sector += STRIPE_SECTORS;
}
- /* If this takes us to the resync_max point where we have to pause,
- * then we need to write out the superblock.
- */
- sector_nr += conf->chunk_size>>9;
- if (sector_nr >= mddev->resync_max) {
- /* Cannot proceed until we've updated the superblock... */
- wait_event(conf->wait_for_overlap,
- atomic_read(&conf->reshape_stripes) == 0);
- mddev->reshape_position = conf->expand_progress;
- set_bit(MD_CHANGE_DEVS, &mddev->flags);
- md_wakeup_thread(mddev->thread);
- wait_event(mddev->sb_wait,
- !test_bit(MD_CHANGE_DEVS, &mddev->flags)
- || kthread_should_stop());
- spin_lock_irq(&conf->device_lock);
- conf->expand_lo = mddev->reshape_position;
- spin_unlock_irq(&conf->device_lock);
- wake_up(&conf->wait_for_overlap);
- }
return conf->chunk_size>>9;
}
@@ -3755,12 +3734,6 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski
if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
return reshape_request(mddev, sector_nr, skipped);
- /* No need to check resync_max as we never do more than one
- * stripe, and as resync_max will always be on a chunk boundary,
- * if the check in md_do_sync didn't fire, there is no chance
- * of overstepping resync_max here
- */
-
/* if there is too many failed drives and we are trying
* to resync, then assert that we are finished, because there is
* nothing we can do.
@@ -3780,9 +3753,6 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski
return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */
}
-
- bitmap_cond_end_sync(mddev->bitmap, sector_nr);
-
pd_idx = stripe_to_pdidx(sector_nr, conf, raid_disks);
sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 1);
if (sh == NULL) {
@@ -3894,7 +3864,7 @@ static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio)
* During the scan, completed stripes are saved for us by the interrupt
* handler, so that they will not have to wait for our next wakeup.
*/
-static void raid5d(mddev_t *mddev)
+static void raid5d (mddev_t *mddev)
{
struct stripe_head *sh;
raid5_conf_t *conf = mddev_to_conf(mddev);
@@ -3919,6 +3889,12 @@ static void raid5d(mddev_t *mddev)
activate_bit_delay(conf);
}
+ if (list_empty(&conf->handle_list) &&
+ atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD &&
+ !blk_queue_plugged(mddev->queue) &&
+ !list_empty(&conf->delayed_list))
+ raid5_activate_delayed(conf);
+
while ((bio = remove_bio_from_retry(conf))) {
int ok;
spin_unlock_irq(&conf->device_lock);
@@ -4132,7 +4108,7 @@ static int run(mddev_t *mddev)
pr_debug("raid5: run(%s) called.\n", mdname(mddev));
- rdev_for_each(rdev, tmp, mddev) {
+ ITERATE_RDEV(mddev,rdev,tmp) {
raid_disk = rdev->raid_disk;
if (raid_disk >= conf->raid_disks
|| raid_disk < 0)
@@ -4545,7 +4521,7 @@ static int raid5_start_reshape(mddev_t *mddev)
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
return -EBUSY;
- rdev_for_each(rdev, rtmp, mddev)
+ ITERATE_RDEV(mddev, rdev, rtmp)
if (rdev->raid_disk < 0 &&
!test_bit(Faulty, &rdev->flags))
spares++;
@@ -4567,7 +4543,7 @@ static int raid5_start_reshape(mddev_t *mddev)
/* Add some new drives, as many as will fit.
* We know there are enough to make the newly sized array work.
*/
- rdev_for_each(rdev, rtmp, mddev)
+ ITERATE_RDEV(mddev, rdev, rtmp)
if (rdev->raid_disk < 0 &&
!test_bit(Faulty, &rdev->flags)) {
if (raid5_add_disk(mddev, rdev)) {
diff --git a/trunk/drivers/md/raid6test/test.c b/trunk/drivers/md/raid6test/test.c
index 559cc41b2585..0d5cd57accd7 100644
--- a/trunk/drivers/md/raid6test/test.c
+++ b/trunk/drivers/md/raid6test/test.c
@@ -1,10 +1,12 @@
/* -*- linux-c -*- ------------------------------------------------------- *
*
- * Copyright 2002-2007 H. Peter Anvin - All Rights Reserved
+ * Copyright 2002 H. Peter Anvin - All Rights Reserved
*
- * This file is part of the Linux kernel, and is made available under
- * the terms of the GNU General Public License version 2 or (at your
- * option) any later version; incorporated herein by reference.
+ * 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, Inc., 53 Temple Place Ste 330,
+ * Bostom MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
*
* ----------------------------------------------------------------------- */
@@ -28,87 +30,67 @@ char *dataptrs[NDISKS];
char data[NDISKS][PAGE_SIZE];
char recovi[PAGE_SIZE], recovj[PAGE_SIZE];
-static void makedata(void)
+void makedata(void)
{
int i, j;
- for (i = 0; i < NDISKS; i++) {
- for (j = 0; j < PAGE_SIZE; j++)
+ for ( i = 0 ; i < NDISKS ; i++ ) {
+ for ( j = 0 ; j < PAGE_SIZE ; j++ ) {
data[i][j] = rand();
-
+ }
dataptrs[i] = data[i];
}
}
-static char disk_type(int d)
-{
- switch (d) {
- case NDISKS-2:
- return 'P';
- case NDISKS-1:
- return 'Q';
- default:
- return 'D';
- }
-}
-
-static int test_disks(int i, int j)
-{
- int erra, errb;
-
- memset(recovi, 0xf0, PAGE_SIZE);
- memset(recovj, 0xba, PAGE_SIZE);
-
- dataptrs[i] = recovi;
- dataptrs[j] = recovj;
-
- raid6_dual_recov(NDISKS, PAGE_SIZE, i, j, (void **)&dataptrs);
-
- erra = memcmp(data[i], recovi, PAGE_SIZE);
- errb = memcmp(data[j], recovj, PAGE_SIZE);
-
- if (i < NDISKS-2 && j == NDISKS-1) {
- /* We don't implement the DQ failure scenario, since it's
- equivalent to a RAID-5 failure (XOR, then recompute Q) */
- erra = errb = 0;
- } else {
- printf("algo=%-8s faila=%3d(%c) failb=%3d(%c) %s\n",
- raid6_call.name,
- i, disk_type(i),
- j, disk_type(j),
- (!erra && !errb) ? "OK" :
- !erra ? "ERRB" :
- !errb ? "ERRA" : "ERRAB");
- }
-
- dataptrs[i] = data[i];
- dataptrs[j] = data[j];
-
- return erra || errb;
-}
-
int main(int argc, char *argv[])
{
- const struct raid6_calls *const *algo;
+ const struct raid6_calls * const * algo;
int i, j;
- int err = 0;
+ int erra, errb;
makedata();
- for (algo = raid6_algos; *algo; algo++) {
- if (!(*algo)->valid || (*algo)->valid()) {
+ for ( algo = raid6_algos ; *algo ; algo++ ) {
+ if ( !(*algo)->valid || (*algo)->valid() ) {
raid6_call = **algo;
/* Nuke syndromes */
memset(data[NDISKS-2], 0xee, 2*PAGE_SIZE);
/* Generate assumed good syndrome */
- raid6_call.gen_syndrome(NDISKS, PAGE_SIZE,
- (void **)&dataptrs);
-
- for (i = 0; i < NDISKS-1; i++)
- for (j = i+1; j < NDISKS; j++)
- err += test_disks(i, j);
+ raid6_call.gen_syndrome(NDISKS, PAGE_SIZE, (void **)&dataptrs);
+
+ for ( i = 0 ; i < NDISKS-1 ; i++ ) {
+ for ( j = i+1 ; j < NDISKS ; j++ ) {
+ memset(recovi, 0xf0, PAGE_SIZE);
+ memset(recovj, 0xba, PAGE_SIZE);
+
+ dataptrs[i] = recovi;
+ dataptrs[j] = recovj;
+
+ raid6_dual_recov(NDISKS, PAGE_SIZE, i, j, (void **)&dataptrs);
+
+ erra = memcmp(data[i], recovi, PAGE_SIZE);
+ errb = memcmp(data[j], recovj, PAGE_SIZE);
+
+ if ( i < NDISKS-2 && j == NDISKS-1 ) {
+ /* We don't implement the DQ failure scenario, since it's
+ equivalent to a RAID-5 failure (XOR, then recompute Q) */
+ } else {
+ printf("algo=%-8s faila=%3d(%c) failb=%3d(%c) %s\n",
+ raid6_call.name,
+ i, (i==NDISKS-2)?'P':'D',
+ j, (j==NDISKS-1)?'Q':(j==NDISKS-2)?'P':'D',
+ (!erra && !errb) ? "OK" :
+ !erra ? "ERRB" :
+ !errb ? "ERRA" :
+ "ERRAB");
+ }
+
+ dataptrs[i] = data[i];
+ dataptrs[j] = data[j];
+ }
+ }
}
printf("\n");
}
@@ -117,8 +99,5 @@ int main(int argc, char *argv[])
/* Pick the best algorithm test */
raid6_select_algo();
- if (err)
- printf("\n*** ERRORS FOUND ***\n");
-
- return err;
+ return 0;
}
diff --git a/trunk/drivers/media/video/Makefile b/trunk/drivers/media/video/Makefile
index 850b8c6f4577..28ddd146c1c5 100644
--- a/trunk/drivers/media/video/Makefile
+++ b/trunk/drivers/media/video/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o
obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o
obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o
+obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o
obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o
diff --git a/trunk/drivers/media/video/tvmixer.c b/trunk/drivers/media/video/tvmixer.c
new file mode 100644
index 000000000000..9fa5b702e073
--- /dev/null
+++ b/trunk/drivers/media/video/tvmixer.c
@@ -0,0 +1,336 @@
+/*
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+
+#define DEV_MAX 4
+
+static int devnr = -1;
+module_param(devnr, int, 0644);
+
+MODULE_AUTHOR("Gerd Knorr");
+MODULE_LICENSE("GPL");
+
+/* ----------------------------------------------------------------------- */
+
+struct TVMIXER {
+ struct i2c_client *dev;
+ int minor;
+ int count;
+};
+
+static struct TVMIXER devices[DEV_MAX];
+
+static int tvmixer_adapters(struct i2c_adapter *adap);
+static int tvmixer_clients(struct i2c_client *client);
+
+/* ----------------------------------------------------------------------- */
+
+static int mix_to_v4l(int i)
+{
+ int r;
+
+ r = ((i & 0xff) * 65536 + 50) / 100;
+ if (r > 65535) r = 65535;
+ if (r < 0) r = 0;
+ return r;
+}
+
+static int v4l_to_mix(int i)
+{
+ int r;
+
+ r = (i * 100 + 32768) / 65536;
+ if (r > 100) r = 100;
+ if (r < 0) r = 0;
+ return r | (r << 8);
+}
+
+static int v4l_to_mix2(int l, int r)
+{
+ r = (r * 100 + 32768) / 65536;
+ if (r > 100) r = 100;
+ if (r < 0) r = 0;
+ l = (l * 100 + 32768) / 65536;
+ if (l > 100) l = 100;
+ if (l < 0) l = 0;
+ return (r << 8) | l;
+}
+
+static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct video_audio va;
+ int left,right,ret,val = 0;
+ struct TVMIXER *mix = file->private_data;
+ struct i2c_client *client = mix->dev;
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+
+ if (NULL == client)
+ return -ENODEV;
+
+ if (cmd == SOUND_MIXER_INFO) {
+ mixer_info info;
+ strlcpy(info.id, "tv card", sizeof(info.id));
+ strlcpy(info.name, client->name, sizeof(info.name));
+ info.modify_counter = 42 /* FIXME */;
+ if (copy_to_user(argp, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+ }
+ if (cmd == SOUND_OLD_MIXER_INFO) {
+ _old_mixer_info info;
+ strlcpy(info.id, "tv card", sizeof(info.id));
+ strlcpy(info.name, client->name, sizeof(info.name));
+ if (copy_to_user(argp, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+ }
+ if (cmd == OSS_GETVERSION)
+ return put_user(SOUND_VERSION, p);
+
+ if (_SIOC_DIR(cmd) & _SIOC_WRITE)
+ if (get_user(val, p))
+ return -EFAULT;
+
+ /* read state */
+ memset(&va,0,sizeof(va));
+ client->driver->command(client,VIDIOCGAUDIO,&va);
+
+ switch (cmd) {
+ case MIXER_READ(SOUND_MIXER_RECMASK):
+ case MIXER_READ(SOUND_MIXER_CAPS):
+ case MIXER_READ(SOUND_MIXER_RECSRC):
+ case MIXER_WRITE(SOUND_MIXER_RECSRC):
+ ret = 0;
+ break;
+
+ case MIXER_READ(SOUND_MIXER_STEREODEVS):
+ ret = SOUND_MASK_VOLUME;
+ break;
+ case MIXER_READ(SOUND_MIXER_DEVMASK):
+ ret = SOUND_MASK_VOLUME;
+ if (va.flags & VIDEO_AUDIO_BASS)
+ ret |= SOUND_MASK_BASS;
+ if (va.flags & VIDEO_AUDIO_TREBLE)
+ ret |= SOUND_MASK_TREBLE;
+ break;
+
+ case MIXER_WRITE(SOUND_MIXER_VOLUME):
+ left = mix_to_v4l(val);
+ right = mix_to_v4l(val >> 8);
+ va.volume = max(left,right);
+ va.balance = (32768*min(left,right)) / (va.volume ? va.volume : 1);
+ va.balance = (leftdriver->command(client,VIDIOCSAUDIO,&va);
+ client->driver->command(client,VIDIOCGAUDIO,&va);
+ /* fall throuth */
+ case MIXER_READ(SOUND_MIXER_VOLUME):
+ left = (min(65536 - va.balance,32768) *
+ va.volume) / 32768;
+ right = (min(va.balance,(u16)32768) *
+ va.volume) / 32768;
+ ret = v4l_to_mix2(left,right);
+ break;
+
+ case MIXER_WRITE(SOUND_MIXER_BASS):
+ va.bass = mix_to_v4l(val);
+ client->driver->command(client,VIDIOCSAUDIO,&va);
+ client->driver->command(client,VIDIOCGAUDIO,&va);
+ /* fall throuth */
+ case MIXER_READ(SOUND_MIXER_BASS):
+ ret = v4l_to_mix(va.bass);
+ break;
+
+ case MIXER_WRITE(SOUND_MIXER_TREBLE):
+ va.treble = mix_to_v4l(val);
+ client->driver->command(client,VIDIOCSAUDIO,&va);
+ client->driver->command(client,VIDIOCGAUDIO,&va);
+ /* fall throuth */
+ case MIXER_READ(SOUND_MIXER_TREBLE):
+ ret = v4l_to_mix(va.treble);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ if (put_user(ret, p))
+ return -EFAULT;
+ return 0;
+}
+
+static int tvmixer_open(struct inode *inode, struct file *file)
+{
+ int i, minor = iminor(inode);
+ struct TVMIXER *mix = NULL;
+ struct i2c_client *client = NULL;
+
+ for (i = 0; i < DEV_MAX; i++) {
+ if (devices[i].minor == minor) {
+ mix = devices+i;
+ client = mix->dev;
+ break;
+ }
+ }
+
+ if (NULL == client)
+ return -ENODEV;
+
+ /* lock bttv in memory while the mixer is in use */
+ file->private_data = mix;
+ if (client->adapter->owner)
+ try_module_get(client->adapter->owner);
+ return 0;
+}
+
+static int tvmixer_release(struct inode *inode, struct file *file)
+{
+ struct TVMIXER *mix = file->private_data;
+ struct i2c_client *client;
+
+ client = mix->dev;
+ if (NULL == client) {
+ return -ENODEV;
+ }
+
+ module_put(client->adapter->owner);
+ return 0;
+}
+
+static struct i2c_driver driver = {
+ .driver = {
+ .name = "tvmixer",
+ },
+ .id = I2C_DRIVERID_TVMIXER,
+ .detach_adapter = tvmixer_adapters,
+ .attach_adapter = tvmixer_adapters,
+ .detach_client = tvmixer_clients,
+};
+
+static const struct file_operations tvmixer_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .ioctl = tvmixer_ioctl,
+ .open = tvmixer_open,
+ .release = tvmixer_release,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static int tvmixer_adapters(struct i2c_adapter *adap)
+{
+ struct i2c_client *client;
+
+ list_for_each_entry(client, &adap->clients, list)
+ tvmixer_clients(client);
+ return 0;
+}
+
+static int tvmixer_clients(struct i2c_client *client)
+{
+ struct video_audio va;
+ int i,minor;
+
+ if (!(client->adapter->class & I2C_CLASS_TV_ANALOG))
+ return -1;
+
+ /* unregister ?? */
+ for (i = 0; i < DEV_MAX; i++) {
+ if (devices[i].dev == client) {
+ /* unregister */
+ unregister_sound_mixer(devices[i].minor);
+ devices[i].dev = NULL;
+ devices[i].minor = -1;
+ printk("tvmixer: %s unregistered (#1)\n",
+ client->name);
+ return 0;
+ }
+ }
+
+ /* look for a free slot */
+ for (i = 0; i < DEV_MAX; i++)
+ if (NULL == devices[i].dev)
+ break;
+ if (i == DEV_MAX) {
+ printk(KERN_WARNING "tvmixer: DEV_MAX too small\n");
+ return -1;
+ }
+
+ /* audio chip with mixer ??? */
+ if (NULL == client->driver->command)
+ return -1;
+ memset(&va,0,sizeof(va));
+ if (0 != client->driver->command(client,VIDIOCGAUDIO,&va))
+ return -1;
+ if (0 == (va.flags & VIDEO_AUDIO_VOLUME))
+ return -1;
+
+ /* everything is fine, register */
+ if ((minor = register_sound_mixer(&tvmixer_fops,devnr)) < 0) {
+ printk(KERN_ERR "tvmixer: cannot allocate mixer device\n");
+ return -1;
+ }
+
+ devices[i].minor = minor;
+ devices[i].count = 0;
+ devices[i].dev = client;
+ printk("tvmixer: %s (%s) registered with minor %d\n",
+ client->name,client->adapter->name,minor);
+
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int __init tvmixer_init_module(void)
+{
+ int i;
+
+ for (i = 0; i < DEV_MAX; i++)
+ devices[i].minor = -1;
+
+ return i2c_add_driver(&driver);
+}
+
+static void __exit tvmixer_cleanup_module(void)
+{
+ int i;
+
+ i2c_del_driver(&driver);
+ for (i = 0; i < DEV_MAX; i++) {
+ if (devices[i].minor != -1) {
+ unregister_sound_mixer(devices[i].minor);
+ printk("tvmixer: %s unregistered (#2)\n",
+ devices[i].dev->name);
+ }
+ }
+}
+
+module_init(tvmixer_init_module);
+module_exit(tvmixer_cleanup_module);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/trunk/drivers/misc/asus-laptop.c b/trunk/drivers/misc/asus-laptop.c
index 0846c33296bc..7dce318df1bd 100644
--- a/trunk/drivers/misc/asus-laptop.c
+++ b/trunk/drivers/misc/asus-laptop.c
@@ -33,6 +33,7 @@
* Sam Lin - GPS support
*/
+#include
#include
#include
#include
diff --git a/trunk/drivers/misc/fujitsu-laptop.c b/trunk/drivers/misc/fujitsu-laptop.c
index 1cfd7f3f1294..c8d62c268b11 100644
--- a/trunk/drivers/misc/fujitsu-laptop.c
+++ b/trunk/drivers/misc/fujitsu-laptop.c
@@ -50,6 +50,7 @@
#include
#include
#include
+#include
#define FUJITSU_DRIVER_VERSION "0.3"
diff --git a/trunk/drivers/misc/lkdtm.c b/trunk/drivers/misc/lkdtm.c
index c884730c5eaf..552b7957a92a 100644
--- a/trunk/drivers/misc/lkdtm.c
+++ b/trunk/drivers/misc/lkdtm.c
@@ -129,28 +129,27 @@ module_param(cpoint_count, int, 0644);
MODULE_PARM_DESC(cpoint_count, " Crash Point Count, number of times the "\
"crash point is to be hit to trigger action");
-static unsigned int jp_do_irq(unsigned int irq)
+unsigned int jp_do_irq(unsigned int irq)
{
lkdtm_handler();
jprobe_return();
return 0;
}
-static irqreturn_t jp_handle_irq_event(unsigned int irq,
- struct irqaction *action)
+irqreturn_t jp_handle_irq_event(unsigned int irq, struct irqaction *action)
{
lkdtm_handler();
jprobe_return();
return 0;
}
-static void jp_tasklet_action(struct softirq_action *a)
+void jp_tasklet_action(struct softirq_action *a)
{
lkdtm_handler();
jprobe_return();
}
-static void jp_ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
+void jp_ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
{
lkdtm_handler();
jprobe_return();
@@ -158,24 +157,23 @@ static void jp_ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
struct scan_control;
-static unsigned long jp_shrink_inactive_list(unsigned long max_scan,
- struct zone *zone,
- struct scan_control *sc)
+unsigned long jp_shrink_inactive_list(unsigned long max_scan,
+ struct zone *zone, struct scan_control *sc)
{
lkdtm_handler();
jprobe_return();
return 0;
}
-static int jp_hrtimer_start(struct hrtimer *timer, ktime_t tim,
- const enum hrtimer_mode mode)
+int jp_hrtimer_start(struct hrtimer *timer, ktime_t tim,
+ const enum hrtimer_mode mode)
{
lkdtm_handler();
jprobe_return();
return 0;
}
-static int jp_scsi_dispatch_cmd(struct scsi_cmnd *cmd)
+int jp_scsi_dispatch_cmd(struct scsi_cmnd *cmd)
{
lkdtm_handler();
jprobe_return();
@@ -272,7 +270,7 @@ void lkdtm_handler(void)
}
}
-static int __init lkdtm_module_init(void)
+int lkdtm_module_init(void)
{
int ret;
@@ -333,7 +331,7 @@ static int __init lkdtm_module_init(void)
return 0;
}
-static void __exit lkdtm_module_exit(void)
+void lkdtm_module_exit(void)
{
unregister_jprobe(&lkdtm);
printk(KERN_INFO "lkdtm : Crash point unregistered\n");
diff --git a/trunk/drivers/misc/msi-laptop.c b/trunk/drivers/misc/msi-laptop.c
index de898c6938f3..83679c762925 100644
--- a/trunk/drivers/misc/msi-laptop.c
+++ b/trunk/drivers/misc/msi-laptop.c
@@ -58,6 +58,7 @@
#include
#include
#include
+#include
#define MSI_DRIVER_VERSION "0.5"
diff --git a/trunk/drivers/misc/phantom.c b/trunk/drivers/misc/phantom.c
index 7fa61e907e1c..cd221fd0fb94 100644
--- a/trunk/drivers/misc/phantom.c
+++ b/trunk/drivers/misc/phantom.c
@@ -25,7 +25,7 @@
#include
#include
-#define PHANTOM_VERSION "n0.9.8"
+#define PHANTOM_VERSION "n0.9.7"
#define PHANTOM_MAX_MINORS 8
@@ -456,9 +456,8 @@ static int phantom_resume(struct pci_dev *pdev)
#endif
static struct pci_device_id phantom_pci_tbl[] __devinitdata = {
- { .vendor = PCI_VENDOR_ID_PLX, .device = PCI_DEVICE_ID_PLX_9050,
- .subvendor = PCI_VENDOR_ID_PLX, .subdevice = PCI_DEVICE_ID_PLX_9050,
- .class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 },
+ { PCI_DEVICE(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050),
+ .class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, phantom_pci_tbl);
diff --git a/trunk/drivers/mtd/devices/block2mtd.c b/trunk/drivers/mtd/devices/block2mtd.c
index eeaaa9dce6ef..be4b9948c762 100644
--- a/trunk/drivers/mtd/devices/block2mtd.c
+++ b/trunk/drivers/mtd/devices/block2mtd.c
@@ -4,7 +4,7 @@
* block2mtd.c - create an mtd from a block device
*
* Copyright (C) 2001,2002 Simon Evans
- * Copyright (C) 2004-2006 Joern Engel
+ * Copyright (C) 2004-2006 Jörn Engel
*
* Licence: GPL
*/
@@ -485,5 +485,5 @@ module_init(block2mtd_init);
module_exit(block2mtd_exit);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Joern Engel ");
+MODULE_AUTHOR("Simon Evans and others");
MODULE_DESCRIPTION("Emulate an MTD using a block device");
diff --git a/trunk/drivers/mtd/devices/phram.c b/trunk/drivers/mtd/devices/phram.c
index 180298b92a7a..56cc1ca7ffd5 100644
--- a/trunk/drivers/mtd/devices/phram.c
+++ b/trunk/drivers/mtd/devices/phram.c
@@ -2,7 +2,7 @@
* $Id: phram.c,v 1.16 2005/11/07 11:14:25 gleixner Exp $
*
* Copyright (c) ???? Jochen Schäuble
- * Copyright (c) 2003-2004 Joern Engel
+ * Copyright (c) 2003-2004 Jörn Engel
*
* Usage:
*
@@ -299,5 +299,5 @@ module_init(init_phram);
module_exit(cleanup_phram);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Joern Engel ");
+MODULE_AUTHOR("Jörn Engel ");
MODULE_DESCRIPTION("MTD driver for physical RAM");
diff --git a/trunk/drivers/mtd/maps/mtx-1_flash.c b/trunk/drivers/mtd/maps/mtx-1_flash.c
index 2a8fde9b92f0..d884f2be28f6 100644
--- a/trunk/drivers/mtd/maps/mtx-1_flash.c
+++ b/trunk/drivers/mtd/maps/mtx-1_flash.c
@@ -4,7 +4,7 @@
* $Id: mtx-1_flash.c,v 1.2 2005/11/07 11:14:27 gleixner Exp $
*
* (C) 2005 Bruno Randolf
- * (C) 2005 Joern Engel
+ * (C) 2005 Jörn Engel
*
*/
diff --git a/trunk/drivers/parport/parport_pc.c b/trunk/drivers/parport/parport_pc.c
index 238628d3a854..e9743d3efaf6 100644
--- a/trunk/drivers/parport/parport_pc.c
+++ b/trunk/drivers/parport/parport_pc.c
@@ -1540,38 +1540,6 @@ static void __devinit detect_and_report_smsc (void)
smsc_check(0x3f0,0x44);
smsc_check(0x370,0x44);
}
-
-static void __devinit detect_and_report_it87(void)
-{
- u16 dev;
- u8 r;
- if (verbose_probing)
- printk(KERN_DEBUG "IT8705 Super-IO detection, now testing port 2E ...\n");
- if (!request_region(0x2e, 1, __FUNCTION__))
- return;
- outb(0x87, 0x2e);
- outb(0x01, 0x2e);
- outb(0x55, 0x2e);
- outb(0x55, 0x2e);
- outb(0x20, 0x2e);
- dev = inb(0x2f) << 8;
- outb(0x21, 0x2e);
- dev |= inb(0x2f);
- if (dev == 0x8712 || dev == 0x8705 || dev == 0x8715 ||
- dev == 0x8716 || dev == 0x8718 || dev == 0x8726) {
- printk(KERN_INFO "IT%04X SuperIO detected.\n", dev);
- outb(0x07, 0x2E); /* Parallel Port */
- outb(0x03, 0x2F);
- outb(0xF0, 0x2E); /* BOOT 0x80 off */
- r = inb(0x2f);
- outb(0xF0, 0x2E);
- outb(r | 8, 0x2F);
- outb(0x02, 0x2E); /* Lock */
- outb(0x02, 0x2F);
-
- release_region(0x2e, 1);
- }
-}
#endif /* CONFIG_PARPORT_PC_SUPERIO */
static int get_superio_dma (struct parport *p)
@@ -2799,7 +2767,6 @@ enum parport_pc_pci_cards {
netmos_9755,
netmos_9805,
netmos_9815,
- quatech_sppxp100,
};
@@ -2876,7 +2843,6 @@ static struct parport_pc_pci {
/* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */
/* netmos_9805 */ { 1, { { 0, -1 }, } }, /* untested */
/* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
- /* quatech_sppxp100 */ { 1, { { 0, 1 }, } },
};
static const struct pci_device_id parport_pc_pci_tbl[] = {
@@ -2960,9 +2926,6 @@ static const struct pci_device_id parport_pc_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 },
- /* Quatech SPPXP-100 Parallel port PCI ExpressCard */
- { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SPPXP_100,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 },
{ 0, } /* terminate list */
};
MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl);
@@ -3196,25 +3159,24 @@ static void __init parport_pc_find_ports (int autoirq, int autodma)
int count = 0, err;
#ifdef CONFIG_PARPORT_PC_SUPERIO
- detect_and_report_it87();
- detect_and_report_winbond();
- detect_and_report_smsc();
+ detect_and_report_winbond ();
+ detect_and_report_smsc ();
#endif
/* Onboard SuperIO chipsets that show themselves on the PCI bus. */
- count += parport_pc_init_superio(autoirq, autodma);
+ count += parport_pc_init_superio (autoirq, autodma);
/* PnP ports, skip detection if SuperIO already found them */
if (!count) {
- err = pnp_register_driver(&parport_pc_pnp_driver);
+ err = pnp_register_driver (&parport_pc_pnp_driver);
if (!err)
pnp_registered_parport = 1;
}
/* ISA ports and whatever (see asm/parport.h). */
- parport_pc_find_nonpci_ports(autoirq, autodma);
+ parport_pc_find_nonpci_ports (autoirq, autodma);
- err = pci_register_driver(&parport_pc_pci_driver);
+ err = pci_register_driver (&parport_pc_pci_driver);
if (!err)
pci_registered_parport = 1;
}
diff --git a/trunk/drivers/parport/parport_serial.c b/trunk/drivers/parport/parport_serial.c
index e2e95b36a603..bd6ad8b38168 100644
--- a/trunk/drivers/parport/parport_serial.c
+++ b/trunk/drivers/parport/parport_serial.c
@@ -77,7 +77,7 @@ static struct parport_pc_pci cards[] __devinitdata = {
/* titan_110l */ { 1, { { 3, -1 }, } },
/* titan_210l */ { 1, { { 3, -1 }, } },
/* netmos_9xx5_combo */ { 1, { { 2, -1 }, }, netmos_parallel_init },
- /* netmos_9855 */ { 1, { { 2, -1 }, }, netmos_parallel_init },
+ /* netmos_9855 */ { 1, { { 0, -1 }, }, netmos_parallel_init },
/* avlab_1s1p */ { 1, { { 1, 2}, } },
/* avlab_1s2p */ { 2, { { 1, 2}, { 3, 4 },} },
/* avlab_2s1p */ { 1, { { 2, 3}, } },
@@ -185,7 +185,7 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
.uart_offset = 8,
},
[netmos_9855] = {
- .flags = FL_BASE4 | FL_BASE_BARS,
+ .flags = FL_BASE2 | FL_BASE_BARS,
.num_ports = 1,
.base_baud = 115200,
.uart_offset = 8,
diff --git a/trunk/drivers/pci/dmar.c b/trunk/drivers/pci/dmar.c
index 8ed26480371f..91b2dc956be5 100644
--- a/trunk/drivers/pci/dmar.c
+++ b/trunk/drivers/pci/dmar.c
@@ -26,7 +26,6 @@
#include
#include
#include "iova.h"
-#include "intel-iommu.h"
#undef PREFIX
#define PREFIX "DMAR:"
diff --git a/trunk/drivers/pci/intel-iommu.c b/trunk/drivers/pci/intel-iommu.c
index 31fa6c92aa5e..4e01df99681a 100644
--- a/trunk/drivers/pci/intel-iommu.c
+++ b/trunk/drivers/pci/intel-iommu.c
@@ -1088,7 +1088,7 @@ static void dmar_init_reserved_ranges(void)
int i;
u64 addr, size;
- init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN);
+ init_iova_domain(&reserved_iova_list);
/* IOAPIC ranges shouldn't be accessed by DMA */
iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
@@ -1142,7 +1142,7 @@ static int domain_init(struct dmar_domain *domain, int guest_width)
int adjust_width, agaw;
unsigned long sagaw;
- init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
+ init_iova_domain(&domain->iovad);
spin_lock_init(&domain->mapping_lock);
domain_reserve_special_ranges(domain);
diff --git a/trunk/drivers/pci/intel-iommu.h b/trunk/drivers/pci/intel-iommu.h
index 0e4862675ad2..459ad1f9dc54 100644
--- a/trunk/drivers/pci/intel-iommu.h
+++ b/trunk/drivers/pci/intel-iommu.h
@@ -23,23 +23,9 @@
#include
#include
-#include
#include "iova.h"
#include
-/*
- * We need a fixed PAGE_SIZE of 4K irrespective of
- * arch PAGE_SIZE for IOMMU page tables.
- */
-#define PAGE_SHIFT_4K (12)
-#define PAGE_SIZE_4K (1UL << PAGE_SHIFT_4K)
-#define PAGE_MASK_4K (((u64)-1) << PAGE_SHIFT_4K)
-#define PAGE_ALIGN_4K(addr) (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K)
-
-#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT_4K)
-#define DMA_32BIT_PFN IOVA_PFN(DMA_32BIT_MASK)
-#define DMA_64BIT_PFN IOVA_PFN(DMA_64BIT_MASK)
-
/*
* Intel IOMMU register specification per version 1.0 public spec.
*/
diff --git a/trunk/drivers/pci/iova.c b/trunk/drivers/pci/iova.c
index 8de7ab6c6d0c..a84571c29360 100644
--- a/trunk/drivers/pci/iova.c
+++ b/trunk/drivers/pci/iova.c
@@ -9,19 +9,19 @@
#include "iova.h"
void
-init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit)
+init_iova_domain(struct iova_domain *iovad)
{
spin_lock_init(&iovad->iova_alloc_lock);
spin_lock_init(&iovad->iova_rbtree_lock);
iovad->rbroot = RB_ROOT;
iovad->cached32_node = NULL;
- iovad->dma_32bit_pfn = pfn_32bit;
+
}
static struct rb_node *
__get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn)
{
- if ((*limit_pfn != iovad->dma_32bit_pfn) ||
+ if ((*limit_pfn != DMA_32BIT_PFN) ||
(iovad->cached32_node == NULL))
return rb_last(&iovad->rbroot);
else {
@@ -37,7 +37,7 @@ static void
__cached_rbnode_insert_update(struct iova_domain *iovad,
unsigned long limit_pfn, struct iova *new)
{
- if (limit_pfn != iovad->dma_32bit_pfn)
+ if (limit_pfn != DMA_32BIT_PFN)
return;
iovad->cached32_node = &new->node;
}
diff --git a/trunk/drivers/pci/iova.h b/trunk/drivers/pci/iova.h
index d521b5b7319c..ae3028d5a941 100644
--- a/trunk/drivers/pci/iova.h
+++ b/trunk/drivers/pci/iova.h
@@ -15,9 +15,22 @@
#include
#include
+/*
+ * We need a fixed PAGE_SIZE of 4K irrespective of
+ * arch PAGE_SIZE for IOMMU page tables.
+ */
+#define PAGE_SHIFT_4K (12)
+#define PAGE_SIZE_4K (1UL << PAGE_SHIFT_4K)
+#define PAGE_MASK_4K (((u64)-1) << PAGE_SHIFT_4K)
+#define PAGE_ALIGN_4K(addr) (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K)
+
/* IO virtual address start page frame number */
#define IOVA_START_PFN (1)
+#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT_4K)
+#define DMA_32BIT_PFN IOVA_PFN(DMA_32BIT_MASK)
+#define DMA_64BIT_PFN IOVA_PFN(DMA_64BIT_MASK)
+
/* iova structure */
struct iova {
struct rb_node node;
@@ -31,7 +44,6 @@ struct iova_domain {
spinlock_t iova_rbtree_lock; /* Lock to protect update of rbtree */
struct rb_root rbroot; /* iova domain rbtree root */
struct rb_node *cached32_node; /* Save last alloced node */
- unsigned long dma_32bit_pfn;
};
struct iova *alloc_iova_mem(void);
@@ -44,7 +56,7 @@ struct iova *alloc_iova(struct iova_domain *iovad, unsigned long size,
struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
unsigned long pfn_hi);
void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to);
-void init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit);
+void init_iova_domain(struct iova_domain *iovad);
struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
void put_iova_domain(struct iova_domain *iovad);
diff --git a/trunk/drivers/pnp/driver.c b/trunk/drivers/pnp/driver.c
index 12a1645a2e43..a262762c5b88 100644
--- a/trunk/drivers/pnp/driver.c
+++ b/trunk/drivers/pnp/driver.c
@@ -161,7 +161,8 @@ static int pnp_bus_suspend(struct device *dev, pm_message_t state)
return error;
}
- if (pnp_can_disable(pnp_dev)) {
+ if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE) &&
+ pnp_can_disable(pnp_dev)) {
error = pnp_stop_dev(pnp_dev);
if (error)
return error;
@@ -184,17 +185,14 @@ static int pnp_bus_resume(struct device *dev)
if (pnp_dev->protocol && pnp_dev->protocol->resume)
pnp_dev->protocol->resume(pnp_dev);
- if (pnp_can_write(pnp_dev)) {
+ if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) {
error = pnp_start_dev(pnp_dev);
if (error)
return error;
}
- if (pnp_drv->resume) {
- error = pnp_drv->resume(pnp_dev);
- if (error)
- return error;
- }
+ if (pnp_drv->resume)
+ return pnp_drv->resume(pnp_dev);
return 0;
}
diff --git a/trunk/drivers/pnp/interface.c b/trunk/drivers/pnp/interface.c
index 982658477a58..31548044fdde 100644
--- a/trunk/drivers/pnp/interface.c
+++ b/trunk/drivers/pnp/interface.c
@@ -10,12 +10,9 @@
#include
#include
#include
-#include
#include