From 1a8a3fc2317e90615dcf61f2ef34ad278cc2dc76 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 14 Sep 2004 23:34:11 +0100 Subject: [CPUFREQ][1/4] cpufreq "cpu group" awareness: add policy->cpus Save the "affected_cpu_map" used in SMT-aware drivers in struct cpufreq_policy->(cpumask_t) cpus, and use it wherever possible. In most cases, the ->get() function is only allowed to run on one CPU [the one passed as argument] to keep code simpler, and as that code path isn't executed often, and only root can do it anyway. Signed-off-by: Dominik Brodowski Signed-off-by: Dave Jones --- include/linux/cpufreq.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 48a23f1588a1..f8543228663f 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -22,6 +22,7 @@ #include #include #include +#include #define CPUFREQ_NAME_LEN 16 @@ -69,7 +70,8 @@ struct cpufreq_real_policy { }; struct cpufreq_policy { - unsigned int cpu; /* cpu nr */ + cpumask_t cpus; /* affected CPUs */ + unsigned int cpu; /* cpu nr of registered CPU */ struct cpufreq_cpuinfo cpuinfo;/* see above */ unsigned int min; /* in kHz */ -- cgit v1.2.3 From fd01b12a3de2f16681fb0c64c796c01ca7736515 Mon Sep 17 00:00:00 2001 From: "Mark M. Hoffman" Date: Tue, 21 Sep 2004 02:39:31 -0700 Subject: [PATCH] i2c: Add Intel VRD 10.0 and AMD Opteron VID support This patch adds support for Intel VRD 10.0 and AMD Opteron VID calculations. It is based on the lm_sensors project CVS, r1.6. Signed-off-by: Mark M. Hoffman Signed-off-by: Greg Kroah-Hartman --- include/linux/i2c-vid.h | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/i2c-vid.h b/include/linux/i2c-vid.h index 62424092e44e..974835e3530f 100644 --- a/include/linux/i2c-vid.h +++ b/include/linux/i2c-vid.h @@ -29,7 +29,22 @@ */ /* - Legal val values 00 - 1F. + AMD Opteron processors don't follow the Intel VRM spec. + I'm going to "make up" 2.4 as the VRM spec for the Opterons. + No good reason just a mnemonic for the 24x Opteron processor + series + + Opteron VID encoding is: + + 00000 = 1.550 V + 00001 = 1.525 V + . . . . + 11110 = 0.800 V + 11111 = 0.000 V (off) + */ + +/* + Legal val values 0x00 - 0x1f; except for VRD 10.0, 0x00 - 0x3f. vrm is the Intel VRM document version. Note: vrm version is scaled by 10 and the return value is scaled by 1000 to avoid floating point in the kernel. @@ -41,9 +56,28 @@ int i2c_which_vrm(void); static inline int vid_from_reg(int val, int vrm) { + int vid; + switch(vrm) { + case 0: return 0; + + case 100: /* VRD 10.0 */ + if((val & 0x1f) == 0x1f) + return 0; + if((val & 0x1f) <= 0x09 || val == 0x0a) + vid = 10875 - (val & 0x1f) * 250; + else + vid = 18625 - (val & 0x1f) * 250; + if(val & 0x20) + vid -= 125; + vid /= 10; /* only return 3 dec. places for now */ + return vid; + + case 24: /* Opteron processor */ + return(val == 0x1f ? 0 : 1550 - val * 25); + case 91: /* VRM 9.1 */ case 90: /* VRM 9.0 */ return(val == 0x1f ? 0 : -- cgit v1.2.3 From 9fd759d3d4a63eb5c9b9db799204ff169043bef4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 5 Oct 2004 21:18:21 -0700 Subject: [PATCH] PCI: make pci_find_subsys() static, as it should not be used anymore Use pci_get_subsys() if you want this functionality. Signed-off-by: Greg Kroah-Hartman --- drivers/pci/search.c | 10 +++++----- include/linux/pci.h | 7 ------- 2 files changed, 5 insertions(+), 12 deletions(-) (limited to 'include/linux') diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 701a83be3b30..6a90177b0ad0 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -156,10 +156,11 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) * the pci device returned by this function can disappear at any moment in * time. */ -struct pci_dev * -pci_find_subsys(unsigned int vendor, unsigned int device, - unsigned int ss_vendor, unsigned int ss_device, - const struct pci_dev *from) +static struct pci_dev * pci_find_subsys(unsigned int vendor, + unsigned int device, + unsigned int ss_vendor, + unsigned int ss_device, + const struct pci_dev *from) { struct list_head *n; struct pci_dev *dev; @@ -351,7 +352,6 @@ EXPORT_SYMBOL(pci_find_class); EXPORT_SYMBOL(pci_find_device); EXPORT_SYMBOL(pci_find_device_reverse); EXPORT_SYMBOL(pci_find_slot); -EXPORT_SYMBOL(pci_find_subsys); EXPORT_SYMBOL(pci_get_device); EXPORT_SYMBOL(pci_get_subsys); EXPORT_SYMBOL(pci_get_slot); diff --git a/include/linux/pci.h b/include/linux/pci.h index 3f76ca047d2f..1e6704bedca2 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -719,9 +719,6 @@ extern void pci_remove_bus_device(struct pci_dev *dev); struct pci_dev *pci_find_device (unsigned int vendor, unsigned int device, const struct pci_dev *from); struct pci_dev *pci_find_device_reverse (unsigned int vendor, unsigned int device, const struct pci_dev *from); -struct pci_dev *pci_find_subsys (unsigned int vendor, unsigned int device, - unsigned int ss_vendor, unsigned int ss_device, - const struct pci_dev *from); struct pci_dev *pci_find_class (unsigned int class, const struct pci_dev *from); struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn); int pci_find_capability (struct pci_dev *dev, int cap); @@ -888,10 +885,6 @@ static inline struct pci_dev *pci_find_class(unsigned int class, const struct pc static inline struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn) { return NULL; } -static inline struct pci_dev *pci_find_subsys(unsigned int vendor, unsigned int device, -unsigned int ss_vendor, unsigned int ss_device, const struct pci_dev *from) -{ return NULL; } - static inline struct pci_dev *pci_get_device (unsigned int vendor, unsigned int device, struct pci_dev *from) { return NULL; } -- cgit v1.2.3 From 35f1f308dbad8a9896f9e1455f0c7c8b49a9cf1a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 5 Oct 2004 21:20:05 -0700 Subject: [PATCH] PCI: add pci_get_class() to make a safe pci_find_class() like call. Signed-off-by: Greg Kroah-Hartman --- Documentation/pci.txt | 5 +++-- drivers/pci/search.c | 38 ++++++++++++++++++++++++++++++++++++++ include/linux/pci.h | 4 ++++ 3 files changed, 45 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/Documentation/pci.txt b/Documentation/pci.txt index af4e5e61ae40..04f1ba9c1a20 100644 --- a/Documentation/pci.txt +++ b/Documentation/pci.txt @@ -146,7 +146,7 @@ Searching by vendor and device ID: Searching by class ID (iterate in a similar way): - pci_find_class(CLASS_ID, dev) + pci_get_class(CLASS_ID, dev) Searching by both vendor/device and subsystem vendor/device ID: @@ -281,5 +281,6 @@ pci_for_each_dev_reverse() Superseded by pci_find_device_reverse() pci_for_each_bus() Superseded by pci_find_next_bus() pci_find_device() Superseded by pci_get_device() pci_find_subsys() Superseded by pci_get_subsys() -pcibios_find_class() Superseded by pci_find_class() +pcibios_find_class() Superseded by pci_get_class() +pci_find_class() Superseded by pci_get_class() pci_(read|write)_*_nodev() Superseded by pci_bus_(read|write)_*() diff --git a/drivers/pci/search.c b/drivers/pci/search.c index b748ff55c6a4..f4a9586e8698 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -348,6 +348,43 @@ exit: return dev; } +/** + * pci_get_class - begin or continue searching for a PCI device by class + * @class: search for a PCI device with this class designation + * @from: Previous PCI device found in search, or %NULL for new search. + * + * Iterates through the list of known PCI devices. If a PCI device is + * found with a matching @class, the reference count to the device is + * incremented and a pointer to its device structure is returned. + * Otherwise, %NULL is returned. + * A new search is initiated by passing %NULL to the @from argument. + * Otherwise if @from is not %NULL, searches continue from next device + * on the global list. The reference count for @from is always decremented + * if it is not %NULL. + */ +struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) +{ + struct list_head *n; + struct pci_dev *dev; + + WARN_ON(in_interrupt()); + spin_lock(&pci_bus_lock); + n = from ? from->global_list.next : pci_devices.next; + + while (n && (n != &pci_devices)) { + dev = pci_dev_g(n); + if (dev->class == class) + goto exit; + n = n->next; + } + dev = NULL; +exit: + pci_dev_put(from); + dev = pci_dev_get(dev); + spin_unlock(&pci_bus_lock); + return dev; +} + EXPORT_SYMBOL(pci_find_bus); EXPORT_SYMBOL(pci_find_class); EXPORT_SYMBOL(pci_find_device); @@ -356,3 +393,4 @@ EXPORT_SYMBOL(pci_find_slot); EXPORT_SYMBOL(pci_get_device); EXPORT_SYMBOL(pci_get_subsys); EXPORT_SYMBOL(pci_get_slot); +EXPORT_SYMBOL(pci_get_class); diff --git a/include/linux/pci.h b/include/linux/pci.h index 1e6704bedca2..ec10ab903fb1 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -730,6 +730,7 @@ struct pci_dev *pci_get_subsys (unsigned int vendor, unsigned int device, unsigned int ss_vendor, unsigned int ss_device, struct pci_dev *from); struct pci_dev *pci_get_slot (struct pci_bus *bus, unsigned int devfn); +struct pci_dev *pci_get_class (unsigned int class, struct pci_dev *from); int pci_bus_read_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 *val); int pci_bus_read_config_word (struct pci_bus *bus, unsigned int devfn, int where, u16 *val); @@ -892,6 +893,9 @@ static inline struct pci_dev *pci_get_subsys (unsigned int vendor, unsigned int unsigned int ss_vendor, unsigned int ss_device, struct pci_dev *from) { return NULL; } +static inline struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) +{ return NULL; } + static inline void pci_set_master(struct pci_dev *dev) { } static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; } static inline void pci_disable_device(struct pci_dev *dev) { } -- cgit v1.2.3 From 6af05face421b768f51950380607b819a0b69926 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 5 Oct 2004 21:32:56 -0700 Subject: [PATCH] PCI: delete the pci_find_class() function as it's unsafe in hotpluggable systems. Signed-off-by: Greg Kroah-Hartman --- drivers/pci/search.c | 40 ---------------------------------------- include/linux/pci.h | 4 ---- 2 files changed, 44 deletions(-) (limited to 'include/linux') diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 346457ec8046..25e64650022f 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -307,45 +307,6 @@ exit: return dev; } - -/** - * pci_find_class - begin or continue searching for a PCI device by class - * @class: search for a PCI device with this class designation - * @from: Previous PCI device found in search, or %NULL for new search. - * - * Iterates through the list of known PCI devices. If a PCI device is - * found with a matching @class, a pointer to its device structure is - * returned. Otherwise, %NULL is returned. - * A new search is initiated by passing %NULL to the @from argument. - * Otherwise if @from is not %NULL, searches continue from next device - * on the global list. - * - * NOTE: Do not use this function anymore, use pci_get_class() instead, as - * the pci device returned by this function can disappear at any moment in - * time. - */ -struct pci_dev * -pci_find_class(unsigned int class, const struct pci_dev *from) -{ - struct list_head *n; - struct pci_dev *dev; - - WARN_ON(in_interrupt()); - spin_lock(&pci_bus_lock); - n = from ? from->global_list.next : pci_devices.next; - - while (n && (n != &pci_devices)) { - dev = pci_dev_g(n); - if (dev->class == class) - goto exit; - n = n->next; - } - dev = NULL; -exit: - spin_unlock(&pci_bus_lock); - return dev; -} - /** * pci_get_class - begin or continue searching for a PCI device by class * @class: search for a PCI device with this class designation @@ -384,7 +345,6 @@ exit: } EXPORT_SYMBOL(pci_find_bus); -EXPORT_SYMBOL(pci_find_class); EXPORT_SYMBOL(pci_find_device); EXPORT_SYMBOL(pci_find_device_reverse); EXPORT_SYMBOL(pci_find_slot); diff --git a/include/linux/pci.h b/include/linux/pci.h index ec10ab903fb1..48d939c7625c 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -719,7 +719,6 @@ extern void pci_remove_bus_device(struct pci_dev *dev); struct pci_dev *pci_find_device (unsigned int vendor, unsigned int device, const struct pci_dev *from); struct pci_dev *pci_find_device_reverse (unsigned int vendor, unsigned int device, const struct pci_dev *from); -struct pci_dev *pci_find_class (unsigned int class, const struct pci_dev *from); struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn); int pci_find_capability (struct pci_dev *dev, int cap); int pci_find_ext_capability (struct pci_dev *dev, int cap); @@ -880,9 +879,6 @@ _PCI_NOP_ALL(write,) static inline struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *from) { return NULL; } -static inline struct pci_dev *pci_find_class(unsigned int class, const struct pci_dev *from) -{ return NULL; } - static inline struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn) { return NULL; } -- cgit v1.2.3 From 7bfaf2ed2f8a64bfb4e12cbcc912766196e0d826 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 5 Oct 2004 22:25:07 -0700 Subject: [PATCH] add-pci_fixup_enable-pass.patch From: Bjorn Helgaas Nick Piggin's USB driver stopped working when I removed the unconditional PCI ACPI IRQ routing stuff. He has verified that the attached patch fixes it. I sort of hate to add another pass of PCI fixups, so I'm open to alternate solutions if anybody suggests one. Add a "pci_fixup_enable" pass of PCI fixups. These are run at the end of pci_enable_device() to fix up things like IRQs that are not set up until then. Some VIA boards require a fixup after the IRQ is set up. Found by Nick Piggin, initial patch by Bjorn Helgaas, reworked to fit into current -mm by Nick. Signed-off-by: Nick Piggin Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 7 ++++++- drivers/pci/quirks.c | 15 ++++++++++++--- include/asm-generic/vmlinux.lds.h | 3 +++ include/linux/pci.h | 7 +++++++ 4 files changed, 28 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 46d56c8ccf10..089eaa832c37 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -382,8 +382,13 @@ pci_enable_device_bars(struct pci_dev *dev, int bars) int pci_enable_device(struct pci_dev *dev) { + int err; + dev->is_enabled = 1; - return pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); + if ((err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1))) + return err; + pci_fixup_device(pci_fixup_enable, dev); + return 0; } /** diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 92067ac842c2..49a9672c0801 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -491,9 +491,9 @@ static void __devinit quirk_via_irqpic(struct pci_dev *dev) pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); } } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irqpic ); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irqpic ); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_6, quirk_via_irqpic ); +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irqpic ); +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irqpic ); +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_6, quirk_via_irqpic ); /* @@ -1003,6 +1003,9 @@ extern struct pci_fixup __start_pci_fixups_header[]; extern struct pci_fixup __end_pci_fixups_header[]; extern struct pci_fixup __start_pci_fixups_final[]; extern struct pci_fixup __end_pci_fixups_final[]; +extern struct pci_fixup __start_pci_fixups_enable[]; +extern struct pci_fixup __end_pci_fixups_enable[]; + void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) { @@ -1018,6 +1021,12 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) start = __start_pci_fixups_final; end = __end_pci_fixups_final; break; + + case pci_fixup_enable: + start = __start_pci_fixups_enable; + end = __end_pci_fixups_enable; + break; + default: /* stupid compiler warning, you would think with an enum... */ return; diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index bb340cb5cb03..da1b3ba89b3e 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -24,6 +24,9 @@ VMLINUX_SYMBOL(__start_pci_fixups_final) = .; \ *(.pci_fixup_final) \ VMLINUX_SYMBOL(__end_pci_fixups_final) = .; \ + VMLINUX_SYMBOL(__start_pci_fixups_enable) = .; \ + *(.pci_fixup_enable) \ + VMLINUX_SYMBOL(__end_pci_fixups_enable) = .; \ } \ \ /* Kernel symbol table: Normal symbols */ \ diff --git a/include/linux/pci.h b/include/linux/pci.h index 48d939c7625c..169badd4917e 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1001,6 +1001,7 @@ struct pci_fixup { enum pci_fixup_pass { pci_fixup_header, /* Called immediately after reading configuration header */ pci_fixup_final, /* Final phase of device fixups */ + pci_fixup_enable, /* pci_enable_device() time */ }; /* Anonymous variables would be nice... */ @@ -1014,6 +1015,12 @@ enum pci_fixup_pass { __attribute__((__section__(".pci_fixup_final"))) = { \ vendor, device, hook }; +#define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook) \ + static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__ \ + __attribute__((__section__(".pci_fixup_enable"))) = { \ + vendor, device, hook }; + + void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev); extern int pci_pci_problems; -- cgit v1.2.3 From d43cd921becdca601aad30966ab6b12d44e125ef Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 5 Oct 2004 23:05:22 -0700 Subject: [PATCH] PCI: Create new function to see if a pci device is present This is needed to help get rid of the pci_find_device() usage in the tree. Signed-off-by: Hanna Linder Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-driver.c | 21 --------------------- drivers/pci/pci.h | 21 +++++++++++++++++++++ drivers/pci/search.c | 34 ++++++++++++++++++++++++++++++++++ include/linux/pci.h | 3 +++ 4 files changed, 58 insertions(+), 21 deletions(-) (limited to 'include/linux') diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 0cf9f2d5129e..807b1418a45a 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -14,27 +14,6 @@ * Registration of PCI drivers and handling of hot-pluggable devices. */ -/** - * pci_match_one_device - Tell if a PCI device structure has a matching - * PCI device id structure - * @id: single PCI device id structure to match - * @dev: the PCI device structure to match against - * - * Returns the matching pci_device_id structure or %NULL if there is no match. - */ - -static inline const struct pci_device_id * -pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev) -{ - if ((id->vendor == PCI_ANY_ID || id->vendor == dev->vendor) && - (id->device == PCI_ANY_ID || id->device == dev->device) && - (id->subvendor == PCI_ANY_ID || id->subvendor == dev->subsystem_vendor) && - (id->subdevice == PCI_ANY_ID || id->subdevice == dev->subsystem_device) && - !((id->class ^ dev->class) & id->class_mask)) - return id; - return NULL; -} - /* * Dynamic device IDs are disabled for !CONFIG_HOTPLUG */ diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index a9b243770580..0c58b65e9c30 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -63,3 +63,24 @@ extern spinlock_t pci_bus_lock; extern int pciehp_msi_quirk; extern struct device_attribute pci_dev_attrs[]; + +/** + * pci_match_one_device - Tell if a PCI device structure has a matching + * PCI device id structure + * @id: single PCI device id structure to match + * @dev: the PCI device structure to match against + * + * Returns the matching pci_device_id structure or %NULL if there is no match. + */ +static inline const struct pci_device_id * +pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev) +{ + if ((id->vendor == PCI_ANY_ID || id->vendor == dev->vendor) && + (id->device == PCI_ANY_ID || id->device == dev->device) && + (id->subvendor == PCI_ANY_ID || id->subvendor == dev->subsystem_vendor) && + (id->subdevice == PCI_ANY_ID || id->subdevice == dev->subsystem_device) && + !((id->class ^ dev->class) & id->class_mask)) + return id; + return NULL; +} + diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 25e64650022f..a1fb8b57d620 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -11,6 +11,7 @@ #include #include #include +#include "pci.h" spinlock_t pci_bus_lock = SPIN_LOCK_UNLOCKED; @@ -344,6 +345,39 @@ exit: return dev; } +/** + * pci_dev_present - Returns 1 if device matching the device list is present, 0 if not. + * @ids: A pointer to a null terminated list of struct pci_device_id structures + * that describe the type of PCI device the caller is trying to find. + * + * Obvious fact: You do not have a reference to any device that might be found + * by this function, so if that device is removed from the system right after + * this function is finished, the value will be stale. Use this function to + * find devices that are usually built into a system, or for a general hint as + * to if another device happens to be present at this specific moment in time. + */ +int pci_dev_present(const struct pci_device_id *ids) +{ + struct pci_dev *dev; + int found = 0; + + WARN_ON(in_interrupt()); + spin_lock(&pci_bus_lock); + while (ids->vendor || ids->subvendor || ids->class_mask) { + list_for_each_entry(dev, &pci_devices, global_list) { + if (pci_match_one_device(ids, dev)) { + found = 1; + goto exit; + } + } + ids++; + } +exit: + spin_unlock(&pci_bus_lock); + return found; +} +EXPORT_SYMBOL(pci_dev_present); + EXPORT_SYMBOL(pci_find_bus); EXPORT_SYMBOL(pci_find_device); EXPORT_SYMBOL(pci_find_device_reverse); diff --git a/include/linux/pci.h b/include/linux/pci.h index 169badd4917e..eb0d2c81c36c 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -730,6 +730,7 @@ struct pci_dev *pci_get_subsys (unsigned int vendor, unsigned int device, struct pci_dev *from); struct pci_dev *pci_get_slot (struct pci_bus *bus, unsigned int devfn); struct pci_dev *pci_get_class (unsigned int class, struct pci_dev *from); +int pci_dev_present(const struct pci_device_id *ids); int pci_bus_read_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 *val); int pci_bus_read_config_word (struct pci_bus *bus, unsigned int devfn, int where, u16 *val); @@ -891,6 +892,8 @@ unsigned int ss_vendor, unsigned int ss_device, struct pci_dev *from) static inline struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) { return NULL; } +static inline int pci_dev_present(const struct pci_device_id *ids) +{ return 0; } static inline void pci_set_master(struct pci_dev *dev) { } static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; } -- cgit v1.2.3 From c4314299e34251fe551d537156debeadee1b43c8 Mon Sep 17 00:00:00 2001 From: Roger Luethi Date: Tue, 5 Oct 2004 23:20:13 -0700 Subject: [PATCH] PCI: remove driver private PCI state, 1 arg for pci_{save,restore}_state This is the second (and hopefully final) iteration of the interface change we talked about a while ago. The patch applies cleanly against 2.6.9-rc2-mm4. This removes the second argument (buffer for storing PCI state) from pci_{save,restore}_state since pci_dev contains such a buffer now. Fixed all callers. Three drivers used to pass a buffer of 256 bytes, one only 48(!). The rest was correct. Changes were compile tested, except for Alpha. Signed-off-by: Roger Luethi Signed-off-by: Greg Kroah-Hartman --- arch/alpha/kernel/pci.c | 4 ++-- arch/alpha/kernel/pci_impl.h | 1 - drivers/char/agp/intel-agp.c | 2 +- drivers/char/agp/intel-mch-agp.c | 2 +- drivers/media/video/bttv-driver.c | 4 ++-- drivers/media/video/bttvp.h | 1 - drivers/media/video/cx88/cx88-video.c | 4 ++-- drivers/media/video/cx88/cx88.h | 1 - drivers/media/video/meye.c | 4 ++-- drivers/media/video/meye.h | 1 - drivers/message/fusion/mptbase.c | 4 ++-- drivers/message/fusion/mptbase.h | 3 --- drivers/net/3c59x.c | 11 +++++----- drivers/net/8139cp.c | 5 ++--- drivers/net/8139too.c | 6 ++---- drivers/net/amd8111e.c | 4 ++-- drivers/net/amd8111e.h | 1 - drivers/net/b44.c | 4 ++-- drivers/net/b44.h | 1 - drivers/net/e100.c | 5 ++--- drivers/net/e1000/e1000.h | 1 - drivers/net/e1000/e1000_main.c | 4 ++-- drivers/net/eepro100.c | 7 ++---- drivers/net/irda/vlsi_ir.c | 4 ++-- drivers/net/irda/vlsi_ir.h | 1 - drivers/net/ixgb/ixgb.h | 1 - drivers/net/ixgb/ixgb_main.c | 2 +- drivers/net/pci-skeleton.c | 5 ++--- drivers/net/s2io.c | 4 ++-- drivers/net/s2io.h | 1 - drivers/net/sis900.c | 6 ++---- drivers/net/tg3.c | 8 +++---- drivers/net/tg3.h | 1 - drivers/net/tulip/xircom_tulip_cb.c | 7 ++---- drivers/net/typhoon.c | 9 ++++---- drivers/net/via-rhine.c | 4 ++-- drivers/net/via-velocity.c | 4 ++-- drivers/net/via-velocity.h | 4 ---- drivers/net/wireless/airo.c | 5 ++--- drivers/net/wireless/prism54/islpci_dev.h | 1 - drivers/net/wireless/prism54/islpci_hotplug.c | 4 ++-- drivers/pci/pci-driver.c | 4 ++-- drivers/pci/pci.c | 31 ++++++--------------------- drivers/pcmcia/yenta_socket.c | 12 +++++------ drivers/pcmcia/yenta_socket.h | 2 +- drivers/scsi/ipr.c | 4 ++-- drivers/scsi/ipr.h | 1 - drivers/scsi/nsp32.c | 5 ++--- drivers/scsi/nsp32.h | 3 --- drivers/usb/core/hcd-pci.c | 4 ++-- drivers/usb/core/hcd.h | 1 - drivers/video/i810/i810.h | 1 - drivers/video/i810/i810_main.c | 4 ++-- include/linux/pci.h | 8 +++---- sound/core/init.c | 2 +- sound/oss/ali5455.c | 5 ++--- sound/oss/i810_audio.c | 5 ++--- 57 files changed, 91 insertions(+), 152 deletions(-) (limited to 'include/linux') diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 0ad3690de99d..1f36bbd0ed5d 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -227,7 +227,7 @@ pdev_save_srm_config(struct pci_dev *dev) tmp->next = srm_saved_configs; tmp->dev = dev; - pci_save_state(dev, tmp->regs); + pci_save_state(dev); srm_saved_configs = tmp; } @@ -243,7 +243,7 @@ pci_restore_srm_config(void) /* Restore SRM config. */ for (tmp = srm_saved_configs; tmp; tmp = tmp->next) { - pci_restore_state(tmp->dev, tmp->regs); + pci_restore_state(tmp->dev); } } #endif diff --git a/arch/alpha/kernel/pci_impl.h b/arch/alpha/kernel/pci_impl.h index 54fb8f178494..f8b74995a002 100644 --- a/arch/alpha/kernel/pci_impl.h +++ b/arch/alpha/kernel/pci_impl.h @@ -166,7 +166,6 @@ struct pdev_srm_saved_conf { struct pdev_srm_saved_conf *next; struct pci_dev *dev; - u32 regs[16]; }; extern void pci_restore_srm_config(void); diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 0f41f748a04e..844a2be9a40c 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -1723,7 +1723,7 @@ static int agp_intel_resume(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); - pci_restore_state(pdev, pdev->saved_config_space); + pci_restore_state(pdev); if (bridge->driver == &intel_generic_driver) intel_configure(); diff --git a/drivers/char/agp/intel-mch-agp.c b/drivers/char/agp/intel-mch-agp.c index 19526d76bafe..c0a2d5897cd2 100644 --- a/drivers/char/agp/intel-mch-agp.c +++ b/drivers/char/agp/intel-mch-agp.c @@ -573,7 +573,7 @@ static int agp_intelmch_resume(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); - pci_restore_state(pdev, pdev->saved_config_space); + pci_restore_state(pdev); if (bridge->driver == &intel_845_driver) intel_845_configure(); diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index f0d54c5f239a..1fa3fbf21161 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -3944,7 +3944,7 @@ static int bttv_suspend(struct pci_dev *pci_dev, u32 state) btv->state.gpio_data = gpio_read(); /* save pci state */ - pci_save_state(pci_dev, btv->state.pci_cfg); + pci_save_state(pci_dev); if (0 != pci_set_power_state(pci_dev, state)) { pci_disable_device(pci_dev); btv->state.disabled = 1; @@ -3965,7 +3965,7 @@ static int bttv_resume(struct pci_dev *pci_dev) btv->state.disabled = 0; } pci_set_power_state(pci_dev, 0); - pci_restore_state(pci_dev, btv->state.pci_cfg); + pci_restore_state(pci_dev); /* restore bt878 state */ bttv_reinit_bt848(btv); diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index 943f8136ab78..bd5235944d7a 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h @@ -277,7 +277,6 @@ struct bttv_input { }; struct bttv_suspend_state { - u32 pci_cfg[64 / sizeof(u32)]; u32 gpio_enable; u32 gpio_data; int disabled; diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index e73b8ce4e210..3db0edc9b5d3 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -2545,7 +2545,7 @@ static int cx8800_suspend(struct pci_dev *pci_dev, u32 state) cx8800_shutdown(dev); del_timer(&dev->vidq.timeout); - pci_save_state(pci_dev, dev->state.pci_cfg); + pci_save_state(pci_dev); if (0 != pci_set_power_state(pci_dev, state)) { pci_disable_device(pci_dev); dev->state.disabled = 1; @@ -2564,7 +2564,7 @@ static int cx8800_resume(struct pci_dev *pci_dev) dev->state.disabled = 0; } pci_set_power_state(pci_dev, 0); - pci_restore_state(pci_dev, dev->state.pci_cfg); + pci_restore_state(pci_dev); /* re-initialize hardware */ cx8800_reset(dev); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index f7e6f0b7e15c..af9d2d3cdc65 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -216,7 +216,6 @@ struct cx8800_fh { }; struct cx8800_suspend_state { - u32 pci_cfg[64 / sizeof(u32)]; int disabled; }; diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index a586b1bc93fa..7471d7a583f0 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -1236,7 +1236,7 @@ static struct video_device meye_template = { #ifdef CONFIG_PM static int meye_suspend(struct pci_dev *pdev, u32 state) { - pci_save_state(pdev, meye.pm_state); + pci_save_state(pdev); meye.pm_mchip_mode = meye.mchip_mode; mchip_hic_stop(); mchip_set(MCHIP_MM_INTA, 0x0); @@ -1245,7 +1245,7 @@ static int meye_suspend(struct pci_dev *pdev, u32 state) static int meye_resume(struct pci_dev *pdev) { - pci_restore_state(pdev, meye.pm_state); + pci_restore_state(pdev); pci_write_config_word(meye.mchip_dev, MCHIP_PCI_SOFTRESET_SET, 1); mchip_delay(MCHIP_HIC_CMD, 0); diff --git a/drivers/media/video/meye.h b/drivers/media/video/meye.h index 0983b8e5792b..f5a40345d1c8 100644 --- a/drivers/media/video/meye.h +++ b/drivers/media/video/meye.h @@ -315,7 +315,6 @@ struct meye { struct video_picture picture; /* video picture parameters */ struct meye_params params; /* additional parameters */ #ifdef CONFIG_PM - u32 pm_state[16]; /* PCI configuration space */ u8 pm_mchip_mode; /* old mchip mode */ #endif }; diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 70a44c9d2f74..97ca4a45dcd0 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1517,7 +1517,7 @@ mptbase_suspend(struct pci_dev *pdev, u32 state) } } - pci_save_state(pdev, ioc->PciState); + pci_save_state(pdev); /* put ioc into READY_STATE */ if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) { @@ -1557,7 +1557,7 @@ mptbase_resume(struct pci_dev *pdev) ioc->name, pdev, pci_name(pdev), device_state); pci_set_power_state(pdev, 0); - pci_restore_state(pdev, ioc->PciState); + pci_restore_state(pdev); pci_enable_device(pdev); /* enable interrupts */ diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 4b9b4934db16..c2321d2e4416 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -663,9 +663,6 @@ typedef struct _MPT_ADAPTER FCPortPage0_t fc_port_page0[2]; LANPage0_t lan_cnfg_page0; LANPage1_t lan_cnfg_page1; -#ifdef CONFIG_PM - u32 PciState[64]; /* save PCI state to this area */ -#endif u8 FirstWhoInit; u8 upload_fw; /* If set, do a fw upload */ u8 reload_fw; /* Force a FW Reload on next reset */ diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 89faad1d2104..c24b5d4a605f 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -817,7 +817,7 @@ struct vortex_private { partner_flow_ctrl:1, /* Partner supports flow control */ has_nway:1, enable_wol:1, /* Wake-on-LAN is enabled */ - pm_state_valid:1, /* power_state[] has sane contents */ + pm_state_valid:1, /* pci_dev->saved_config_space has sane contents */ open:1, medialock:1, must_free_region:1, /* Flag: if zero, Cardbus owns the I/O region */ @@ -834,7 +834,6 @@ struct vortex_private { u16 io_size; /* Size of PCI region (for release_region) */ spinlock_t lock; /* Serialise access to device & its vortex_private */ spinlock_t mdio_lock; /* Serialise access to mdio hardware */ - u32 power_state[16]; }; #ifdef CONFIG_PCI @@ -1494,7 +1493,7 @@ static int __devinit vortex_probe1(struct device *gendev, #endif if (pdev && vp->enable_wol) { vp->pm_state_valid = 1; - pci_save_state(VORTEX_PCI(vp), vp->power_state); + pci_save_state(VORTEX_PCI(vp)); acpi_set_WOL(dev); } retval = register_netdev(dev); @@ -1551,7 +1550,7 @@ vortex_up(struct net_device *dev) if (VORTEX_PCI(vp) && vp->enable_wol) { pci_set_power_state(VORTEX_PCI(vp), 0); /* Go active */ - pci_restore_state(VORTEX_PCI(vp), vp->power_state); + pci_restore_state(VORTEX_PCI(vp)); } /* Before initializing select the active media port. */ @@ -2708,7 +2707,7 @@ vortex_down(struct net_device *dev, int final_down) outl(0, ioaddr + DownListPtr); if (final_down && VORTEX_PCI(vp) && vp->enable_wol) { - pci_save_state(VORTEX_PCI(vp), vp->power_state); + pci_save_state(VORTEX_PCI(vp)); acpi_set_WOL(dev); } } @@ -3166,7 +3165,7 @@ static void __devexit vortex_remove_one (struct pci_dev *pdev) if (VORTEX_PCI(vp) && vp->enable_wol) { pci_set_power_state(VORTEX_PCI(vp), 0); /* Go active */ if (vp->pm_state_valid) - pci_restore_state(VORTEX_PCI(vp), vp->power_state); + pci_restore_state(VORTEX_PCI(vp)); } /* Should really use issue_and_wait() here */ outw(TotalReset|0x14, dev->base_addr + EL3_CMD); diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 1b18b3acad44..e68df9aa5c29 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -366,7 +366,6 @@ struct cp_private { #endif unsigned int wol_enabled : 1; /* Is Wake-on-LAN enabled? */ - u32 power_state[16]; struct mii_if_info mii_if; }; @@ -1845,7 +1844,7 @@ static int cp_suspend (struct pci_dev *pdev, u32 state) spin_unlock_irqrestore (&cp->lock, flags); if (cp->pdev && cp->wol_enabled) { - pci_save_state (cp->pdev, cp->power_state); + pci_save_state (cp->pdev); cp_set_d3_state (cp); } @@ -1864,7 +1863,7 @@ static int cp_resume (struct pci_dev *pdev) if (cp->pdev && cp->wol_enabled) { pci_set_power_state (cp->pdev, 0); - pci_restore_state (cp->pdev, cp->power_state); + pci_restore_state (cp->pdev); } cp_init_hw (cp); diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 2a94719a4226..83978f6ea795 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -567,7 +567,6 @@ struct rtl8139_private { void *mmio_addr; int drv_flags; struct pci_dev *pci_dev; - u32 pci_state[16]; u32 msg_enable; struct net_device_stats stats; unsigned char *rx_ring; @@ -2589,7 +2588,7 @@ static int rtl8139_suspend (struct pci_dev *pdev, u32 state) void *ioaddr = tp->mmio_addr; unsigned long flags; - pci_save_state (pdev, tp->pci_state); + pci_save_state (pdev); if (!netif_running (dev)) return 0; @@ -2617,9 +2616,8 @@ static int rtl8139_suspend (struct pci_dev *pdev, u32 state) static int rtl8139_resume (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = dev->priv; - pci_restore_state (pdev, tp->pci_state); + pci_restore_state (pdev); if (!netif_running (dev)) return 0; pci_set_power_state (pdev, 0); diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index 91fa987dc8a8..1cc9be4b7ce3 100755 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -1874,7 +1874,7 @@ static int amd8111e_suspend(struct pci_dev *pci_dev, u32 state) pci_enable_wake(pci_dev, 4, 0); /* 4 == D3 cold */ } - pci_save_state(pci_dev, lp->pm_state); + pci_save_state(pci_dev); pci_set_power_state(pci_dev, 3); return 0; @@ -1888,7 +1888,7 @@ static int amd8111e_resume(struct pci_dev *pci_dev) return 0; pci_set_power_state(pci_dev, 0); - pci_restore_state(pci_dev, lp->pm_state); + pci_restore_state(pci_dev); pci_enable_wake(pci_dev, 3, 0); pci_enable_wake(pci_dev, 4, 0); /* D3 cold */ diff --git a/drivers/net/amd8111e.h b/drivers/net/amd8111e.h index f95425d5f687..f28eb8846459 100755 --- a/drivers/net/amd8111e.h +++ b/drivers/net/amd8111e.h @@ -780,7 +780,6 @@ struct amd8111e_priv{ struct amd8111e_link_config link_config; int pm_cap; - u32 pm_state[12]; struct net_device *next; int mii; diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 02d58a237913..adb24b740ddd 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1827,7 +1827,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev, pci_set_drvdata(pdev, dev); - pci_save_state(bp->pdev, bp->pci_cfg_state); + pci_save_state(bp->pdev); printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name); for (i = 0; i < 6; i++) @@ -1893,7 +1893,7 @@ static int b44_resume(struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata(pdev); struct b44 *bp = dev->priv; - pci_restore_state(pdev, bp->pci_cfg_state); + pci_restore_state(pdev); if (!netif_running(dev)) return 0; diff --git a/drivers/net/b44.h b/drivers/net/b44.h index 22647be2c026..5b4ffd2c2ba8 100644 --- a/drivers/net/b44.h +++ b/drivers/net/b44.h @@ -535,7 +535,6 @@ struct b44 { u32 rx_pending; u32 tx_pending; - u32 pci_cfg_state[64 / sizeof(u32)]; u8 phy_addr; u8 mdc_port; u8 core_unit; diff --git a/drivers/net/e100.c b/drivers/net/e100.c index a39b58c8102e..42f089acafe5 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -563,7 +563,6 @@ struct nic { u16 leds; u16 eeprom_wc; u16 eeprom[256]; - u32 pm_state[16]; }; static inline void e100_write_flush(struct nic *nic) @@ -2310,7 +2309,7 @@ static int e100_suspend(struct pci_dev *pdev, u32 state) e100_hw_reset(nic); netif_device_detach(netdev); - pci_save_state(pdev, nic->pm_state); + pci_save_state(pdev); pci_enable_wake(pdev, state, nic->flags & (wol_magic | e100_asf(nic))); pci_disable_device(pdev); pci_set_power_state(pdev, state); @@ -2324,7 +2323,7 @@ static int e100_resume(struct pci_dev *pdev) struct nic *nic = netdev_priv(netdev); pci_set_power_state(pdev, 0); - pci_restore_state(pdev, nic->pm_state); + pci_restore_state(pdev); e100_hw_init(nic); netif_device_attach(netdev); diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 108e33145ab6..1951644a9afc 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -254,7 +254,6 @@ struct e1000_adapter { struct e1000_desc_ring test_rx_ring; - uint32_t pci_state[16]; int msg_enable; }; #endif /* _E1000_H_ */ diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index cac241e5ab3d..7019e413a7b7 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2867,7 +2867,7 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state) pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */ } - pci_save_state(pdev, adapter->pci_state); + pci_save_state(pdev); if(adapter->hw.mac_type >= e1000_82540 && adapter->hw.media_type == e1000_media_type_copper) { @@ -2898,7 +2898,7 @@ e1000_resume(struct pci_dev *pdev) pci_enable_device(pdev); pci_set_power_state(pdev, 0); - pci_restore_state(pdev, adapter->pci_state); + pci_restore_state(pdev); pci_enable_wake(pdev, 3, 0); pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */ diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 1132101ec73c..3d0edb66562f 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -490,9 +490,6 @@ struct speedo_private { unsigned short partner; /* Link partner caps. */ struct mii_if_info mii_if; /* MII API hooks, info */ u32 msg_enable; /* debug message level */ -#ifdef CONFIG_PM - u32 pm_state[16]; -#endif }; /* The parameters for a CmdConfigure operation. @@ -2334,7 +2331,7 @@ static int eepro100_suspend(struct pci_dev *pdev, u32 state) struct speedo_private *sp = netdev_priv(dev); long ioaddr = dev->base_addr; - pci_save_state(pdev, sp->pm_state); + pci_save_state(pdev); if (!netif_running(dev)) return 0; @@ -2354,7 +2351,7 @@ static int eepro100_resume(struct pci_dev *pdev) struct speedo_private *sp = netdev_priv(dev); long ioaddr = dev->base_addr; - pci_restore_state(pdev, sp->pm_state); + pci_restore_state(pdev); if (!netif_running(dev)) return 0; diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index eda2d01a5d8e..5ee2550ff32c 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -1768,7 +1768,7 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, u32 state) if (netif_running(ndev)) { netif_device_detach(ndev); vlsi_stop_hw(idev); - pci_save_state(pdev, idev->cfg_space); + pci_save_state(pdev); if (!idev->new_baud) /* remember speed settings to restore on resume */ idev->new_baud = idev->baud; @@ -1819,7 +1819,7 @@ static int vlsi_irda_resume(struct pci_dev *pdev) } if (netif_running(ndev)) { - pci_restore_state(pdev, idev->cfg_space); + pci_restore_state(pdev); vlsi_start_hw(idev); netif_device_attach(ndev); } diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h index 55e4a7f34fb1..1e947e6ad134 100644 --- a/drivers/net/irda/vlsi_ir.h +++ b/drivers/net/irda/vlsi_ir.h @@ -769,7 +769,6 @@ typedef struct vlsi_irda_dev { spinlock_t lock; struct semaphore sem; - u32 cfg_space[64/sizeof(u32)]; u8 resume_ok; struct proc_dir_entry *proc_entry; diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h index 5111c8e6badf..24311a57a376 100644 --- a/drivers/net/ixgb/ixgb.h +++ b/drivers/net/ixgb/ixgb.h @@ -178,6 +178,5 @@ struct ixgb_adapter { /* structs defined in ixgb_hw.h */ struct ixgb_hw hw; struct ixgb_hw_stats stats; - uint32_t pci_state[16]; }; #endif /* _IXGB_H_ */ diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 26af3785dd56..fab5d39e524d 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -2117,7 +2117,7 @@ static int ixgb_suspend(struct pci_dev *pdev, uint32_t state) if (netif_running(netdev)) ixgb_down(adapter, TRUE); - pci_save_state(pdev, adapter->pci_state); + pci_save_state(pdev); state = (state > 0) ? 3 : 0; pci_set_power_state(pdev, state); diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index f931248987f7..c867b17c9e05 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -481,7 +481,6 @@ struct netdrv_private { unsigned int mediasense:1; /* Media sensing in progress. */ spinlock_t lock; chip_t chipset; - u32 pci_state[16]; /* Data saved during suspend */ }; MODULE_AUTHOR ("Jeff Garzik "); @@ -1921,7 +1920,7 @@ static int netdrv_suspend (struct pci_dev *pdev, u32 state) spin_unlock_irqrestore (&tp->lock, flags); - pci_save_state (pdev, tp->pci_state); + pci_save_state (pdev); pci_set_power_state (pdev, 3); return 0; @@ -1936,7 +1935,7 @@ static int netdrv_resume (struct pci_dev *pdev) if (!netif_running(dev)) return 0; pci_set_power_state (pdev, 0); - pci_restore_state (pdev, tp->pci_state); + pci_restore_state (pdev); netif_device_attach (dev); netdrv_hw_start (dev); diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index c68c1c0e7163..de33878a489b 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -1935,7 +1935,7 @@ void s2io_reset(nic_t * sp) schedule_timeout(HZ / 4); /* Restore the PCI state saved during initializarion. */ - pci_restore_state(sp->pdev, sp->config_space); + pci_restore_state(sp->pdev); s2io_init_pci(sp); set_current_state(TASK_UNINTERRUPTIBLE); @@ -4238,7 +4238,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) goto register_failed; } - pci_save_state(sp->pdev, sp->config_space); + pci_save_state(sp->pdev); /* Setting swapper control on the NIC, for proper reset operation */ if (s2io_set_swapper(sp)) { diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index e9a166450656..94754485ac17 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -667,7 +667,6 @@ typedef struct s2io_nic { u8 cache_line; u32 rom_expansion; u16 pcix_cmd; - u32 config_space[256 / sizeof(u32)]; u32 irq; atomic_t rx_bufs_left[MAX_RX_RINGS]; diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 1a87a82a83cc..8ddf9d02f973 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -172,7 +172,6 @@ struct sis900_private { unsigned int tx_full; /* The Tx queue is full. */ u8 host_bridge_rev; - u32 pci_state[16]; }; MODULE_AUTHOR("Jim Huang , Ollie Lho "); @@ -2200,7 +2199,6 @@ static void __devexit sis900_remove(struct pci_dev *pci_dev) static int sis900_suspend(struct pci_dev *pci_dev, u32 state) { struct net_device *net_dev = pci_get_drvdata(pci_dev); - struct sis900_private *sis_priv = net_dev->priv; long ioaddr = net_dev->base_addr; if(!netif_running(net_dev)) @@ -2213,7 +2211,7 @@ static int sis900_suspend(struct pci_dev *pci_dev, u32 state) outl(RxDIS | TxDIS | inl(ioaddr + cr), ioaddr + cr); pci_set_power_state(pci_dev, 3); - pci_save_state(pci_dev, sis_priv->pci_state); + pci_save_state(pci_dev); return 0; } @@ -2226,7 +2224,7 @@ static int sis900_resume(struct pci_dev *pci_dev) if(!netif_running(net_dev)) return 0; - pci_restore_state(pci_dev, sis_priv->pci_state); + pci_restore_state(pci_dev); pci_set_power_state(pci_dev, 0); sis900_init_rxfilter(net_dev); diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 1a26b11fb39a..9d60208af243 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -3788,7 +3788,7 @@ static int tg3_chip_reset(struct tg3 *tp) val |= PCISTATE_RETRY_SAME_DMA; pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val); - pci_restore_state(tp->pdev, tp->pci_cfg_state); + pci_restore_state(tp->pdev); /* Make sure PCI-X relaxed ordering bit is clear. */ pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val); @@ -8316,7 +8316,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, */ if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) || (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { - pci_save_state(tp->pdev, tp->pci_cfg_state); + pci_save_state(tp->pdev); tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); tg3_halt(tp); } @@ -8355,7 +8355,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, * of the PCI config space. We need to restore this after * GRC_MISC_CFG core clock resets and some resume events. */ - pci_save_state(tp->pdev, tp->pci_cfg_state); + pci_save_state(tp->pdev); printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT Ethernet ", dev->name, @@ -8474,7 +8474,7 @@ static int tg3_resume(struct pci_dev *pdev) if (!netif_running(dev)) return 0; - pci_restore_state(tp->pdev, tp->pci_cfg_state); + pci_restore_state(tp->pdev); err = tg3_set_power_state(tp, 0); if (err) diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 5a6bd6276722..6f7e17cd7ae0 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2120,7 +2120,6 @@ struct tg3 { u8 pci_lat_timer; u8 pci_hdr_type; u8 pci_bist; - u32 pci_cfg_state[64 / sizeof(u32)]; int pm_cap; diff --git a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c index 62417cc980eb..f6811cd1cada 100644 --- a/drivers/net/tulip/xircom_tulip_cb.c +++ b/drivers/net/tulip/xircom_tulip_cb.c @@ -329,9 +329,6 @@ struct xircom_private { int saved_if_port; struct pci_dev *pdev; spinlock_t lock; -#ifdef CONFIG_PM - u32 pci_state[16]; -#endif }; static int mdio_read(struct net_device *dev, int phy_id, int location); @@ -1677,7 +1674,7 @@ static int xircom_suspend(struct pci_dev *pdev, u32 state) if (tp->open) xircom_down(dev); - pci_save_state(pdev, tp->pci_state); + pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, 3); @@ -1693,7 +1690,7 @@ static int xircom_resume(struct pci_dev *pdev) pci_set_power_state(pdev,0); pci_enable_device(pdev); - pci_restore_state(pdev, tp->pci_state); + pci_restore_state(pdev); /* Bring the chip out of sleep mode. Caution: Snooze mode does not work with some boards! */ diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index ea5643afddc9..224fd771c316 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -279,7 +279,6 @@ struct typhoon { u16 xcvr_select; u16 wol_events; u32 offload; - u32 pci_state[16]; /* unused stuff (future use) */ int capabilities; @@ -1894,7 +1893,7 @@ typhoon_wakeup(struct typhoon *tp, int wait_type) void __iomem *ioaddr = tp->ioaddr; pci_set_power_state(pdev, 0); - pci_restore_state(pdev, tp->pci_state); + pci_restore_state(pdev); /* Post 2.x.x versions of the Sleep Image require a reset before * we can download the Runtime Image. But let's not make users of @@ -2309,7 +2308,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) * we lost our configuration and need to restore it to the * conditions at boot. */ - pci_restore_state(pdev, NULL); + pci_restore_state(pdev); err = pci_set_dma_mask(pdev, 0xffffffffULL); if(err < 0) { @@ -2377,7 +2376,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->dev = dev; /* need to be able to restore PCI state after a suspend */ - pci_save_state(pdev, tp->pci_state); + pci_save_state(pdev); /* Init sequence: * 1) Reset the adapter to clear any bad juju @@ -2542,7 +2541,7 @@ typhoon_remove_one(struct pci_dev *pdev) unregister_netdev(dev); pci_set_power_state(pdev, 0); - pci_restore_state(pdev, tp->pci_state); + pci_restore_state(pdev); typhoon_reset(tp->ioaddr, NoWait); iounmap(tp->ioaddr); pci_free_consistent(pdev, sizeof(struct typhoon_shared), diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 20bfbb9c7eb6..33c3137c016e 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -1951,7 +1951,7 @@ static int rhine_suspend(struct pci_dev *pdev, u32 state) return 0; netif_device_detach(dev); - pci_save_state(pdev, pdev->saved_config_space); + pci_save_state(pdev); spin_lock_irqsave(&rp->lock, flags); rhine_shutdown(&pdev->dev); @@ -1975,7 +1975,7 @@ static int rhine_resume(struct pci_dev *pdev) printk(KERN_INFO "%s: Entering power state D0 %s (%d).\n", dev->name, ret ? "failed" : "succeeded", ret); - pci_restore_state(pdev, pdev->saved_config_space); + pci_restore_state(pdev); spin_lock_irqsave(&rp->lock, flags); #ifdef USE_MMIO diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 57a6d2924ba7..8ee25c1c674f 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -3221,7 +3221,7 @@ static int velocity_suspend(struct pci_dev *pdev, u32 state) netif_device_detach(vptr->dev); spin_lock_irqsave(&vptr->lock, flags); - pci_save_state(pdev, vptr->pci_state); + pci_save_state(pdev); #ifdef ETHTOOL_GWOL if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) { velocity_get_ip(vptr); @@ -3254,7 +3254,7 @@ static int velocity_resume(struct pci_dev *pdev) pci_set_power_state(pdev, 0); pci_enable_wake(pdev, 0, 0); - pci_restore_state(pdev, vptr->pci_state); + pci_restore_state(pdev); mac_wol_reset(vptr->mac_regs); diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h index 9a187de48e52..d55625c81d71 100644 --- a/drivers/net/via-velocity.h +++ b/drivers/net/via-velocity.h @@ -1739,10 +1739,6 @@ struct velocity_info { struct net_device *dev; struct net_device_stats stats; -#ifdef CONFIG_PM - u32 pci_state[16]; -#endif - dma_addr_t rd_pool_dma; dma_addr_t td_pool_dma[TX_QUEUE_NO]; diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 041b15b0f9fd..8de18e1768dd 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -1210,7 +1210,6 @@ struct airo_info { SsidRid *SSID; APListRid *APList; #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE - u32 pci_state[16]; char proc_name[IFNAMSIZ]; }; @@ -5492,7 +5491,7 @@ static int airo_pci_suspend(struct pci_dev *pdev, u32 state) issuecommand(ai, &cmd, &rsp); pci_enable_wake(pdev, state, 1); - pci_save_state(pdev, ai->pci_state); + pci_save_state(pdev); return pci_set_power_state(pdev, state); } @@ -5503,7 +5502,7 @@ static int airo_pci_resume(struct pci_dev *pdev) Resp rsp; pci_set_power_state(pdev, 0); - pci_restore_state(pdev, ai->pci_state); + pci_restore_state(pdev); pci_enable_wake(pdev, ai->power, 0); if (ai->power > 1) { diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h index 628fb910768d..9c81cb839ad2 100644 --- a/drivers/net/wireless/prism54/islpci_dev.h +++ b/drivers/net/wireless/prism54/islpci_dev.h @@ -106,7 +106,6 @@ typedef struct { /* PCI bus allocation & configuration members */ struct pci_dev *pdev; /* PCI structure information */ - u32 pci_state[16]; /* used for suspend/resume */ char firmware[33]; void __iomem *device_base; /* ioremapped device base address */ diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index 11b315ba15e5..03f20357daba 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -273,7 +273,7 @@ prism54_suspend(struct pci_dev *pdev, u32 state) printk(KERN_NOTICE "%s: got suspend request (state %d)\n", ndev->name, state); - pci_save_state(pdev, priv->pci_state); + pci_save_state(pdev); /* tell the device not to trigger interrupts for now... */ isl38xx_disable_interrupts(priv->device_base); @@ -297,7 +297,7 @@ prism54_resume(struct pci_dev *pdev) printk(KERN_NOTICE "%s: got resume request\n", ndev->name); - pci_restore_state(pdev, priv->pci_state); + pci_restore_state(pdev); /* alright let's go into the PREBOOT state */ islpci_reset(priv, 1); diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 807b1418a45a..2061ce7d5357 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -309,7 +309,7 @@ static int pci_device_suspend(struct device * dev, u32 state) if (drv && drv->suspend) i = drv->suspend(pci_dev, dev_state); - pci_save_state(pci_dev, pci_dev->saved_config_space); + pci_save_state(pci_dev); return i; } @@ -321,7 +321,7 @@ static int pci_device_suspend(struct device * dev, u32 state) static void pci_default_resume(struct pci_dev *pci_dev) { /* restore the PCI config space */ - pci_restore_state(pci_dev, pci_dev->saved_config_space); + pci_restore_state(pci_dev); /* if the device was enabled before suspend, reenable */ if (pci_dev->is_enabled) pci_enable_device(pci_dev); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 3ca4002b6533..7bb774a38f3f 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -308,14 +308,12 @@ pci_set_power_state(struct pci_dev *dev, int state) * (>= 64 bytes). */ int -pci_save_state(struct pci_dev *dev, u32 *buffer) +pci_save_state(struct pci_dev *dev) { int i; - if (buffer) { - /* XXX: 100% dword access ok here? */ - for (i = 0; i < 16; i++) - pci_read_config_dword(dev, i * 4,&buffer[i]); - } + /* XXX: 100% dword access ok here? */ + for (i = 0; i < 16; i++) + pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]); return 0; } @@ -326,27 +324,12 @@ pci_save_state(struct pci_dev *dev, u32 *buffer) * */ int -pci_restore_state(struct pci_dev *dev, u32 *buffer) +pci_restore_state(struct pci_dev *dev) { int i; - if (buffer) { - for (i = 0; i < 16; i++) - pci_write_config_dword(dev,i * 4, buffer[i]); - } - /* - * otherwise, write the context information we know from bootup. - * This works around a problem where warm-booting from Windows - * combined with a D3(hot)->D0 transition causes PCI config - * header data to be forgotten. - */ - else { - for (i = 0; i < 6; i ++) - pci_write_config_dword(dev, - PCI_BASE_ADDRESS_0 + (i * 4), - dev->resource[i].start); - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - } + for (i = 0; i < 16; i++) + pci_write_config_dword(dev,i * 4, dev->saved_config_space[i]); return 0; } diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index d6974a147b9d..2199139ce657 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -1023,9 +1023,9 @@ static int yenta_dev_suspend (struct pci_dev *dev, u32 state) socket->type->save_state(socket); /* FIXME: pci_save_state needs to have a better interface */ - pci_save_state(dev, socket->saved_state); - pci_read_config_dword(dev, 16*4, &socket->saved_state[16]); - pci_read_config_dword(dev, 17*4, &socket->saved_state[17]); + pci_save_state(dev); + pci_read_config_dword(dev, 16*4, &socket->saved_state[0]); + pci_read_config_dword(dev, 17*4, &socket->saved_state[1]); pci_set_power_state(dev, 3); } @@ -1040,9 +1040,9 @@ static int yenta_dev_resume (struct pci_dev *dev) if (socket) { pci_set_power_state(dev, 0); /* FIXME: pci_restore_state needs to have a better interface */ - pci_restore_state(dev, socket->saved_state); - pci_write_config_dword(dev, 16*4, socket->saved_state[16]); - pci_write_config_dword(dev, 17*4, socket->saved_state[17]); + pci_restore_state(dev); + pci_write_config_dword(dev, 16*4, socket->saved_state[0]); + pci_write_config_dword(dev, 17*4, socket->saved_state[1]); if (socket->type && socket->type->restore_state) socket->type->restore_state(socket); diff --git a/drivers/pcmcia/yenta_socket.h b/drivers/pcmcia/yenta_socket.h index 7f04a6b736ef..4e637eef2076 100644 --- a/drivers/pcmcia/yenta_socket.h +++ b/drivers/pcmcia/yenta_socket.h @@ -120,7 +120,7 @@ struct yenta_socket { unsigned int private[8]; /* PCI saved state */ - u32 saved_state[18]; + u32 saved_state[2]; }; diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 40bfff7f2de9..fea019fc3672 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -4935,7 +4935,7 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) int rc; ENTER; - rc = pci_restore_state(ioa_cfg->pdev, ioa_cfg->pci_cfg_buf); + rc = pci_restore_state(ioa_cfg->pdev); if (rc != PCIBIOS_SUCCESSFUL) { ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); @@ -5749,7 +5749,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, } /* Save away PCI config space for use following IOA reset */ - rc = pci_save_state(pdev, ioa_cfg->pci_cfg_buf); + rc = pci_save_state(pdev); if (rc != PCIBIOS_SUCCESSFUL) { dev_err(&pdev->dev, "Failed to save PCI config space\n"); diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index e91afc446a04..ef9439536160 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -889,7 +889,6 @@ struct ipr_ioa_cfg { unsigned long ioa_mailbox; struct ipr_interrupts regs; - u32 pci_cfg_buf[64]; u16 saved_pcix_cmd_reg; u16 reset_retries; diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c index 9735d05ad532..af424db188eb 100644 --- a/drivers/scsi/nsp32.c +++ b/drivers/scsi/nsp32.c @@ -3439,11 +3439,10 @@ static int nsp32_prom_read_bit(nsp32_hw_data *data) static int nsp32_suspend(struct pci_dev *pdev, u32 state) { struct Scsi_Host *host = pci_get_drvdata(pdev); - nsp32_hw_data *data = (nsp32_hw_data *)host->hostdata; nsp32_msg(KERN_INFO, "pci-suspend: pdev=0x%p, state=%ld, slot=%s, host=0x%p", pdev, state, pci_name(pdev), host); - pci_save_state (pdev, data->PciState); + pci_save_state (pdev); pci_disable_device (pdev); pci_set_power_state(pdev, state); @@ -3461,7 +3460,7 @@ static int nsp32_resume(struct pci_dev *pdev) pci_set_power_state(pdev, 0); pci_enable_wake (pdev, 0, 0); - pci_restore_state (pdev, data->PciState); + pci_restore_state (pdev); reg = nsp32_read2(data->BaseAddress, INDEX_REG); diff --git a/drivers/scsi/nsp32.h b/drivers/scsi/nsp32.h index eddb950c5d3e..eef6cdfbc967 100644 --- a/drivers/scsi/nsp32.h +++ b/drivers/scsi/nsp32.h @@ -605,9 +605,6 @@ typedef struct _nsp32_hw_data { unsigned char msginbuf [MSGINBUF_MAX]; /* megin buffer */ char msgin_len; /* msginbuf length */ -#ifdef CONFIG_PM - u32 PciState[16]; /* save PCI state to this area */ -#endif } nsp32_hw_data; /* diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 5fdaae079cf6..fd86c786fdcc 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -305,7 +305,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state) retval); else { hcd->state = HCD_STATE_SUSPENDED; - pci_save_state (dev, hcd->pci_state); + pci_save_state (dev); #ifdef CONFIG_USB_SUSPEND pci_enable_wake (dev, state, hcd->remote_wakeup); pci_enable_wake (dev, 4, hcd->remote_wakeup); @@ -365,7 +365,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev) return retval; } pci_set_master (dev); - pci_restore_state (dev, hcd->pci_state); + pci_restore_state (dev); #ifdef CONFIG_USB_SUSPEND pci_enable_wake (dev, dev->current_state, 0); pci_enable_wake (dev, 4, 0); diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 340977b72925..5b3dc0d393a2 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -81,7 +81,6 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */ #ifdef CONFIG_PCI int region; /* pci region for regs */ - u32 pci_state [16]; /* for PM state save */ #endif #define HCD_BUFFER_POOLS 4 diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h index 68b64233a1aa..55aa70e54585 100644 --- a/drivers/video/i810/i810.h +++ b/drivers/video/i810/i810.h @@ -254,7 +254,6 @@ struct i810fb_par { drm_agp_t *drm_agp; atomic_t use_count; u32 pseudo_palette[17]; - u32 pci_state[16]; unsigned long mmio_start_phys; u8 *mmio_start_virtual; u32 pitch; diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 6acde2569975..ec837053563b 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -1517,7 +1517,7 @@ static int i810fb_suspend(struct pci_dev *dev, u32 state) par->drm_agp->unbind_memory(par->i810_gtt.i810_cursor_memory); pci_disable_device(dev); } - pci_save_state(dev, par->pci_state); + pci_save_state(dev); pci_set_power_state(dev, state); return 0; @@ -1531,7 +1531,7 @@ static int i810fb_resume(struct pci_dev *dev) if (par->cur_state == 0) return 0; - pci_restore_state(dev, par->pci_state); + pci_restore_state(dev); pci_set_power_state(dev, 0); pci_enable_device(dev); par->drm_agp->bind_memory(par->i810_gtt.i810_fb_memory, diff --git a/include/linux/pci.h b/include/linux/pci.h index eb0d2c81c36c..3ed159d12035 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -777,8 +777,8 @@ int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask); int pci_assign_resource(struct pci_dev *dev, int i); /* Power management related routines */ -int pci_save_state(struct pci_dev *dev, u32 *buffer); -int pci_restore_state(struct pci_dev *dev, u32 *buffer); +int pci_save_state(struct pci_dev *dev); +int pci_restore_state(struct pci_dev *dev); int pci_set_power_state(struct pci_dev *dev, int state); int pci_enable_wake(struct pci_dev *dev, u32 state, int enable); @@ -909,8 +909,8 @@ static inline int pci_find_ext_capability (struct pci_dev *dev, int cap) {return static inline const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { return NULL; } /* Power management related routines */ -static inline int pci_save_state(struct pci_dev *dev, u32 *buffer) { return 0; } -static inline int pci_restore_state(struct pci_dev *dev, u32 *buffer) { return 0; } +static inline int pci_save_state(struct pci_dev *dev) { return 0; } +static inline int pci_restore_state(struct pci_dev *dev) { return 0; } static inline int pci_set_power_state(struct pci_dev *dev, int state) { return 0; } static inline int pci_enable_wake(struct pci_dev *dev, u32 state, int enable) { return 0; } diff --git a/sound/core/init.c b/sound/core/init.c index 1ff7667d7284..2873a17bd34b 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -801,7 +801,7 @@ int snd_card_pci_resume(struct pci_dev *dev) if (card->power_state == SNDRV_CTL_POWER_D0) return 0; /* restore the PCI config space */ - pci_restore_state(dev, dev->saved_config_space); + pci_restore_state(dev); /* FIXME: correct state value? */ return card->pm_resume(card, 0); } diff --git a/sound/oss/ali5455.c b/sound/oss/ali5455.c index 8976224f5ae1..35ff1c43c200 100644 --- a/sound/oss/ali5455.c +++ b/sound/oss/ali5455.c @@ -311,7 +311,6 @@ struct ali_card { u16 pci_id; #ifdef CONFIG_PM u16 pm_suspended; - u32 pm_save_state[64 / sizeof(u32)]; int pm_saved_mixer_settings[SOUND_MIXER_NRDEVICES][NR_AC97]; #endif /* soundcore stuff */ @@ -3576,7 +3575,7 @@ static int ali_pm_suspend(struct pci_dev *dev, u32 pm_state) } } } - pci_save_state(dev, card->pm_save_state); /* XXX do we need this? */ + pci_save_state(dev); /* XXX do we need this? */ pci_disable_device(dev); /* disable busmastering */ pci_set_power_state(dev, 3); /* Zzz. */ return 0; @@ -3588,7 +3587,7 @@ static int ali_pm_resume(struct pci_dev *dev) int num_ac97, i = 0; struct ali_card *card = pci_get_drvdata(dev); pci_enable_device(dev); - pci_restore_state(dev, card->pm_save_state); + pci_restore_state(dev); /* observation of a toshiba portege 3440ct suggests that the hardware has to be more or less completely reinitialized from scratch after an apm suspend. Works For Me. -dan */ diff --git a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c index 47e5bed02bb0..9cd2703ab704 100644 --- a/sound/oss/i810_audio.c +++ b/sound/oss/i810_audio.c @@ -406,7 +406,6 @@ struct i810_card { u16 pci_id_internal; /* used to access card_cap[] */ #ifdef CONFIG_PM u16 pm_suspended; - u32 pm_save_state[64/sizeof(u32)]; int pm_saved_mixer_settings[SOUND_MIXER_NRDEVICES][NR_AC97]; #endif /* soundcore stuff */ @@ -3385,7 +3384,7 @@ static int i810_pm_suspend(struct pci_dev *dev, u32 pm_state) } } } - pci_save_state(dev,card->pm_save_state); /* XXX do we need this? */ + pci_save_state(dev); /* XXX do we need this? */ pci_disable_device(dev); /* disable busmastering */ pci_set_power_state(dev,3); /* Zzz. */ @@ -3398,7 +3397,7 @@ static int i810_pm_resume(struct pci_dev *dev) int num_ac97,i=0; struct i810_card *card=pci_get_drvdata(dev); pci_enable_device(dev); - pci_restore_state (dev,card->pm_save_state); + pci_restore_state (dev); /* observation of a toshiba portege 3440ct suggests that the hardware has to be more or less completely reinitialized from -- cgit v1.2.3 From 605fda94db0010e427d15a0f33314a49a92749e3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 6 Oct 2004 00:00:18 -0700 Subject: [PATCH] PCI: remove all usages of pci_dma_sync_sg as it's obsolete. Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/megaraid/megaraid_mbox.c | 4 ++-- include/linux/pci.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 6ff9a71cb1ea..32f7d3ded5a8 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -1559,7 +1559,7 @@ mbox_post_cmd(adapter_t *adapter, scb_t *scb) PCI_DMA_TODEVICE); } else { - pci_dma_sync_sg(adapter->pdev, scb->scp->request_buffer, + pci_dma_sync_sg_for_cpu(adapter->pdev, scb->scp->request_buffer, scb->scp->use_sg, PCI_DMA_TODEVICE); } } @@ -2345,7 +2345,7 @@ megaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb) case MRAID_DMA_WSG: if (scb->dma_direction == PCI_DMA_FROMDEVICE) { - pci_dma_sync_sg(adapter->pdev, + pci_dma_sync_sg_for_cpu(adapter->pdev, scb->scp->request_buffer, scb->scp->use_sg, PCI_DMA_FROMDEVICE); } diff --git a/include/linux/pci.h b/include/linux/pci.h index 3ed159d12035..1ff807d655c1 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -860,7 +860,6 @@ extern void msi_remove_pci_irq_vectors(struct pci_dev *dev); /* Backwards compat, remove in 2.7.x */ #define pci_dma_sync_single pci_dma_sync_single_for_cpu -#define pci_dma_sync_sg pci_dma_sync_sg_for_cpu /* * If the system does not have PCI, clearly these return errors. Define -- cgit v1.2.3 From d675deb6fbf33ae0667643f50d0678d4352fb238 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 6 Oct 2004 00:02:56 -0700 Subject: [PATCH] PCI: remove all usages of pci_dma_sync_single as it's obsolete. Signed-off-by: Greg Kroah-Hartman --- drivers/atm/idt77252.c | 13 +++++++------ drivers/net/wireless/prism54/islpci_mgt.c | 4 ++-- drivers/scsi/megaraid/megaraid_mbox.c | 4 ++-- include/linux/pci.h | 5 +---- 4 files changed, 12 insertions(+), 14 deletions(-) (limited to 'include/linux') diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index 3959cf83e5ae..f16f46879aff 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -1266,8 +1266,9 @@ idt77252_rx_raw(struct idt77252_dev *card) head = IDT77252_PRV_PADDR(queue) + (queue->data - queue->head - 16); tail = readl(SAR_REG_RAWCT); - pci_dma_sync_single(card->pcidev, IDT77252_PRV_PADDR(queue), - queue->end - queue->head - 16, PCI_DMA_FROMDEVICE); + pci_dma_sync_single_for_cpu(card->pcidev, IDT77252_PRV_PADDR(queue), + queue->end - queue->head - 16, + PCI_DMA_FROMDEVICE); while (head != tail) { unsigned int vpi, vci, pti; @@ -1360,10 +1361,10 @@ drop: if (next) { card->raw_cell_head = next; queue = card->raw_cell_head; - pci_dma_sync_single(card->pcidev, - IDT77252_PRV_PADDR(queue), - queue->end - queue->data, - PCI_DMA_FROMDEVICE); + pci_dma_sync_single_for_cpu(card->pcidev, + IDT77252_PRV_PADDR(queue), + queue->end - queue->data, + PCI_DMA_FROMDEVICE); } else { card->raw_cell_head = NULL; printk("%s: raw cell queue overrun\n", diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c index 95b709c907c5..93a7b3172a9b 100644 --- a/drivers/net/wireless/prism54/islpci_mgt.c +++ b/drivers/net/wireless/prism54/islpci_mgt.c @@ -319,8 +319,8 @@ islpci_mgt_receive(struct net_device *ndev) } /* Ensure the results of device DMA are visible to the CPU. */ - pci_dma_sync_single(priv->pdev, buf->pci_addr, - buf->size, PCI_DMA_FROMDEVICE); + pci_dma_sync_single_for_cpu(priv->pdev, buf->pci_addr, + buf->size, PCI_DMA_FROMDEVICE); /* Perform endianess conversion for PIMFOR header in-place. */ header = pimfor_decode_header(buf->mem, frag_len); diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 32f7d3ded5a8..e633d3cd656d 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -1554,7 +1554,7 @@ mbox_post_cmd(adapter_t *adapter, scb_t *scb) if (scb->dma_direction == PCI_DMA_TODEVICE) { if (!scb->scp->use_sg) { // sg list not used - pci_dma_sync_single(adapter->pdev, ccb->buf_dma_h, + pci_dma_sync_single_for_cpu(adapter->pdev, ccb->buf_dma_h, scb->scp->request_bufflen, PCI_DMA_TODEVICE); } @@ -2332,7 +2332,7 @@ megaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb) case MRAID_DMA_WBUF: if (scb->dma_direction == PCI_DMA_FROMDEVICE) { - pci_dma_sync_single(adapter->pdev, + pci_dma_sync_single_for_cpu(adapter->pdev, ccb->buf_dma_h, scb->scp->request_bufflen, PCI_DMA_FROMDEVICE); diff --git a/include/linux/pci.h b/include/linux/pci.h index 1ff807d655c1..f021797cd805 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1,5 +1,5 @@ /* - * $Id: pci.h,v 1.87 1998/10/11 15:13:12 mj Exp $ + * pci.h * * PCI defines and function prototypes * Copyright 1994, Drew Eckhardt @@ -858,9 +858,6 @@ extern void msi_remove_pci_irq_vectors(struct pci_dev *dev); #include -/* Backwards compat, remove in 2.7.x */ -#define pci_dma_sync_single pci_dma_sync_single_for_cpu - /* * If the system does not have PCI, clearly these return errors. Define * these as simple inline functions to avoid hair in drivers. -- cgit v1.2.3 From f807c9a8e5dc916c8816f244542c20331eadd2b3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 6 Oct 2004 00:08:21 -0700 Subject: [PATCH] PCI: pci_module_init() is identical to pci_register_driver() so just make it a #define It needs to stay this way until all usages of pci_module_init() are purged from the tree. Signed-off-by: Greg Kroah-Hartman --- include/linux/pci.h | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) (limited to 'include/linux') diff --git a/include/linux/pci.h b/include/linux/pci.h index f021797cd805..9bb6c7a96b0e 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -674,6 +674,12 @@ struct pci_driver { .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID +/* + * pci_module_init is obsolete, this stays here till we fix up all usages of it + * in the tree. + */ +#define pci_module_init pci_register_driver + /* these external functions are only available when PCI support is enabled */ #ifdef CONFIG_PCI @@ -894,7 +900,6 @@ static inline int pci_dev_present(const struct pci_device_id *ids) static inline void pci_set_master(struct pci_dev *dev) { } static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; } static inline void pci_disable_device(struct pci_dev *dev) { } -static inline int pci_module_init(struct pci_driver *drv) { return -ENODEV; } static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask) { return -EIO; } static inline int pci_dac_set_dma_mask(struct pci_dev *dev, u64 mask) { return -EIO; } static inline int pci_assign_resource(struct pci_dev *dev, int i) { return -EBUSY;} @@ -914,19 +919,6 @@ static inline int pci_enable_wake(struct pci_dev *dev, u32 state, int enable) { #else -/* - * a helper function which helps ensure correct pci_driver - * setup and cleanup for commonly-encountered hotplug/modular cases - * - * This MUST stay in a header, as it checks for -DMODULE - */ -static inline int pci_module_init(struct pci_driver *drv) -{ - int rc = pci_register_driver (drv); - - return rc < 0 ? rc : 0; -} - /* * PCI domain support. Sometimes called PCI segment (eg by ACPI), * a PCI domain is defined to be a set of PCI busses which share -- cgit v1.2.3 From dedae7945b7df4f6fe57fc059f9d6aa9bf2b0a4f Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 6 Oct 2004 03:20:23 -0700 Subject: [PATCH] PCI: CONFIG_PCI=n build fix With CONFIG_PCI=n: arch/i386/kernel/cpu/cyrix.c: In function `init_cyrix': arch/i386/kernel/cpu/cyrix.c:285: `cyrix_55x0' undeclared (first use in this function) arch/i386/kernel/cpu/cyrix.c:285: (Each undeclared identifier is reported only once arch/i386/kernel/cpu/cyrix.c:285: for each function it appears in.) Make pci_dev_present() a macro. It doesn't make sense to require that pci_device_id's be in scope when CONFIG_PCI=n Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- include/linux/pci.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/pci.h b/include/linux/pci.h index 9bb6c7a96b0e..7dcb03795de6 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -894,8 +894,8 @@ unsigned int ss_vendor, unsigned int ss_device, struct pci_dev *from) static inline struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) { return NULL; } -static inline int pci_dev_present(const struct pci_device_id *ids) -{ return 0; } + +#define pci_dev_present(ids) (0) static inline void pci_set_master(struct pci_dev *dev) { } static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; } -- cgit v1.2.3 From 7363fb21ab812459f4f62065524b5efda8022510 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 6 Oct 2004 03:20:53 -0700 Subject: [PATCH] PCI: pci_dev_put() build fix With CONFIG_PCI=n: arch/i386/kernel/cpu/mtrr/main.c: In function `have_wrcomb': arch/i386/kernel/cpu/mtrr/main.c:86: warning: implicit declaration of function `pci_dev_put Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- include/linux/pci.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/pci.h b/include/linux/pci.h index 7dcb03795de6..7a3f983ccae9 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -896,6 +896,7 @@ static inline struct pci_dev *pci_get_class(unsigned int class, struct pci_dev * { return NULL; } #define pci_dev_present(ids) (0) +#define pci_dev_put(dev) do { } while (0) static inline void pci_set_master(struct pci_dev *dev) { } static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; } -- cgit v1.2.3 From c684195ea577f5575dfae2b23a9de85d2f3064c6 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 19 Oct 2004 06:53:12 -0400 Subject: [AGPGART] Fix incorrect VIA PT880 entry. There was a mistake in the list of IDs I got from VIA, which meant this chipset was incorrectly recognised. Signed-off-by: Dave Jones --- include/linux/pci_ids.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index bc69e1f29b46..11f24660ed25 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1198,6 +1198,7 @@ #define PCI_DEVICE_ID_VIA_8763_0 0x0198 #define PCI_DEVICE_ID_VIA_8380_0 0x0204 #define PCI_DEVICE_ID_VIA_3238_0 0x0238 +#define PCI_DEVICE_ID_VIA_PT880 0x0258 #define PCI_DEVICE_ID_VIA_PX8X0_0 0x0259 #define PCI_DEVICE_ID_VIA_3269_0 0x0269 #define PCI_DEVICE_ID_VIA_K8T800PRO_0 0x0282 @@ -1256,7 +1257,6 @@ #define PCI_DEVICE_ID_VIA_8377_0 0x3189 #define PCI_DEVICE_ID_VIA_8378_0 0x3205 #define PCI_DEVICE_ID_VIA_8783_0 0x3208 -#define PCI_DEVICE_ID_VIA_PT880 0x3258 #define PCI_DEVICE_ID_VIA_P4M400 0x3209 #define PCI_DEVICE_ID_VIA_8237 0x3227 #define PCI_DEVICE_ID_VIA_3296_0 0x0296 -- cgit v1.2.3 From 162aa2bca3010f84f734016cec915f0eea7f748c Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 19 Oct 2004 23:46:59 +0200 Subject: [ide] add sg_init_one() helper and teach ide about it Signed-off-by: Bartlomiej Zolnierkiewicz --- arch/cris/arch-v10/drivers/ide.c | 8 ++------ drivers/ide/arm/icside.c | 6 ++---- drivers/ide/ide-dma.c | 11 +++-------- drivers/ide/ppc/pmac.c | 11 +++-------- include/linux/scatterlist.h | 14 ++++++++++++++ 5 files changed, 24 insertions(+), 26 deletions(-) create mode 100644 include/linux/scatterlist.h (limited to 'include/linux') diff --git a/arch/cris/arch-v10/drivers/ide.c b/arch/cris/arch-v10/drivers/ide.c index 335473c453cf..32ded35c63a7 100644 --- a/arch/cris/arch-v10/drivers/ide.c +++ b/arch/cris/arch-v10/drivers/ide.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -624,12 +625,7 @@ static int e100_ide_build_dmatable (ide_drive_t *drive) ata_tot_size = 0; if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) { - u8 *virt_addr = rq->buffer; - int sector_count = rq->nr_sectors; - memset(&sg[0], 0, sizeof(*sg)); - sg[0].page = virt_to_page(virt_addr); - sg[0].offset = offset_in_page(virt_addr); - sg[0].length = sector_count * SECTOR_SIZE; + sg_init_one(&sg[0], rq->buffer, rq->nr_sectors * SECTOR_SIZE); hwif->sg_nents = i = 1; } else diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index edc9de780165..dde480e55099 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -223,10 +224,7 @@ static void icside_build_sglist(ide_drive_t *drive, struct request *rq) else hwif->sg_dma_direction = DMA_FROM_DEVICE; - memset(sg, 0, sizeof(*sg)); - sg->page = virt_to_page(rq->buffer); - sg->offset = offset_in_page(rq->buffer); - sg->length = rq->nr_sectors * SECTOR_SIZE; + sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE); nents = 1; } else { nents = blk_rq_map_sg(drive->queue, rq, sg); diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index cd32057b53a9..dd7cabd1834b 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -85,6 +85,7 @@ #include #include #include +#include #include #include @@ -253,18 +254,12 @@ int ide_raw_build_sglist(ide_drive_t *drive, struct request *rq) #else while (sector_count > 128) { #endif - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].page = virt_to_page(virt_addr); - sg[nents].offset = offset_in_page(virt_addr); - sg[nents].length = 128 * SECTOR_SIZE; + sg_init_one(&sg[nents], virt_addr, 128 * SECTOR_SIZE); nents++; virt_addr = virt_addr + (128 * SECTOR_SIZE); sector_count -= 128; } - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].page = virt_to_page(virt_addr); - sg[nents].offset = offset_in_page(virt_addr); - sg[nents].length = sector_count * SECTOR_SIZE; + sg_init_one(&sg[nents], virt_addr, sector_count * SECTOR_SIZE); nents++; return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction); diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 3625e38a7dce..fabbdef2ee10 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -1604,18 +1605,12 @@ pmac_ide_raw_build_sglist(ide_drive_t *drive, struct request *rq) pmif->sg_dma_direction = PCI_DMA_FROMDEVICE; if (sector_count > 128) { - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].page = virt_to_page(virt_addr); - sg[nents].offset = offset_in_page(virt_addr); - sg[nents].length = 128 * SECTOR_SIZE; + sg_init_one(&sg[nents], virt_addr, 128 * SECTOR_SIZE); nents++; virt_addr = virt_addr + (128 * SECTOR_SIZE); sector_count -= 128; } - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].page = virt_to_page(virt_addr); - sg[nents].offset = offset_in_page(virt_addr); - sg[nents].length = sector_count * SECTOR_SIZE; + sg_init_one(&sg[nents], virt_addr, sector_count * SECTOR_SIZE); nents++; return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction); diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h new file mode 100644 index 000000000000..7f717e95ae37 --- /dev/null +++ b/include/linux/scatterlist.h @@ -0,0 +1,14 @@ +#ifndef _LINUX_SCATTERLIST_H +#define _LINUX_SCATTERLIST_H + +static inline void sg_init_one(struct scatterlist *sg, + u8 *buf, unsigned int buflen) +{ + memset(sg, 0, sizeof(*sg)); + + sg->page = virt_to_page(buf); + sg->offset = offset_in_page(buf); + sg->length = buflen; +} + +#endif /* _LINUX_SCATTERLIST_H */ -- cgit v1.2.3 From b925236ddb6a73d854f8839ceebce8c91cef90bb Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 20 Oct 2004 01:49:30 +0200 Subject: [ide] add ide_hwif_t->dma_setup() * tag REQ_DRIVE_TASKFILE write requests with REQ_RW * split off ->dma_setup() from ->ide_dma_[read,write] functions * use ->dma_setup() directly in ATAPI drivers and remove media checks from ->ide_dma_[read,write] * ->ide_dma_[read,write,begin] cannot fail now * in Etrax ide.c setup DMA for ATAPI devices before sending command to drive (so setup order is the same as for disks) Signed-off-by: Bartlomiej Zolnierkiewicz --- arch/cris/arch-v10/drivers/ide.c | 62 +++++++++++++++---------------------- drivers/ide/arm/icside.c | 24 ++++++--------- drivers/ide/ide-cd.c | 12 ++------ drivers/ide/ide-disk.c | 16 +++++++--- drivers/ide/ide-dma.c | 43 +++++++++----------------- drivers/ide/ide-floppy.c | 10 ++---- drivers/ide/ide-tape.c | 8 ++--- drivers/ide/ide-taskfile.c | 13 ++++++-- drivers/ide/ide.c | 1 + drivers/ide/pci/alim15x3.c | 21 +++++++------ drivers/ide/pci/ns87415.c | 18 ++--------- drivers/ide/pci/sgiioc4.c | 41 +++++++++++++------------ drivers/ide/pci/trm290.c | 66 +++++++++++++++++++--------------------- drivers/ide/ppc/pmac.c | 19 ++---------- drivers/scsi/ide-scsi.c | 9 ++---- include/linux/ide.h | 5 ++- 16 files changed, 154 insertions(+), 214 deletions(-) (limited to 'include/linux') diff --git a/arch/cris/arch-v10/drivers/ide.c b/arch/cris/arch-v10/drivers/ide.c index 32ded35c63a7..cb57b2e55598 100644 --- a/arch/cris/arch-v10/drivers/ide.c +++ b/arch/cris/arch-v10/drivers/ide.c @@ -282,6 +282,29 @@ static void tune_e100_ide(ide_drive_t *drive, byte pio) } } +static int e100_dma_setup(ide_drive_t *drive) +{ + struct request *rq = drive->hwif->hwgroup->rq; + + if (rq_data_dir(rq)) { + e100_read_command = 0; + + RESET_DMA(ATA_TX_DMA_NBR); /* sometimes the DMA channel get stuck so we need to do this */ + WAIT_DMA(ATA_TX_DMA_NBR); + } else { + e100_read_command = 1; + + RESET_DMA(ATA_RX_DMA_NBR); /* sometimes the DMA channel get stuck so we need to do this */ + WAIT_DMA(ATA_RX_DMA_NBR); + } + + /* set up the Etrax DMA descriptors */ + if (e100_ide_build_dmatable(drive)) + return 1; + + return 0; +} + void __init init_e100_ide (void) { @@ -303,6 +326,7 @@ init_e100_ide (void) hwif->atapi_output_bytes = &e100_atapi_output_bytes; hwif->ide_dma_check = &e100_dma_check; hwif->ide_dma_end = &e100_dma_end; + hwif->dma_setup = &e100_dma_setup; hwif->ide_dma_write = &e100_dma_write; hwif->ide_dma_read = &e100_dma_read; hwif->ide_dma_begin = &e100_dma_begin; @@ -769,10 +793,6 @@ static ide_startstop_t etrax_dma_intr (ide_drive_t *drive) * sector address using CHS or LBA. All that remains is to prepare for DMA * and then issue the actual read/write DMA/PIO command to the drive. * - * For ATAPI devices, we just prepare for DMA and return. The caller should - * then issue the packet command to the drive and call us again with - * ide_dma_begin afterwards. - * * Returns 0 if all went well. * Returns 1 if DMA read/write could not be started, in which case * the caller should revert to PIO for the current request. @@ -793,14 +813,6 @@ static int e100_start_dma(ide_drive_t *drive, int atapi, int reading) { if(reading) { - RESET_DMA(ATA_RX_DMA_NBR); /* sometimes the DMA channel get stuck so we need to do this */ - WAIT_DMA(ATA_RX_DMA_NBR); - - /* set up the Etrax DMA descriptors */ - - if(e100_ide_build_dmatable (drive)) - return 1; - if(!atapi) { /* set the irq handler which will finish the request when DMA is done */ @@ -851,14 +863,6 @@ static int e100_start_dma(ide_drive_t *drive, int atapi, int reading) } else { /* writing */ - RESET_DMA(ATA_TX_DMA_NBR); /* sometimes the DMA channel get stuck so we need to do this */ - WAIT_DMA(ATA_TX_DMA_NBR); - - /* set up the Etrax DMA descriptors */ - - if(e100_ide_build_dmatable (drive)) - return 1; - if(!atapi) { /* set the irq handler which will finish the request when DMA is done */ @@ -903,27 +907,11 @@ static int e100_start_dma(ide_drive_t *drive, int atapi, int reading) static int e100_dma_write(ide_drive_t *drive) { - e100_read_command = 0; - /* ATAPI-devices (not disks) first call ide_dma_read/write to set the direction - * then they call ide_dma_begin after they have issued the appropriate drive command - * themselves to actually start the chipset DMA. so we just return here if we're - * not a diskdrive. - */ - if (drive->media != ide_disk) - return 0; return e100_start_dma(drive, 0, 0); } static int e100_dma_read(ide_drive_t *drive) { - e100_read_command = 1; - /* ATAPI-devices (not disks) first call ide_dma_read/write to set the direction - * then they call ide_dma_begin after they have issued the appropriate drive command - * themselves to actually start the chipset DMA. so we just return here if we're - * not a diskdrive. - */ - if (drive->media != ide_disk) - return 0; return e100_start_dma(drive, 0, 1); } @@ -932,7 +920,7 @@ static int e100_dma_begin(ide_drive_t *drive) /* begin DMA, used by ATAPI devices which want to issue the * appropriate IDE command themselves. * - * they have already called ide_dma_read/write to set the + * they have already called ->dma_setup to set the * static reading flag, now they call ide_dma_begin to do * the real stuff. we tell our code below not to issue * any IDE commands itself and jump into it. diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index dde480e55099..63e7c4bf297c 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -439,11 +439,16 @@ static ide_startstop_t icside_dmaintr(ide_drive_t *drive) return DRIVER(drive)->error(drive, __FUNCTION__, stat); } -static int -icside_dma_common(ide_drive_t *drive, struct request *rq, - unsigned int dma_mode) +static int icside_dma_setup(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); + struct request *rq = hwif->hwgroup->rq; + unsigned int dma_mode; + + if (rq_data_dir(rq)) + dma_mode = DMA_MODE_WRITE; + else + dma_mode = DMA_MODE_READ; /* * We can not enable DMA on both channels. @@ -484,12 +489,6 @@ static int icside_dma_read(ide_drive_t *drive) struct request *rq = HWGROUP(drive)->rq; task_ioreg_t cmd; - if (icside_dma_common(drive, rq, DMA_MODE_READ)) - return 1; - - if (drive->media != ide_disk) - return 0; - BUG_ON(HWGROUP(drive)->handler != NULL); /* @@ -521,12 +520,6 @@ static int icside_dma_write(ide_drive_t *drive) struct request *rq = HWGROUP(drive)->rq; task_ioreg_t cmd; - if (icside_dma_common(drive, rq, DMA_MODE_WRITE)) - return 1; - - if (drive->media != ide_disk) - return 0; - BUG_ON(HWGROUP(drive)->handler != NULL); /* @@ -621,6 +614,7 @@ static int icside_dma_init(ide_hwif_t *hwif) hwif->ide_dma_off_quietly = icside_dma_off_quietly; hwif->ide_dma_host_on = icside_dma_host_on; hwif->ide_dma_on = icside_dma_on; + hwif->dma_setup = icside_dma_setup; hwif->ide_dma_read = icside_dma_read; hwif->ide_dma_write = icside_dma_write; hwif->ide_dma_begin = icside_dma_begin; diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 895f245fcced..820178c1134d 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -865,20 +865,14 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, { ide_startstop_t startstop; struct cdrom_info *info = drive->driver_data; + ide_hwif_t *hwif = drive->hwif; /* Wait for the controller to be idle. */ if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY)) return startstop; - if (info->dma) { - if (info->cmd == READ) { - info->dma = !HWIF(drive)->ide_dma_read(drive); - } else if (info->cmd == WRITE) { - info->dma = !HWIF(drive)->ide_dma_write(drive); - } else { - printk("ide-cd: DMA set, but not allowed\n"); - } - } + if (info->dma) + info->dma = !hwif->dma_setup(drive); /* Set up the controller registers. */ /* FIXME: for Virtual DMA we must check harder */ diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 020bb4c11a31..81741fca487e 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -419,10 +419,19 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector hwif->OUTB(head|drive->select.all,IDE_SELECT_REG); } - if (rq_data_dir(rq) == READ) { - if (dma && !hwif->ide_dma_read(drive)) + if (dma) { + if (!hwif->dma_setup(drive)) { + if (rq_data_dir(rq)) { + hwif->ide_dma_write(drive); + } else { + hwif->ide_dma_read(drive); + } return ide_started; + } + /* fallback to PIO */ + } + if (rq_data_dir(rq) == READ) { command = ((drive->mult_count) ? ((lba48) ? WIN_MULTREAD_EXT : WIN_MULTREAD) : ((lba48) ? WIN_READ_EXT : WIN_READ)); @@ -431,9 +440,6 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector } else { ide_startstop_t startstop; - if (dma && !hwif->ide_dma_write(drive)) - return ide_started; - command = ((drive->mult_count) ? ((lba48) ? WIN_MULTWRITE_EXT : WIN_MULTWRITE) : ((lba48) ? WIN_WRITE_EXT : WIN_WRITE)); diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index dd7cabd1834b..339c571daa23 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -585,10 +585,8 @@ int __ide_dma_check (ide_drive_t *drive) EXPORT_SYMBOL(__ide_dma_check); /** - * ide_start_dma - begin a DMA phase - * @hwif: interface + * ide_dma_setup - begin a DMA phase * @drive: target device - * @reading: set if reading, clear if writing * * Build an IDE DMA PRD (IDE speak for scatter gather table) * and then set up the DMA transfer registers for a device @@ -598,12 +596,19 @@ EXPORT_SYMBOL(__ide_dma_check); * Returns 0 on success. If a PIO fallback is required then 1 * is returned. */ - -int ide_start_dma(ide_hwif_t *hwif, ide_drive_t *drive, int reading) + +int ide_dma_setup(ide_drive_t *drive) { + ide_hwif_t *hwif = drive->hwif; struct request *rq = HWGROUP(drive)->rq; + unsigned int reading; u8 dma_stat; + if (rq_data_dir(rq)) + reading = 0; + else + reading = 1 << 3; + /* fall back to pio! */ if (!ide_build_dmatable(drive, rq)) return 1; @@ -623,23 +628,15 @@ int ide_start_dma(ide_hwif_t *hwif, ide_drive_t *drive, int reading) return 0; } -EXPORT_SYMBOL(ide_start_dma); +EXPORT_SYMBOL_GPL(ide_dma_setup); -int __ide_dma_read (ide_drive_t *drive /*, struct request *rq */) +static int __ide_dma_read(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); struct request *rq = HWGROUP(drive)->rq; - unsigned int reading = 1 << 3; u8 lba48 = (drive->addressing == 1) ? 1 : 0; task_ioreg_t command = WIN_NOP; - /* try pio */ - if (ide_start_dma(hwif, drive, reading)) - return 1; - - if (drive->media != ide_disk) - return 0; - command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA; if (drive->vdma) @@ -655,23 +652,13 @@ int __ide_dma_read (ide_drive_t *drive /*, struct request *rq */) return hwif->ide_dma_begin(drive); } -EXPORT_SYMBOL(__ide_dma_read); - -int __ide_dma_write (ide_drive_t *drive /*, struct request *rq */) +static int __ide_dma_write(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); struct request *rq = HWGROUP(drive)->rq; - unsigned int reading = 0; u8 lba48 = (drive->addressing == 1) ? 1 : 0; task_ioreg_t command = WIN_NOP; - /* try PIO instead of DMA */ - if (ide_start_dma(hwif, drive, reading)) - return 1; - - if (drive->media != ide_disk) - return 0; - command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; if (drive->vdma) command = (lba48) ? WIN_WRITE_EXT: WIN_WRITE; @@ -687,8 +674,6 @@ int __ide_dma_write (ide_drive_t *drive /*, struct request *rq */) return hwif->ide_dma_begin(drive); } -EXPORT_SYMBOL(__ide_dma_write); - int __ide_dma_begin (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); @@ -1004,6 +989,8 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p hwif->ide_dma_host_on = &__ide_dma_host_on; if (!hwif->ide_dma_check) hwif->ide_dma_check = &__ide_dma_check; + if (!hwif->dma_setup) + hwif->dma_setup = &ide_dma_setup; if (!hwif->ide_dma_read) hwif->ide_dma_read = &__ide_dma_read; if (!hwif->ide_dma_write) diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 7383f44a2d0b..ded2893cc8d2 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -995,6 +995,7 @@ static ide_startstop_t idefloppy_transfer_pc1 (ide_drive_t *drive) static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc) { idefloppy_floppy_t *floppy = drive->driver_data; + ide_hwif_t *hwif = drive->hwif; atapi_feature_t feature; atapi_bcount_t bcount; ide_handler_t *pkt_xfer_routine; @@ -1049,13 +1050,8 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p } feature.all = 0; - if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) { - if (test_bit(PC_WRITING, &pc->flags)) { - feature.b.dma = !HWIF(drive)->ide_dma_write(drive); - } else { - feature.b.dma = !HWIF(drive)->ide_dma_read(drive); - } - } + if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) + feature.b.dma = !hwif->dma_setup(drive); if (IDE_CONTROL_REG) HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG); diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 9d19fab9cc8a..8422980eade7 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -2135,12 +2135,8 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape "reverting to PIO\n"); (void)__ide_dma_off(drive); } - if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) { - if (test_bit(PC_WRITING, &pc->flags)) - dma_ok = !HWIF(drive)->ide_dma_write(drive); - else - dma_ok = !HWIF(drive)->ide_dma_read(drive); - } + if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) + dma_ok = !hwif->dma_setup(drive); if (IDE_CONTROL_REG) hwif->OUTB(drive->ctl, IDE_CONTROL_REG); diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 8de2a111b9f7..f53de7bdb281 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -150,15 +150,19 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) case WIN_WRITEDMA_ONCE: case WIN_WRITEDMA: case WIN_WRITEDMA_EXT: - if (!hwif->ide_dma_write(drive)) + if (!hwif->dma_setup(drive)) { + hwif->ide_dma_write(drive); return ide_started; + } break; case WIN_READDMA_ONCE: case WIN_READDMA: case WIN_READDMA_EXT: case WIN_IDENTIFY_DMA: - if (!hwif->ide_dma_read(drive)) + if (!hwif->dma_setup(drive)) { + hwif->ide_dma_read(drive); return ide_started; + } break; default: if (task->handler == NULL) @@ -517,6 +521,9 @@ int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_ rq.hard_nr_sectors = rq.nr_sectors; rq.hard_cur_sectors = rq.current_nr_sectors = rq.nr_sectors; + + if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) + rq.flags |= REQ_RW; } rq.special = args; @@ -896,11 +903,13 @@ ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) case TASKFILE_OUT_DMAQ: case TASKFILE_OUT_DMA: + hwif->dma_setup(drive); hwif->ide_dma_write(drive); break; case TASKFILE_IN_DMAQ: case TASKFILE_IN_DMA: + hwif->dma_setup(drive); hwif->ide_dma_read(drive); break; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index c57bd4cc9e20..b4e720869aba 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -685,6 +685,7 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->atapi_input_bytes = tmp_hwif->atapi_input_bytes; hwif->atapi_output_bytes = tmp_hwif->atapi_output_bytes; + hwif->dma_setup = tmp_hwif->dma_setup; hwif->ide_dma_read = tmp_hwif->ide_dma_read; hwif->ide_dma_write = tmp_hwif->ide_dma_write; hwif->ide_dma_begin = tmp_hwif->ide_dma_begin; diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index 82a449dc8222..51ea019da0cc 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -558,18 +558,19 @@ no_dma_set: } /** - * ali15x3_dma_write - do a DMA IDE write - * @drive: drive to issue write for + * ali15x3_dma_setup - begin a DMA phase + * @drive: target device * - * Returns 1 if the DMA write cannot be performed, zero on - * success. + * Returns 1 if the DMA cannot be performed, zero on success. */ - -static int ali15x3_dma_write (ide_drive_t *drive) + +static int ali15x3_dma_setup(ide_drive_t *drive) { - if ((m5229_revision < 0xC2) && (drive->media != ide_disk)) - return 1; /* try PIO instead of DMA */ - return __ide_dma_write(drive); + if (m5229_revision < 0xC2 && drive->media != ide_disk) { + if (rq_data_dir(drive->hwif->hwgroup->rq)) + return 1; /* try PIO instead of DMA */ + } + return ide_dma_setup(drive); } /** @@ -773,7 +774,7 @@ static void __init init_hwif_common_ali15x3 (ide_hwif_t *hwif) * M1543C or newer for DMAing */ hwif->ide_dma_check = &ali15x3_config_drive_for_dma; - hwif->ide_dma_write = &ali15x3_dma_write; + hwif->dma_setup = &ali15x3_dma_setup; if (!noautodma) hwif->autodma = 1; if (!(hwif->udma_four)) diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c index 44f7824924d8..b2efe20585e5 100644 --- a/drivers/ide/pci/ns87415.c +++ b/drivers/ide/pci/ns87415.c @@ -101,22 +101,11 @@ static int ns87415_ide_dma_end (ide_drive_t *drive) return (dma_stat & 7) != 4; } -static int ns87415_ide_dma_read (ide_drive_t *drive) +static int ns87415_ide_dma_setup(ide_drive_t *drive) { /* select DMA xfer */ ns87415_prepare_drive(drive, 1); - if (!(__ide_dma_read(drive))) - return 0; - /* DMA failed: select PIO xfer */ - ns87415_prepare_drive(drive, 0); - return 1; -} - -static int ns87415_ide_dma_write (ide_drive_t *drive) -{ - /* select DMA xfer */ - ns87415_prepare_drive(drive, 1); - if (!(__ide_dma_write(drive))) + if (!ide_dma_setup(drive)) return 0; /* DMA failed: select PIO xfer */ ns87415_prepare_drive(drive, 0); @@ -204,8 +193,7 @@ static void __init init_hwif_ns87415 (ide_hwif_t *hwif) return; hwif->OUTB(0x60, hwif->dma_status); - hwif->ide_dma_read = &ns87415_ide_dma_read; - hwif->ide_dma_write = &ns87415_ide_dma_write; + hwif->dma_setup = &ns87415_ide_dma_setup; hwif->ide_dma_check = &ns87415_ide_dma_check; hwif->ide_dma_end = &ns87415_ide_dma_end; diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 6a3d79b2945a..4790d656fb92 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -574,36 +574,36 @@ use_pio_instead: return 0; /* revert to PIO for this request */ } -static int -sgiioc4_ide_dma_read(ide_drive_t * drive) +static int sgiioc4_ide_dma_setup(ide_drive_t *drive) { struct request *rq = HWGROUP(drive)->rq; unsigned int count = 0; + int ddir; + + if (rq_data_dir(rq)) + ddir = PCI_DMA_TODEVICE; + else + ddir = PCI_DMA_FROMDEVICE; - if (!(count = sgiioc4_build_dma_table(drive, rq, PCI_DMA_FROMDEVICE))) { + if (!(count = sgiioc4_build_dma_table(drive, rq, ddir))) { /* try PIO instead of DMA */ return 1; } - /* Writes FROM the IOC4 TO Main Memory */ - sgiioc4_configure_for_dma(IOC4_DMA_WRITE, drive); + + if (rq_data_dir(rq)) + /* Writes TO the IOC4 FROM Main Memory */ + ddir = IOC4_DMA_READ; + else + /* Writes FROM the IOC4 TO Main Memory */ + ddir = IOC4_DMA_WRITE; + + sgiioc4_configure_for_dma(ddir, drive); return 0; } -static int -sgiioc4_ide_dma_write(ide_drive_t * drive) +static int sgiioc4_ide_dma_dummy(ide_drive_t *drive) { - struct request *rq = HWGROUP(drive)->rq; - unsigned int count = 0; - - if (!(count = sgiioc4_build_dma_table(drive, rq, PCI_DMA_TODEVICE))) { - /* try PIO instead of DMA */ - return 1; - } - - sgiioc4_configure_for_dma(IOC4_DMA_READ, drive); - /* Writes TO the IOC4 FROM Main Memory */ - return 0; } @@ -629,8 +629,9 @@ ide_init_sgiioc4(ide_hwif_t * hwif) hwif->quirkproc = NULL; hwif->busproc = NULL; - hwif->ide_dma_read = &sgiioc4_ide_dma_read; - hwif->ide_dma_write = &sgiioc4_ide_dma_write; + hwif->dma_setup = &sgiioc4_ide_dma_setup; + hwif->ide_dma_read = &sgiioc4_ide_dma_dummy; + hwif->ide_dma_write = &sgiioc4_ide_dma_dummy; hwif->ide_dma_begin = &sgiioc4_ide_dma_begin; hwif->ide_dma_end = &sgiioc4_ide_dma_end; hwif->ide_dma_check = &sgiioc4_ide_dma_check; diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c index bb7de7a96dba..c3c3793a13a8 100644 --- a/drivers/ide/pci/trm290.c +++ b/drivers/ide/pci/trm290.c @@ -185,28 +185,7 @@ static int trm290_ide_dma_write (ide_drive_t *drive /*, struct request *rq */) struct request *rq = HWGROUP(drive)->rq; // ide_task_t *args = rq->special; task_ioreg_t command = WIN_NOP; - unsigned int count, reading = 2, writing = 0; - reading = 0; - writing = 1; -#ifdef TRM290_NO_DMA_WRITES - /* always use PIO for writes */ - trm290_prepare_drive(drive, 0); /* select PIO xfer */ - return 1; -#endif - if (!(count = ide_build_dmatable(drive, rq))) { - /* try PIO instead of DMA */ - trm290_prepare_drive(drive, 0); /* select PIO xfer */ - return 1; - } - /* select DMA xfer */ - trm290_prepare_drive(drive, 1); - hwif->OUTL(hwif->dmatable_dma|reading|writing, hwif->dma_command); - drive->waiting_for_dma = 1; - /* start DMA */ - hwif->OUTW((count * 2) - 1, hwif->dma_status); - if (drive->media != ide_disk) - return 0; if (HWGROUP(drive)->handler != NULL) /* paranoia check */ BUG(); ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); @@ -236,21 +215,7 @@ static int trm290_ide_dma_read (ide_drive_t *drive /*, struct request *rq */) struct request *rq = HWGROUP(drive)->rq; // ide_task_t *args = rq->special; task_ioreg_t command = WIN_NOP; - unsigned int count, reading = 2, writing = 0; - if (!(count = ide_build_dmatable(drive, rq))) { - /* try PIO instead of DMA */ - trm290_prepare_drive(drive, 0); /* select PIO xfer */ - return 1; - } - /* select DMA xfer */ - trm290_prepare_drive(drive, 1); - hwif->OUTL(hwif->dmatable_dma|reading|writing, hwif->dma_command); - drive->waiting_for_dma = 1; - /* start DMA */ - hwif->OUTW((count * 2) - 1, hwif->dma_status); - if (drive->media != ide_disk) - return 0; if (HWGROUP(drive)->handler != NULL) /* paranoia check */ BUG(); ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); @@ -274,6 +239,36 @@ static int trm290_ide_dma_read (ide_drive_t *drive /*, struct request *rq */) return hwif->ide_dma_begin(drive); } +static int trm290_ide_dma_setup(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + struct request *rq = hwif->hwgroup->rq; + unsigned int count, rw; + + if (rq_data_dir(rq)) { +#ifdef TRM290_NO_DMA_WRITES + /* always use PIO for writes */ + trm290_prepare_drive(drive, 0); /* select PIO xfer */ + return 1; +#endif + rw = 1; + } else + rw = 2; + + if (!(count = ide_build_dmatable(drive, rq))) { + /* try PIO instead of DMA */ + trm290_prepare_drive(drive, 0); /* select PIO xfer */ + return 1; + } + /* select DMA xfer */ + trm290_prepare_drive(drive, 1); + hwif->OUTL(hwif->dmatable_dma|rw, hwif->dma_command); + drive->waiting_for_dma = 1; + /* start DMA */ + hwif->OUTW((count * 2) - 1, hwif->dma_status); + return 0; +} + static int trm290_ide_dma_begin (ide_drive_t *drive) { return 0; @@ -347,6 +342,7 @@ void __devinit init_hwif_trm290(ide_hwif_t *hwif) ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3); #ifdef CONFIG_BLK_DEV_IDEDMA + hwif->dma_setup = &trm290_ide_dma_setup; hwif->ide_dma_write = &trm290_ide_dma_write; hwif->ide_dma_read = &trm290_ide_dma_read; hwif->ide_dma_begin = &trm290_ide_dma_begin; diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index fabbdef2ee10..f0737df3c62f 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -1880,7 +1880,7 @@ pmac_ide_dma_check(ide_drive_t *drive) * a read on KeyLargo ATA/66 and mark us as waiting for DMA completion */ static int __pmac -pmac_ide_dma_start(ide_drive_t *drive, int reading) +pmac_ide_dma_setup(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data; @@ -1897,7 +1897,7 @@ pmac_ide_dma_start(ide_drive_t *drive, int reading) /* Apple adds 60ns to wrDataSetup on reads */ if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) { - writel(pmif->timings[unit] + (reading ? 0x00800000UL : 0), + writel(pmif->timings[unit] + (!rq_data_dir(rq) ? 0x00800000UL : 0), PMAC_IDE_REG(IDE_TIMING_CONFIG)); (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG)); } @@ -1917,12 +1917,6 @@ pmac_ide_dma_read(ide_drive_t *drive) u8 lba48 = (drive->addressing == 1) ? 1 : 0; task_ioreg_t command = WIN_NOP; - if (pmac_ide_dma_start(drive, 1)) - return 1; - - if (drive->media != ide_disk) - return 0; - command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA; if (drive->vdma) @@ -1949,12 +1943,6 @@ pmac_ide_dma_write (ide_drive_t *drive) u8 lba48 = (drive->addressing == 1) ? 1 : 0; task_ioreg_t command = WIN_NOP; - if (pmac_ide_dma_start(drive, 0)) - return 1; - - if (drive->media != ide_disk) - return 0; - command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; if (drive->vdma) command = (lba48) ? WIN_WRITE_EXT: WIN_WRITE; @@ -1980,8 +1968,6 @@ pmac_ide_dma_begin (ide_drive_t *drive) pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; volatile struct dbdma_regs __iomem *dma; - if (pmif == NULL) - return 1; dma = pmif->dma_regs; writel((RUN << 16) | RUN, &dma->control); @@ -2143,6 +2129,7 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) hwif->ide_dma_off_quietly = &__ide_dma_off_quietly; hwif->ide_dma_on = &__ide_dma_on; hwif->ide_dma_check = &pmac_ide_dma_check; + hwif->dma_setup = &pmac_ide_dma_setup; hwif->ide_dma_read = &pmac_ide_dma_read; hwif->ide_dma_write = &pmac_ide_dma_write; hwif->ide_dma_begin = &pmac_ide_dma_begin; diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 7c63c9276978..166e0a6ab95a 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -590,6 +590,7 @@ static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive) static ide_startstop_t idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc) { idescsi_scsi_t *scsi = drive_to_idescsi(drive); + ide_hwif_t *hwif = drive->hwif; atapi_feature_t feature; atapi_bcount_t bcount; struct request *rq = pc->rq; @@ -600,12 +601,8 @@ static ide_startstop_t idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc) bcount.all = min(pc->request_transfer, 63 * 1024); /* Request to transfer the entire buffer at once */ feature.all = 0; - if (drive->using_dma && rq->bio) { - if (test_bit(PC_WRITING, &pc->flags)) - feature.b.dma = !HWIF(drive)->ide_dma_write(drive); - else - feature.b.dma = !HWIF(drive)->ide_dma_read(drive); - } + if (drive->using_dma && rq->bio) + feature.b.dma = !hwif->dma_setup(drive); SELECT_DRIVE(drive); if (IDE_CONTROL_REG) diff --git a/include/linux/ide.h b/include/linux/ide.h index f6a39379ada9..54b89ce7435a 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -887,6 +887,7 @@ typedef struct hwif_s { void (*atapi_input_bytes)(ide_drive_t *, void *, u32); void (*atapi_output_bytes)(ide_drive_t *, void *, u32); + int (*dma_setup)(ide_drive_t *); int (*ide_dma_read)(ide_drive_t *drive); int (*ide_dma_write)(ide_drive_t *drive); int (*ide_dma_begin)(ide_drive_t *drive); @@ -1544,15 +1545,13 @@ extern void ide_destroy_dmatable(ide_drive_t *); extern ide_startstop_t ide_dma_intr(ide_drive_t *); extern int ide_release_dma(ide_hwif_t *); extern void ide_setup_dma(ide_hwif_t *, unsigned long, unsigned int); -extern int ide_start_dma(ide_hwif_t *, ide_drive_t *, int); extern int __ide_dma_host_off(ide_drive_t *); extern int __ide_dma_off_quietly(ide_drive_t *); extern int __ide_dma_host_on(ide_drive_t *); extern int __ide_dma_on(ide_drive_t *); extern int __ide_dma_check(ide_drive_t *); -extern int __ide_dma_read(ide_drive_t *); -extern int __ide_dma_write(ide_drive_t *); +extern int ide_dma_setup(ide_drive_t *); extern int __ide_dma_begin(ide_drive_t *); extern int __ide_dma_end(ide_drive_t *); extern int __ide_dma_test_irq(ide_drive_t *); -- cgit v1.2.3 From e40ed6c72edad47e93fd69b2702317352f31cd21 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 20 Oct 2004 02:00:15 +0200 Subject: [ide] add ide_hwif_t->dma_exec_cmd() * split off ->dma_exec_cmd() from ->ide_dma_[read,write] functions * choose command to execute by ->dma_exec_cmd() in higher layers and remove ->ide_dma_[read,write] * in Etrax ide.c driver REQ_DRIVE_TASKFILE requests weren't handled properly for drive->addressing == 0 * in trm290.c read and write commands were interchanged * in sgiioc4.c commands weren't sent to disk devices Signed-off-by: Bartlomiej Zolnierkiewicz --- arch/cris/arch-v10/drivers/ide.c | 77 +++++++--------------------------------- drivers/ide/arm/icside.c | 62 ++------------------------------ drivers/ide/ide-disk.c | 10 ++++-- drivers/ide/ide-dma.c | 46 ++---------------------- drivers/ide/ide-taskfile.c | 15 +++----- drivers/ide/ide.c | 3 +- drivers/ide/pci/sgiioc4.c | 7 ---- drivers/ide/pci/trm290.c | 54 ++-------------------------- drivers/ide/ppc/pmac.c | 51 ++------------------------ include/linux/ide.h | 3 +- 10 files changed, 36 insertions(+), 292 deletions(-) (limited to 'include/linux') diff --git a/arch/cris/arch-v10/drivers/ide.c b/arch/cris/arch-v10/drivers/ide.c index cb57b2e55598..155b3e679dab 100644 --- a/arch/cris/arch-v10/drivers/ide.c +++ b/arch/cris/arch-v10/drivers/ide.c @@ -210,8 +210,6 @@ etrax100_ide_inb(ide_ioreg_t reg) static int e100_dma_check (ide_drive_t *drive); static int e100_dma_begin (ide_drive_t *drive); static int e100_dma_end (ide_drive_t *drive); -static int e100_dma_read (ide_drive_t *drive); -static int e100_dma_write (ide_drive_t *drive); static void e100_ide_input_data (ide_drive_t *drive, void *, unsigned int); static void e100_ide_output_data (ide_drive_t *drive, void *, unsigned int); static void e100_atapi_input_bytes(ide_drive_t *drive, void *, unsigned int); @@ -305,6 +303,15 @@ static int e100_dma_setup(ide_drive_t *drive) return 0; } +static void e100_dma_exec_cmd(ide_drive_t *drive, u8 command) +{ + /* set the irq handler which will finish the request when DMA is done */ + ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL); + + /* issue cmd to drive */ + etrax100_ide_outb(command, IDE_COMMAND_REG); +} + void __init init_e100_ide (void) { @@ -327,8 +334,7 @@ init_e100_ide (void) hwif->ide_dma_check = &e100_dma_check; hwif->ide_dma_end = &e100_dma_end; hwif->dma_setup = &e100_dma_setup; - hwif->ide_dma_write = &e100_dma_write; - hwif->ide_dma_read = &e100_dma_read; + hwif->dma_exec_cmd = &e100_dma_exec_cmd; hwif->ide_dma_begin = &e100_dma_begin; hwif->OUTB = &etrax100_ide_outb; hwif->OUTW = &etrax100_ide_outw; @@ -809,27 +815,9 @@ static int e100_dma_end(ide_drive_t *drive) return 0; } -static int e100_start_dma(ide_drive_t *drive, int atapi, int reading) +static int e100_dma_begin(ide_drive_t *drive) { - if(reading) { - - if(!atapi) { - /* set the irq handler which will finish the request when DMA is done */ - - ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL); - - /* issue cmd to drive */ - if ((HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) && - (drive->addressing == 1)) { - ide_task_t *args = HWGROUP(drive)->rq->special; - etrax100_ide_outb(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); - } else if (drive->addressing) { - etrax100_ide_outb(WIN_READDMA_EXT, IDE_COMMAND_REG); - } else { - etrax100_ide_outb(WIN_READDMA, IDE_COMMAND_REG); - } - } - + if (e100_read_command) { /* begin DMA */ /* need to do this before RX DMA due to a chip bug @@ -862,24 +850,6 @@ static int e100_start_dma(ide_drive_t *drive, int atapi, int reading) } else { /* writing */ - - if(!atapi) { - /* set the irq handler which will finish the request when DMA is done */ - - ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL); - - /* issue cmd to drive */ - if ((HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) && - (drive->addressing == 1)) { - ide_task_t *args = HWGROUP(drive)->rq->special; - etrax100_ide_outb(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); - } else if (drive->addressing) { - etrax100_ide_outb(WIN_WRITEDMA_EXT, IDE_COMMAND_REG); - } else { - etrax100_ide_outb(WIN_WRITEDMA, IDE_COMMAND_REG); - } - } - /* begin DMA */ *R_DMA_CH2_FIRST = virt_to_phys(ata_descrs); @@ -904,26 +874,3 @@ static int e100_start_dma(ide_drive_t *drive, int atapi, int reading) } return 0; } - -static int e100_dma_write(ide_drive_t *drive) -{ - return e100_start_dma(drive, 0, 0); -} - -static int e100_dma_read(ide_drive_t *drive) -{ - return e100_start_dma(drive, 0, 1); -} - -static int e100_dma_begin(ide_drive_t *drive) -{ - /* begin DMA, used by ATAPI devices which want to issue the - * appropriate IDE command themselves. - * - * they have already called ->dma_setup to set the - * static reading flag, now they call ide_dma_begin to do - * the real stuff. we tell our code below not to issue - * any IDE commands itself and jump into it. - */ - return e100_start_dma(drive, 1, e100_read_command); -} diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index 63e7c4bf297c..0abc096dfbf2 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -484,67 +484,10 @@ static int icside_dma_setup(ide_drive_t *drive) return 0; } -static int icside_dma_read(ide_drive_t *drive) +static void icside_dma_exec_cmd(ide_drive_t *drive, u8 command) { - struct request *rq = HWGROUP(drive)->rq; - task_ioreg_t cmd; - - BUG_ON(HWGROUP(drive)->handler != NULL); - - /* - * FIX ME to use only ACB ide_task_t args Struct - */ -#if 0 - { - ide_task_t *args = rq->special; - cmd = args->tfRegister[IDE_COMMAND_OFFSET]; - } -#else - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - cmd = args->tfRegister[IDE_COMMAND_OFFSET]; - } else if (drive->addressing == 1) { - cmd = WIN_READDMA_EXT; - } else { - cmd = WIN_READDMA; - } -#endif - /* issue cmd to drive */ - ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL); - - return icside_dma_begin(drive); -} - -static int icside_dma_write(ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - task_ioreg_t cmd; - - BUG_ON(HWGROUP(drive)->handler != NULL); - - /* - * FIX ME to use only ACB ide_task_t args Struct - */ -#if 0 - { - ide_task_t *args = rq->special; - cmd = args->tfRegister[IDE_COMMAND_OFFSET]; - } -#else - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - cmd = args->tfRegister[IDE_COMMAND_OFFSET]; - } else if (drive->addressing == 1) { - cmd = WIN_WRITEDMA_EXT; - } else { - cmd = WIN_WRITEDMA; - } -#endif - /* issue cmd to drive */ ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL); - - return icside_dma_begin(drive); } static int icside_dma_test_irq(ide_drive_t *drive) @@ -615,8 +558,7 @@ static int icside_dma_init(ide_hwif_t *hwif) hwif->ide_dma_host_on = icside_dma_host_on; hwif->ide_dma_on = icside_dma_on; hwif->dma_setup = icside_dma_setup; - hwif->ide_dma_read = icside_dma_read; - hwif->ide_dma_write = icside_dma_write; + hwif->dma_exec_cmd = icside_dma_exec_cmd; hwif->ide_dma_begin = icside_dma_begin; hwif->ide_dma_end = icside_dma_end; hwif->ide_dma_test_irq = icside_dma_test_irq; diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 81741fca487e..ebc4dbb07bce 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -422,10 +422,16 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector if (dma) { if (!hwif->dma_setup(drive)) { if (rq_data_dir(rq)) { - hwif->ide_dma_write(drive); + command = lba48 ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; + if (drive->vdma) + command = lba48 ? WIN_WRITE_EXT: WIN_WRITE; } else { - hwif->ide_dma_read(drive); + command = lba48 ? WIN_READDMA_EXT : WIN_READDMA; + if (drive->vdma) + command = lba48 ? WIN_READ_EXT: WIN_READ; } + hwif->dma_exec_cmd(drive, command); + hwif->ide_dma_begin(drive); return ide_started; } /* fallback to PIO */ diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 339c571daa23..d2d4d3bf114c 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -630,48 +630,10 @@ int ide_dma_setup(ide_drive_t *drive) EXPORT_SYMBOL_GPL(ide_dma_setup); -static int __ide_dma_read(ide_drive_t *drive) +static void ide_dma_exec_cmd(ide_drive_t *drive, u8 command) { - ide_hwif_t *hwif = HWIF(drive); - struct request *rq = HWGROUP(drive)->rq; - u8 lba48 = (drive->addressing == 1) ? 1 : 0; - task_ioreg_t command = WIN_NOP; - - command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA; - - if (drive->vdma) - command = (lba48) ? WIN_READ_EXT: WIN_READ; - - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; - } - /* issue cmd to drive */ ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); - return hwif->ide_dma_begin(drive); -} - -static int __ide_dma_write(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct request *rq = HWGROUP(drive)->rq; - u8 lba48 = (drive->addressing == 1) ? 1 : 0; - task_ioreg_t command = WIN_NOP; - - command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; - if (drive->vdma) - command = (lba48) ? WIN_WRITE_EXT: WIN_WRITE; - - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; - } - - /* issue cmd to drive */ - ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); - - return hwif->ide_dma_begin(drive); } int __ide_dma_begin (ide_drive_t *drive) @@ -991,10 +953,8 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p hwif->ide_dma_check = &__ide_dma_check; if (!hwif->dma_setup) hwif->dma_setup = &ide_dma_setup; - if (!hwif->ide_dma_read) - hwif->ide_dma_read = &__ide_dma_read; - if (!hwif->ide_dma_write) - hwif->ide_dma_write = &__ide_dma_write; + if (!hwif->dma_exec_cmd) + hwif->dma_exec_cmd = &ide_dma_exec_cmd; if (!hwif->ide_dma_begin) hwif->ide_dma_begin = &__ide_dma_begin; if (!hwif->ide_dma_end) diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index f53de7bdb281..69547858dfab 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -150,17 +150,13 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) case WIN_WRITEDMA_ONCE: case WIN_WRITEDMA: case WIN_WRITEDMA_EXT: - if (!hwif->dma_setup(drive)) { - hwif->ide_dma_write(drive); - return ide_started; - } - break; case WIN_READDMA_ONCE: case WIN_READDMA: case WIN_READDMA_EXT: case WIN_IDENTIFY_DMA: if (!hwif->dma_setup(drive)) { - hwif->ide_dma_read(drive); + hwif->dma_exec_cmd(drive, taskfile->command); + hwif->ide_dma_begin(drive); return ide_started; } break; @@ -903,14 +899,11 @@ ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) case TASKFILE_OUT_DMAQ: case TASKFILE_OUT_DMA: - hwif->dma_setup(drive); - hwif->ide_dma_write(drive); - break; - case TASKFILE_IN_DMAQ: case TASKFILE_IN_DMA: hwif->dma_setup(drive); - hwif->ide_dma_read(drive); + hwif->dma_exec_cmd(drive, taskfile->command); + hwif->ide_dma_begin(drive); break; default: diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index b4e720869aba..3ce862997c5b 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -686,8 +686,7 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->atapi_output_bytes = tmp_hwif->atapi_output_bytes; hwif->dma_setup = tmp_hwif->dma_setup; - hwif->ide_dma_read = tmp_hwif->ide_dma_read; - hwif->ide_dma_write = tmp_hwif->ide_dma_write; + hwif->dma_exec_cmd = tmp_hwif->dma_exec_cmd; hwif->ide_dma_begin = tmp_hwif->ide_dma_begin; hwif->ide_dma_end = tmp_hwif->ide_dma_end; hwif->ide_dma_check = tmp_hwif->ide_dma_check; diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 4790d656fb92..e8c19d2c8cd9 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -602,11 +602,6 @@ static int sgiioc4_ide_dma_setup(ide_drive_t *drive) return 0; } -static int sgiioc4_ide_dma_dummy(ide_drive_t *drive) -{ - return 0; -} - static void __init ide_init_sgiioc4(ide_hwif_t * hwif) { @@ -630,8 +625,6 @@ ide_init_sgiioc4(ide_hwif_t * hwif) hwif->busproc = NULL; hwif->dma_setup = &sgiioc4_ide_dma_setup; - hwif->ide_dma_read = &sgiioc4_ide_dma_dummy; - hwif->ide_dma_write = &sgiioc4_ide_dma_dummy; hwif->ide_dma_begin = &sgiioc4_ide_dma_begin; hwif->ide_dma_end = &sgiioc4_ide_dma_end; hwif->ide_dma_check = &sgiioc4_ide_dma_check; diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c index c3c3793a13a8..fa12ce293cd4 100644 --- a/drivers/ide/pci/trm290.c +++ b/drivers/ide/pci/trm290.c @@ -179,64 +179,15 @@ static void trm290_selectproc (ide_drive_t *drive) } #ifdef CONFIG_BLK_DEV_IDEDMA -static int trm290_ide_dma_write (ide_drive_t *drive /*, struct request *rq */) +static void trm290_ide_dma_exec_cmd(ide_drive_t *drive, u8 command) { ide_hwif_t *hwif = HWIF(drive); - struct request *rq = HWGROUP(drive)->rq; -// ide_task_t *args = rq->special; - task_ioreg_t command = WIN_NOP; if (HWGROUP(drive)->handler != NULL) /* paranoia check */ BUG(); ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); - /* - * FIX ME to use only ACB ide_task_t args Struct - */ -#if 0 - { - ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; - } -#else - command = /* (lba48) ? WIN_READDMA_EXT : */ WIN_READDMA; - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; - } -#endif - /* issue cmd to drive */ - hwif->OUTB(command, IDE_COMMAND_REG); - return hwif->ide_dma_begin(drive); -} - -static int trm290_ide_dma_read (ide_drive_t *drive /*, struct request *rq */) -{ - ide_hwif_t *hwif = HWIF(drive); - struct request *rq = HWGROUP(drive)->rq; -// ide_task_t *args = rq->special; - task_ioreg_t command = WIN_NOP; - - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); - /* - * FIX ME to use only ACB ide_task_t args Struct - */ -#if 0 - { - ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; - } -#else - command = /* (lba48) ? WIN_WRITEDMA_EXT : */ WIN_WRITEDMA; - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; - } -#endif /* issue cmd to drive */ hwif->OUTB(command, IDE_COMMAND_REG); - return hwif->ide_dma_begin(drive); } static int trm290_ide_dma_setup(ide_drive_t *drive) @@ -343,8 +294,7 @@ void __devinit init_hwif_trm290(ide_hwif_t *hwif) #ifdef CONFIG_BLK_DEV_IDEDMA hwif->dma_setup = &trm290_ide_dma_setup; - hwif->ide_dma_write = &trm290_ide_dma_write; - hwif->ide_dma_read = &trm290_ide_dma_read; + hwif->dma_exec_cmd = &trm290_ide_dma_exec_cmd; hwif->ide_dma_begin = &trm290_ide_dma_begin; hwif->ide_dma_end = &trm290_ide_dma_end; hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq; diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index f0737df3c62f..0043bb35d2fb 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -1907,55 +1907,11 @@ pmac_ide_dma_setup(ide_drive_t *drive) return 0; } -/* - * Start a DMA READ command - */ -static int __pmac -pmac_ide_dma_read(ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - u8 lba48 = (drive->addressing == 1) ? 1 : 0; - task_ioreg_t command = WIN_NOP; - - command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA; - - if (drive->vdma) - command = (lba48) ? WIN_READ_EXT: WIN_READ; - - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; - } - - /* issue cmd to drive */ - ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, NULL); - - return pmac_ide_dma_begin(drive); -} - -/* - * Start a DMA WRITE command - */ -static int __pmac -pmac_ide_dma_write (ide_drive_t *drive) +static void __pmac +pmac_ide_dma_exec_cmd(ide_drive_t *drive, u8 command) { - struct request *rq = HWGROUP(drive)->rq; - u8 lba48 = (drive->addressing == 1) ? 1 : 0; - task_ioreg_t command = WIN_NOP; - - command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; - if (drive->vdma) - command = (lba48) ? WIN_WRITE_EXT: WIN_WRITE; - - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; - } - /* issue cmd to drive */ ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, NULL); - - return pmac_ide_dma_begin(drive); } /* @@ -2130,8 +2086,7 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) hwif->ide_dma_on = &__ide_dma_on; hwif->ide_dma_check = &pmac_ide_dma_check; hwif->dma_setup = &pmac_ide_dma_setup; - hwif->ide_dma_read = &pmac_ide_dma_read; - hwif->ide_dma_write = &pmac_ide_dma_write; + hwif->dma_exec_cmd = &pmac_ide_dma_exec_cmd; hwif->ide_dma_begin = &pmac_ide_dma_begin; hwif->ide_dma_end = &pmac_ide_dma_end; hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq; diff --git a/include/linux/ide.h b/include/linux/ide.h index 54b89ce7435a..d1a78fe8a1ed 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -888,8 +888,7 @@ typedef struct hwif_s { void (*atapi_output_bytes)(ide_drive_t *, void *, u32); int (*dma_setup)(ide_drive_t *); - int (*ide_dma_read)(ide_drive_t *drive); - int (*ide_dma_write)(ide_drive_t *drive); + void (*dma_exec_cmd)(ide_drive_t *, u8); int (*ide_dma_begin)(ide_drive_t *drive); int (*ide_dma_end)(ide_drive_t *drive); int (*ide_dma_check)(ide_drive_t *drive); -- cgit v1.2.3 From 5a8191fbe506cae8e640c1d96e2ad5c46ccca001 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 20 Oct 2004 02:06:01 +0200 Subject: [ide] convert ide_hwif_t->ide_dma_begin() to ->dma_start() Make ->ide_dma_begin() functions void and rename them to ->dma_start(). Signed-off-by: Bartlomiej Zolnierkiewicz --- arch/cris/arch-v10/drivers/ide.c | 7 +++---- drivers/ide/arm/icside.c | 5 ++--- drivers/ide/ide-cd.c | 3 ++- drivers/ide/ide-disk.c | 2 +- drivers/ide/ide-dma.c | 9 ++++----- drivers/ide/ide-floppy.c | 2 +- drivers/ide/ide-tape.c | 2 +- drivers/ide/ide-taskfile.c | 4 ++-- drivers/ide/ide.c | 2 +- drivers/ide/pci/hpt366.c | 8 ++++---- drivers/ide/pci/pdc202xx_old.c | 6 +++--- drivers/ide/pci/sgiioc4.c | 7 ++----- drivers/ide/pci/sl82c105.c | 8 +++----- drivers/ide/pci/trm290.c | 5 ++--- drivers/ide/ppc/pmac.c | 8 +++----- drivers/scsi/ide-scsi.c | 3 ++- include/linux/ide.h | 4 ++-- 17 files changed, 38 insertions(+), 47 deletions(-) (limited to 'include/linux') diff --git a/arch/cris/arch-v10/drivers/ide.c b/arch/cris/arch-v10/drivers/ide.c index 155b3e679dab..cd9c0fa9899f 100644 --- a/arch/cris/arch-v10/drivers/ide.c +++ b/arch/cris/arch-v10/drivers/ide.c @@ -208,7 +208,7 @@ etrax100_ide_inb(ide_ioreg_t reg) #define ATA_PIO0_HOLD 4 static int e100_dma_check (ide_drive_t *drive); -static int e100_dma_begin (ide_drive_t *drive); +static void e100_dma_start(ide_drive_t *drive); static int e100_dma_end (ide_drive_t *drive); static void e100_ide_input_data (ide_drive_t *drive, void *, unsigned int); static void e100_ide_output_data (ide_drive_t *drive, void *, unsigned int); @@ -335,7 +335,7 @@ init_e100_ide (void) hwif->ide_dma_end = &e100_dma_end; hwif->dma_setup = &e100_dma_setup; hwif->dma_exec_cmd = &e100_dma_exec_cmd; - hwif->ide_dma_begin = &e100_dma_begin; + hwif->dma_start = &e100_dma_start; hwif->OUTB = &etrax100_ide_outb; hwif->OUTW = &etrax100_ide_outw; hwif->OUTBSYNC = &etrax100_ide_outbsync; @@ -815,7 +815,7 @@ static int e100_dma_end(ide_drive_t *drive) return 0; } -static int e100_dma_begin(ide_drive_t *drive) +static void e100_dma_start(ide_drive_t *drive) { if (e100_read_command) { /* begin DMA */ @@ -872,5 +872,4 @@ static int e100_dma_begin(ide_drive_t *drive) D(printk("dma write of %d bytes.\n", ata_tot_size)); } - return 0; } diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index 0abc096dfbf2..330167da7290 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -400,14 +400,13 @@ static int icside_dma_end(ide_drive_t *drive) return get_dma_residue(hwif->hw.dma) != 0; } -static int icside_dma_begin(ide_drive_t *drive) +static void icside_dma_start(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); /* We can not enable DMA on both channels simultaneously. */ BUG_ON(dma_channel_active(hwif->hw.dma)); enable_dma(hwif->hw.dma); - return 0; } /* @@ -559,7 +558,7 @@ static int icside_dma_init(ide_hwif_t *hwif) hwif->ide_dma_on = icside_dma_on; hwif->dma_setup = icside_dma_setup; hwif->dma_exec_cmd = icside_dma_exec_cmd; - hwif->ide_dma_begin = icside_dma_begin; + hwif->dma_start = icside_dma_start; hwif->ide_dma_end = icside_dma_end; hwif->ide_dma_test_irq = icside_dma_test_irq; hwif->ide_dma_verbose = icside_dma_verbose; diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 820178c1134d..d63974201962 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -910,6 +910,7 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, struct request *rq, ide_handler_t *handler) { + ide_hwif_t *hwif = drive->hwif; int cmd_len; struct cdrom_info *info = drive->driver_data; ide_startstop_t startstop; @@ -941,7 +942,7 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, /* Start the DMA if need be */ if (info->dma) - (void) HWIF(drive)->ide_dma_begin(drive); + hwif->dma_start(drive); return ide_started; } diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index ebc4dbb07bce..70e93aa031cb 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -431,7 +431,7 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector command = lba48 ? WIN_READ_EXT: WIN_READ; } hwif->dma_exec_cmd(drive, command); - hwif->ide_dma_begin(drive); + hwif->dma_start(drive); return ide_started; } /* fallback to PIO */ diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index d2d4d3bf114c..d041da5674e0 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -636,7 +636,7 @@ static void ide_dma_exec_cmd(ide_drive_t *drive, u8 command) ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); } -int __ide_dma_begin (ide_drive_t *drive) +void ide_dma_start(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); u8 dma_cmd = hwif->INB(hwif->dma_command); @@ -650,10 +650,9 @@ int __ide_dma_begin (ide_drive_t *drive) hwif->OUTB(dma_cmd|1, hwif->dma_command); hwif->dma = 1; wmb(); - return 0; } -EXPORT_SYMBOL(__ide_dma_begin); +EXPORT_SYMBOL_GPL(ide_dma_start); /* returns 1 on error, 0 otherwise */ int __ide_dma_end (ide_drive_t *drive) @@ -955,8 +954,8 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p hwif->dma_setup = &ide_dma_setup; if (!hwif->dma_exec_cmd) hwif->dma_exec_cmd = &ide_dma_exec_cmd; - if (!hwif->ide_dma_begin) - hwif->ide_dma_begin = &__ide_dma_begin; + if (!hwif->dma_start) + hwif->dma_start = &ide_dma_start; if (!hwif->ide_dma_end) hwif->ide_dma_end = &__ide_dma_end; if (!hwif->ide_dma_test_irq) diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index ded2893cc8d2..99eef3064b04 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1063,7 +1063,7 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p if (feature.b.dma) { /* Begin DMA, if necessary */ set_bit(PC_DMA_IN_PROGRESS, &pc->flags); - (void) (HWIF(drive)->ide_dma_begin(drive)); + hwif->dma_start(drive); } /* Can we transfer the packet when we get the interrupt or wait? */ diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 8422980eade7..3ec7ff671c65 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -2067,7 +2067,7 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive) #ifdef CONFIG_BLK_DEV_IDEDMA /* Begin DMA, if necessary */ if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) - (void) (HWIF(drive)->ide_dma_begin(drive)); + hwif->dma_start(drive); #endif /* Send the actual packet */ HWIF(drive)->atapi_output_bytes(drive, pc->c, 12); diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 69547858dfab..4a8019475c02 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -156,7 +156,7 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) case WIN_IDENTIFY_DMA: if (!hwif->dma_setup(drive)) { hwif->dma_exec_cmd(drive, taskfile->command); - hwif->ide_dma_begin(drive); + hwif->dma_start(drive); return ide_started; } break; @@ -903,7 +903,7 @@ ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) case TASKFILE_IN_DMA: hwif->dma_setup(drive); hwif->dma_exec_cmd(drive, taskfile->command); - hwif->ide_dma_begin(drive); + hwif->dma_start(drive); break; default: diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 3ce862997c5b..5f0a43527219 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -687,7 +687,7 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->dma_setup = tmp_hwif->dma_setup; hwif->dma_exec_cmd = tmp_hwif->dma_exec_cmd; - hwif->ide_dma_begin = tmp_hwif->ide_dma_begin; + hwif->dma_start = tmp_hwif->dma_start; hwif->ide_dma_end = tmp_hwif->ide_dma_end; hwif->ide_dma_check = tmp_hwif->ide_dma_check; hwif->ide_dma_on = tmp_hwif->ide_dma_on; diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index d1e8adbe779d..5597ecf031dd 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -577,7 +577,7 @@ static int hpt366_ide_dma_lostirq (ide_drive_t *drive) /* how about we flush and reset, mmmkay? */ pci_write_config_byte(dev, 0x51, 0x1F); /* fall through to a reset */ - case ide_dma_begin: + case dma_start: case ide_dma_end: /* reset the chips state over and over.. */ pci_write_config_byte(dev, 0x51, 0x13); @@ -592,12 +592,12 @@ static void hpt370_clear_engine (ide_drive_t *drive) udelay(10); } -static int hpt370_ide_dma_begin (ide_drive_t *drive) +static void hpt370_ide_dma_start(ide_drive_t *drive) { #ifdef HPT_RESET_STATE_ENGINE hpt370_clear_engine(drive); #endif - return __ide_dma_begin(drive); + ide_dma_start(drive); } static int hpt370_ide_dma_end (ide_drive_t *drive) @@ -1230,7 +1230,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; hwif->ide_dma_end = &hpt374_ide_dma_end; } else if (hpt_minimum_revision(dev,3)) { - hwif->ide_dma_begin = &hpt370_ide_dma_begin; + hwif->dma_start = &hpt370_ide_dma_start; hwif->ide_dma_end = &hpt370_ide_dma_end; hwif->ide_dma_timeout = &hpt370_ide_dma_timeout; hwif->ide_dma_lostirq = &hpt370_ide_dma_lostirq; diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index 651879a49832..d139727318e2 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -494,7 +494,7 @@ static int pdc202xx_quirkproc (ide_drive_t *drive) return ((int) check_in_drive_lists(drive, pdc_quirk_drives)); } -static int pdc202xx_old_ide_dma_begin(ide_drive_t *drive) +static void pdc202xx_old_ide_dma_start(ide_drive_t *drive) { if (drive->current_speed > XFER_UDMA_2) pdc_old_enable_66MHz_clock(drive->hwif); @@ -515,7 +515,7 @@ static int pdc202xx_old_ide_dma_begin(ide_drive_t *drive) word_count | 0x06000000; hwif->OUTL(word_count, atapi_reg); } - return __ide_dma_begin(drive); + ide_dma_start(drive); } static int pdc202xx_old_ide_dma_end(ide_drive_t *drive) @@ -736,7 +736,7 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif) if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) { if (!(hwif->udma_four)) hwif->udma_four = (pdc202xx_old_cable_detect(hwif)) ? 0 : 1; - hwif->ide_dma_begin = &pdc202xx_old_ide_dma_begin; + hwif->dma_start = &pdc202xx_old_ide_dma_start; hwif->ide_dma_end = &pdc202xx_old_ide_dma_end; } hwif->ide_dma_test_irq = &pdc202xx_old_ide_dma_test_irq; diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index e8c19d2c8cd9..ca2ef5404a5a 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -192,16 +192,13 @@ sgiioc4_clearirq(ide_drive_t * drive) return intr_reg & 3; } -static int -sgiioc4_ide_dma_begin(ide_drive_t * drive) +static void sgiioc4_ide_dma_start(ide_drive_t * drive) { ide_hwif_t *hwif = HWIF(drive); unsigned int reg = hwif->INL(hwif->dma_base + IOC4_DMA_CTRL * 4); unsigned int temp_reg = reg | IOC4_S_DMA_START; hwif->OUTL(temp_reg, hwif->dma_base + IOC4_DMA_CTRL * 4); - - return 0; } static u32 @@ -625,7 +622,7 @@ ide_init_sgiioc4(ide_hwif_t * hwif) hwif->busproc = NULL; hwif->dma_setup = &sgiioc4_ide_dma_setup; - hwif->ide_dma_begin = &sgiioc4_ide_dma_begin; + hwif->dma_start = &sgiioc4_ide_dma_start; hwif->ide_dma_end = &sgiioc4_ide_dma_end; hwif->ide_dma_check = &sgiioc4_ide_dma_check; hwif->ide_dma_on = &sgiioc4_ide_dma_on; diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c index 563c44c7dae8..d0cfec0559aa 100644 --- a/drivers/ide/pci/sl82c105.c +++ b/drivers/ide/pci/sl82c105.c @@ -236,15 +236,13 @@ static int sl82c105_ide_dma_lost_irq(ide_drive_t *drive) * The generic IDE core will have disabled the BMEN bit before this * function is called. */ -static int sl82c105_ide_dma_begin(ide_drive_t *drive) +static void sl82c105_ide_dma_start(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; -// DBG(("sl82c105_ide_dma_begin(drive:%s)\n", drive->name)); - sl82c105_reset_host(dev); - return __ide_dma_begin(drive); + ide_dma_start(drive); } static int sl82c105_ide_dma_timeout(ide_drive_t *drive) @@ -469,7 +467,7 @@ static void __init init_hwif_sl82c105(ide_hwif_t *hwif) hwif->ide_dma_on = &sl82c105_ide_dma_on; hwif->ide_dma_off_quietly = &sl82c105_ide_dma_off_quietly; hwif->ide_dma_lostirq = &sl82c105_ide_dma_lost_irq; - hwif->ide_dma_begin = &sl82c105_ide_dma_begin; + hwif->dma_start = &sl82c105_ide_dma_start; hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout; if (!noautodma) diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c index fa12ce293cd4..17250160029e 100644 --- a/drivers/ide/pci/trm290.c +++ b/drivers/ide/pci/trm290.c @@ -220,9 +220,8 @@ static int trm290_ide_dma_setup(ide_drive_t *drive) return 0; } -static int trm290_ide_dma_begin (ide_drive_t *drive) +static void trm290_ide_dma_start(ide_drive_t *drive) { - return 0; } static int trm290_ide_dma_end (ide_drive_t *drive) @@ -295,7 +294,7 @@ void __devinit init_hwif_trm290(ide_hwif_t *hwif) #ifdef CONFIG_BLK_DEV_IDEDMA hwif->dma_setup = &trm290_ide_dma_setup; hwif->dma_exec_cmd = &trm290_ide_dma_exec_cmd; - hwif->ide_dma_begin = &trm290_ide_dma_begin; + hwif->dma_start = &trm290_ide_dma_start; hwif->ide_dma_end = &trm290_ide_dma_end; hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq; #endif /* CONFIG_BLK_DEV_IDEDMA */ diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 0043bb35d2fb..643bbc3a6267 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -362,7 +362,6 @@ static int pmac_ide_tune_chipset(ide_drive_t *drive, u8 speed); static void pmac_ide_tuneproc(ide_drive_t *drive, u8 pio); static void pmac_ide_selectproc(ide_drive_t *drive); static void pmac_ide_kauai_selectproc(ide_drive_t *drive); -static int pmac_ide_dma_begin (ide_drive_t *drive); #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ @@ -1918,8 +1917,8 @@ pmac_ide_dma_exec_cmd(ide_drive_t *drive, u8 command) * Kick the DMA controller into life after the DMA command has been issued * to the drive. */ -static int __pmac -pmac_ide_dma_begin (ide_drive_t *drive) +static void __pmac +pmac_ide_dma_start(ide_drive_t *drive) { pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; volatile struct dbdma_regs __iomem *dma; @@ -1929,7 +1928,6 @@ pmac_ide_dma_begin (ide_drive_t *drive) writel((RUN << 16) | RUN, &dma->control); /* Make sure it gets to the controller right now */ (void)readl(&dma->control); - return 0; } /* @@ -2087,7 +2085,7 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) hwif->ide_dma_check = &pmac_ide_dma_check; hwif->dma_setup = &pmac_ide_dma_setup; hwif->dma_exec_cmd = &pmac_ide_dma_exec_cmd; - hwif->ide_dma_begin = &pmac_ide_dma_begin; + hwif->dma_start = &pmac_ide_dma_start; hwif->ide_dma_end = &pmac_ide_dma_end; hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq; hwif->ide_dma_host_off = &pmac_ide_dma_host_off; diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 166e0a6ab95a..ea0527e9837e 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -555,6 +555,7 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive) static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive) { + ide_hwif_t *hwif = drive->hwif; idescsi_scsi_t *scsi = drive_to_idescsi(drive); idescsi_pc_t *pc = scsi->pc; atapi_ireason_t ireason; @@ -579,7 +580,7 @@ static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive) atapi_output_bytes(drive, scsi->pc->c, 12); if (test_bit (PC_DMA_OK, &pc->flags)) { set_bit (PC_DMA_IN_PROGRESS, &pc->flags); - (void) (HWIF(drive)->ide_dma_begin(drive)); + hwif->dma_start(drive); } return ide_started; } diff --git a/include/linux/ide.h b/include/linux/ide.h index d1a78fe8a1ed..c05eb8673a4e 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -889,7 +889,7 @@ typedef struct hwif_s { int (*dma_setup)(ide_drive_t *); void (*dma_exec_cmd)(ide_drive_t *, u8); - int (*ide_dma_begin)(ide_drive_t *drive); + void (*dma_start)(ide_drive_t *); int (*ide_dma_end)(ide_drive_t *drive); int (*ide_dma_check)(ide_drive_t *drive); int (*ide_dma_on)(ide_drive_t *drive); @@ -1551,7 +1551,7 @@ extern int __ide_dma_host_on(ide_drive_t *); extern int __ide_dma_on(ide_drive_t *); extern int __ide_dma_check(ide_drive_t *); extern int ide_dma_setup(ide_drive_t *); -extern int __ide_dma_begin(ide_drive_t *); +extern void ide_dma_start(ide_drive_t *); extern int __ide_dma_end(ide_drive_t *); extern int __ide_dma_test_irq(ide_drive_t *); extern int __ide_dma_verbose(ide_drive_t *); -- cgit v1.2.3 From 403031116ad5131296b844c180f249e6ab38ac69 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 20 Oct 2004 01:41:47 +0100 Subject: [SERIAL] serial_reg.h update. This includes a fuller definition of the 8250 and compatible bits, and adding notes where the definition varies between different chips. This also fixes the following build error: drivers/serial/8250.c:185: error: `UART_FCR_R_TRIG_10' --- include/linux/serial_reg.h | 279 ++++++++++++++++++++++++--------------------- 1 file changed, 146 insertions(+), 133 deletions(-) (limited to 'include/linux') diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h index 7b2414bd5837..faa0c3662bc3 100644 --- a/include/linux/serial_reg.h +++ b/include/linux/serial_reg.h @@ -14,47 +14,63 @@ #ifndef _LINUX_SERIAL_REG_H #define _LINUX_SERIAL_REG_H -#define UART_RX 0 /* In: Receive buffer (DLAB=0) */ -#define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */ -#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */ -#define UART_TRG 0 /* (LCR=BF) FCTR bit 7 selects Rx or Tx - * In: Fifo count - * Out: Fifo custom trigger levels - * XR16C85x only */ +/* + * DLAB=0 + */ +#define UART_RX 0 /* In: Receive buffer */ +#define UART_TX 0 /* Out: Transmit buffer */ -#define UART_DLM 1 /* Out: Divisor Latch High (DLAB=1) */ #define UART_IER 1 /* Out: Interrupt Enable Register */ -#define UART_FCTR 1 /* (LCR=BF) Feature Control Register - * XR16C85x only */ +#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */ +#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */ +#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */ +#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */ +/* + * Sleep mode for ST16650 and TI16750. For the ST16650, EFR[4]=1 + */ +#define UART_IERX_SLEEP 0x10 /* Enable sleep mode */ #define UART_IIR 2 /* In: Interrupt ID Register */ -#define UART_FCR 2 /* Out: FIFO Control Register */ -#define UART_EFR 2 /* I/O: Extended Features Register */ - /* (DLAB=1, 16C660 only) */ +#define UART_IIR_NO_INT 0x01 /* No interrupts pending */ +#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */ +#define UART_IIR_MSI 0x00 /* Modem status interrupt */ +#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */ +#define UART_IIR_RDI 0x04 /* Receiver data interrupt */ +#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ -#define UART_LCR 3 /* Out: Line Control Register */ -#define UART_MCR 4 /* Out: Modem Control Register */ -#define UART_LSR 5 /* In: Line Status Register */ -#define UART_MSR 6 /* In: Modem Status Register */ -#define UART_SCR 7 /* I/O: Scratch Register */ -#define UART_EMSR 7 /* (LCR=BF) Extended Mode Select Register - * FCTR bit 6 selects SCR or EMSR - * XR16c85x only */ - -/* - * These are the definitions for the FIFO Control Register - * (16650 only) - */ +#define UART_FCR 2 /* Out: FIFO Control Register */ #define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */ #define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */ #define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */ #define UART_FCR_DMA_SELECT 0x08 /* For DMA applications */ +/* + * Note: The FIFO trigger levels are chip specific: + * RX:76 = 00 01 10 11 TX:54 = 00 01 10 11 + * PC16550D: 1 4 8 14 xx xx xx xx + * TI16C550A: 1 4 8 14 xx xx xx xx + * TI16C550C: 1 4 8 14 xx xx xx xx + * ST16C550: 1 4 8 14 xx xx xx xx + * ST16C650: 8 16 24 28 16 8 24 30 PORT_16650V2 + * NS16C552: 1 4 8 14 xx xx xx xx + * ST16C654: 8 16 56 60 8 16 32 56 PORT_16654 + * TI16C750: 1 16 32 56 xx xx xx xx PORT_16750 + * TI16C752: 8 16 56 60 8 16 32 56 + */ +#define UART_FCR_R_TRIG_00 0x00 +#define UART_FCR_R_TRIG_01 0x40 +#define UART_FCR_R_TRIG_10 0x80 +#define UART_FCR_R_TRIG_11 0xc0 +#define UART_FCR_T_TRIG_00 0x00 +#define UART_FCR_T_TRIG_01 0x10 +#define UART_FCR_T_TRIG_10 0x20 +#define UART_FCR_T_TRIG_11 0x30 + #define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */ #define UART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */ #define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */ #define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */ #define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */ -/* 16650 redefinitions */ +/* 16650 definitions */ #define UART_FCR6_R_TRIGGER_8 0x00 /* Mask for receive trigger set at 1 */ #define UART_FCR6_R_TRIGGER_16 0x40 /* Mask for receive trigger set at 4 */ #define UART_FCR6_R_TRIGGER_24 0x80 /* Mask for receive trigger set at 8 */ @@ -63,83 +79,129 @@ #define UART_FCR6_T_TRIGGER_8 0x10 /* Mask for transmit trigger set at 8 */ #define UART_FCR6_T_TRIGGER_24 0x20 /* Mask for transmit trigger set at 24 */ #define UART_FCR6_T_TRIGGER_30 0x30 /* Mask for transmit trigger set at 30 */ -/* TI 16750 definitions */ -#define UART_FCR7_64BYTE 0x20 /* Go into 64 byte mode */ +#define UART_FCR7_64BYTE 0x20 /* Go into 64 byte mode (TI16C750) */ +#define UART_LCR 3 /* Out: Line Control Register */ /* - * These are the definitions for the Line Control Register - * * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits. */ -#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ -#define UART_LCR_SBC 0x40 /* Set break control */ -#define UART_LCR_SPAR 0x20 /* Stick parity (?) */ -#define UART_LCR_EPAR 0x10 /* Even parity select */ -#define UART_LCR_PARITY 0x08 /* Parity Enable */ -#define UART_LCR_STOP 0x04 /* Stop bits: 0=1 stop bit, 1= 2 stop bits */ -#define UART_LCR_WLEN5 0x00 /* Wordlength: 5 bits */ -#define UART_LCR_WLEN6 0x01 /* Wordlength: 6 bits */ -#define UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */ -#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */ +#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ +#define UART_LCR_SBC 0x40 /* Set break control */ +#define UART_LCR_SPAR 0x20 /* Stick parity (?) */ +#define UART_LCR_EPAR 0x10 /* Even parity select */ +#define UART_LCR_PARITY 0x08 /* Parity Enable */ +#define UART_LCR_STOP 0x04 /* Stop bits: 0=1 bit, 1=2 bits */ +#define UART_LCR_WLEN5 0x00 /* Wordlength: 5 bits */ +#define UART_LCR_WLEN6 0x01 /* Wordlength: 6 bits */ +#define UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */ +#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */ + +#define UART_MCR 4 /* Out: Modem Control Register */ +#define UART_MCR_CLKSEL 0x80 /* Divide clock by 4 (TI16C752, EFR[4]=1) */ +#define UART_MCR_TCRTLR 0x40 /* Access TCR/TLR (TI16C752, EFR[4]=1) */ +#define UART_MCR_XONANY 0x20 /* Enable Xon Any (TI16C752, EFR[4]=1) */ +#define UART_MCR_AFE 0x20 /* Enable auto-RTS/CTS (TI16C550C/TI16C750) */ +#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ +#define UART_MCR_OUT2 0x08 /* Out2 complement */ +#define UART_MCR_OUT1 0x04 /* Out1 complement */ +#define UART_MCR_RTS 0x02 /* RTS complement */ +#define UART_MCR_DTR 0x01 /* DTR complement */ + +#define UART_LSR 5 /* In: Line Status Register */ +#define UART_LSR_TEMT 0x40 /* Transmitter empty */ +#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ +#define UART_LSR_BI 0x10 /* Break interrupt indicator */ +#define UART_LSR_FE 0x08 /* Frame error indicator */ +#define UART_LSR_PE 0x04 /* Parity error indicator */ +#define UART_LSR_OE 0x02 /* Overrun error indicator */ +#define UART_LSR_DR 0x01 /* Receiver data ready */ + +#define UART_MSR 6 /* In: Modem Status Register */ +#define UART_MSR_DCD 0x80 /* Data Carrier Detect */ +#define UART_MSR_RI 0x40 /* Ring Indicator */ +#define UART_MSR_DSR 0x20 /* Data Set Ready */ +#define UART_MSR_CTS 0x10 /* Clear to Send */ +#define UART_MSR_DDCD 0x08 /* Delta DCD */ +#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */ +#define UART_MSR_DDSR 0x02 /* Delta DSR */ +#define UART_MSR_DCTS 0x01 /* Delta CTS */ +#define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */ + +#define UART_SCR 7 /* I/O: Scratch Register */ /* - * These are the definitions for the Line Status Register + * DLAB=1 */ -#define UART_LSR_TEMT 0x40 /* Transmitter empty */ -#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ -#define UART_LSR_BI 0x10 /* Break interrupt indicator */ -#define UART_LSR_FE 0x08 /* Frame error indicator */ -#define UART_LSR_PE 0x04 /* Parity error indicator */ -#define UART_LSR_OE 0x02 /* Overrun error indicator */ -#define UART_LSR_DR 0x01 /* Receiver data ready */ +#define UART_DLL 0 /* Out: Divisor Latch Low */ +#define UART_DLM 1 /* Out: Divisor Latch High */ /* - * These are the definitions for the Interrupt Identification Register + * LCR=0xBF (or DLAB=1 for 16C660) + */ +#define UART_EFR 2 /* I/O: Extended Features Register */ +#define UART_EFR_CTS 0x80 /* CTS flow control */ +#define UART_EFR_RTS 0x40 /* RTS flow control */ +#define UART_EFR_SCD 0x20 /* Special character detect */ +#define UART_EFR_ECB 0x10 /* Enhanced control bit */ +/* + * the low four bits control software flow control */ -#define UART_IIR_NO_INT 0x01 /* No interrupts pending */ -#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */ - -#define UART_IIR_MSI 0x00 /* Modem status interrupt */ -#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */ -#define UART_IIR_RDI 0x04 /* Receiver data interrupt */ -#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ /* - * These are the definitions for the Interrupt Enable Register + * LCR=0xBF, TI16C752, ST16650, ST16650A, ST16654 */ -#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */ -#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */ -#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */ -#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */ +#define UART_XON1 4 /* I/O: Xon character 1 */ +#define UART_XON2 5 /* I/O: Xon character 2 */ +#define UART_XOFF1 6 /* I/O: Xoff character 1 */ +#define UART_XOFF2 7 /* I/O: Xoff character 2 */ + /* - * Sleep mode for ST16650 and TI16750. - * Note that for 16650, EFR-bit 4 must be selected as well. + * EFR[4]=1 MCR[6]=1, TI16C752 */ -#define UART_IERX_SLEEP 0x10 /* Enable sleep mode */ +#define UART_TI752_TCR 6 /* I/O: transmission control register */ +#define UART_TI752_TLR 7 /* I/O: trigger level register */ /* - * These are the definitions for the Modem Control Register + * LCR=0xBF, XR16C85x */ -#define UART_MCR_AFE 0x20 /* Enable auto-RTS/CTS (TI16C750) */ -#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ -#define UART_MCR_OUT2 0x08 /* Out2 complement */ -#define UART_MCR_OUT1 0x04 /* Out1 complement */ -#define UART_MCR_RTS 0x02 /* RTS complement */ -#define UART_MCR_DTR 0x01 /* DTR complement */ +#define UART_TRG 0 /* FCTR bit 7 selects Rx or Tx + * In: Fifo count + * Out: Fifo custom trigger levels */ +/* + * These are the definitions for the Programmable Trigger Register + */ +#define UART_TRG_1 0x01 +#define UART_TRG_4 0x04 +#define UART_TRG_8 0x08 +#define UART_TRG_16 0x10 +#define UART_TRG_32 0x20 +#define UART_TRG_64 0x40 +#define UART_TRG_96 0x60 +#define UART_TRG_120 0x78 +#define UART_TRG_128 0x80 + +#define UART_FCTR 1 /* Feature Control Register */ +#define UART_FCTR_RTS_NODELAY 0x00 /* RTS flow control delay */ +#define UART_FCTR_RTS_4DELAY 0x01 +#define UART_FCTR_RTS_6DELAY 0x02 +#define UART_FCTR_RTS_8DELAY 0x03 +#define UART_FCTR_IRDA 0x04 /* IrDa data encode select */ +#define UART_FCTR_TX_INT 0x08 /* Tx interrupt type select */ +#define UART_FCTR_TRGA 0x00 /* Tx/Rx 550 trigger table select */ +#define UART_FCTR_TRGB 0x10 /* Tx/Rx 650 trigger table select */ +#define UART_FCTR_TRGC 0x20 /* Tx/Rx 654 trigger table select */ +#define UART_FCTR_TRGD 0x30 /* Tx/Rx 850 programmable trigger select */ +#define UART_FCTR_SCR_SWAP 0x40 /* Scratch pad register swap */ +#define UART_FCTR_RX 0x00 /* Programmable trigger mode select */ +#define UART_FCTR_TX 0x80 /* Programmable trigger mode select */ /* - * These are the definitions for the Modem Status Register + * LCR=0xBF, FCTR[6]=1 */ -#define UART_MSR_DCD 0x80 /* Data Carrier Detect */ -#define UART_MSR_RI 0x40 /* Ring Indicator */ -#define UART_MSR_DSR 0x20 /* Data Set Ready */ -#define UART_MSR_CTS 0x10 /* Clear to Send */ -#define UART_MSR_DDCD 0x08 /* Delta DCD */ -#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */ -#define UART_MSR_DDSR 0x02 /* Delta DSR */ -#define UART_MSR_DCTS 0x01 /* Delta CTS */ -#define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */ +#define UART_EMSR 7 /* Extended Mode Select Register */ +#define UART_EMSR_FIFO_COUNT 0x01 /* Rx/Tx select */ +#define UART_EMSR_ALT_COUNT 0x02 /* Alternating count select */ /* * The Intel XScale on-chip UARTs define these bits @@ -156,17 +218,8 @@ #define UART_FCR_PXAR16 0x80 /* receive FIFO treshold = 16 */ #define UART_FCR_PXAR32 0xc0 /* receive FIFO treshold = 32 */ -/* - * These are the definitions for the Extended Features Register - * (StarTech 16C660 only, when DLAB=1) - */ -#define UART_EFR_CTS 0x80 /* CTS flow control */ -#define UART_EFR_RTS 0x40 /* RTS flow control */ -#define UART_EFR_SCD 0x20 /* Special character detect */ -#define UART_EFR_ECB 0x10 /* Enhanced control bit */ -/* - * the low four bits control software flow control - */ + + /* * These register definitions are for the 16C950 @@ -203,47 +256,7 @@ #define UART_ACR_ICRRD 0x40 /* ICR Read enable */ #define UART_ACR_ASREN 0x80 /* Additional status enable */ -/* - * These are the definitions for the Feature Control Register - * (XR16C85x only, when LCR=bf; doubles with the Interrupt Enable - * Register, UART register #1) - */ -#define UART_FCTR_RTS_NODELAY 0x00 /* RTS flow control delay */ -#define UART_FCTR_RTS_4DELAY 0x01 -#define UART_FCTR_RTS_6DELAY 0x02 -#define UART_FCTR_RTS_8DELAY 0x03 -#define UART_FCTR_IRDA 0x04 /* IrDa data encode select */ -#define UART_FCTR_TX_INT 0x08 /* Tx interrupt type select */ -#define UART_FCTR_TRGA 0x00 /* Tx/Rx 550 trigger table select */ -#define UART_FCTR_TRGB 0x10 /* Tx/Rx 650 trigger table select */ -#define UART_FCTR_TRGC 0x20 /* Tx/Rx 654 trigger table select */ -#define UART_FCTR_TRGD 0x30 /* Tx/Rx 850 programmable trigger select */ -#define UART_FCTR_SCR_SWAP 0x40 /* Scratch pad register swap */ -#define UART_FCTR_RX 0x00 /* Programmable trigger mode select */ -#define UART_FCTR_TX 0x80 /* Programmable trigger mode select */ - -/* - * These are the definitions for the Enhanced Mode Select Register - * (XR16C85x only, when LCR=bf and FCTR bit 6=1; doubles with the - * Scratch register, UART register #7) - */ -#define UART_EMSR_FIFO_COUNT 0x01 /* Rx/Tx select */ -#define UART_EMSR_ALT_COUNT 0x02 /* Alternating count select */ -/* - * These are the definitions for the Programmable Trigger - * Register (XR16C85x only, when LCR=bf; doubles with the UART RX/TX - * register, UART register #0) - */ -#define UART_TRG_1 0x01 -#define UART_TRG_4 0x04 -#define UART_TRG_8 0x08 -#define UART_TRG_16 0x10 -#define UART_TRG_32 0x20 -#define UART_TRG_64 0x40 -#define UART_TRG_96 0x60 -#define UART_TRG_120 0x78 -#define UART_TRG_128 0x80 /* * These definitions are for the RSA-DV II/S card, from -- cgit v1.2.3 From a5e370d536855e8aeb20a19b4aaa1970bdcf2151 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 19 Oct 2004 04:00:00 -0700 Subject: [PKT_SCHED]: Use gnet_stats API to copy statistics into netlink message Adapts qdisc API to use new gnet_stats functions to copy statistics into netlink message. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- include/linux/rtnetlink.h | 1 + net/sched/sch_api.c | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index ac4528ead16e..9bb86160c2f2 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -698,6 +698,7 @@ enum TCA_XSTATS, TCA_RATE, TCA_FCNT, + TCA_STATS2, __TCA_MAX }; diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 5da7b7312642..3c985a58145c 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -750,6 +750,7 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, struct tcmsg *tcm; struct nlmsghdr *nlh; unsigned char *b = skb->tail; + struct gnet_dump d; nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*tcm)); nlh->nlmsg_flags = flags; @@ -762,9 +763,22 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, RTA_PUT(skb, TCA_KIND, IFNAMSIZ, q->ops->id); if (q->ops->dump && q->ops->dump(q, skb) < 0) goto rtattr_failure; - q->stats.qlen = q->q.qlen; - if (qdisc_copy_stats(skb, &q->stats, q->stats_lock)) + q->qstats.qlen = q->q.qlen; + + if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, + TCA_XSTATS, q->stats_lock, &d) < 0) + goto rtattr_failure; + + if (gnet_stats_copy_basic(&d, &q->bstats) < 0 || +#ifdef CONFIG_NET_ESTIMATOR + gnet_stats_copy_rate_est(&d, &q->rate_est) < 0 || +#endif + gnet_stats_copy_queue(&d, &q->qstats) < 0) + goto rtattr_failure; + + if (gnet_stats_finish_copy(&d) < 0) goto rtattr_failure; + nlh->nlmsg_len = skb->tail - b; return skb->len; -- cgit v1.2.3 From ad162bcb2f881599224225a98fb4dbe807a5fc3a Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Tue, 19 Oct 2004 07:46:00 -0700 Subject: [NET]: Add Mirred TC action. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/linux/tc_act/tc_mirred.h | 28 ++++ include/net/tc_act/tc_mirred.h | 15 ++ net/sched/Kconfig | 7 + net/sched/Makefile | 1 + net/sched/mirred.c | 318 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 369 insertions(+) create mode 100644 include/linux/tc_act/tc_mirred.h create mode 100644 include/net/tc_act/tc_mirred.h create mode 100644 net/sched/mirred.c (limited to 'include/linux') diff --git a/include/linux/tc_act/tc_mirred.h b/include/linux/tc_act/tc_mirred.h new file mode 100644 index 000000000000..71d63409d568 --- /dev/null +++ b/include/linux/tc_act/tc_mirred.h @@ -0,0 +1,28 @@ +#ifndef __LINUX_TC_MIR_H +#define __LINUX_TC_MIR_H + +#include + +#define TCA_ACT_MIRRED 8 +#define TCA_EGRESS_REDIR 1 /* packet redirect to EGRESS*/ +#define TCA_EGRESS_MIRROR 2 /* mirror packet to EGRESS */ +#define TCA_INGRESS_REDIR 3 /* packet redirect to INGRESS*/ +#define TCA_INGRESS_MIRROR 4 /* mirror packet to INGRESS */ + +struct tc_mirred +{ + tc_gen; + int eaction; /* one of IN/EGRESS_MIRROR/REDIR */ + __u32 ifindex; /* ifindex of egress port */ +}; + +enum +{ + TCA_MIRRED_UNSPEC, + TCA_MIRRED_TM, + TCA_MIRRED_PARMS, + __TCA_MIRRED_MAX +}; +#define TCA_MIRRED_MAX (__TCA_MIRRED_MAX - 1) + +#endif diff --git a/include/net/tc_act/tc_mirred.h b/include/net/tc_act/tc_mirred.h new file mode 100644 index 000000000000..f7f9b76c2511 --- /dev/null +++ b/include/net/tc_act/tc_mirred.h @@ -0,0 +1,15 @@ +#ifndef __NET_TC_MIR_H +#define __NET_TC_MIR_H + +#include + +struct tcf_mirred +{ + tca_gen(mirred); + int eaction; + int ifindex; + int ok_push; + struct net_device *dev; +}; + +#endif diff --git a/net/sched/Kconfig b/net/sched/Kconfig index c0df054b5e7e..2258c267e385 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -399,3 +399,10 @@ config GACT_PROB depends on NET_ACT_GACT ---help--- Allows generic actions to be randomly or deterministically used + +config NET_ACT_MIRRED + tristate "Packet In/Egress redirecton/mirror Actions" + depends on NET_CLS_ACT + ---help--- + requires new iproute2 + This allows packets to be mirrored or redirected to netdevices diff --git a/net/sched/Makefile b/net/sched/Makefile index 912677ad0cfa..a2857685b3c1 100644 --- a/net/sched/Makefile +++ b/net/sched/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_NET_CLS_ACT) += act_api.o obj-$(CONFIG_NET_ACT_POLICE) += police.o obj-$(CONFIG_NET_CLS_POLICE) += police.o obj-$(CONFIG_NET_ACT_GACT) += gact.o +obj-$(CONFIG_NET_ACT_MIRRED) += mirred.o obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o obj-$(CONFIG_NET_SCH_HPFQ) += sch_hpfq.o diff --git a/net/sched/mirred.c b/net/sched/mirred.c new file mode 100644 index 000000000000..9d3098548348 --- /dev/null +++ b/net/sched/mirred.c @@ -0,0 +1,318 @@ +/* + * net/sched/mirred.c packet mirroring and redirect actions + * + * 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. + * + * Authors: Jamal Hadi Salim (2002-4) + * + * TODO: Add ingress support (and socket redirect support) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +/* use generic hash table */ +#define MY_TAB_SIZE 8 +#define MY_TAB_MASK (MY_TAB_SIZE - 1) +static u32 idx_gen; +static struct tcf_mirred *tcf_mirred_ht[MY_TAB_SIZE]; +static rwlock_t mirred_lock = RW_LOCK_UNLOCKED; + +/* ovewrride the defaults */ +#define tcf_st tcf_mirred +#define tc_st tc_mirred +#define tcf_t_lock mirred_lock +#define tcf_ht tcf_mirred_ht + +#define CONFIG_NET_ACT_INIT 1 +#include + +static inline int +tcf_mirred_release(struct tcf_mirred *p, int bind) +{ + if (p) { + if (bind) { + p->bindcnt--; + } + + p->refcnt--; + if(!p->bindcnt && p->refcnt <= 0) { + dev_put(p->dev); + tcf_hash_destroy(p); + return 1; + } + } + + return 0; +} + +int +tcf_mirred_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,int ovr, int bind) +{ + struct rtattr *tb[TCA_MIRRED_MAX]; + struct tc_mirred *parm; + struct tcf_mirred *p; + struct net_device *dev = NULL; + int size = sizeof (*p), new = 0; + + + if (rtattr_parse(tb, TCA_MIRRED_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < 0) { + DPRINTK("tcf_mirred_init BUG in user space couldnt parse properly\n"); + return -1; + } + + if (NULL == a || NULL == tb[TCA_MIRRED_PARMS - 1]) { + DPRINTK("BUG: tcf_mirred_init called with NULL params\n"); + return -1; + } + + parm = RTA_DATA(tb[TCA_MIRRED_PARMS - 1]); + + p = tcf_hash_check(parm, a, ovr, bind); + if (NULL == p) { /* new */ + p = tcf_hash_create(parm,est,a,size,ovr,bind); + new = 1; + if (NULL == p) + return -1; + } + + if (parm->ifindex) { + dev = dev_get_by_index(parm->ifindex); + if (NULL == dev) { + printk("BUG: tcf_mirred_init called with bad device\n"); + return -1; + } + switch (dev->type) { + case ARPHRD_TUNNEL: + case ARPHRD_TUNNEL6: + case ARPHRD_SIT: + case ARPHRD_IPGRE: + case ARPHRD_VOID: + case ARPHRD_NONE: + p->ok_push = 0; + break; + default: + p->ok_push = 1; + break; + } + } else { + if (new) { + kfree(p); + return -1; + } + } + + if (new || ovr) { + spin_lock(&p->lock); + p->action = parm->action; + p->eaction = parm->eaction; + if (parm->ifindex) { + p->ifindex = parm->ifindex; + p->dev = dev; + dev_hold(p->dev); + } + spin_unlock(&p->lock); + } + + + DPRINTK(" tcf_mirred_init index %d action %d eaction %d device %s ifndex %d\n",parm->index,parm->action,parm->eaction,dev->name,parm->ifindex); + return new; + +} + +int +tcf_mirred_cleanup(struct tc_action *a, int bind) +{ + struct tcf_mirred *p; + p = PRIV(a,mirred); + if (NULL != p) + return tcf_mirred_release(p, bind); + return 0; +} + +int +tcf_mirred(struct sk_buff **pskb, struct tc_action *a) +{ + struct tcf_mirred *p; + struct net_device *dev; + struct sk_buff *skb2 = NULL; + struct sk_buff *skb = *pskb; + __u32 at = G_TC_AT(skb->tc_verd); + + if (NULL == a) { + if (net_ratelimit()) + printk("BUG: tcf_mirred called with NULL action!\n"); + return -1; + } + + p = PRIV(a,mirred); + + if (NULL == p) { + if (net_ratelimit()) + printk("BUG: tcf_mirred called with NULL params\n"); + return -1; + } + + spin_lock(&p->lock); + + dev = p->dev; + p->tm.lastuse = jiffies; + + if (NULL == dev || !(dev->flags&IFF_UP) ) { + if (net_ratelimit()) + printk("mirred to Houston: device %s is gone!\n", + dev?dev->name:""); +bad_mirred: + if (NULL != skb2) + kfree_skb(skb2); + p->stats.overlimits++; + p->stats.bytes += skb->len; + p->stats.packets++; + spin_unlock(&p->lock); + /* should we be asking for packet to be dropped? + * may make sense for redirect case only + */ + return TC_ACT_SHOT; + } + + skb2 = skb_clone(skb, GFP_ATOMIC); + if (skb2 == NULL) { + goto bad_mirred; + } + if (TCA_EGRESS_MIRROR != p->eaction && + TCA_EGRESS_REDIR != p->eaction) { + if (net_ratelimit()) + printk("tcf_mirred unknown action %d\n",p->eaction); + goto bad_mirred; + } + + p->stats.bytes += skb2->len; + p->stats.packets++; + if ( !(at & AT_EGRESS)) { + if (p->ok_push) { + skb_push(skb2, skb2->dev->hard_header_len); + } + } + + /* mirror is always swallowed */ + if (TCA_EGRESS_MIRROR != p->eaction) + skb2->tc_verd = SET_TC_FROM(skb2->tc_verd,at); + + skb2->dev = dev; + skb2->input_dev = skb->dev; + dev_queue_xmit(skb2); + spin_unlock(&p->lock); + return p->action; +} + +int +tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a,int bind, int ref) +{ + unsigned char *b = skb->tail; + struct tc_mirred opt; + struct tcf_mirred *p; + struct tcf_t t; + + p = PRIV(a,mirred); + if (NULL == p) { + printk("BUG: tcf_mirred_dump called with NULL params\n"); + goto rtattr_failure; + } + + opt.index = p->index; + opt.action = p->action; + opt.refcnt = p->refcnt - ref; + opt.bindcnt = p->bindcnt - bind; + opt.eaction = p->eaction; + opt.ifindex = p->ifindex; + DPRINTK(" tcf_mirred_dump index %d action %d eaction %d ifndex %d\n",p->index,p->action,p->eaction,p->ifindex); + RTA_PUT(skb, TCA_MIRRED_PARMS, sizeof (opt), &opt); + t.install = jiffies - p->tm.install; + t.lastuse = jiffies - p->tm.lastuse; + t.expires = p->tm.expires; + RTA_PUT(skb, TCA_MIRRED_TM, sizeof (t), &t); + return skb->len; + + rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; +} + +int +tcf_mirred_stats(struct sk_buff *skb, struct tc_action *a) +{ + struct tcf_mirred *p; + p = PRIV(a,mirred); + + if (NULL != p) + return qdisc_copy_stats(skb, &p->stats, p->stats_lock); + + return 1; +} + +static struct tc_action_ops act_mirred_ops = { + .next = NULL, + .kind = "mirred", + .type = TCA_ACT_MIRRED, + .capab = TCA_CAP_NONE, + .owner = THIS_MODULE, + .act = tcf_mirred, + .get_stats = tcf_mirred_stats, + .dump = tcf_mirred_dump, + .cleanup = tcf_mirred_cleanup, + .lookup = tcf_hash_search, + .init = tcf_mirred_init, + .walk = tcf_generic_walker +}; + +MODULE_AUTHOR("Jamal Hadi Salim(2002)"); +MODULE_DESCRIPTION("Device Mirror/redirect actions"); +MODULE_LICENSE("GPL"); + + +static int __init +mirred_init_module(void) +{ + printk("Mirror/redirect action on\n"); + return tcf_register_action(&act_mirred_ops); +} + +static void __exit +mirred_cleanup_module(void) +{ + tcf_unregister_action(&act_mirred_ops); +} + +module_init(mirred_init_module); +module_exit(mirred_cleanup_module); + -- cgit v1.2.3 From ff517ce26c77913b4e1c3e9f5f8ff4052b427b81 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 19 Oct 2004 08:00:45 -0700 Subject: [NET]: Need to disable preempt in softirq check of netif_rx_ni. Signed-off-by: David S. Miller --- include/linux/netdevice.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 8325475d6ea0..08a7c1e5b7f9 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -695,8 +695,12 @@ extern int netdev_nit; static inline int netif_rx_ni(struct sk_buff *skb) { int err = netif_rx(skb); + + preempt_disable(); if (softirq_pending(smp_processor_id())) do_softirq(); + preempt_enable(); + return err; } -- cgit v1.2.3 From 9229204bae3b2928b68351bc3a2c26769ea74047 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 19 Oct 2004 18:10:43 -0700 Subject: [PATCH] module_param_array() should take a pointer module_param_array() takes a variable to put the number of elements in. Looking through the uses, many people don't care, so they declare a dummy or share one variable between several parameters. The latter is problematic because sysfs uses that number to decide how many to display. The solution is to change the variable arg to a pointer, and if the pointer is NULL, use the "max" value. This change is fairly small, but fixing up the callers is a lot of (trivial) churn. Signed-off-by: Rusty Russell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 12 ++++----- drivers/eisa/eisa-bus.c | 4 +-- drivers/i2c/busses/scx200_acb.c | 3 +-- drivers/input/joystick/amijoy.c | 3 +-- drivers/input/joystick/analog.c | 2 +- drivers/input/joystick/db9.c | 6 ++--- drivers/input/joystick/gamecon.c | 6 ++--- drivers/input/joystick/turbografx.c | 6 ++--- drivers/net/acenic.c | 15 +++++------ drivers/net/pcnet32.c | 7 +++-- drivers/pcmcia/i82365.c | 2 +- drivers/pcmcia/tcic.c | 2 +- drivers/s390/block/xpram.c | 3 +-- drivers/scsi/pcmcia/sym53c500_cs.c | 3 +-- drivers/scsi/tmscsim.c | 3 +-- drivers/serial/8250.c | 2 +- drivers/serial/serial_cs.c | 2 +- drivers/usb/gadget/file_storage.c | 8 +++--- drivers/usb/media/sn9c102_core.c | 3 +-- drivers/usb/media/w9968cf.c | 48 +++++++++++++++++----------------- include/linux/i2c.h | 2 +- include/linux/moduleparam.h | 10 +++---- kernel/params.c | 4 +-- net/decnet/dn_dev.c | 3 +-- net/ipv4/ipvs/ip_vs_ftp.c | 3 +-- net/ipv4/netfilter/ip_conntrack_ftp.c | 2 +- net/ipv4/netfilter/ip_conntrack_irc.c | 2 +- net/ipv4/netfilter/ip_conntrack_tftp.c | 2 +- net/ipv4/netfilter/ip_nat_ftp.c | 2 +- net/ipv4/netfilter/ip_nat_irc.c | 2 +- net/ipv4/netfilter/ip_nat_tftp.c | 2 +- sound/core/memalloc.c | 3 +-- sound/core/oss/pcm_oss.c | 5 ++-- sound/core/rawmidi.c | 5 ++-- sound/core/seq/seq.c | 3 +-- sound/drivers/dummy.c | 13 +++++---- sound/drivers/mpu401/mpu401.c | 13 +++++---- sound/drivers/serial-u16550.c | 23 ++++++++-------- sound/drivers/virmidi.c | 9 +++---- sound/isa/ad1816a/ad1816a.c | 21 +++++++-------- sound/isa/ad1848/ad1848.c | 15 +++++------ sound/isa/als100.c | 21 +++++++-------- sound/isa/azt2320.c | 23 ++++++++-------- sound/isa/cmi8330.c | 23 ++++++++-------- sound/isa/cs423x/cs4231.c | 19 +++++++------- sound/isa/cs423x/cs4236.c | 27 +++++++++---------- sound/isa/dt019x.c | 19 +++++++------- sound/isa/es1688/es1688.c | 17 ++++++------ sound/isa/es18xx.c | 21 +++++++-------- sound/isa/gus/gusclassic.c | 21 +++++++-------- sound/isa/gus/gusextreme.c | 29 ++++++++++---------- sound/isa/gus/gusmax.c | 21 +++++++-------- sound/isa/gus/interwave.c | 27 +++++++++---------- sound/isa/opl3sa2.c | 27 +++++++++---------- sound/isa/sb/es968.c | 13 +++++---- sound/isa/sb/sb16.c | 29 ++++++++++---------- sound/isa/sb/sb8.c | 13 +++++---- sound/isa/sgalaxy.c | 13 +++++---- sound/isa/sscape.c | 13 +++++---- sound/isa/wavefront/wavefront.c | 29 ++++++++++---------- sound/parisc/harmony.c | 7 +++-- sound/pci/ali5451/ali5451.c | 11 ++++---- sound/pci/als4000.c | 9 +++---- sound/pci/atiixp.c | 11 ++++---- sound/pci/atiixp_modem.c | 9 +++---- sound/pci/au88x0/au88x0.c | 9 +++---- sound/pci/azt3328.c | 9 +++---- sound/pci/bt87x.c | 9 +++---- sound/pci/cmipci.c | 15 +++++------ sound/pci/cs4281.c | 9 +++---- sound/pci/cs46xx/cs46xx.c | 13 +++++---- sound/pci/emu10k1/emu10k1.c | 19 +++++++------- sound/pci/ens1370.c | 11 ++++---- sound/pci/es1938.c | 7 +++-- sound/pci/es1968.c | 21 +++++++-------- sound/pci/fm801.c | 9 +++---- sound/pci/ice1712/ice1712.c | 13 +++++---- sound/pci/intel8x0.c | 17 ++++++------ sound/pci/intel8x0m.c | 9 +++---- sound/pci/korg1212/korg1212.c | 7 +++-- sound/pci/maestro3.c | 11 ++++---- sound/pci/mixart/mixart.c | 7 +++-- sound/pci/nm256/nm256.c | 19 +++++++------- sound/pci/rme32.c | 9 +++---- sound/pci/rme9652/hdsp.c | 11 ++++---- sound/pci/rme9652/rme9652.c | 9 +++---- sound/pci/sonicvibes.c | 11 ++++---- sound/pci/trident/trident.c | 11 ++++---- sound/pci/via82xx.c | 17 ++++++------ sound/pci/vx222/vx222.c | 11 ++++---- sound/pci/ymfpci/ymfpci.c | 15 +++++------ sound/pcmcia/pdaudiocf/pdaudiocf.c | 9 +++---- sound/pcmcia/vx/vxpocket.c | 11 ++++---- sound/sparc/amd7930.c | 7 +++-- sound/sparc/cs4231.c | 7 +++-- sound/usb/usbaudio.c | 11 ++++---- sound/usb/usx2y/usbusx2y.c | 7 +++-- 97 files changed, 510 insertions(+), 586 deletions(-) (limited to 'include/linux') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 002a7ef2c3a0..9793c70ba5ff 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -923,34 +923,34 @@ MODULE_PARM_DESC(type, "Defines the type of each interface, each" " interface separated by commas. The types are 'kcs'," " 'smic', and 'bt'. For example si_type=kcs,bt will set" " the first interface to kcs and the second to bt"); -module_param_array(addrs, long, num_addrs, 0); +module_param_array(addrs, long, &num_addrs, 0); MODULE_PARM_DESC(addrs, "Sets the memory address of each interface, the" " addresses separated by commas. Only use if an interface" " is in memory. Otherwise, set it to zero or leave" " it blank."); -module_param_array(ports, int, num_ports, 0); +module_param_array(ports, int, &num_ports, 0); MODULE_PARM_DESC(ports, "Sets the port address of each interface, the" " addresses separated by commas. Only use if an interface" " is a port. Otherwise, set it to zero or leave" " it blank."); -module_param_array(irqs, int, num_irqs, 0); +module_param_array(irqs, int, &num_irqs, 0); MODULE_PARM_DESC(irqs, "Sets the interrupt of each interface, the" " addresses separated by commas. Only use if an interface" " has an interrupt. Otherwise, set it to zero or leave" " it blank."); -module_param_array(regspacings, int, num_regspacings, 0); +module_param_array(regspacings, int, &num_regspacings, 0); MODULE_PARM_DESC(regspacings, "The number of bytes between the start address" " and each successive register used by the interface. For" " instance, if the start address is 0xca2 and the spacing" " is 2, then the second address is at 0xca4. Defaults" " to 1."); -module_param_array(regsizes, int, num_regsizes, 0); +module_param_array(regsizes, int, &num_regsizes, 0); MODULE_PARM_DESC(regsizes, "The size of the specific IPMI register in bytes." " This should generally be 1, 2, 4, or 8 for an 8-bit," " 16-bit, 32-bit, or 64-bit register. Use this if you" " the 8-bit IPMI register has to be read from a larger" " register."); -module_param_array(regshifts, int, num_regshifts, 0); +module_param_array(regshifts, int, &num_regshifts, 0); MODULE_PARM_DESC(regshifts, "The amount to shift the data read from the." " IPMI register, in bits. For instance, if the data" " is read from a 32-bit word and the IPMI data is in" diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index af825fc3018e..6381ba53853c 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -418,8 +418,8 @@ static int __init eisa_init (void) return 0; } -module_param_array(enable_dev, int, enable_dev_count, 0444); -module_param_array(disable_dev, int, disable_dev_count, 0444); +module_param_array(enable_dev, int, &enable_dev_count, 0444); +module_param_array(disable_dev, int, &disable_dev_count, 0444); postcore_initcall (eisa_init); diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index b402aadf6702..08d7c60a3048 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -45,8 +45,7 @@ MODULE_LICENSE("GPL"); #define MAX_DEVICES 4 static int base[MAX_DEVICES] = { 0x820, 0x840 }; -static int num_base; -module_param_array(base, int, num_base, 0); +module_param_array(base, int, NULL, 0); MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers"); #ifdef DEBUG diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c index 8b5fc358d806..cf36ca9b92f3 100644 --- a/drivers/input/joystick/amijoy.c +++ b/drivers/input/joystick/amijoy.c @@ -46,8 +46,7 @@ MODULE_DESCRIPTION("Driver for Amiga joysticks"); MODULE_LICENSE("GPL"); static int amijoy[2] = { 0, 1 }; -static int amijoy_nargs; -module_param_array_named(map, amijoy, uint, amijoy_nargs, 0); +module_param_array_named(map, amijoy, uint, NULL, 0); MODULE_PARM_DESC(map, "Map of attached joysticks in form of , (default is 0,1)"); __obsolete_setup("amijoy="); diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 7e52f96096a9..df7b2aadbf86 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -53,7 +53,7 @@ MODULE_LICENSE("GPL"); static char *js[ANALOG_PORTS]; static int js_nargs; static int analog_options[ANALOG_PORTS]; -module_param_array_named(map, js, charp, js_nargs, 0); +module_param_array_named(map, js, charp, &js_nargs, 0); MODULE_PARM_DESC(map, "Describes analog joysticks type/capabilities"); __obsolete_setup("js="); diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index 5ad612751c81..c5c6115dc4c5 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c @@ -45,17 +45,17 @@ MODULE_LICENSE("GPL"); static int db9[] __initdata = { -1, 0 }; static int db9_nargs __initdata = 0; -module_param_array_named(dev, db9, int, db9_nargs, 0); +module_param_array_named(dev, db9, int, &db9_nargs, 0); MODULE_PARM_DESC(dev, "Describes first attached device (,)"); static int db9_2[] __initdata = { -1, 0 }; static int db9_nargs_2 __initdata = 0; -module_param_array_named(dev2, db9_2, int, db9_nargs_2, 0); +module_param_array_named(dev2, db9_2, int, &db9_nargs_2, 0); MODULE_PARM_DESC(dev2, "Describes second attached device (,)"); static int db9_3[] __initdata = { -1, 0 }; static int db9_nargs_3 __initdata = 0; -module_param_array_named(dev3, db9_3, int, db9_nargs_3, 0); +module_param_array_named(dev3, db9_3, int, &db9_nargs_3, 0); MODULE_PARM_DESC(dev3, "Describes third attached device (,)"); __obsolete_setup("db9="); diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 46326b701743..3f2cdb6a32a2 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -43,17 +43,17 @@ MODULE_LICENSE("GPL"); static int gc[] __initdata = { -1, 0, 0, 0, 0, 0 }; static int gc_nargs __initdata = 0; -module_param_array_named(map, gc, int, gc_nargs, 0); +module_param_array_named(map, gc, int, &gc_nargs, 0); MODULE_PARM_DESC(map, "Describers first set of devices (,,,..)"); static int gc_2[] __initdata = { -1, 0, 0, 0, 0, 0 }; static int gc_nargs_2 __initdata = 0; -module_param_array_named(map2, gc_2, int, gc_nargs_2, 0); +module_param_array_named(map2, gc_2, int, &gc_nargs_2, 0); MODULE_PARM_DESC(map2, "Describers second set of devices"); static int gc_3[] __initdata = { -1, 0, 0, 0, 0, 0 }; static int gc_nargs_3 __initdata = 0; -module_param_array_named(map3, gc_3, int, gc_nargs_3, 0); +module_param_array_named(map3, gc_3, int, &gc_nargs_3, 0); MODULE_PARM_DESC(map3, "Describers third set of devices"); __obsolete_setup("gc="); diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index 123ff5f9d42a..0e620cb882cd 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c @@ -44,17 +44,17 @@ MODULE_LICENSE("GPL"); static int tgfx[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 }; static int tgfx_nargs __initdata = 0; -module_param_array_named(map, tgfx, int, tgfx_nargs, 0); +module_param_array_named(map, tgfx, int, &tgfx_nargs, 0); MODULE_PARM_DESC(map, "Describes first set of devices (,,,.."); static int tgfx_2[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 }; static int tgfx_nargs_2 __initdata = 0; -module_param_array_named(map2, tgfx_2, int, tgfx_nargs_2, 0); +module_param_array_named(map2, tgfx_2, int, &tgfx_nargs_2, 0); MODULE_PARM_DESC(map2, "Describes second set of devices"); static int tgfx_3[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 }; static int tgfx_nargs_3 __initdata = 0; -module_param_array_named(map3, tgfx_3, int, tgfx_nargs_3, 0); +module_param_array_named(map3, tgfx_3, int, &tgfx_nargs_3, 0); MODULE_PARM_DESC(map3, "Describes third set of devices"); __obsolete_setup("tgfx="); diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index cc56ca3ac02a..492ae24203d1 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -427,14 +427,13 @@ MODULE_AUTHOR("Jes Sorensen "); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver"); -static int num_params; -module_param_array(link, int, num_params, 0); -module_param_array(trace, int, num_params, 0); -module_param_array(tx_coal_tick, int, num_params, 0); -module_param_array(max_tx_desc, int, num_params, 0); -module_param_array(rx_coal_tick, int, num_params, 0); -module_param_array(max_rx_desc, int, num_params, 0); -module_param_array(tx_ratio, int, num_params, 0); +module_param_array(link, int, NULL, 0); +module_param_array(trace, int, NULL, 0); +module_param_array(tx_coal_tick, int, NULL, 0); +module_param_array(max_tx_desc, int, NULL, 0); +module_param_array(rx_coal_tick, int, NULL, 0); +module_param_array(max_rx_desc, int, NULL, 0); +module_param_array(tx_ratio, int, NULL, 0); MODULE_PARM_DESC(link, "AceNIC/3C985/NetGear link state"); MODULE_PARM_DESC(trace, "AceNIC/3C985/NetGear firmware trace level"); MODULE_PARM_DESC(tx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first tx descriptor arrives"); diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index effbad31d11e..a0af06c18a23 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -2264,7 +2264,6 @@ static struct pci_driver pcnet32_driver = { static int debug = -1; static int tx_start_pt = -1; static int pcnet32_have_pci; -static int num_params; module_param(debug, int, 0); MODULE_PARM_DESC(debug, DRV_NAME " debug level"); @@ -2276,12 +2275,12 @@ module_param(tx_start_pt, int, 0); MODULE_PARM_DESC(tx_start_pt, DRV_NAME " transmit start point (0-3)"); module_param(pcnet32vlb, int, 0); MODULE_PARM_DESC(pcnet32vlb, DRV_NAME " Vesa local bus (VLB) support (0/1)"); -module_param_array(options, int, num_params, 0); +module_param_array(options, int, NULL, 0); MODULE_PARM_DESC(options, DRV_NAME " initial option setting(s) (0-15)"); -module_param_array(full_duplex, int, num_params, 0); +module_param_array(full_duplex, int, NULL, 0); MODULE_PARM_DESC(full_duplex, DRV_NAME " full duplex setting(s) (1)"); /* Module Parameter for HomePNA cards added by Patrick Simmons, 2004 */ -module_param_array(homepna, int, num_params, 0); +module_param_array(homepna, int, NULL, 0); MODULE_PARM_DESC(homepna, DRV_NAME " mode for 79C978 cards (1 for HomePNA, 0 for Ethernet, default Ethernet"); MODULE_AUTHOR("Thomas Bogendoerfer"); diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index 561974efbe63..fd404eee5c6f 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c @@ -134,7 +134,7 @@ module_param(i365_base, int, 0444); module_param(ignore, int, 0444); module_param(extra_sockets, int, 0444); module_param(irq_mask, int, 0444); -module_param_array(irq_list, int, irq_list_count, 0444); +module_param_array(irq_list, int, &irq_list_count, 0444); module_param(cs_irq, int, 0444); module_param(async_clock, int, 0444); module_param(cable_mode, int, 0444); diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c index d986d13f288b..0bb9017d0b77 100644 --- a/drivers/pcmcia/tcic.c +++ b/drivers/pcmcia/tcic.c @@ -109,7 +109,7 @@ module_param(tcic_base, int, 0444); module_param(ignore, int, 0444); module_param(do_scan, int, 0444); module_param(irq_mask, int, 0444); -module_param_array(irq_list, int, irq_list_count, 0444); +module_param_array(irq_list, int, &irq_list_count, 0444); module_param(cs_irq, int, 0444); module_param(poll_interval, int, 0444); module_param(poll_quick, int, 0444); diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index 312057e93b28..d428c909b8a0 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c @@ -74,10 +74,9 @@ static int xpram_devs; */ static int devs = XPRAM_DEVS; static unsigned int sizes[XPRAM_MAX_DEVS]; -static unsigned int sizes_count; module_param(devs, int, 0); -module_param_array(sizes, int, sizes_count, 0); +module_param_array(sizes, int, NULL, 0); MODULE_PARM_DESC(devs, "number of devices (\"partitions\"), " \ "the default is " __MODULE_STRING(XPRAM_DEVS) "\n"); diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index 4277db3b6fee..a58dc7e6301e 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -97,11 +97,10 @@ static char *version = /* Bit map of interrupts to choose from */ static unsigned int irq_mask = 0xdeb8; /* 3, 6, 7, 9-12, 14, 15 */ static int irq_list[4] = { -1 }; -static int num_irqs = 1; module_param(irq_mask, int, 0); MODULE_PARM_DESC(irq_mask, "IRQ mask bits (default: 0xdeb8)"); -module_param_array(irq_list, int, num_irqs, 0); +module_param_array(irq_list, int, NULL, 0); MODULE_PARM_DESC(irq_list, "Comma-separated list of up to 4 IRQs to try (default: auto select)."); /* ================================================================== */ diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index 8513ed699e24..4a6e8d2c89a8 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c @@ -282,9 +282,8 @@ static u8 dc390_adapterCnt = 0; /* Startup values, to be overriden on the commandline */ static int tmscsim[] = {-2, -2, -2, -2, -2, -2}; -static int tmscsim_paramnum = ARRAY_SIZE(tmscsim); -module_param_array(tmscsim, int, tmscsim_paramnum, 0); +module_param_array(tmscsim, int, NULL, 0); MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1), DelayReset (s)"); MODULE_AUTHOR("C.L. Huang / Kurt Garloff"); MODULE_DESCRIPTION("SCSI host adapter driver for Tekram DC390 and other AMD53C974A based PCI SCSI adapters"); diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index b0fc3fb35e8e..a5e821bbcd73 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -2430,7 +2430,7 @@ MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices" " (unsafe)"); #ifdef CONFIG_SERIAL_8250_RSA -module_param_array(probe_rsa, ulong, probe_rsa_count, 0444); +module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444); MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA"); #endif MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR); diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 8557ed1ce7f5..a36650b87fb2 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -81,7 +81,7 @@ static int do_sound = 1; static int buggy_uart; module_param(irq_mask, uint, 0444); -module_param_array(irq_list, int, irq_list_count, 0444); +module_param_array(irq_list, int, &irq_list_count, 0444); module_param(do_sound, int, 0444); module_param(buggy_uart, int, 0444); diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index d8c8ab7750ec..1fe4a6fca50c 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -369,16 +369,16 @@ static struct { }; -module_param_array(file, charp, mod_data.num_filenames, S_IRUGO); +module_param_array(file, charp, &mod_data.num_filenames, S_IRUGO); MODULE_PARM_DESC(file, "names of backing files or devices"); -module_param_array(ro, bool, mod_data.num_ros, S_IRUGO); +module_param_array(ro, bool, &mod_data.num_ros, S_IRUGO); MODULE_PARM_DESC(ro, "true to force read-only"); -module_param_named(luns, mod_data.nluns, uint, S_IRUGO); +module_param_named(luns, &mod_data.nluns, uint, S_IRUGO); MODULE_PARM_DESC(luns, "number of LUNs"); -module_param_named(removable, mod_data.removable, bool, S_IRUGO); +module_param_named(removable, &mod_data.removable, bool, S_IRUGO); MODULE_PARM_DESC(removable, "true to simulate removable media"); diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c index 6d428a5b8d03..96ae7b103ff8 100644 --- a/drivers/usb/media/sn9c102_core.c +++ b/drivers/usb/media/sn9c102_core.c @@ -53,8 +53,7 @@ MODULE_VERSION(SN9C102_MODULE_VERSION); MODULE_LICENSE(SN9C102_MODULE_LICENSE); static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1}; -static unsigned int nv; -module_param_array(video_nr, short, nv, 0444); +module_param_array(video_nr, short, NULL, 0444); MODULE_PARM_DESC(video_nr, "\n<-1|n[,...]> Specify V4L2 minor mode number." "\n -1 = use next available (default)" diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c index 36fbe800f368..3131a509b650 100644 --- a/drivers/usb/media/w9968cf.c +++ b/drivers/usb/media/w9968cf.c @@ -111,30 +111,30 @@ module_param(ovmod_load, bool, 0644); module_param(vppmod_load, bool, 0444); #endif module_param(simcams, ushort, 0644); -module_param_array(video_nr, short, param_nv[0], 0444); -module_param_array(packet_size, uint, param_nv[1], 0444); -module_param_array(max_buffers, ushort, param_nv[2], 0444); -module_param_array(double_buffer, bool, param_nv[3], 0444); -module_param_array(clamping, bool, param_nv[4], 0444); -module_param_array(filter_type, ushort, param_nv[5], 0444); -module_param_array(largeview, bool, param_nv[6], 0444); -module_param_array(decompression, ushort, param_nv[7], 0444); -module_param_array(upscaling, bool, param_nv[8], 0444); -module_param_array(force_palette, ushort, param_nv[9], 0444); -module_param_array(force_rgb, ushort, param_nv[10], 0444); -module_param_array(autobright, bool, param_nv[11], 0444); -module_param_array(autoexp, bool, param_nv[12], 0444); -module_param_array(lightfreq, ushort, param_nv[13], 0444); -module_param_array(bandingfilter, bool, param_nv[14], 0444); -module_param_array(clockdiv, short, param_nv[15], 0444); -module_param_array(backlight, bool, param_nv[16], 0444); -module_param_array(mirror, bool, param_nv[17], 0444); -module_param_array(monochrome, bool, param_nv[18], 0444); -module_param_array(brightness, uint, param_nv[19], 0444); -module_param_array(hue, uint, param_nv[20], 0444); -module_param_array(colour, uint, param_nv[21], 0444); -module_param_array(contrast, uint, param_nv[22], 0444); -module_param_array(whiteness, uint, param_nv[23], 0444); +module_param_array(video_nr, short, ¶m_nv[0], 0444); +module_param_array(packet_size, uint, ¶m_nv[1], 0444); +module_param_array(max_buffers, ushort, ¶m_nv[2], 0444); +module_param_array(double_buffer, bool, ¶m_nv[3], 0444); +module_param_array(clamping, bool, ¶m_nv[4], 0444); +module_param_array(filter_type, ushort, ¶m_nv[5], 0444); +module_param_array(largeview, bool, ¶m_nv[6], 0444); +module_param_array(decompression, ushort, ¶m_nv[7], 0444); +module_param_array(upscaling, bool, ¶m_nv[8], 0444); +module_param_array(force_palette, ushort, ¶m_nv[9], 0444); +module_param_array(force_rgb, ushort, ¶m_nv[10], 0444); +module_param_array(autobright, bool, ¶m_nv[11], 0444); +module_param_array(autoexp, bool, ¶m_nv[12], 0444); +module_param_array(lightfreq, ushort, ¶m_nv[13], 0444); +module_param_array(bandingfilter, bool, ¶m_nv[14], 0444); +module_param_array(clockdiv, short, ¶m_nv[15], 0444); +module_param_array(backlight, bool, ¶m_nv[16], 0444); +module_param_array(mirror, bool, ¶m_nv[17], 0444); +module_param_array(monochrome, bool, ¶m_nv[18], 0444); +module_param_array(brightness, uint, ¶m_nv[19], 0444); +module_param_array(hue, uint, ¶m_nv[20], 0444); +module_param_array(colour, uint, ¶m_nv[21], 0444); +module_param_array(contrast, uint, ¶m_nv[22], 0444); +module_param_array(whiteness, uint, ¶m_nv[23], 0444); #ifdef W9968CF_DEBUG module_param(debug, ushort, 0644); module_param(specific_debug, bool, 0644); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index caac24868d85..bd2735bdca6b 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -568,7 +568,7 @@ union i2c_smbus_data { static unsigned short var[I2C_CLIENT_MAX_OPTS] = I2C_CLIENT_DEFAULTS; \ static unsigned int var##_num; \ /*MODULE_PARM(var,I2C_CLIENT_MODPARM);*/ \ - module_param_array(var, short, var##_num, 0); \ + module_param_array(var, short, &var##_num, 0); \ MODULE_PARM_DESC(var,desc) /* This is the one you want to use in your own modules */ diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index 7a145cd86c40..4e6e7a51d74f 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h @@ -129,16 +129,16 @@ extern int param_set_invbool(const char *val, struct kernel_param *kp); extern int param_get_invbool(char *buffer, struct kernel_param *kp); #define param_check_invbool(name, p) __param_check(name, p, int) -/* Comma-separated array: num is set to number they actually specified. */ -#define module_param_array_named(name, array, type, num, perm) \ +/* Comma-separated array: *nump is set to number they actually specified. */ +#define module_param_array_named(name, array, type, nump, perm) \ static struct kparam_array __param_arr_##name \ - = { ARRAY_SIZE(array), &num, param_set_##type, param_get_##type,\ + = { ARRAY_SIZE(array), nump, param_set_##type, param_get_##type,\ sizeof(array[0]), array }; \ module_param_call(name, param_array_set, param_array_get, \ &__param_arr_##name, perm) -#define module_param_array(name, type, num, perm) \ - module_param_array_named(name, name, type, num, perm) +#define module_param_array(name, type, nump, perm) \ + module_param_array_named(name, name, type, nump, perm) extern int param_array_set(const char *val, struct kernel_param *kp); extern int param_array_get(char *buffer, struct kernel_param *kp); diff --git a/kernel/params.c b/kernel/params.c index cfd8a8413bf6..ebb3031cd6cc 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -304,7 +304,7 @@ int param_array_set(const char *val, struct kernel_param *kp) struct kparam_array *arr = kp->arg; return param_array(kp->name, val, 1, arr->max, arr->elem, - arr->elemsize, arr->set, arr->num); + arr->elemsize, arr->set, arr->num ?: &arr->max); } int param_array_get(char *buffer, struct kernel_param *kp) @@ -314,7 +314,7 @@ int param_array_get(char *buffer, struct kernel_param *kp) struct kernel_param p; p = *kp; - for (i = off = 0; i < *arr->num; i++) { + for (i = off = 0; i < (arr->num ? *arr->num : arr->max); i++) { if (i) buffer[off++] = ','; p.arg = arr->elem + arr->elemsize * i; diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index a21a326808b4..2965ba95242a 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -1484,8 +1484,7 @@ static struct rtnetlink_link dnet_rtnetlink_table[RTM_MAX-RTM_BASE+1] = }; static int __initdata addr[2]; -static int __initdata num; -module_param_array(addr, int, num, 0444); +module_param_array(addr, int, NULL, 0444); MODULE_PARM_DESC(addr, "The DECnet address of this machine: area,node"); void __init dn_dev_init(void) diff --git a/net/ipv4/ipvs/ip_vs_ftp.c b/net/ipv4/ipvs/ip_vs_ftp.c index 0165cc6e34c0..a19a33ceb811 100644 --- a/net/ipv4/ipvs/ip_vs_ftp.c +++ b/net/ipv4/ipvs/ip_vs_ftp.c @@ -45,8 +45,7 @@ * First port is set to the default port. */ static int ports[IP_VS_APP_MAX_PORTS] = {21, 0}; -static int ports_c; -module_param_array(ports, int, ports_c, 0); +module_param_array(ports, int, NULL, 0); /* * Debug level diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c index df7008989c38..8038cadeaa94 100644 --- a/net/ipv4/netfilter/ip_conntrack_ftp.c +++ b/net/ipv4/netfilter/ip_conntrack_ftp.c @@ -34,7 +34,7 @@ struct module *ip_conntrack_ftp = THIS_MODULE; #define MAX_PORTS 8 static int ports[MAX_PORTS]; static int ports_c; -module_param_array(ports, int, ports_c, 0400); +module_param_array(ports, int, &ports_c, 0400); static int loose; module_param(loose, int, 0600); diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c index d007bc9950cf..2a048b527ec5 100644 --- a/net/ipv4/netfilter/ip_conntrack_irc.c +++ b/net/ipv4/netfilter/ip_conntrack_irc.c @@ -46,7 +46,7 @@ static DECLARE_LOCK(irc_buffer_lock); MODULE_AUTHOR("Harald Welte "); MODULE_DESCRIPTION("IRC (DCC) connection tracking helper"); MODULE_LICENSE("GPL"); -module_param_array(ports, int, ports_c, 0400); +module_param_array(ports, int, &ports_c, 0400); MODULE_PARM_DESC(ports, "port numbers of IRC servers"); module_param(max_dcc_channels, int, 0400); MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session"); diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c index d132a3c48d8d..01a5e53e81bb 100644 --- a/net/ipv4/netfilter/ip_conntrack_tftp.c +++ b/net/ipv4/netfilter/ip_conntrack_tftp.c @@ -28,7 +28,7 @@ MODULE_LICENSE("GPL"); #define MAX_PORTS 8 static int ports[MAX_PORTS]; static int ports_c; -module_param_array(ports, int, ports_c, 0400); +module_param_array(ports, int, &ports_c, 0400); MODULE_PARM_DESC(ports, "port numbers of tftp servers"); #if 0 diff --git a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c index be00284f8a1d..65da7b3367d7 100644 --- a/net/ipv4/netfilter/ip_nat_ftp.c +++ b/net/ipv4/netfilter/ip_nat_ftp.c @@ -34,7 +34,7 @@ MODULE_DESCRIPTION("ftp NAT helper"); static int ports[MAX_PORTS]; static int ports_c; -module_param_array(ports, int, ports_c, 0400); +module_param_array(ports, int, &ports_c, 0400); /* FIXME: Time out? --RR */ diff --git a/net/ipv4/netfilter/ip_nat_irc.c b/net/ipv4/netfilter/ip_nat_irc.c index 5eb60a25ac8e..4086f95542bd 100644 --- a/net/ipv4/netfilter/ip_nat_irc.c +++ b/net/ipv4/netfilter/ip_nat_irc.c @@ -42,7 +42,7 @@ static int ports_c; MODULE_AUTHOR("Harald Welte "); MODULE_DESCRIPTION("IRC (DCC) NAT helper"); MODULE_LICENSE("GPL"); -module_param_array(ports, int, ports_c, 0400); +module_param_array(ports, int, &ports_c, 0400); MODULE_PARM_DESC(ports, "port numbers of IRC servers"); /* FIXME: Time out? --RR */ diff --git a/net/ipv4/netfilter/ip_nat_tftp.c b/net/ipv4/netfilter/ip_nat_tftp.c index cacaab6f768c..aedd7828c04f 100644 --- a/net/ipv4/netfilter/ip_nat_tftp.c +++ b/net/ipv4/netfilter/ip_nat_tftp.c @@ -42,7 +42,7 @@ MODULE_LICENSE("GPL"); static int ports[MAX_PORTS]; static int ports_c = 0; -module_param_array(ports, int, ports_c, 0400); +module_param_array(ports, int, &ports_c, 0400); MODULE_PARM_DESC(ports, "port numbers of tftp servers"); #if 0 diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index cc0b6028c25c..ed31d8609522 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -49,8 +49,7 @@ MODULE_LICENSE("GPL"); /* FIXME: so far only some PCI devices have the preallocation table */ #ifdef CONFIG_PCI static int enable[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; -static int boot_devs; -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable cards to allocate buffers."); #endif diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 5d87847c616e..fc8736191b2d 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -47,14 +47,13 @@ static int dsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 0}; static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; static int nonblock_open; -static int boot_devs; MODULE_AUTHOR("Jaroslav Kysela , Abramo Bagnara "); MODULE_DESCRIPTION("PCM OSS emulation for ALSA."); MODULE_LICENSE("GPL"); -module_param_array(dsp_map, int, boot_devs, 0444); +module_param_array(dsp_map, int, NULL, 0444); MODULE_PARM_DESC(dsp_map, "PCM device number assigned to 1st OSS device."); -module_param_array(adsp_map, int, boot_devs, 0444); +module_param_array(adsp_map, int, NULL, 0444); MODULE_PARM_DESC(adsp_map, "PCM device number assigned to 2nd OSS device."); module_param(nonblock_open, bool, 0644); MODULE_PARM_DESC(nonblock_open, "Don't block opening busy PCM devices."); diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 1c753cda66f4..6c7609329bc0 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -42,10 +42,9 @@ MODULE_LICENSE("GPL"); #ifdef CONFIG_SND_OSSEMUL static int midi_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 0}; static int amidi_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; -static int boot_devs; -module_param_array(midi_map, int, boot_devs, 0444); +module_param_array(midi_map, int, NULL, 0444); MODULE_PARM_DESC(midi_map, "Raw MIDI device number assigned to 1st OSS device."); -module_param_array(amidi_map, int, boot_devs, 0444); +module_param_array(amidi_map, int, NULL, 0444); MODULE_PARM_DESC(amidi_map, "Raw MIDI device number assigned to 2nd OSS device."); #endif /* CONFIG_SND_OSSEMUL */ diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c index f8d629362db3..fd51a3e45c41 100644 --- a/sound/core/seq/seq.c +++ b/sound/core/seq/seq.c @@ -51,8 +51,7 @@ MODULE_AUTHOR("Frank van de Pol , Jaroslav Kysela io_port + ESSIO_REG_##x) diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index e97a7e8d7a37..9a4bc82cef32 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -135,28 +135,27 @@ static int enable_mpu[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; #ifdef SUPPORT_JOYSTICK static int joystick[SNDRV_CARDS]; #endif -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); -module_param_array(total_bufsize, int, boot_devs, 0444); +module_param_array(total_bufsize, int, NULL, 0444); MODULE_PARM_DESC(total_bufsize, "Total buffer size in kB."); -module_param_array(pcm_substreams_p, int, boot_devs, 0444); +module_param_array(pcm_substreams_p, int, NULL, 0444); MODULE_PARM_DESC(pcm_substreams_p, "PCM Playback substreams for " CARD_NAME " soundcard."); -module_param_array(pcm_substreams_c, int, boot_devs, 0444); +module_param_array(pcm_substreams_c, int, NULL, 0444); MODULE_PARM_DESC(pcm_substreams_c, "PCM Capture substreams for " CARD_NAME " soundcard."); -module_param_array(clock, int, boot_devs, 0444); +module_param_array(clock, int, NULL, 0444); MODULE_PARM_DESC(clock, "Clock on " CARD_NAME " soundcard. (0 = auto-detect)"); -module_param_array(use_pm, int, boot_devs, 0444); +module_param_array(use_pm, int, NULL, 0444); MODULE_PARM_DESC(use_pm, "Toggle power-management. (0 = off, 1 = on, 2 = auto)"); -module_param_array(enable_mpu, int, boot_devs, 0444); +module_param_array(enable_mpu, int, NULL, 0444); MODULE_PARM_DESC(enable_mpu, "Enable MPU401. (0 = off, 1 = on, 2 = auto)"); #ifdef SUPPORT_JOYSTICK -module_param_array(joystick, bool, boot_devs, 0444); +module_param_array(joystick, bool, NULL, 0444); MODULE_PARM_DESC(joystick, "Enable joystick."); #endif diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 9a0e1580b58e..2f19d7601da2 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -57,15 +57,14 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card * * High 16-bits are video (radio) device number + 1 */ static int tea575x_tuner[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for the FM801 soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for the FM801 soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable FM801 soundcard."); -module_param_array(tea575x_tuner, bool, boot_devs, 0444); +module_param_array(tea575x_tuner, bool, NULL, 0444); MODULE_PARM_DESC(tea575x_tuner, "Enable TEA575x tuner."); /* diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 194dc5431c38..b481e4439737 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -86,19 +86,18 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card static char *model[SNDRV_CARDS]; static int omni[SNDRV_CARDS]; /* Delta44 & 66 Omni I/O support */ static int cs8427_timeout[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 500}; /* CS8427 S/PDIF transciever reset timeout value in msec */ -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for ICE1712 soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for ICE1712 soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable ICE1712 soundcard."); -module_param_array(omni, bool, boot_devs, 0444); +module_param_array(omni, bool, NULL, 0444); MODULE_PARM_DESC(omni, "Enable Midiman M-Audio Delta Omni I/O support."); -module_param_array(cs8427_timeout, int, boot_devs, 0444); +module_param_array(cs8427_timeout, int, NULL, 0444); MODULE_PARM_DESC(cs8427_timeout, "Define reset timeout for cs8427 chip in msec resolution."); -module_param_array(model, charp, boot_devs, 0444); +module_param_array(model, charp, NULL, 0444); MODULE_PARM_DESC(model, "Use the given board model."); #ifndef PCI_VENDOR_ID_ICE diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 0fa7e8a033b0..058ee208dc2d 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -81,26 +81,25 @@ static int joystick[SNDRV_CARDS]; #ifdef SUPPORT_MIDI static int mpu_port[SNDRV_CARDS]; /* disabled */ #endif -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for Intel i8x0 soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable Intel i8x0 soundcard."); -module_param_array(ac97_clock, int, boot_devs, 0444); +module_param_array(ac97_clock, int, NULL, 0444); MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect)."); -module_param_array(ac97_quirk, int, boot_devs, 0444); +module_param_array(ac97_quirk, int, NULL, 0444); MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); -module_param_array(buggy_irq, bool, boot_devs, 0444); +module_param_array(buggy_irq, bool, NULL, 0444); MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards."); #ifdef SUPPORT_JOYSTICK -module_param_array(joystick, bool, boot_devs, 0444); +module_param_array(joystick, bool, NULL, 0444); MODULE_PARM_DESC(joystick, "Enable joystick for Intel i8x0 soundcard."); #endif #ifdef SUPPORT_MIDI -module_param_array(mpu_port, int, boot_devs, 0444); +module_param_array(mpu_port, int, NULL, 0444); MODULE_PARM_DESC(mpu_port, "MPU401 port # for Intel i8x0 driver."); #endif diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index a9b3175477d4..0cb2e40eaa74 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -55,15 +55,14 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Intel i8x0 modemcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for Intel i8x0 modemcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable Intel i8x0 modemcard."); -module_param_array(ac97_clock, int, boot_devs, 0444); +module_param_array(ac97_clock, int, NULL, 0444); MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect)."); /* diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index c04462fd16c3..5de1f7dca033 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -410,13 +410,12 @@ MODULE_SUPPORTED_DEVICE("{{KORG,korg1212}}"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Korg 1212 soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for Korg 1212 soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable Korg 1212 soundcard."); MODULE_AUTHOR("Haroldo Gamal "); diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 8cf0e185df73..4b3d2b4c0e2b 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -62,17 +62,16 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* all enabled */ static int external_amp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; static int amp_gpio[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable this soundcard."); -module_param_array(external_amp, bool, boot_devs, 0444); +module_param_array(external_amp, bool, NULL, 0444); MODULE_PARM_DESC(external_amp, "Enable external amp for " CARD_NAME " soundcard."); -module_param_array(amp_gpio, int, boot_devs, 0444); +module_param_array(amp_gpio, int, NULL, 0444); MODULE_PARM_DESC(amp_gpio, "GPIO pin number for external amp. (default = -1)"); #define MAX_PLAYBACKS 2 diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 9dff42a19867..0b773012bbc0 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -47,13 +47,12 @@ MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Digigram " CARD_NAME " soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for Digigram " CARD_NAME " soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard."); /* diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index e65e7de31f26..578b7f1acf9d 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -61,25 +61,24 @@ static int force_ac97[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* disable static int buffer_top[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* not specified */ static int use_cache[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* disabled */ static int vaio_hack[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* disabled */ -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable this soundcard."); -module_param_array(playback_bufsize, int, boot_devs, 0444); +module_param_array(playback_bufsize, int, NULL, 0444); MODULE_PARM_DESC(playback_bufsize, "DAC frame size in kB for " CARD_NAME " soundcard."); -module_param_array(capture_bufsize, int, boot_devs, 0444); +module_param_array(capture_bufsize, int, NULL, 0444); MODULE_PARM_DESC(capture_bufsize, "ADC frame size in kB for " CARD_NAME " soundcard."); -module_param_array(force_ac97, bool, boot_devs, 0444); +module_param_array(force_ac97, bool, NULL, 0444); MODULE_PARM_DESC(force_ac97, "Force to use AC97 codec for " CARD_NAME " soundcard."); -module_param_array(buffer_top, int, boot_devs, 0444); +module_param_array(buffer_top, int, NULL, 0444); MODULE_PARM_DESC(buffer_top, "Set the top address of audio buffer for " CARD_NAME " soundcard."); -module_param_array(use_cache, bool, boot_devs, 0444); +module_param_array(use_cache, bool, NULL, 0444); MODULE_PARM_DESC(use_cache, "Enable the cache for coefficient table access."); -module_param_array(vaio_hack, bool, boot_devs, 0444); +module_param_array(vaio_hack, bool, NULL, 0444); MODULE_PARM_DESC(vaio_hack, "Enable workaround for Sony VAIO notebooks."); /* diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index ddc8695cbb74..583f4452edb5 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -92,15 +92,14 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ static int fullduplex[SNDRV_CARDS]; // = {[0 ... (SNDRV_CARDS - 1)] = 1}; -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for RME Digi32 soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for RME Digi32 soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable RME Digi32 soundcard."); -module_param_array(fullduplex, bool, boot_devs, 0444); +module_param_array(fullduplex, bool, NULL, 0444); MODULE_PARM_DESC(fullduplex, "Support full-duplex mode."); MODULE_AUTHOR("Martin Langer , Pilo Chambert "); MODULE_DESCRIPTION("RME Digi32, Digi32/8, Digi32 PRO"); diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index a2c59b948188..56d47fd411cb 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -48,17 +48,16 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ static int precise_ptr[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* Enable precise pointer */ static int line_outs_monitor[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0}; /* Send all inputs/playback to line outs */ -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for RME Hammerfall DSP interface."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable/disable specific Hammerfall DSP soundcards."); -module_param_array(precise_ptr, bool, boot_devs, 0444); +module_param_array(precise_ptr, bool, NULL, 0444); MODULE_PARM_DESC(precise_ptr, "Enable precise pointer (doesn't work reliably)."); -module_param_array(line_outs_monitor, bool, boot_devs, 0444); +module_param_array(line_outs_monitor, bool, NULL, 0444); MODULE_PARM_DESC(line_outs_monitor, "Send all input and playback streams to line outs by default."); MODULE_AUTHOR("Paul Davis , Marcus Andersson, Thomas Charbonnel "); MODULE_DESCRIPTION("RME Hammerfall DSP"); diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index c6cbccce4430..3a34039dc286 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -42,15 +42,14 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ static int precise_ptr[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* Enable precise pointer */ -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for RME Digi9652 (Hammerfall) soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for RME Digi9652 (Hammerfall) soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable/disable specific RME96{52,36} soundcards."); -module_param_array(precise_ptr, bool, boot_devs, 0444); +module_param_array(precise_ptr, bool, NULL, 0444); MODULE_PARM_DESC(precise_ptr, "Enable precise pointer (doesn't work reliably)."); MODULE_AUTHOR("Paul Davis , Winfried Ritsch"); MODULE_DESCRIPTION("RME Digi9652/Digi9636"); diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index bb6802714fce..54e6c20d3f3b 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -59,17 +59,16 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card * static int reverb[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; static int mge[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; static unsigned int dmaio = 0x7a00; /* DDMA i/o address */ -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for S3 SonicVibes soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for S3 SonicVibes soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable S3 SonicVibes soundcard."); -module_param_array(reverb, bool, boot_devs, 0444); +module_param_array(reverb, bool, NULL, 0444); MODULE_PARM_DESC(reverb, "Enable reverb (SRAM is present) for S3 SonicVibes soundcard."); -module_param_array(mge, bool, boot_devs, 0444); +module_param_array(mge, bool, NULL, 0444); MODULE_PARM_DESC(mge, "MIC Gain Enable for S3 SonicVibes soundcard."); module_param(dmaio, uint, 0444); MODULE_PARM_DESC(dmaio, "DDMA i/o base address for S3 SonicVibes soundcard."); diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index f68d3a3728aa..8304190f855c 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c @@ -51,17 +51,16 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 32}; static int wavetable_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8192}; -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Trident 4DWave PCI soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for Trident 4DWave PCI soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable Trident 4DWave PCI soundcard."); -module_param_array(pcm_channels, int, boot_devs, 0444); +module_param_array(pcm_channels, int, NULL, 0444); MODULE_PARM_DESC(pcm_channels, "Number of hardware channels assigned for PCM."); -module_param_array(wavetable_size, int, boot_devs, 0444); +module_param_array(wavetable_size, int, NULL, 0444); MODULE_PARM_DESC(wavetable_size, "Maximum memory size in kB for wavetable synth."); static struct pci_device_id snd_trident_ids[] = { diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index fb549ea9eec9..1599be5598e5 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -83,25 +83,24 @@ static int joystick[SNDRV_CARDS]; static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 48000}; static int ac97_quirk[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = AC97_TUNE_DEFAULT}; static int dxs_support[SNDRV_CARDS]; -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for VIA 82xx bridge."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for VIA 82xx bridge."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable audio part of VIA 82xx bridge."); -module_param_array(mpu_port, long, boot_devs, 0444); +module_param_array(mpu_port, long, NULL, 0444); MODULE_PARM_DESC(mpu_port, "MPU-401 port. (VT82C686x only)"); #ifdef SUPPORT_JOYSTICK -module_param_array(joystick, bool, boot_devs, 0444); +module_param_array(joystick, bool, NULL, 0444); MODULE_PARM_DESC(joystick, "Enable joystick. (VT82C686x only)"); #endif -module_param_array(ac97_clock, int, boot_devs, 0444); +module_param_array(ac97_clock, int, NULL, 0444); MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); -module_param_array(ac97_quirk, int, boot_devs, 0444); +module_param_array(ac97_quirk, int, NULL, 0444); MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); -module_param_array(dxs_support, int, boot_devs, 0444); +module_param_array(dxs_support, int, NULL, 0444); MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA)"); diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index 4dd658d42e99..e4e64a88a52f 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c @@ -40,17 +40,16 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ static int mic[SNDRV_CARDS]; /* microphone */ static int ibl[SNDRV_CARDS]; /* microphone */ -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Digigram " CARD_NAME " soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for Digigram " CARD_NAME " soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard."); -module_param_array(mic, bool, boot_devs, 0444); +module_param_array(mic, bool, NULL, 0444); MODULE_PARM_DESC(mic, "Enable Microphone."); -module_param_array(ibl, int, boot_devs, 0444); +module_param_array(ibl, int, NULL, 0444); MODULE_PARM_DESC(ibl, "Capture IBL size."); /* diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 4440e1df6b26..a4afa4b694e1 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c @@ -49,23 +49,22 @@ static long mpu_port[SNDRV_CARDS]; static long joystick_port[SNDRV_CARDS]; #endif static int rear_switch[SNDRV_CARDS]; -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for the Yamaha DS-XG PCI soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for the Yamaha DS-XG PCI soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable Yamaha DS-XG soundcard."); -module_param_array(mpu_port, long, boot_devs, 0444); +module_param_array(mpu_port, long, NULL, 0444); MODULE_PARM_DESC(mpu_port, "MPU-401 Port."); -module_param_array(fm_port, long, boot_devs, 0444); +module_param_array(fm_port, long, NULL, 0444); MODULE_PARM_DESC(fm_port, "FM OPL-3 Port."); #ifdef SUPPORT_JOYSTICK -module_param_array(joystick_port, long, boot_devs, 0444); +module_param_array(joystick_port, long, NULL, 0444); MODULE_PARM_DESC(joystick_port, "Joystick port address"); #endif -module_param_array(rear_switch, bool, boot_devs, 0444); +module_param_array(rear_switch, bool, NULL, 0444); MODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch"); static struct pci_device_id snd_ymfpci_ids[] = { diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 1eb9e54fe1d3..0434acf1f75a 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -44,17 +44,16 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */ static unsigned int irq_mask = 0xffff; static int irq_list[4] = { -1 }; -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); module_param(irq_mask, int, 0444); MODULE_PARM_DESC(irq_mask, "IRQ bitmask for " CARD_NAME " soundcard."); -module_param_array(irq_list, int, boot_devs, 0444); +module_param_array(irq_list, int, NULL, 0444); MODULE_PARM_DESC(irq_list, "List of Available interrupts for " CARD_NAME " soundcard."); diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 27608e4c6958..63aebb2b07f2 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c @@ -58,19 +58,18 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */ static unsigned int irq_mask = 0xffff; static int irq_list[4] = { -1 }; static int ibl[SNDRV_CARDS]; -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); module_param(irq_mask, int, 0444); MODULE_PARM_DESC(irq_mask, "IRQ bitmask for " CARD_NAME " soundcard."); -module_param_array(irq_list, int, boot_devs, 0444); +module_param_array(irq_list, int, NULL, 0444); MODULE_PARM_DESC(irq_list, "List of Available interrupts for " CARD_NAME " soundcard."); -module_param_array(ibl, int, boot_devs, 0444); +module_param_array(ibl, int, NULL, 0444); MODULE_PARM_DESC(ibl, "Capture IBL size for " CARD_NAME " soundcard."); diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index aa14c340dadd..bd8a850e93ea 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c @@ -50,13 +50,12 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Sun AMD7930 soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for Sun AMD7930 soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable Sun AMD7930 soundcard."); MODULE_AUTHOR("Thomas K. Dyas and David S. Miller"); MODULE_DESCRIPTION("Sun AMD7930"); diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index f084dc1211a8..9806b60367bb 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -49,13 +49,12 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Sun CS4231 soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for Sun CS4231 soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable Sun CS4231 soundcard."); MODULE_AUTHOR("Jaroslav Kysela, Derrick J. Brashear and David S. Miller"); MODULE_DESCRIPTION("Sun CS4231"); diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 1f3548c5d9b1..94a84b643468 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -68,17 +68,16 @@ static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Vendor ID for static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Product ID for this card */ static int nrpacks = 4; /* max. number of packets per urb */ static int async_unlink = 1; -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for the USB audio adapter."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for the USB audio adapter."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable USB audio adapter."); -module_param_array(vid, int, boot_devs, 0444); +module_param_array(vid, int, NULL, 0444); MODULE_PARM_DESC(vid, "Vendor ID for the USB audio device."); -module_param_array(pid, int, boot_devs, 0444); +module_param_array(pid, int, NULL, 0444); MODULE_PARM_DESC(pid, "Product ID for the USB audio device."); module_param(nrpacks, int, 0444); MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB."); diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index 44a73816ff19..269d7fd9e560 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c @@ -122,13 +122,12 @@ MODULE_SUPPORTED_DEVICE("{{TASCAM(0x1604), "NAME_ALLCAPS"(0x8001)(0x8005)(0x8007 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for "NAME_ALLCAPS"."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for "NAME_ALLCAPS"."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS"."); -- cgit v1.2.3 From a497f5c2ae5db510df44b7957ca4a9fa8e8d8044 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 19 Oct 2004 18:14:40 -0700 Subject: [PATCH] remove dead exports from fs/fat/ These were used by the defunct umsdos code only. Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fat/dir.c | 8 ++++++-- fs/fat/fatfs_syms.c | 9 --------- fs/fat/inode.c | 11 +++++++---- include/linux/msdos_fs.h | 8 -------- 4 files changed, 13 insertions(+), 23 deletions(-) (limited to 'include/linux') diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 993d50c0db39..184cdc0a30d7 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -22,6 +22,10 @@ #include +static int fat_dir_ioctl(struct inode * inode, struct file * filp, + unsigned int cmd, unsigned long arg); +static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir); + struct file_operations fat_dir_operations = { .read = generic_read_dir, .readdir = fat_readdir, @@ -567,7 +571,7 @@ out: return ret; } -int fat_readdir(struct file *filp, void *dirent, filldir_t filldir) +static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir) { struct inode *inode = filp->f_dentry->d_inode; return fat_readdirx(inode, filp, dirent, filldir, 0, 0); @@ -624,7 +628,7 @@ efault: return -EFAULT; } -int fat_dir_ioctl(struct inode * inode, struct file * filp, +static int fat_dir_ioctl(struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg) { struct fat_ioctl_filldir_callback buf; diff --git a/fs/fat/fatfs_syms.c b/fs/fat/fatfs_syms.c index aba880e20123..6df55e272d1c 100644 --- a/fs/fat/fatfs_syms.c +++ b/fs/fat/fatfs_syms.c @@ -12,26 +12,17 @@ #include EXPORT_SYMBOL(fat_new_dir); -EXPORT_SYMBOL(fat_get_block); -EXPORT_SYMBOL(fat_clear_inode); EXPORT_SYMBOL(fat_date_unix2dos); -EXPORT_SYMBOL(fat_delete_inode); EXPORT_SYMBOL(fat__get_entry); EXPORT_SYMBOL(fat_notify_change); -EXPORT_SYMBOL(fat_put_super); EXPORT_SYMBOL(fat_attach); EXPORT_SYMBOL(fat_detach); EXPORT_SYMBOL(fat_build_inode); EXPORT_SYMBOL(fat_fill_super); EXPORT_SYMBOL(fat_search_long); -EXPORT_SYMBOL(fat_readdir); EXPORT_SYMBOL(fat_scan); -EXPORT_SYMBOL(fat_statfs); -EXPORT_SYMBOL(fat_write_inode); -EXPORT_SYMBOL(fat_dir_ioctl); EXPORT_SYMBOL(fat_add_entries); EXPORT_SYMBOL(fat_dir_empty); -EXPORT_SYMBOL(fat_truncate); int __init fat_init_inodecache(void); void __exit fat_destroy_inodecache(void); diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 88368130e798..a3a6e08f36a4 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -31,6 +31,9 @@ static int fat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE; static char fat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET; +static int fat_statfs(struct super_block *sb, struct kstatfs *buf); +static void fat_write_inode(struct inode *inode, int wait); + /* * New FAT inode stuff. We do the following: * a) i_ino is constant and has nothing with on-disk location. @@ -143,7 +146,7 @@ out: return inode; } -void fat_delete_inode(struct inode *inode) +static void fat_delete_inode(struct inode *inode) { if (!is_bad_inode(inode)) { inode->i_size = 0; @@ -152,7 +155,7 @@ void fat_delete_inode(struct inode *inode) clear_inode(inode); } -void fat_clear_inode(struct inode *inode) +static void fat_clear_inode(struct inode *inode) { if (is_bad_inode(inode)) return; @@ -164,7 +167,7 @@ void fat_clear_inode(struct inode *inode) unlock_kernel(); } -void fat_put_super(struct super_block *sb) +static void fat_put_super(struct super_block *sb) { struct msdos_sb_info *sbi = MSDOS_SB(sb); @@ -1072,7 +1075,7 @@ out_fail: return error; } -int fat_statfs(struct super_block *sb, struct kstatfs *buf) +static int fat_statfs(struct super_block *sb, struct kstatfs *buf) { int free, nr, ret; diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h index d35fe747bd94..812b01fe3bbe 100644 --- a/include/linux/msdos_fs.h +++ b/include/linux/msdos_fs.h @@ -244,9 +244,6 @@ extern struct file_operations fat_dir_operations; extern int fat_search_long(struct inode *inode, const unsigned char *name, int name_len, int anycase, loff_t *spos, loff_t *lpos); -extern int fat_readdir(struct file *filp, void *dirent, filldir_t filldir); -extern int fat_dir_ioctl(struct inode * inode, struct file * filp, - unsigned int cmd, unsigned long arg); extern int fat_add_entries(struct inode *dir, int slots, struct buffer_head **bh, struct msdos_dir_entry **de, loff_t *i_pos); extern int fat_new_dir(struct inode *dir, struct inode *parent, int is_vfat); @@ -270,13 +267,8 @@ extern void fat_detach(struct inode *inode); extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos); extern struct inode *fat_build_inode(struct super_block *sb, struct msdos_dir_entry *de, loff_t i_pos, int *res); -extern void fat_delete_inode(struct inode *inode); -extern void fat_clear_inode(struct inode *inode); -extern void fat_put_super(struct super_block *sb); int fat_fill_super(struct super_block *sb, void *data, int silent, struct inode_operations *fs_dir_inode_ops, int isvfat); -extern int fat_statfs(struct super_block *sb, struct kstatfs *buf); -extern int fat_write_inode(struct inode *inode, int wait); extern int fat_notify_change(struct dentry * dentry, struct iattr * attr); /* fat/misc.c */ -- cgit v1.2.3 From 13f17cb5b700b2aa5ee54c8d6e248ccc97ce3511 Mon Sep 17 00:00:00 2001 From: Hirofumi Ogawa Date: Tue, 19 Oct 2004 18:14:52 -0700 Subject: [PATCH] FAT: use hlist_head for fat_inode_hashtable Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fat/inode.c | 22 ++++++++++------------ include/linux/msdos_fs_i.h | 2 +- 2 files changed, 11 insertions(+), 13 deletions(-) (limited to 'include/linux') diff --git a/fs/fat/inode.c b/fs/fat/inode.c index a3a6e08f36a4..ba3b68ebea68 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -61,15 +61,14 @@ static void fat_write_inode(struct inode *inode, int wait); #define FAT_HASH_BITS 8 #define FAT_HASH_SIZE (1UL << FAT_HASH_BITS) #define FAT_HASH_MASK (FAT_HASH_SIZE-1) -static struct list_head fat_inode_hashtable[FAT_HASH_SIZE]; +static struct hlist_head fat_inode_hashtable[FAT_HASH_SIZE]; static spinlock_t fat_inode_lock = SPIN_LOCK_UNLOCKED; void fat_hash_init(void) { int i; - for(i = 0; i < FAT_HASH_SIZE; i++) { - INIT_LIST_HEAD(&fat_inode_hashtable[i]); - } + for (i = 0; i < FAT_HASH_SIZE; i++) + INIT_HLIST_HEAD(&fat_inode_hashtable[i]); } static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos) @@ -83,7 +82,7 @@ void fat_attach(struct inode *inode, loff_t i_pos) { spin_lock(&fat_inode_lock); MSDOS_I(inode)->i_pos = i_pos; - list_add(&MSDOS_I(inode)->i_fat_hash, + hlist_add_head(&MSDOS_I(inode)->i_fat_hash, fat_inode_hashtable + fat_hash(inode->i_sb, i_pos)); spin_unlock(&fat_inode_lock); } @@ -92,20 +91,19 @@ void fat_detach(struct inode *inode) { spin_lock(&fat_inode_lock); MSDOS_I(inode)->i_pos = 0; - list_del_init(&MSDOS_I(inode)->i_fat_hash); + hlist_del_init(&MSDOS_I(inode)->i_fat_hash); spin_unlock(&fat_inode_lock); } struct inode *fat_iget(struct super_block *sb, loff_t i_pos) { - struct list_head *p = fat_inode_hashtable + fat_hash(sb, i_pos); - struct list_head *walk; + struct hlist_head *head = fat_inode_hashtable + fat_hash(sb, i_pos); + struct hlist_node *_p; struct msdos_inode_info *i; struct inode *inode = NULL; spin_lock(&fat_inode_lock); - list_for_each(walk, p) { - i = list_entry(walk, struct msdos_inode_info, i_fat_hash); + hlist_for_each_entry(i, _p, head, i_fat_hash) { if (i->vfs_inode.i_sb != sb) continue; if (i->i_pos != i_pos) @@ -162,7 +160,7 @@ static void fat_clear_inode(struct inode *inode) lock_kernel(); spin_lock(&fat_inode_lock); fat_cache_inval_inode(inode); - list_del_init(&MSDOS_I(inode)->i_fat_hash); + hlist_del_init(&MSDOS_I(inode)->i_fat_hash); spin_unlock(&fat_inode_lock); unlock_kernel(); } @@ -738,7 +736,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) { - INIT_LIST_HEAD(&ei->i_fat_hash); + INIT_HLIST_NODE(&ei->i_fat_hash); inode_init_once(&ei->vfs_inode); } } diff --git a/include/linux/msdos_fs_i.h b/include/linux/msdos_fs_i.h index f2383d22a831..13717b437be0 100644 --- a/include/linux/msdos_fs_i.h +++ b/include/linux/msdos_fs_i.h @@ -18,7 +18,7 @@ struct msdos_inode_info { int i_attrs; /* unused attribute bits */ int i_ctime_ms; /* unused change time in milliseconds */ loff_t i_pos; /* on-disk position of directory entry or 0 */ - struct list_head i_fat_hash; /* hash by i_location */ + struct hlist_node i_fat_hash; /* hash by i_location */ struct inode vfs_inode; }; -- cgit v1.2.3 From f93a17341607ea8e03c047ca123871989b1da280 Mon Sep 17 00:00:00 2001 From: Hirofumi Ogawa Date: Tue, 19 Oct 2004 18:15:04 -0700 Subject: [PATCH] FAT: rewrite the cache for file allocation table lookup This rewrites the cache stuff for file allocation table (FAT). This cache stocks the more pieces of FAT-chain by counting the number of contiguous data blocks. And if cache hit, since a block number can calculate without looking FAT-chain up, fat_get_block() become more fast. But if data blocks was fragmenting, unfortunately this cache is unuseful. read from block device [1st]# time dd if=/dev/hda6 of=/dev/null bs=1M count=2048 2147483648 bytes transferred in 229.524189 seconds (9356241 bytes/sec) real 3m49.557s, user 0m0.026s, sys 1m20.414s [2nd]# time dd if=/dev/hda6 of=/dev/null bs=1M count=2048 2147483648 bytes transferred in 229.539358 seconds (9355623 bytes/sec) real 3m49.647s, user 0m0.036s, sys 1m20.144s read from full contiguous file with this patch [1st]# time dd if=data of=/dev/null bs=1M count=2048 2147483648 bytes transferred in 337.959477 seconds (6354264 bytes/sec) real 5m37.970s, user 0m0.031s, sys 1m21.915s [2nd]# time dd if=data of=/dev/null bs=1M count=2048 2147483648 bytes transferred in 225.401699 seconds (9527362 bytes/sec) real 3m45.476s, user 0m0.027s, sys 1m19.286s read from full fragmented file with this patch [1st]# time dd if=data of=/dev/null bs=1M count=2048 2147483647 bytes transferred in 1146.529081 seconds (1873030 bytes/sec) real 19m6.538s, user 0m0.020s, sys 1m32.774s [2nd]# time dd if=data of=/dev/null bs=1M count=2048 2147483647 bytes transferred in 1045.084822 seconds (2054841 bytes/sec) real 17m25.152s, user 0m0.022s, sys 1m34.801s read from full contiguous file without this patch [1st]# time dd if=data of=/dev/null bs=1M count=2048 2147483648 bytes transferred in 348.144707 seconds (6168365 bytes/sec) real 5m48.169s, user 0m0.019s, sys 1m29.962s [2nd]# time dd if=data of=/dev/null bs=1M count=2048 2147483648 bytes transferred in 324.017361 seconds (6627681 bytes/sec) real 5m24.038s, user 0m0.023s, sys 1m20.602s read from full fragmented file without this patch [1st]# time dd if=data of=/dev/null bs=1M count=2048 2147483647 bytes transferred in 1156.845693 seconds (1856327 bytes/sec) real 19m16.855s, user 0m0.031s, sys 1m32.172s [2nd]# time dd if=data of=/dev/null bs=1M count=2048 2147483647 bytes transferred in 1066.518713 seconds (2013545 bytes/sec) real 17m46.526s, user 0m0.023s, sys 1m33.630s Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fat/cache.c | 370 +++++++++++++++++++++++++------------------- fs/fat/fatfs_syms.c | 7 + fs/fat/inode.c | 6 +- fs/fat/misc.c | 2 +- include/linux/msdos_fs.h | 2 - include/linux/msdos_fs_i.h | 5 +- include/linux/msdos_fs_sb.h | 10 -- 7 files changed, 226 insertions(+), 176 deletions(-) (limited to 'include/linux') diff --git a/fs/fat/cache.c b/fs/fat/cache.c index ad8ff5fc6e08..d40566b7a31a 100644 --- a/fs/fat/cache.c +++ b/fs/fat/cache.c @@ -12,6 +12,204 @@ #include #include +#if 0 +#define debug_pr(fmt, args...) printk(fmt, ##args) +#else +#define debug_pr(fmt, args...) +#endif + +/* this must be > 0. */ +#define FAT_MAX_CACHE 8 + +struct fat_cache { + struct list_head cache_list; + int nr_contig; /* number of contiguous clusters */ + int fcluster; /* cluster number in the file. */ + int dcluster; /* cluster number on disk. */ +}; + +static inline int fat_max_cache(struct inode *inode) +{ + return FAT_MAX_CACHE; +} + +static kmem_cache_t *fat_cache_cachep; + +static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags) +{ + struct fat_cache *cache = (struct fat_cache *)foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == + SLAB_CTOR_CONSTRUCTOR) + INIT_LIST_HEAD(&cache->cache_list); +} + +int __init fat_cache_init(void) +{ + fat_cache_cachep = kmem_cache_create("fat_cache", + sizeof(struct fat_cache), + 0, SLAB_RECLAIM_ACCOUNT, + init_once, NULL); + if (fat_cache_cachep == NULL) + return -ENOMEM; + return 0; +} + +void __exit fat_cache_destroy(void) +{ + if (kmem_cache_destroy(fat_cache_cachep)) + printk(KERN_INFO "fat_cache: not all structures were freed\n"); +} + +static inline struct fat_cache *fat_cache_alloc(struct inode *inode) +{ + return kmem_cache_alloc(fat_cache_cachep, SLAB_KERNEL); +} + +static inline void fat_cache_free(struct fat_cache *cache) +{ + BUG_ON(!list_empty(&cache->cache_list)); + kmem_cache_free(fat_cache_cachep, cache); +} + +static inline void fat_cache_update_lru(struct inode *inode, + struct fat_cache *cache) +{ + if (MSDOS_I(inode)->cache_lru.next != &cache->cache_list) + list_move(&cache->cache_list, &MSDOS_I(inode)->cache_lru); +} + +static int fat_cache_lookup(struct inode *inode, int fclus, + struct fat_cache *cache, + int *cached_fclus, int *cached_dclus) +{ + static struct fat_cache nohit = { .fcluster = 0, }; + + struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); + struct fat_cache *hit = &nohit, *p; + int offset = -1; + + spin_lock(&sbi->cache_lock); + debug_pr("FAT: %s, fclus %d", __FUNCTION__, fclus); + list_for_each_entry(p, &MSDOS_I(inode)->cache_lru, cache_list) { + if (p->fcluster <= fclus && hit->fcluster < p->fcluster) { + hit = p; + debug_pr(", fclus %d, dclus %d, cont %d", + p->fcluster, p->dcluster, p->nr_contig); + if ((hit->fcluster + hit->nr_contig) < fclus) { + offset = hit->nr_contig; + debug_pr(" (off %d, hit)", offset); + } else { + offset = fclus - hit->fcluster; + debug_pr(" (off %d, full hit)", offset); + break; + } + } + } + if (hit != &nohit) { + fat_cache_update_lru(inode, hit); + *cache = *hit; + *cached_fclus = cache->fcluster + offset; + *cached_dclus = cache->dcluster + offset; + } + debug_pr("\n"); + spin_unlock(&sbi->cache_lock); + + return offset; +} + +static struct fat_cache *fat_cache_merge(struct inode *inode, + struct fat_cache *new) +{ + struct fat_cache *p, *hit = NULL; + + list_for_each_entry(p, &MSDOS_I(inode)->cache_lru, cache_list) { + if (p->fcluster == new->fcluster) { + BUG_ON(p->dcluster != new->dcluster); + debug_pr("FAT: %s: merged fclus %d, dclus %d, " + "cur cont %d => new cont %d\n", __FUNCTION__, + p->fcluster, p->dcluster, p->nr_contig, + new->nr_contig); + if (new->nr_contig > p->nr_contig) + p->nr_contig = new->nr_contig; + hit = p; + break; + } + } + return hit; +} + +static void fat_cache_add(struct inode *inode, struct fat_cache *new) +{ + struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); + struct fat_cache *cache, *tmp; + + debug_pr("FAT: %s: fclus %d, dclus %d, cont %d\n", __FUNCTION__, + new->fcluster, new->dcluster, new->nr_contig); + + if (new->fcluster == -1) /* dummy cache */ + return; + + spin_lock(&sbi->cache_lock); + cache = fat_cache_merge(inode, new); + if (cache == NULL) { + if (MSDOS_I(inode)->nr_caches < fat_max_cache(inode)) { + MSDOS_I(inode)->nr_caches++; + spin_unlock(&sbi->cache_lock); + + tmp = fat_cache_alloc(inode); + spin_lock(&sbi->cache_lock); + cache = fat_cache_merge(inode, new); + if (cache != NULL) { + MSDOS_I(inode)->nr_caches--; + fat_cache_free(tmp); + goto out; + } + cache = tmp; + } else { + struct list_head *p = MSDOS_I(inode)->cache_lru.prev; + cache = list_entry(p, struct fat_cache, cache_list); + } + cache->fcluster = new->fcluster; + cache->dcluster = new->dcluster; + cache->nr_contig = new->nr_contig; + } +out: + fat_cache_update_lru(inode, cache); + + debug_pr("FAT: "); + list_for_each_entry(cache, &MSDOS_I(inode)->cache_lru, cache_list) { + debug_pr("(fclus %d, dclus %d, cont %d), ", + cache->fcluster, cache->dcluster, cache->nr_contig); + } + debug_pr("\n"); + spin_unlock(&sbi->cache_lock); +} + +/* + * Cache invalidation occurs rarely, thus the LRU chain is not updated. It + * fixes itself after a while. + */ +static void __fat_cache_inval_inode(struct inode *inode) +{ + struct msdos_inode_info *i = MSDOS_I(inode); + struct fat_cache *cache; + while (!list_empty(&i->cache_lru)) { + cache = list_entry(i->cache_lru.next, struct fat_cache, cache_list); + list_del_init(&cache->cache_list); + MSDOS_I(inode)->nr_caches--; + fat_cache_free(cache); + } + debug_pr("FAT: %s\n", __FUNCTION__); +} + +void fat_cache_inval_inode(struct inode *inode) +{ + spin_lock(&MSDOS_SB(inode->i_sb)->cache_lock); + __fat_cache_inval_inode(inode); + spin_unlock(&MSDOS_SB(inode->i_sb)->cache_lock); +} + int __fat_access(struct super_block *sb, int nr, int new_value) { struct msdos_sb_info *sbi = MSDOS_SB(sb); @@ -130,170 +328,24 @@ out: return next; } -void fat_cache_init(struct super_block *sb) +static inline int cache_contiguous(struct fat_cache *cache, int dclus) { - struct msdos_sb_info *sbi = MSDOS_SB(sb); - int count; - - spin_lock_init(&sbi->cache_lock); - - for (count = 0; count < FAT_CACHE_NR - 1; count++) { - sbi->cache_array[count].start_cluster = 0; - sbi->cache_array[count].next = &sbi->cache_array[count + 1]; - } - sbi->cache_array[count].start_cluster = 0; - sbi->cache_array[count].next = NULL; - sbi->cache = sbi->cache_array; + cache->nr_contig++; + return ((cache->dcluster + cache->nr_contig) == dclus); } -static void -fat_cache_lookup(struct inode *inode, int cluster, int *f_clu, int *d_clu) +static inline void cache_init(struct fat_cache *cache, int fclus, int dclus) { - struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); - struct fat_cache *walk; - int first; - - BUG_ON(cluster == 0); - - first = MSDOS_I(inode)->i_start; - if (!first) - return; - - spin_lock(&sbi->cache_lock); - - if (MSDOS_I(inode)->disk_cluster && - MSDOS_I(inode)->file_cluster <= cluster) { - *d_clu = MSDOS_I(inode)->disk_cluster; - *f_clu = MSDOS_I(inode)->file_cluster; - } - - for (walk = sbi->cache; walk; walk = walk->next) { - if (walk->start_cluster == first - && walk->file_cluster <= cluster - && walk->file_cluster > *f_clu) { - *d_clu = walk->disk_cluster; - *f_clu = walk->file_cluster; -#ifdef DEBUG - printk("cache hit: %d (%d)\n", *f_clu, *d_clu); -#endif - if (*f_clu == cluster) - goto out; - } - } -#ifdef DEBUG - printk("cache miss\n"); -#endif -out: - spin_unlock(&sbi->cache_lock); -} - -#ifdef DEBUG -static void list_cache(struct super_block *sb) -{ - struct msdos_sb_info *sbi = MSDOS_SB(sb); - struct fat_cache *walk; - - for (walk = sbi->cache; walk; walk = walk->next) { - if (walk->start_cluster) - printk("<%s,%d>(%d,%d) ", sb->s_id, - walk->start_cluster, walk->file_cluster, - walk->disk_cluster); - else - printk("-- "); - } - printk("\n"); -} -#endif - -/* - * Cache invalidation occurs rarely, thus the LRU chain is not updated. It - * fixes itself after a while. - */ -static void __fat_cache_inval_inode(struct inode *inode) -{ - struct fat_cache *walk; - int first = MSDOS_I(inode)->i_start; - MSDOS_I(inode)->file_cluster = MSDOS_I(inode)->disk_cluster = 0; - for (walk = MSDOS_SB(inode->i_sb)->cache; walk; walk = walk->next) - if (walk->start_cluster == first) - walk->start_cluster = 0; -} - -void fat_cache_inval_inode(struct inode *inode) -{ - struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); - spin_lock(&sbi->cache_lock); - __fat_cache_inval_inode(inode); - spin_unlock(&sbi->cache_lock); -} - -void fat_cache_add(struct inode *inode, int f_clu, int d_clu) -{ - struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); - struct fat_cache *walk, *last; - int first, prev_f_clu, prev_d_clu; - - if (f_clu == 0) - return; - first = MSDOS_I(inode)->i_start; - if (!first) - return; - - last = NULL; - spin_lock(&sbi->cache_lock); - - if (MSDOS_I(inode)->file_cluster == f_clu) - goto out; - else { - prev_f_clu = MSDOS_I(inode)->file_cluster; - prev_d_clu = MSDOS_I(inode)->disk_cluster; - MSDOS_I(inode)->file_cluster = f_clu; - MSDOS_I(inode)->disk_cluster = d_clu; - if (prev_f_clu == 0) - goto out; - f_clu = prev_f_clu; - d_clu = prev_d_clu; - } - - for (walk = sbi->cache; walk->next; walk = (last = walk)->next) { - if (walk->start_cluster == first && - walk->file_cluster == f_clu) { - if (walk->disk_cluster != d_clu) { - printk(KERN_ERR "FAT: cache corruption " - "(i_pos %lld)\n", MSDOS_I(inode)->i_pos); - __fat_cache_inval_inode(inode); - goto out; - } - if (last == NULL) - goto out; - - /* update LRU */ - last->next = walk->next; - walk->next = sbi->cache; - sbi->cache = walk; -#ifdef DEBUG - list_cache(); -#endif - goto out; - } - } - walk->start_cluster = first; - walk->file_cluster = f_clu; - walk->disk_cluster = d_clu; - last->next = NULL; - walk->next = sbi->cache; - sbi->cache = walk; -#ifdef DEBUG - list_cache(); -#endif -out: - spin_unlock(&sbi->cache_lock); + cache->fcluster = fclus; + cache->dcluster = dclus; + cache->nr_contig = 0; } int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus) { struct super_block *sb = inode->i_sb; const int limit = sb->s_maxbytes >> MSDOS_SB(sb)->cluster_bits; + struct fat_cache cache; int nr; BUG_ON(MSDOS_I(inode)->i_start == 0); @@ -303,7 +355,9 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus) if (cluster == 0) return 0; - fat_cache_lookup(inode, cluster, fclus, dclus); + if (fat_cache_lookup(inode, cluster, &cache, fclus, dclus) < 0) + cache_init(&cache, -1, -1); /* dummy, always not contiguous */ + while (*fclus < cluster) { /* prevent the infinite loop of cluster chain */ if (*fclus > limit) { @@ -322,13 +376,15 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus) MSDOS_I(inode)->i_pos); return -EIO; } else if (nr == FAT_ENT_EOF) { - fat_cache_add(inode, *fclus, *dclus); + fat_cache_add(inode, &cache); return FAT_ENT_EOF; } (*fclus)++; *dclus = nr; + if (!cache_contiguous(&cache, *dclus)) + cache_init(&cache, *fclus, *dclus); } - fat_cache_add(inode, *fclus, *dclus); + fat_cache_add(inode, &cache); return 0; } diff --git a/fs/fat/fatfs_syms.c b/fs/fat/fatfs_syms.c index 6df55e272d1c..1a260e440f33 100644 --- a/fs/fat/fatfs_syms.c +++ b/fs/fat/fatfs_syms.c @@ -24,16 +24,23 @@ EXPORT_SYMBOL(fat_scan); EXPORT_SYMBOL(fat_add_entries); EXPORT_SYMBOL(fat_dir_empty); +int __init fat_cache_init(void); +void __exit fat_cache_destroy(void); int __init fat_init_inodecache(void); void __exit fat_destroy_inodecache(void); static int __init init_fat_fs(void) { + int ret; fat_hash_init(); + ret = fat_cache_init(); + if (ret < 0) + return ret; return fat_init_inodecache(); } static void __exit exit_fat_fs(void) { + fat_cache_destroy(); fat_destroy_inodecache(); } diff --git a/fs/fat/inode.c b/fs/fat/inode.c index ba3b68ebea68..bff8173bc8af 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -533,7 +533,6 @@ static int fat_read_root(struct inode *inode) struct msdos_sb_info *sbi = MSDOS_SB(sb); int error; - MSDOS_I(inode)->file_cluster = MSDOS_I(inode)->disk_cluster = 0; MSDOS_I(inode)->i_pos = 0; inode->i_uid = sbi->options.fs_uid; inode->i_gid = sbi->options.fs_gid; @@ -736,6 +735,8 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) { + ei->nr_caches = 0; + INIT_LIST_HEAD(&ei->cache_lru); INIT_HLIST_NODE(&ei->i_fat_hash); inode_init_once(&ei->vfs_inode); } @@ -819,7 +820,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, if (error) goto out_fail; - fat_cache_init(sb); + spin_lock_init(&MSDOS_SB(sb)->cache_lock); /* set up enough so that it can read an inode */ init_MUTEX(&sbi->fat_lock); @@ -1164,7 +1165,6 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) struct msdos_sb_info *sbi = MSDOS_SB(sb); int error; - MSDOS_I(inode)->file_cluster = MSDOS_I(inode)->disk_cluster = 0; MSDOS_I(inode)->i_pos = 0; inode->i_uid = sbi->options.fs_uid; inode->i_gid = sbi->options.fs_gid; diff --git a/fs/fat/misc.c b/fs/fat/misc.c index 85a85ec5a8ce..69e2a3cc0efa 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c @@ -155,7 +155,7 @@ int fat_add_cluster(struct inode *inode) ret = fat_access(sb, last, new_dclus); if (ret < 0) return ret; - fat_cache_add(inode, new_fclus, new_dclus); +// fat_cache_add(inode, new_fclus, new_dclus); } else { MSDOS_I(inode)->i_start = new_dclus; MSDOS_I(inode)->i_logstart = new_dclus; diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h index 812b01fe3bbe..d1f429b41d4c 100644 --- a/include/linux/msdos_fs.h +++ b/include/linux/msdos_fs.h @@ -232,8 +232,6 @@ static inline void fatwchar_to16(__u8 *dst, const wchar_t *src, size_t len) extern int fat_access(struct super_block *sb, int nr, int new_value); extern int __fat_access(struct super_block *sb, int nr, int new_value); extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys); -extern void fat_cache_init(struct super_block *sb); -extern void fat_cache_add(struct inode *inode, int f_clu, int d_clu); extern void fat_cache_inval_inode(struct inode *inode); extern int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus); diff --git a/include/linux/msdos_fs_i.h b/include/linux/msdos_fs_i.h index 13717b437be0..a29b7d993e3f 100644 --- a/include/linux/msdos_fs_i.h +++ b/include/linux/msdos_fs_i.h @@ -8,9 +8,8 @@ */ struct msdos_inode_info { - /* cache of lastest accessed cluster */ - int file_cluster; /* cluster number in the file. */ - int disk_cluster; /* cluster number on disk. */ + struct list_head cache_lru; + int nr_caches; loff_t mmu_private; int i_start; /* first cluster or 0 */ diff --git a/include/linux/msdos_fs_sb.h b/include/linux/msdos_fs_sb.h index c79a172225d3..3c69d6f36075 100644 --- a/include/linux/msdos_fs_sb.h +++ b/include/linux/msdos_fs_sb.h @@ -26,15 +26,6 @@ struct fat_mount_options { nocase:1; /* Does this need case conversion? 0=need case conversion*/ }; -#define FAT_CACHE_NR 8 /* number of FAT cache */ - -struct fat_cache { - int start_cluster; /* first cluster of the chain. */ - int file_cluster; /* cluster number in the file. */ - int disk_cluster; /* cluster number on disk. */ - struct fat_cache *next; /* next cache entry */ -}; - struct msdos_sb_info { unsigned short sec_per_clus; /* sectors/cluster */ unsigned short cluster_bits; /* log2(cluster_size) */ @@ -59,7 +50,6 @@ struct msdos_sb_info { int dir_per_block_bits; /* log2(dir_per_block) */ spinlock_t cache_lock; - struct fat_cache cache_array[FAT_CACHE_NR], *cache; }; #endif -- cgit v1.2.3 From ec1528b041d7b412c646a51f4ca47f9223cd664d Mon Sep 17 00:00:00 2001 From: Hirofumi Ogawa Date: Tue, 19 Oct 2004 18:15:15 -0700 Subject: [PATCH] FAT: cache lock from per sb to per inode Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fat/cache.c | 18 ++++++++---------- fs/fat/inode.c | 2 +- include/linux/msdos_fs_i.h | 1 + include/linux/msdos_fs_sb.h | 2 -- 4 files changed, 10 insertions(+), 13 deletions(-) (limited to 'include/linux') diff --git a/fs/fat/cache.c b/fs/fat/cache.c index d40566b7a31a..72528f8fe315 100644 --- a/fs/fat/cache.c +++ b/fs/fat/cache.c @@ -85,11 +85,10 @@ static int fat_cache_lookup(struct inode *inode, int fclus, { static struct fat_cache nohit = { .fcluster = 0, }; - struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); struct fat_cache *hit = &nohit, *p; int offset = -1; - spin_lock(&sbi->cache_lock); + spin_lock(&MSDOS_I(inode)->cache_lru_lock); debug_pr("FAT: %s, fclus %d", __FUNCTION__, fclus); list_for_each_entry(p, &MSDOS_I(inode)->cache_lru, cache_list) { if (p->fcluster <= fclus && hit->fcluster < p->fcluster) { @@ -113,7 +112,7 @@ static int fat_cache_lookup(struct inode *inode, int fclus, *cached_dclus = cache->dcluster + offset; } debug_pr("\n"); - spin_unlock(&sbi->cache_lock); + spin_unlock(&MSDOS_I(inode)->cache_lru_lock); return offset; } @@ -141,7 +140,6 @@ static struct fat_cache *fat_cache_merge(struct inode *inode, static void fat_cache_add(struct inode *inode, struct fat_cache *new) { - struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); struct fat_cache *cache, *tmp; debug_pr("FAT: %s: fclus %d, dclus %d, cont %d\n", __FUNCTION__, @@ -150,15 +148,15 @@ static void fat_cache_add(struct inode *inode, struct fat_cache *new) if (new->fcluster == -1) /* dummy cache */ return; - spin_lock(&sbi->cache_lock); + spin_lock(&MSDOS_I(inode)->cache_lru_lock); cache = fat_cache_merge(inode, new); if (cache == NULL) { if (MSDOS_I(inode)->nr_caches < fat_max_cache(inode)) { MSDOS_I(inode)->nr_caches++; - spin_unlock(&sbi->cache_lock); + spin_unlock(&MSDOS_I(inode)->cache_lru_lock); tmp = fat_cache_alloc(inode); - spin_lock(&sbi->cache_lock); + spin_lock(&MSDOS_I(inode)->cache_lru_lock); cache = fat_cache_merge(inode, new); if (cache != NULL) { MSDOS_I(inode)->nr_caches--; @@ -183,7 +181,7 @@ out: cache->fcluster, cache->dcluster, cache->nr_contig); } debug_pr("\n"); - spin_unlock(&sbi->cache_lock); + spin_unlock(&MSDOS_I(inode)->cache_lru_lock); } /* @@ -205,9 +203,9 @@ static void __fat_cache_inval_inode(struct inode *inode) void fat_cache_inval_inode(struct inode *inode) { - spin_lock(&MSDOS_SB(inode->i_sb)->cache_lock); + spin_lock(&MSDOS_I(inode)->cache_lru_lock); __fat_cache_inval_inode(inode); - spin_unlock(&MSDOS_SB(inode->i_sb)->cache_lock); + spin_unlock(&MSDOS_I(inode)->cache_lru_lock); } int __fat_access(struct super_block *sb, int nr, int new_value) diff --git a/fs/fat/inode.c b/fs/fat/inode.c index bff8173bc8af..be0c0d5b434e 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -735,6 +735,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) { + spin_lock_init(&ei->cache_lru_lock); ei->nr_caches = 0; INIT_LIST_HEAD(&ei->cache_lru); INIT_HLIST_NODE(&ei->i_fat_hash); @@ -820,7 +821,6 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, if (error) goto out_fail; - spin_lock_init(&MSDOS_SB(sb)->cache_lock); /* set up enough so that it can read an inode */ init_MUTEX(&sbi->fat_lock); diff --git a/include/linux/msdos_fs_i.h b/include/linux/msdos_fs_i.h index a29b7d993e3f..a7b7f7ce0511 100644 --- a/include/linux/msdos_fs_i.h +++ b/include/linux/msdos_fs_i.h @@ -8,6 +8,7 @@ */ struct msdos_inode_info { + spinlock_t cache_lru_lock; struct list_head cache_lru; int nr_caches; diff --git a/include/linux/msdos_fs_sb.h b/include/linux/msdos_fs_sb.h index 3c69d6f36075..a94d990c7fb3 100644 --- a/include/linux/msdos_fs_sb.h +++ b/include/linux/msdos_fs_sb.h @@ -48,8 +48,6 @@ struct msdos_sb_info { void *dir_ops; /* Opaque; default directory operations */ int dir_per_block; /* dir entries per block */ int dir_per_block_bits; /* log2(dir_per_block) */ - - spinlock_t cache_lock; }; #endif -- cgit v1.2.3 From 7ff228f05f3949cce5ce7d5258b5c87b48af0cb8 Mon Sep 17 00:00:00 2001 From: Hirofumi Ogawa Date: Tue, 19 Oct 2004 18:15:30 -0700 Subject: [PATCH] FAT: the inode hash from per module to per sb Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fat/fatfs_syms.c | 2 +- fs/fat/inode.c | 57 ++++++++++++++++++++++++--------------------- include/linux/msdos_fs.h | 1 - include/linux/msdos_fs_sb.h | 7 ++++++ 4 files changed, 39 insertions(+), 28 deletions(-) (limited to 'include/linux') diff --git a/fs/fat/fatfs_syms.c b/fs/fat/fatfs_syms.c index 1a260e440f33..3645d73f0b54 100644 --- a/fs/fat/fatfs_syms.c +++ b/fs/fat/fatfs_syms.c @@ -31,7 +31,7 @@ void __exit fat_destroy_inodecache(void); static int __init init_fat_fs(void) { int ret; - fat_hash_init(); + ret = fat_cache_init(); if (ret < 0) return ret; diff --git a/fs/fat/inode.c b/fs/fat/inode.c index be0c0d5b434e..77834b95ea82 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -58,17 +58,14 @@ static void fat_write_inode(struct inode *inode, int wait); * and consider negative result as cache miss. */ -#define FAT_HASH_BITS 8 -#define FAT_HASH_SIZE (1UL << FAT_HASH_BITS) -#define FAT_HASH_MASK (FAT_HASH_SIZE-1) -static struct hlist_head fat_inode_hashtable[FAT_HASH_SIZE]; -static spinlock_t fat_inode_lock = SPIN_LOCK_UNLOCKED; - -void fat_hash_init(void) +static void fat_hash_init(struct super_block *sb) { + struct msdos_sb_info *sbi = MSDOS_SB(sb); int i; + + spin_lock_init(&sbi->inode_hash_lock); for (i = 0; i < FAT_HASH_SIZE; i++) - INIT_HLIST_HEAD(&fat_inode_hashtable[i]); + INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); } static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos) @@ -80,39 +77,43 @@ static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos) void fat_attach(struct inode *inode, loff_t i_pos) { - spin_lock(&fat_inode_lock); + struct super_block *sb = inode->i_sb; + struct msdos_sb_info *sbi = MSDOS_SB(sb); + + spin_lock(&sbi->inode_hash_lock); MSDOS_I(inode)->i_pos = i_pos; hlist_add_head(&MSDOS_I(inode)->i_fat_hash, - fat_inode_hashtable + fat_hash(inode->i_sb, i_pos)); - spin_unlock(&fat_inode_lock); + sbi->inode_hashtable + fat_hash(sb, i_pos)); + spin_unlock(&sbi->inode_hash_lock); } void fat_detach(struct inode *inode) { - spin_lock(&fat_inode_lock); + struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); + spin_lock(&sbi->inode_hash_lock); MSDOS_I(inode)->i_pos = 0; hlist_del_init(&MSDOS_I(inode)->i_fat_hash); - spin_unlock(&fat_inode_lock); + spin_unlock(&sbi->inode_hash_lock); } struct inode *fat_iget(struct super_block *sb, loff_t i_pos) { - struct hlist_head *head = fat_inode_hashtable + fat_hash(sb, i_pos); + struct msdos_sb_info *sbi = MSDOS_SB(sb); + struct hlist_head *head = sbi->inode_hashtable + fat_hash(sb, i_pos); struct hlist_node *_p; struct msdos_inode_info *i; struct inode *inode = NULL; - spin_lock(&fat_inode_lock); + spin_lock(&sbi->inode_hash_lock); hlist_for_each_entry(i, _p, head, i_fat_hash) { - if (i->vfs_inode.i_sb != sb) - continue; + BUG_ON(i->vfs_inode.i_sb != sb); if (i->i_pos != i_pos) continue; inode = igrab(&i->vfs_inode); if (inode) break; } - spin_unlock(&fat_inode_lock); + spin_unlock(&sbi->inode_hash_lock); return inode; } @@ -155,13 +156,15 @@ static void fat_delete_inode(struct inode *inode) static void fat_clear_inode(struct inode *inode) { + struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); + if (is_bad_inode(inode)) return; lock_kernel(); - spin_lock(&fat_inode_lock); + spin_lock(&sbi->inode_hash_lock); fat_cache_inval_inode(inode); hlist_del_init(&MSDOS_I(inode)->i_fat_hash); - spin_unlock(&fat_inode_lock); + spin_unlock(&sbi->inode_hash_lock); unlock_kernel(); } @@ -822,6 +825,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, goto out_fail; /* set up enough so that it can read an inode */ + fat_hash_init(sb); init_MUTEX(&sbi->fat_lock); error = -EIO; @@ -1231,6 +1235,7 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) int fat_write_inode(struct inode *inode, int wait) { struct super_block *sb = inode->i_sb; + struct msdos_sb_info *sbi = MSDOS_SB(sb); struct buffer_head *bh; struct msdos_dir_entry *raw_entry; loff_t i_pos; @@ -1241,22 +1246,22 @@ retry: return 0; } lock_kernel(); - if (!(bh = sb_bread(sb, i_pos >> MSDOS_SB(sb)->dir_per_block_bits))) { + if (!(bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits))) { printk(KERN_ERR "FAT: unable to read inode block " "for updating (i_pos %lld)\n", i_pos); unlock_kernel(); return -EIO; } - spin_lock(&fat_inode_lock); + spin_lock(&sbi->inode_hash_lock); if (i_pos != MSDOS_I(inode)->i_pos) { - spin_unlock(&fat_inode_lock); + spin_unlock(&sbi->inode_hash_lock); brelse(bh); unlock_kernel(); goto retry; } raw_entry = &((struct msdos_dir_entry *) (bh->b_data)) - [i_pos & (MSDOS_SB(sb)->dir_per_block - 1)]; + [i_pos & (sbi->dir_per_block - 1)]; if (S_ISDIR(inode->i_mode)) { raw_entry->attr = ATTR_DIR; raw_entry->size = 0; @@ -1270,11 +1275,11 @@ retry: raw_entry->start = CT_LE_W(MSDOS_I(inode)->i_logstart); raw_entry->starthi = CT_LE_W(MSDOS_I(inode)->i_logstart >> 16); fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date); - if (MSDOS_SB(sb)->options.isvfat) { + if (sbi->options.isvfat) { fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate); raw_entry->ctime_ms = MSDOS_I(inode)->i_ctime_ms; /* use i_ctime.tv_nsec? */ } - spin_unlock(&fat_inode_lock); + spin_unlock(&sbi->inode_hash_lock); mark_buffer_dirty(bh); brelse(bh); unlock_kernel(); diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h index d1f429b41d4c..4edc5dee1cb0 100644 --- a/include/linux/msdos_fs.h +++ b/include/linux/msdos_fs.h @@ -259,7 +259,6 @@ extern int fat_get_block(struct inode *inode, sector_t iblock, extern void fat_truncate(struct inode *inode); /* fat/inode.c */ -extern void fat_hash_init(void); extern void fat_attach(struct inode *inode, loff_t i_pos); extern void fat_detach(struct inode *inode); extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos); diff --git a/include/linux/msdos_fs_sb.h b/include/linux/msdos_fs_sb.h index a94d990c7fb3..3310996efbcc 100644 --- a/include/linux/msdos_fs_sb.h +++ b/include/linux/msdos_fs_sb.h @@ -26,6 +26,10 @@ struct fat_mount_options { nocase:1; /* Does this need case conversion? 0=need case conversion*/ }; +#define FAT_HASH_BITS 8 +#define FAT_HASH_SIZE (1UL << FAT_HASH_BITS) +#define FAT_HASH_MASK (FAT_HASH_SIZE-1) + struct msdos_sb_info { unsigned short sec_per_clus; /* sectors/cluster */ unsigned short cluster_bits; /* log2(cluster_size) */ @@ -48,6 +52,9 @@ struct msdos_sb_info { void *dir_ops; /* Opaque; default directory operations */ int dir_per_block; /* dir entries per block */ int dir_per_block_bits; /* log2(dir_per_block) */ + + spinlock_t inode_hash_lock; + struct hlist_head inode_hashtable[FAT_HASH_SIZE]; }; #endif -- cgit v1.2.3 From be591191813b7746f3e969e3fb77b73f9d33d1f1 Mon Sep 17 00:00:00 2001 From: Hirofumi Ogawa Date: Tue, 19 Oct 2004 18:15:45 -0700 Subject: [PATCH] FAT: Fix the race bitween fat_free() and fat_get_cluster() This patch fixes the race condition | fat_free | fat_get_cluster +------------------------------+----------------------- fat_cache_lookup() (get the copy of cache) fat_cache_inval_inode() (invalidate caches on inode) fat_cache_add() (update/add the getted cache) The above race has possible that invalidated cache is added. This patch fixes the race condition by adding the cache-id to copy of cache. Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fat/cache.c | 75 +++++++++++++++++++++++++++++++--------------- fs/fat/inode.c | 1 + include/linux/msdos_fs_i.h | 4 +++ 3 files changed, 56 insertions(+), 24 deletions(-) (limited to 'include/linux') diff --git a/fs/fat/cache.c b/fs/fat/cache.c index 72528f8fe315..2644eb8a7794 100644 --- a/fs/fat/cache.c +++ b/fs/fat/cache.c @@ -28,6 +28,13 @@ struct fat_cache { int dcluster; /* cluster number on disk. */ }; +struct fat_cache_id { + unsigned int id; + int nr_contig; + int fcluster; + int dcluster; +}; + static inline int fat_max_cache(struct inode *inode) { return FAT_MAX_CACHE; @@ -80,7 +87,7 @@ static inline void fat_cache_update_lru(struct inode *inode, } static int fat_cache_lookup(struct inode *inode, int fclus, - struct fat_cache *cache, + struct fat_cache_id *cid, int *cached_fclus, int *cached_dclus) { static struct fat_cache nohit = { .fcluster = 0, }; @@ -107,9 +114,13 @@ static int fat_cache_lookup(struct inode *inode, int fclus, } if (hit != &nohit) { fat_cache_update_lru(inode, hit); - *cache = *hit; - *cached_fclus = cache->fcluster + offset; - *cached_dclus = cache->dcluster + offset; + + cid->id = MSDOS_I(inode)->cache_valid_id; + cid->nr_contig = hit->nr_contig; + cid->fcluster = hit->fcluster; + cid->dcluster = hit->dcluster; + *cached_fclus = cid->fcluster + offset; + *cached_dclus = cid->dcluster + offset; } debug_pr("\n"); spin_unlock(&MSDOS_I(inode)->cache_lru_lock); @@ -118,7 +129,7 @@ static int fat_cache_lookup(struct inode *inode, int fclus, } static struct fat_cache *fat_cache_merge(struct inode *inode, - struct fat_cache *new) + struct fat_cache_id *new) { struct fat_cache *p, *hit = NULL; @@ -138,7 +149,7 @@ static struct fat_cache *fat_cache_merge(struct inode *inode, return hit; } -static void fat_cache_add(struct inode *inode, struct fat_cache *new) +static void fat_cache_add(struct inode *inode, struct fat_cache_id *new) { struct fat_cache *cache, *tmp; @@ -149,7 +160,12 @@ static void fat_cache_add(struct inode *inode, struct fat_cache *new) return; spin_lock(&MSDOS_I(inode)->cache_lru_lock); + if (new->id != FAT_CACHE_VALID && + new->id != MSDOS_I(inode)->cache_valid_id) + goto out; /* this cache was invalidated */ + cache = fat_cache_merge(inode, new); + BUG_ON(new->id == FAT_CACHE_VALID && cache != NULL); if (cache == NULL) { if (MSDOS_I(inode)->nr_caches < fat_max_cache(inode)) { MSDOS_I(inode)->nr_caches++; @@ -161,7 +177,7 @@ static void fat_cache_add(struct inode *inode, struct fat_cache *new) if (cache != NULL) { MSDOS_I(inode)->nr_caches--; fat_cache_free(tmp); - goto out; + goto out_update_lru; } cache = tmp; } else { @@ -172,9 +188,9 @@ static void fat_cache_add(struct inode *inode, struct fat_cache *new) cache->dcluster = new->dcluster; cache->nr_contig = new->nr_contig; } -out: +out_update_lru: fat_cache_update_lru(inode, cache); - +out: debug_pr("FAT: "); list_for_each_entry(cache, &MSDOS_I(inode)->cache_lru, cache_list) { debug_pr("(fclus %d, dclus %d, cont %d), ", @@ -192,12 +208,17 @@ static void __fat_cache_inval_inode(struct inode *inode) { struct msdos_inode_info *i = MSDOS_I(inode); struct fat_cache *cache; + while (!list_empty(&i->cache_lru)) { cache = list_entry(i->cache_lru.next, struct fat_cache, cache_list); list_del_init(&cache->cache_list); - MSDOS_I(inode)->nr_caches--; + i->nr_caches--; fat_cache_free(cache); } + /* Update. The copy of caches before this id is discarded. */ + i->cache_valid_id++; + if (i->cache_valid_id == FAT_CACHE_VALID) + i->cache_valid_id++; debug_pr("FAT: %s\n", __FUNCTION__); } @@ -326,24 +347,25 @@ out: return next; } -static inline int cache_contiguous(struct fat_cache *cache, int dclus) +static inline int cache_contiguous(struct fat_cache_id *cid, int dclus) { - cache->nr_contig++; - return ((cache->dcluster + cache->nr_contig) == dclus); + cid->nr_contig++; + return ((cid->dcluster + cid->nr_contig) == dclus); } -static inline void cache_init(struct fat_cache *cache, int fclus, int dclus) +static inline void cache_init(struct fat_cache_id *cid, int fclus, int dclus) { - cache->fcluster = fclus; - cache->dcluster = dclus; - cache->nr_contig = 0; + cid->id = FAT_CACHE_VALID; + cid->fcluster = fclus; + cid->dcluster = dclus; + cid->nr_contig = 0; } int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus) { struct super_block *sb = inode->i_sb; const int limit = sb->s_maxbytes >> MSDOS_SB(sb)->cluster_bits; - struct fat_cache cache; + struct fat_cache_id cid; int nr; BUG_ON(MSDOS_I(inode)->i_start == 0); @@ -353,8 +375,13 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus) if (cluster == 0) return 0; - if (fat_cache_lookup(inode, cluster, &cache, fclus, dclus) < 0) - cache_init(&cache, -1, -1); /* dummy, always not contiguous */ + if (fat_cache_lookup(inode, cluster, &cid, fclus, dclus) < 0) { + /* + * dummy, always not contiguous + * This is reinitialized by cache_init(), later. + */ + cache_init(&cid, -1, -1); + } while (*fclus < cluster) { /* prevent the infinite loop of cluster chain */ @@ -374,15 +401,15 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus) MSDOS_I(inode)->i_pos); return -EIO; } else if (nr == FAT_ENT_EOF) { - fat_cache_add(inode, &cache); + fat_cache_add(inode, &cid); return FAT_ENT_EOF; } (*fclus)++; *dclus = nr; - if (!cache_contiguous(&cache, *dclus)) - cache_init(&cache, *fclus, *dclus); + if (!cache_contiguous(&cid, *dclus)) + cache_init(&cid, *fclus, *dclus); } - fat_cache_add(inode, &cache); + fat_cache_add(inode, &cid); return 0; } diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 77834b95ea82..ba1fb521f52d 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -740,6 +740,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) SLAB_CTOR_CONSTRUCTOR) { spin_lock_init(&ei->cache_lru_lock); ei->nr_caches = 0; + ei->cache_valid_id = FAT_CACHE_VALID + 1; INIT_LIST_HEAD(&ei->cache_lru); INIT_HLIST_NODE(&ei->i_fat_hash); inode_init_once(&ei->vfs_inode); diff --git a/include/linux/msdos_fs_i.h b/include/linux/msdos_fs_i.h index a7b7f7ce0511..b50018cf7e3d 100644 --- a/include/linux/msdos_fs_i.h +++ b/include/linux/msdos_fs_i.h @@ -7,10 +7,14 @@ * MS-DOS file system inode data in memory */ +#define FAT_CACHE_VALID 0 /* special case for valid cache */ + struct msdos_inode_info { spinlock_t cache_lru_lock; struct list_head cache_lru; int nr_caches; + /* for avoiding the race between fat_free() and fat_get_cluster() */ + unsigned int cache_valid_id; loff_t mmu_private; int i_start; /* first cluster or 0 */ -- cgit v1.2.3 From 97a28b9a991f5eee548fca291911d4d7bdf868eb Mon Sep 17 00:00:00 2001 From: Hirofumi Ogawa Date: Tue, 19 Oct 2004 18:16:45 -0700 Subject: [PATCH] FAT: removal of C[FT]_LE_[WL] macro Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fat/cache.c | 8 ++++---- fs/fat/dir.c | 8 ++++---- fs/fat/inode.c | 48 +++++++++++++++++++++++++----------------------- fs/fat/misc.c | 3 ++- fs/msdos/namei.c | 4 ++-- include/linux/msdos_fs.h | 4 ++-- 6 files changed, 39 insertions(+), 36 deletions(-) (limited to 'include/linux') diff --git a/fs/fat/cache.c b/fs/fat/cache.c index d63297dccf53..33c0fbb93bad 100644 --- a/fs/fat/cache.c +++ b/fs/fat/cache.c @@ -237,13 +237,13 @@ int __fat_access(struct super_block *sb, int nr, int new_value) } if (sbi->fat_bits == 32) { p_first = p_last = NULL; /* GCC needs that stuff */ - next = CF_LE_L(((__le32 *) bh->b_data)[(first & + next = le32_to_cpu(((__le32 *) bh->b_data)[(first & (sb->s_blocksize - 1)) >> 2]); /* Fscking Microsoft marketing department. Their "32" is 28. */ next &= 0x0fffffff; } else if (sbi->fat_bits == 16) { p_first = p_last = NULL; /* GCC needs that stuff */ - next = CF_LE_W(((__le16 *) bh->b_data)[(first & + next = le16_to_cpu(((__le16 *) bh->b_data)[(first & (sb->s_blocksize - 1)) >> 1]); } else { p_first = &((__u8 *)bh->b_data)[first & (sb->s_blocksize - 1)]; @@ -256,10 +256,10 @@ int __fat_access(struct super_block *sb, int nr, int new_value) if (new_value != -1) { if (sbi->fat_bits == 32) { ((__le32 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 2] - = CT_LE_L(new_value); + = cpu_to_le32(new_value); } else if (sbi->fat_bits == 16) { ((__le16 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 1] - = CT_LE_W(new_value); + = cpu_to_le16(new_value); } else { if (nr & 1) { *p_first = (*p_first & 0xf) | (new_value << 4); diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 184cdc0a30d7..78af33c56047 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -737,10 +737,10 @@ int fat_new_dir(struct inode *dir, struct inode *parent, int is_vfat) de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = date; } - de[0].start = CT_LE_W(MSDOS_I(dir)->i_logstart); - de[0].starthi = CT_LE_W(MSDOS_I(dir)->i_logstart>>16); - de[1].start = CT_LE_W(MSDOS_I(parent)->i_logstart); - de[1].starthi = CT_LE_W(MSDOS_I(parent)->i_logstart>>16); + de[0].start = cpu_to_le16(MSDOS_I(dir)->i_logstart); + de[0].starthi = cpu_to_le16(MSDOS_I(dir)->i_logstart>>16); + de[1].start = cpu_to_le16(MSDOS_I(parent)->i_logstart); + de[1].starthi = cpu_to_le16(MSDOS_I(parent)->i_logstart>>16); mark_buffer_dirty(bh); brelse(bh); dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; diff --git a/fs/fat/inode.c b/fs/fat/inode.c index ea904da486c6..3d345dd97b3c 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -864,7 +864,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, brelse(bh); goto out_invalid; } - logical_sector_size = CF_LE_W(get_unaligned((__le16 *)&b->sector_size)); + logical_sector_size = + le16_to_cpu(get_unaligned((__le16 *)&b->sector_size)); if (!logical_sector_size || (logical_sector_size & (logical_sector_size - 1)) || (logical_sector_size < 512) @@ -913,8 +914,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, sbi->cluster_bits = ffs(sbi->cluster_size) - 1; sbi->fats = b->fats; sbi->fat_bits = 0; /* Don't know yet */ - sbi->fat_start = CF_LE_W(b->reserved); - sbi->fat_length = CF_LE_W(b->fat_length); + sbi->fat_start = le16_to_cpu(b->reserved); + sbi->fat_length = le16_to_cpu(b->fat_length); sbi->root_cluster = 0; sbi->free_clusters = -1; /* Don't know yet */ sbi->prev_free = -1; @@ -925,13 +926,13 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, /* Must be FAT32 */ sbi->fat_bits = 32; - sbi->fat_length = CF_LE_L(b->fat32_length); - sbi->root_cluster = CF_LE_L(b->root_cluster); + sbi->fat_length = le32_to_cpu(b->fat32_length); + sbi->root_cluster = le32_to_cpu(b->root_cluster); sb->s_maxbytes = 0xffffffff; /* MC - if info_sector is 0, don't multiply by 0 */ - sbi->fsinfo_sector = CF_LE_W(b->info_sector); + sbi->fsinfo_sector = le16_to_cpu(b->info_sector); if (sbi->fsinfo_sector == 0) sbi->fsinfo_sector = 1; @@ -949,12 +950,12 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, "FAT: Did not find valid FSINFO signature.\n" " Found signature1 0x%08x signature2 0x%08x" " (sector = %lu)\n", - CF_LE_L(fsinfo->signature1), - CF_LE_L(fsinfo->signature2), + le32_to_cpu(fsinfo->signature1), + le32_to_cpu(fsinfo->signature2), sbi->fsinfo_sector); } else { - sbi->free_clusters = CF_LE_L(fsinfo->free_clusters); - sbi->prev_free = CF_LE_L(fsinfo->next_cluster); + sbi->free_clusters = le32_to_cpu(fsinfo->free_clusters); + sbi->prev_free = le32_to_cpu(fsinfo->next_cluster); } brelse(fsinfo_bh); @@ -964,7 +965,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1; sbi->dir_start = sbi->fat_start + sbi->fats * sbi->fat_length; - sbi->dir_entries = CF_LE_W(get_unaligned((__le16 *)&b->dir_entries)); + sbi->dir_entries = + le16_to_cpu(get_unaligned((__le16 *)&b->dir_entries)); if (sbi->dir_entries & (sbi->dir_per_block - 1)) { if (!silent) printk(KERN_ERR "FAT: bogus directroy-entries per block" @@ -976,9 +978,9 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, rootdir_sectors = sbi->dir_entries * sizeof(struct msdos_dir_entry) / sb->s_blocksize; sbi->data_start = sbi->dir_start + rootdir_sectors; - total_sectors = CF_LE_W(get_unaligned((__le16 *)&b->sectors)); + total_sectors = le16_to_cpu(get_unaligned((__le16 *)&b->sectors)); if (total_sectors == 0) - total_sectors = CF_LE_L(b->total_sect); + total_sectors = le32_to_cpu(b->total_sect); total_clusters = (total_sectors - sbi->data_start) / sbi->sec_per_clus; @@ -1186,9 +1188,9 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) inode->i_op = sbi->dir_ops; inode->i_fop = &fat_dir_operations; - MSDOS_I(inode)->i_start = CF_LE_W(de->start); + MSDOS_I(inode)->i_start = le16_to_cpu(de->start); if (sbi->fat_bits == 32) - MSDOS_I(inode)->i_start |= (CF_LE_W(de->starthi) << 16); + MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16); MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start; error = fat_calc_dir_size(inode); @@ -1204,12 +1206,12 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) !is_exec(de->ext)) ? S_IRUGO|S_IWUGO : S_IRWXUGO) & ~sbi->options.fs_fmask) | S_IFREG; - MSDOS_I(inode)->i_start = CF_LE_W(de->start); + MSDOS_I(inode)->i_start = le16_to_cpu(de->start); if (sbi->fat_bits == 32) - MSDOS_I(inode)->i_start |= (CF_LE_W(de->starthi) << 16); + MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16); MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start; - inode->i_size = CF_LE_L(de->size); + inode->i_size = le32_to_cpu(de->size); inode->i_op = &fat_file_inode_operations; inode->i_fop = &fat_file_operations; inode->i_mapping->a_ops = &fat_aops; @@ -1224,11 +1226,11 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) & ~((loff_t)sbi->cluster_size - 1)) >> 9; inode->i_mtime.tv_sec = inode->i_atime.tv_sec = - date_dos2unix(CF_LE_W(de->time),CF_LE_W(de->date)); + date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date)); inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = 0; inode->i_ctime.tv_sec = MSDOS_SB(sb)->options.isvfat - ? date_dos2unix(CF_LE_W(de->ctime),CF_LE_W(de->cdate)) + ? date_dos2unix(le16_to_cpu(de->ctime), le16_to_cpu(de->cdate)) : inode->i_mtime.tv_sec; inode->i_ctime.tv_nsec = de->ctime_ms * 1000000; MSDOS_I(inode)->i_ctime_ms = de->ctime_ms; @@ -1272,12 +1274,12 @@ retry: } else { raw_entry->attr = ATTR_NONE; - raw_entry->size = CT_LE_L(inode->i_size); + raw_entry->size = cpu_to_le32(inode->i_size); } raw_entry->attr |= MSDOS_MKATTR(inode->i_mode) | MSDOS_I(inode)->i_attrs; - raw_entry->start = CT_LE_W(MSDOS_I(inode)->i_logstart); - raw_entry->starthi = CT_LE_W(MSDOS_I(inode)->i_logstart >> 16); + raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart); + raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16); fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date); if (sbi->options.isvfat) { fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate); diff --git a/fs/fat/misc.c b/fs/fat/misc.c index 69e2a3cc0efa..d6f149cb2d58 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c @@ -69,7 +69,8 @@ void fat_clusters_flush(struct super_block *sb) printk(KERN_ERR "FAT: Did not find valid FSINFO signature.\n" " Found signature1 0x%08x signature2 0x%08x" " (sector = %lu)\n", - CF_LE_L(fsinfo->signature1), CF_LE_L(fsinfo->signature2), + le32_to_cpu(fsinfo->signature1), + le32_to_cpu(fsinfo->signature2), sbi->fsinfo_sector); } else { if (sbi->free_clusters != -1) diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index 817f57aa90e6..50be17dd2917 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c @@ -501,8 +501,8 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, mark_inode_dirty(new_inode); } if (dotdot_bh) { - dotdot_de->start = CT_LE_W(MSDOS_I(new_dir)->i_logstart); - dotdot_de->starthi = CT_LE_W((MSDOS_I(new_dir)->i_logstart) >> 16); + dotdot_de->start = cpu_to_le16(MSDOS_I(new_dir)->i_logstart); + dotdot_de->starthi = cpu_to_le16((MSDOS_I(new_dir)->i_logstart) >> 16); mark_buffer_dirty(dotdot_bh); old_dir->i_nlink--; mark_inode_dirty(old_dir); diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h index 4edc5dee1cb0..d6097bfc6715 100644 --- a/include/linux/msdos_fs.h +++ b/include/linux/msdos_fs.h @@ -87,8 +87,8 @@ #define FAT_FSINFO_SIG1 0x41615252 #define FAT_FSINFO_SIG2 0x61417272 -#define IS_FSINFO(x) (CF_LE_L((x)->signature1) == FAT_FSINFO_SIG1 \ - && CF_LE_L((x)->signature2) == FAT_FSINFO_SIG2) +#define IS_FSINFO(x) (le32_to_cpu((x)->signature1) == FAT_FSINFO_SIG1 \ + && le32_to_cpu((x)->signature2) == FAT_FSINFO_SIG2) /* * ioctl commands -- cgit v1.2.3 From 1b46884a372f362e5edb1bb406bf0c5ca98bade7 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Tue, 19 Oct 2004 18:17:12 -0700 Subject: [PATCH] lighten mmlist_lock Let's lighten the global spinlock mmlist_lock. What's it for? 1. Its original role is to guard mmlist. 2. It later got a second role, to prevent get_task_mm from raising mm_users from the dead, just after it went down to 0. Firstly consider the second: __exit_mm sets tsk->mm NULL while holding task_lock before calling mmput; so mmlist_lock only guards against the exceptional case, of get_task_mm on a kernel workthread which did AIO's use_mm (which transiently sets its tsk->mm without raising mm_users) on an mm now exiting. Well, I don't think get_task_mm should succeed at all on use_mm tasks. It's mainly used by /proc/pid and ptrace, seems at best confusing for those to present the kernel thread as having a user mm, which it won't have a moment later. Define PF_BORROWED_MM, set in use_mm, clear in unuse_mm (though we could just leave it), get_task_mm give NULL if set. Secondly consider the first: and what's mmlist for? 1. Its original role was for swap_out to scan: rmap ended that in 2.5.27. 2. In 2.4.10 it got a second role, for try_to_unuse to scan for swapoff. So, make mmlist a list of mms which maybe have pages on swap: add mm to mmlist when first swap entry is assigned in try_to_unmap_one (pageout), or in copy_page_range (fork); and mmput remove it from mmlist as before, except usually list_empty and there's no need to lock. drain_mmlist added to swapoff, to empty out the mmlist if no swap is then in use. mmput leave mm on mmlist until after its exit_mmap, so try_to_unmap_one can still add mm to mmlist without worrying about the mm_users 0 case; but try_to_unuse must avoid the mm_users 0 case (when an mm might be removed from mmlist, and freed, while it's down in unuse_process): use atomic_inc_return now all architectures support that. Some of the detailed comments in try_to_unuse have grown out of date: updated and trimmed some, but leave SWAP_MAP_MAX for another occasion. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/mm/pgtable.c | 6 ++---- fs/aio.c | 2 ++ fs/exec.c | 6 ------ include/linux/sched.h | 5 ++--- kernel/fork.c | 37 +++++++++++-------------------------- mm/memory.c | 9 ++++++++- mm/rmap.c | 6 ++++++ mm/swapfile.c | 49 +++++++++++++++++++++++++++++++++---------------- 8 files changed, 64 insertions(+), 56 deletions(-) (limited to 'include/linux') diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c index 137d18db72ff..1152545ef8ad 100644 --- a/arch/i386/mm/pgtable.c +++ b/arch/i386/mm/pgtable.c @@ -165,10 +165,8 @@ void pmd_ctor(void *pmd, kmem_cache_t *cache, unsigned long flags) * against pageattr.c; it is the unique case in which a valid change * of kernel pagetables can't be lazily synchronized by vmalloc faults. * vmalloc faults work because attached pagetables are never freed. - * If the locking proves to be non-performant, a ticketing scheme with - * checks at dup_mmap(), exec(), and other mmlist addition points - * could be used. The locking scheme was chosen on the basis of - * manfred's recommendations and having no core impact whatsoever. + * The locking scheme was chosen on the basis of manfred's + * recommendations and having no core impact whatsoever. * -- wli */ spinlock_t pgd_lock = SPIN_LOCK_UNLOCKED; diff --git a/fs/aio.c b/fs/aio.c index 23d5f00f2bee..1d980625cabf 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -572,6 +572,7 @@ static void use_mm(struct mm_struct *mm) struct task_struct *tsk = current; task_lock(tsk); + tsk->flags |= PF_BORROWED_MM; active_mm = tsk->active_mm; atomic_inc(&mm->mm_count); tsk->mm = mm; @@ -598,6 +599,7 @@ void unuse_mm(struct mm_struct *mm) struct task_struct *tsk = current; task_lock(tsk); + tsk->flags &= ~PF_BORROWED_MM; tsk->mm = NULL; /* active_mm is still 'mm' */ enter_lazy_tlb(mm, tsk); diff --git a/fs/exec.c b/fs/exec.c index 4915bffb045d..e83bb202a60c 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -530,12 +530,6 @@ static int exec_mmap(struct mm_struct *mm) struct task_struct *tsk; struct mm_struct * old_mm, *active_mm; - /* Add it to the list of mm's */ - spin_lock(&mmlist_lock); - list_add(&mm->mmlist, &init_mm.mmlist); - mmlist_nr++; - spin_unlock(&mmlist_lock); - /* Notify parent that we're no longer interested in the old VM */ tsk = current; old_mm = current->mm; diff --git a/include/linux/sched.h b/include/linux/sched.h index c8f981f108d4..1c556975b2dd 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -218,7 +218,7 @@ struct mm_struct { struct rw_semaphore mmap_sem; spinlock_t page_table_lock; /* Protects task page tables and mm->rss */ - struct list_head mmlist; /* List of all active mm's. These are globally strung + struct list_head mmlist; /* List of maybe swapped mm's. These are globally strung * together off init_mm.mmlist, and are protected * by mmlist_lock */ @@ -252,8 +252,6 @@ struct mm_struct { struct kioctx default_kioctx; }; -extern int mmlist_nr; - struct sighand_struct { atomic_t count; struct k_sigaction action[_NSIG]; @@ -722,6 +720,7 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0) #define PF_SWAPOFF 0x00080000 /* I am in swapoff */ #define PF_LESS_THROTTLE 0x00100000 /* Throttle me less: I clean memory */ #define PF_SYNCWRITE 0x00200000 /* I am doing a sync write */ +#define PF_BORROWED_MM 0x00400000 /* I am a kthread doing use_mm */ #ifdef CONFIG_SMP extern int set_cpus_allowed(task_t *p, cpumask_t new_mask); diff --git a/kernel/fork.c b/kernel/fork.c index 96714c501cc8..7d9cd6f7b278 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -179,17 +179,6 @@ static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm) rb_parent = NULL; pprev = &mm->mmap; - /* - * Add it to the mmlist after the parent. - * Doing it this way means that we can order the list, - * and fork() won't mess up the ordering significantly. - * Add it first so that swapoff can see any swap entries. - */ - spin_lock(&mmlist_lock); - list_add(&mm->mmlist, ¤t->mm->mmlist); - mmlist_nr++; - spin_unlock(&mmlist_lock); - for (mpnt = current->mm->mmap ; mpnt ; mpnt = mpnt->vm_next) { struct file *file; @@ -289,7 +278,6 @@ static inline void mm_free_pgd(struct mm_struct * mm) #endif /* CONFIG_MMU */ spinlock_t mmlist_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; -int mmlist_nr; #define allocate_mm() (kmem_cache_alloc(mm_cachep, SLAB_KERNEL)) #define free_mm(mm) (kmem_cache_free(mm_cachep, (mm))) @@ -301,6 +289,7 @@ static struct mm_struct * mm_init(struct mm_struct * mm) atomic_set(&mm->mm_users, 1); atomic_set(&mm->mm_count, 1); init_rwsem(&mm->mmap_sem); + INIT_LIST_HEAD(&mm->mmlist); mm->core_waiters = 0; mm->nr_ptes = 0; mm->page_table_lock = SPIN_LOCK_UNLOCKED; @@ -350,12 +339,14 @@ void fastcall __mmdrop(struct mm_struct *mm) */ void mmput(struct mm_struct *mm) { - if (atomic_dec_and_lock(&mm->mm_users, &mmlist_lock)) { - list_del(&mm->mmlist); - mmlist_nr--; - spin_unlock(&mmlist_lock); + if (atomic_dec_and_test(&mm->mm_users)) { exit_aio(mm); exit_mmap(mm); + if (!list_empty(&mm->mmlist)) { + spin_lock(&mmlist_lock); + list_del(&mm->mmlist); + spin_unlock(&mmlist_lock); + } put_swap_token(mm); mmdrop(mm); } @@ -365,15 +356,11 @@ EXPORT_SYMBOL_GPL(mmput); /** * get_task_mm - acquire a reference to the task's mm * - * Returns %NULL if the task has no mm. Checks if the use count - * of the mm is non-zero and if so returns a reference to it, after + * Returns %NULL if the task has no mm. Checks PF_BORROWED_MM (meaning + * this kernel workthread has transiently adopted a user mm with use_mm, + * to do its AIO) is not set and if so returns a reference to it, after * bumping up the use count. User must release the mm via mmput() * after use. Typically used by /proc and ptrace. - * - * If the use count is zero, it means that this mm is going away, - * so return %NULL. This only happens in the case of an AIO daemon - * which has temporarily adopted an mm (see use_mm), in the course - * of its final mmput, before exit_aio has completed. */ struct mm_struct *get_task_mm(struct task_struct *task) { @@ -382,12 +369,10 @@ struct mm_struct *get_task_mm(struct task_struct *task) task_lock(task); mm = task->mm; if (mm) { - spin_lock(&mmlist_lock); - if (!atomic_read(&mm->mm_users)) + if (task->flags & PF_BORROWED_MM) mm = NULL; else atomic_inc(&mm->mm_users); - spin_unlock(&mmlist_lock); } task_unlock(task); return mm; diff --git a/mm/memory.c b/mm/memory.c index 52f96233a13c..c43881bbd00d 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -289,8 +289,15 @@ skip_copy_pte_range: goto cont_copy_pte_range_noset; /* pte contains position in swap, so copy. */ if (!pte_present(pte)) { - if (!pte_file(pte)) + if (!pte_file(pte)) { swap_duplicate(pte_to_swp_entry(pte)); + if (list_empty(&dst->mmlist)) { + spin_lock(&mmlist_lock); + list_add(&dst->mmlist, + &src->mmlist); + spin_unlock(&mmlist_lock); + } + } set_pte(dst_pte, pte); goto cont_copy_pte_range_noset; } diff --git a/mm/rmap.c b/mm/rmap.c index f1c40c722fe6..d4a9a6a50fc8 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -35,6 +35,7 @@ * mm->page_table_lock * zone->lru_lock (in mark_page_accessed) * swap_list_lock (in swap_free etc's swap_info_get) + * mmlist_lock (in mmput, drain_mmlist and others) * swap_device_lock (in swap_duplicate, swap_info_get) * mapping->private_lock (in __set_page_dirty_buffers) * inode_lock (in set_page_dirty's __mark_inode_dirty) @@ -576,6 +577,11 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma) */ BUG_ON(!PageSwapCache(page)); swap_duplicate(entry); + if (list_empty(&mm->mmlist)) { + spin_lock(&mmlist_lock); + list_add(&mm->mmlist, &init_mm.mmlist); + spin_unlock(&mmlist_lock); + } set_pte(pte, swp_entry_to_pte(entry)); BUG_ON(pte_file(*pte)); } diff --git a/mm/swapfile.c b/mm/swapfile.c index 55bb488aa10f..446b6fd9871e 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -648,11 +648,12 @@ static int try_to_unuse(unsigned int type) * * A simpler strategy would be to start at the last mm we * freed the previous entry from; but that would take less - * advantage of mmlist ordering (now preserved by swap_out()), - * which clusters forked address spaces together, most recent - * child immediately after parent. If we race with dup_mmap(), - * we very much want to resolve parent before child, otherwise - * we may miss some entries: using last mm would invert that. + * advantage of mmlist ordering, which clusters forked mms + * together, child after parent. If we race with dup_mmap(), we + * prefer to resolve parent before child, lest we miss entries + * duplicated after we scanned child: using last mm would invert + * that. Though it's only a serious concern when an overflowed + * swap count is reset from SWAP_MAP_MAX, preventing a rescan. */ start_mm = &init_mm; atomic_inc(&init_mm.mm_users); @@ -660,15 +661,7 @@ static int try_to_unuse(unsigned int type) /* * Keep on scanning until all entries have gone. Usually, * one pass through swap_map is enough, but not necessarily: - * mmput() removes mm from mmlist before exit_mmap() and its - * zap_page_range(). That's not too bad, those entries are - * on their way out, and handled faster there than here. - * do_munmap() behaves similarly, taking the range out of mm's - * vma list before zap_page_range(). But unfortunately, when - * unmapping a part of a vma, it takes the whole out first, - * then reinserts what's left after (might even reschedule if - * open() method called) - so swap entries may be invisible - * to swapoff for a while, then reappear - but that is rare. + * there are races when an instance of an entry might be missed. */ while ((i = find_next_to_unuse(si, i)) != 0) { if (signal_pending(current)) { @@ -720,7 +713,7 @@ static int try_to_unuse(unsigned int type) wait_on_page_writeback(page); /* - * Remove all references to entry, without blocking. + * Remove all references to entry. * Whenever we reach init_mm, there's no address space * to search, but use it as a reminder to search shmem. */ @@ -745,7 +738,10 @@ static int try_to_unuse(unsigned int type) while (*swap_map > 1 && !retval && (p = p->next) != &start_mm->mmlist) { mm = list_entry(p, struct mm_struct, mmlist); - atomic_inc(&mm->mm_users); + if (atomic_inc_return(&mm->mm_users) == 1) { + atomic_dec(&mm->mm_users); + continue; + } spin_unlock(&mmlist_lock); mmput(prev_mm); prev_mm = mm; @@ -858,6 +854,26 @@ static int try_to_unuse(unsigned int type) return retval; } +/* + * After a successful try_to_unuse, if no swap is now in use, we know we + * can empty the mmlist. swap_list_lock must be held on entry and exit. + * Note that mmlist_lock nests inside swap_list_lock, and an mm must be + * added to the mmlist just after page_duplicate - before would be racy. + */ +static void drain_mmlist(void) +{ + struct list_head *p, *next; + unsigned int i; + + for (i = 0; i < nr_swapfiles; i++) + if (swap_info[i].inuse_pages) + return; + spin_lock(&mmlist_lock); + list_for_each_safe(p, next, &init_mm.mmlist) + list_del_init(p); + spin_unlock(&mmlist_lock); +} + /* * Use this swapdev's extent info to locate the (PAGE_SIZE) block which * corresponds to page offset `offset'. @@ -1172,6 +1188,7 @@ asmlinkage long sys_swapoff(const char __user * specialfile) } down(&swapon_sem); swap_list_lock(); + drain_mmlist(); swap_device_lock(p); swap_file = p->swap_file; p->swap_file = NULL; -- cgit v1.2.3 From d75097d0c539c9ae6aff4e3dce16faf046e7e833 Mon Sep 17 00:00:00 2001 From: Michael Hunold Date: Tue, 19 Oct 2004 18:20:16 -0700 Subject: [PATCH] DVB: core update - [DVB] remove non-linux compatibility stuff from dvb_functions. rest in peace. - [DVB] remove home-brewn dvb-i2c stuff. rest in peace. - [DVB] convert MODULE_PARM() to module_param() - [DVB] convert dvb_delay() to mdelay() - [DVB] convert C++ comments to C comments - [DVB] dvb_ca_en50221: fix for matrix CAMs from Sjoerd Simons, use c99 initializers, Fix for aston CAM read timeout problems, Moved CAM CTRL IF reset to a better place, better debugging with multiple cards (Sjoerd Simons) - [DVB] dvb-frontend: patch by Wolfgang Fritz: suppress spurious events during tuning, Do not allow write (and related) ioctls when frontend is opened RDONLY, Properly lock the frontend module on open/close, patch by Christopher Pascoe: remove bogus up(fe->sem) on fe thread exit, patch by Christopher Pascoe: remove bogus up(fe->sem) on fe thread exit - [DVB] dvb-demux: using spin_lock instead of spin_lock_irq caused a race condition between irq/tasklet and user space task - [DVB] dvb-core: add sysfs/udev support using "class_simple", prevent Oops when PES filter is set with invalid pes_type, protect feed_list with spin_locks Signed-off-by: Michael Hunold Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/dvb-core/Makefile | 4 +- drivers/media/dvb/dvb-core/dmxdev.c | 8 +- drivers/media/dvb/dvb-core/dvb_ca_en50221.c | 178 ++++++++--------- drivers/media/dvb/dvb-core/dvb_ca_en50221.h | 3 + drivers/media/dvb/dvb-core/dvb_demux.c | 13 +- drivers/media/dvb/dvb-core/dvb_frontend.c | 262 +++++++++++++------------ drivers/media/dvb/dvb-core/dvb_frontend.h | 35 +++- drivers/media/dvb/dvb-core/dvb_functions.c | 89 --------- drivers/media/dvb/dvb-core/dvb_functions.h | 50 ----- drivers/media/dvb/dvb-core/dvb_i2c.c | 290 ---------------------------- drivers/media/dvb/dvb-core/dvb_i2c.h | 63 ------ drivers/media/dvb/dvb-core/dvb_ksyms.c | 7 +- drivers/media/dvb/dvb-core/dvb_net.c | 2 - drivers/media/dvb/dvb-core/dvbdev.c | 104 ++++++++-- drivers/media/dvb/dvb-core/dvbdev.h | 11 ++ include/linux/dvb/frontend.h | 5 +- 16 files changed, 386 insertions(+), 738 deletions(-) delete mode 100644 drivers/media/dvb/dvb-core/dvb_functions.c delete mode 100644 drivers/media/dvb/dvb-core/dvb_functions.h delete mode 100644 drivers/media/dvb/dvb-core/dvb_i2c.c delete mode 100644 drivers/media/dvb/dvb-core/dvb_i2c.h (limited to 'include/linux') diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile index 7127789146cc..9d534602a864 100644 --- a/drivers/media/dvb/dvb-core/Makefile +++ b/drivers/media/dvb/dvb-core/Makefile @@ -3,7 +3,7 @@ # dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ - dvb_ca_en50221.o dvb_functions.o dvb_frontend.o \ - dvb_i2c.o dvb_net.o dvb_ksyms.o dvb_ringbuffer.o + dvb_ca_en50221.o dvb_frontend.o \ + dvb_net.o dvb_ksyms.o dvb_ringbuffer.o obj-$(CONFIG_DVB_CORE) += dvb-core.o diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index 1d685f6bcd00..09ad79e08371 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -33,10 +34,11 @@ #include #include "dmxdev.h" -#include "dvb_functions.h" -MODULE_PARM(debug,"i"); -static int debug = 0; +static int debug; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); #define dprintk if (debug) printk diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c index e3af0c0253f3..0c60e813b01f 100644 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c @@ -32,16 +32,19 @@ #include #include #include +#include #include #include -#include -#include +#include #include "dvb_ca_en50221.h" -#include "dvb_functions.h" #include "dvb_ringbuffer.h" -static int dvb_ca_en50221_debug = 0; +static int dvb_ca_en50221_debug; + +module_param_named(cam_debug, dvb_ca_en50221_debug, int, 0644); +MODULE_PARM_DESC(cam_debug, "enable verbose debug messages"); + #define dprintk if (dvb_ca_en50221_debug) printk #define INIT_TIMEOUT_SECS 5 @@ -108,7 +111,7 @@ struct dvb_ca_slot { int link_buf_size; /* semaphore for syncing access to slot structure */ - struct semaphore sem; + struct rw_semaphore sem; /* buffer for incoming packets */ struct dvb_ringbuffer rx_buffer; @@ -199,7 +202,6 @@ static u8* findstr(u8* haystack, int hlen, u8* needle, int nlen) static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private* ca, int slot) { int slot_status; - int status; int cam_present_now; int cam_changed; @@ -209,9 +211,7 @@ static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private* ca, int slot) } /* poll mode */ - if ((status = down_interruptible(&ca->slot_info[slot].sem)) != 0) return status; slot_status = ca->pub->poll_slot_status(ca->pub, slot); - up(&ca->slot_info[slot].sem); cam_present_now = (slot_status & DVB_CA_EN50221_POLL_CAM_PRESENT) ? 1: 0; cam_changed = (slot_status & DVB_CA_EN50221_POLL_CAM_CHANGED) ? 1: 0; @@ -277,7 +277,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private* ca, int slot, u8 } /* wait for a bit */ - dvb_delay(1); + msleep(1); } dprintk("%s failed timeout:%lu\n", __FUNCTION__, jiffies - start); @@ -306,10 +306,6 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private* ca, int slot) /* we'll be determining these during this function */ ca->slot_info[slot].da_irq_supported = 0; - /* reset the link interface. Note CAM IRQs are disabled */ - if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, CMDREG_RS)) != 0) return ret; - if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ/10)) != 0) return ret; - /* set the host link buffer size temporarily. it will be overwritten with the * real negotiated size later. */ ca->slot_info[slot].link_buf_size = 2; @@ -360,6 +356,13 @@ static int dvb_ca_en50221_read_tuple(struct dvb_ca_private* ca, int slot, /* grab the next tuple length and type */ if ((_tupleType = ca->pub->read_attribute_mem(ca->pub, slot, _address)) < 0) return _tupleType; + if (_tupleType == 0xff) { + dprintk("END OF CHAIN TUPLE type:0x%x\n", _tupleType); + *address += 2; + *tupleType = _tupleType; + *tupleLength = 0; + return 0; + } if ((_tupleLength = ca->pub->read_attribute_mem(ca->pub, slot, _address+2)) < 0) return _tupleLength; _address += 4; @@ -452,8 +455,8 @@ static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private* ca, int slot) /* is it a version we support? */ if (strncmp(dvb_str + 8, "1.00", 4)) { - printk("dvb_ca: Unsupported DVB CAM module version %c%c%c%c\n", - dvb_str[8], dvb_str[9], dvb_str[10], dvb_str[11]); + printk("dvb_ca adapter %d: Unsupported DVB CAM module version %c%c%c%c\n", + ca->dvbdev->adapter->num, dvb_str[8], dvb_str[9], dvb_str[10], dvb_str[11]); return -EINVAL; } @@ -550,25 +553,22 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private* ca, int slot, u8* ebu dprintk ("%s\n", __FUNCTION__); - /* acquire the slot */ - if ((status = down_interruptible(&ca->slot_info[slot].sem)) != 0) return status; - /* check if we have space for a link buf in the rx_buffer */ if (ebuf == NULL) { - if (dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer) < - (ca->slot_info[slot].link_buf_size + DVB_RINGBUFFER_PKTHDRSIZE)) { + int buf_free; + + down_read(&ca->slot_info[slot].sem); + buf_free = dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer); + up_read(&ca->slot_info[slot].sem); + + if (buf_free < (ca->slot_info[slot].link_buf_size + DVB_RINGBUFFER_PKTHDRSIZE)) { status = -EAGAIN; goto exit; } } - /* reset the interface if there's been a tx error */ + /* check if there is data available */ if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit; - if (status & STATUSREG_TXERR) { - ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; - status = -EIO; - goto exit; - } if (!(status & STATUSREG_DA)) { /* no data */ status = 0; @@ -584,20 +584,20 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private* ca, int slot, u8* ebu /* check it will fit */ if (ebuf == NULL) { if (bytes_read > ca->slot_info[slot].link_buf_size) { - printk("dvb_ca: CAM tried to send a buffer larger than the link buffer size!\n"); + printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size!\n", ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; status = -EIO; goto exit; } if (bytes_read < 2) { - printk("dvb_ca: CAM sent a buffer that was less than 2 bytes!\n"); + printk("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n", ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; status = -EIO; goto exit; } } else { if (bytes_read > ecount) { - printk("dvb_ca: CAM tried to send a buffer larger than the ecount size!\n"); + printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n", ca->dvbdev->adapter->num); status = -EIO; goto exit; } @@ -612,20 +612,25 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private* ca, int slot, u8* ebu buf[i] = status; } - /* check for read error (RE should now go to 0) */ + /* check for read error (RE should now be 0) */ if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit; if (status & STATUSREG_RE) { + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; status = -EIO; goto exit; } /* OK, add it to the receive buffer, or copy into external buffer if supplied */ if (ebuf == NULL) { + down_read(&ca->slot_info[slot].sem); dvb_ringbuffer_pkt_write(&ca->slot_info[slot].rx_buffer, buf, bytes_read); + up_read(&ca->slot_info[slot].sem); } else { memcpy(ebuf, buf, bytes_read); } + dprintk("Received CA packet for slot %i connection id 0x%x last_frag:%i size:0x%x\n", slot, buf[0], (buf[1] & 0x80) == 0, bytes_read); + /* wake up readers when a last_fragment is received */ if ((buf[1] & 0x80) == 0x00) { wake_up_interruptible(&ca->wait_queue); @@ -634,7 +639,6 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private* ca, int slot, u8* ebu status = bytes_read; exit: - up(&ca->slot_info[slot].sem); return status; } @@ -662,19 +666,9 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private* ca, int slot, u8* bu // sanity check if (bytes_write > ca->slot_info[slot].link_buf_size) return -EINVAL; - /* acquire the slot */ - if ((status = down_interruptible(&ca->slot_info[slot].sem)) != 0) return status; - - /* reset the interface if there's been a tx error */ + /* check if interface is actually waiting for us to read from it, or if a read is in progress */ if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exitnowrite; - if (status & STATUSREG_TXERR) { - ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; - status = -EIO; - goto exitnowrite; - } - - /* check if interface is actually waiting for us to read from it */ - if (status & STATUSREG_DA) { + if (status & (STATUSREG_DA|STATUSREG_RE)) { status = -EAGAIN; goto exitnowrite; } @@ -702,16 +696,18 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private* ca, int slot, u8* bu /* check for write error (WE should now be 0) */ if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit; if (status & STATUSREG_WE) { + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; status = -EIO; goto exit; } status = bytes_write; + dprintk("Wrote CA packet for slot %i, connection id 0x%x last_frag:%i size:0x%x\n", slot, buf[0], (buf[1] & 0x80) == 0, bytes_write); + exit: ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN); exitnowrite: - up(&ca->slot_info[slot].sem); return status; } @@ -729,16 +725,14 @@ exitnowrite: */ static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private* ca, int slot) { - int status; - dprintk ("%s\n", __FUNCTION__); - if ((status = down_interruptible(&ca->slot_info[slot].sem)) != 0) return status; + down_write(&ca->slot_info[slot].sem); ca->pub->slot_shutdown(ca->pub, slot); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; if (ca->slot_info[slot].rx_buffer.data) vfree(ca->slot_info[slot].rx_buffer.data); ca->slot_info[slot].rx_buffer.data = NULL; - up(&ca->slot_info[slot].sem); + up_write(&ca->slot_info[slot].sem); /* need to wake up all processes to check if they're now trying to write to a defunct CAM */ @@ -821,10 +815,7 @@ void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221* pubca, int slot) break; case DVB_CA_SLOTSTATE_RUNNING: - flags = ca->pub->read_cam_control(pubca, slot, CTRLIF_STATUS); - if (flags & STATUSREG_DA) { - dvb_ca_en50221_thread_wakeup(ca); - } + if (ca->open) dvb_ca_en50221_read_data(ca, slot, NULL, 0); break; } } @@ -934,7 +925,11 @@ static int dvb_ca_en50221_thread(void* data) /* setup kernel thread */ snprintf(name, sizeof(name), "kdvb-ca-%i:%i", ca->dvbdev->adapter->num, ca->dvbdev->id); - dvb_kernel_thread_setup(name); + + lock_kernel (); + daemonize (name); + sigfillset (¤t->blocked); + unlock_kernel (); /* choose the correct initial delay */ dvb_ca_en50221_thread_update_delay(ca); @@ -984,7 +979,7 @@ static int dvb_ca_en50221_thread(void* data) case DVB_CA_SLOTSTATE_WAITREADY: if (time_after(jiffies, ca->slot_info[slot].timeout)) { - printk("dvb_ca: PC card did not respond :(\n"); + printk("dvb_ca adaptor %d: PC card did not respond :(\n", ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; dvb_ca_en50221_thread_update_delay(ca); break; @@ -994,13 +989,19 @@ static int dvb_ca_en50221_thread(void* data) case DVB_CA_SLOTSTATE_VALIDATE: if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) { - printk("dvb_ca: Invalid PC card inserted :(\n"); + printk("dvb_ca adapter %d: Invalid PC card inserted :(\n", ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; - dvb_ca_en50221_thread_update_delay(ca); + dvb_ca_en50221_thread_update_delay(ca); break; } if (dvb_ca_en50221_set_configoption(ca, slot) != 0) { - printk("dvb_ca: Unable to initialise CAM :(\n"); + printk("dvb_ca adapter %d: Unable to initialise CAM :(\n", ca->dvbdev->adapter->num); + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + if (ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, CMDREG_RS) != 0) { + printk("dvb_ca adapter %d: Unable to reset CAM IF\n", ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; dvb_ca_en50221_thread_update_delay(ca); break; @@ -1015,7 +1016,7 @@ static int dvb_ca_en50221_thread(void* data) case DVB_CA_SLOTSTATE_WAITFR: if (time_after(jiffies, ca->slot_info[slot].timeout)) { - printk("dvb_ca: DVB CAM did not respond :(\n"); + printk("dvb_ca adapter %d: DVB CAM did not respond :(\n", ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; dvb_ca_en50221_thread_update_delay(ca); break; @@ -1030,7 +1031,7 @@ static int dvb_ca_en50221_thread(void* data) case DVB_CA_SLOTSTATE_LINKINIT: if (dvb_ca_en50221_link_init(ca, slot) != 0) { - printk("dvb_ca: DVB CAM link initialisation failed :(\n"); + printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; dvb_ca_en50221_thread_update_delay(ca); break; @@ -1038,7 +1039,7 @@ static int dvb_ca_en50221_thread(void* data) rxbuf = vmalloc(RX_BUFFER_SIZE); if (rxbuf == NULL) { - printk("dvb_ca: Unable to allocate CAM rx buffer :(\n"); + printk("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n", ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; dvb_ca_en50221_thread_update_delay(ca); break; @@ -1048,12 +1049,16 @@ static int dvb_ca_en50221_thread(void* data) ca->pub->slot_ts_enable(ca->pub, slot); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING; dvb_ca_en50221_thread_update_delay(ca); - printk("dvb_ca: DVB CAM detected and initialised successfully\n"); + printk("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n", ca->dvbdev->adapter->num); break; case DVB_CA_SLOTSTATE_RUNNING: if (!ca->open) break; + // no need to poll if the CAM supports IRQs + if (ca->slot_info[slot].da_irq_supported) break; + + // poll mode pktcount = 0; while(dvb_ca_en50221_read_data(ca, slot, NULL, 0) > 0) { if (!ca->open) break; @@ -1196,7 +1201,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file, const char __user *buf int status; char fragbuf[HOST_LINK_BUF_SIZE]; int fragpos = 0; - size_t fraglen; + int fraglen; unsigned long timeout; int written; @@ -1233,7 +1238,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file, const char __user *buf } if (status != -EAGAIN) goto exit; - dvb_delay(1); + msleep(1); } if (!written) { status = -EIO; @@ -1257,7 +1262,7 @@ static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private* ca, int* resu int slot; int slot_count = 0; int idx; - size_t fraglen; + int fraglen; int connection_id = -1; int found = 0; u8 hdr[2]; @@ -1266,7 +1271,7 @@ static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private* ca, int* resu while((slot_count < ca->slot_count) && (!found)) { if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) goto nextslot; - if ((*result = down_interruptible(&ca->slot_info[slot].sem)) != 0) return 1; + down_read(&ca->slot_info[slot].sem); idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen); while(idx != -1) { @@ -1281,7 +1286,7 @@ static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private* ca, int* resu idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen); } - if (!found) up(&ca->slot_info[slot].sem); + if (!found) up_read(&ca->slot_info[slot].sem); nextslot: slot = (slot + 1) % ca->slot_count; @@ -1341,7 +1346,7 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user *buf, size_ pktlen = 2; do { if (idx == -1) { - printk("dvb_ca: BUG: read packet ended before last_fragment encountered\n"); + printk("dvb_ca adapter %d: BUG: read packet ended before last_fragment encountered\n", ca->dvbdev->adapter->num); status = -EIO; goto exit; } @@ -1378,7 +1383,7 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user *buf, size_ status = pktlen; exit: - up(&ca->slot_info[slot].sem); + up_read(&ca->slot_info[slot].sem); return status; } @@ -1406,7 +1411,9 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file) for(i=0; i< ca->slot_count; i++) { if (ca->slot_info[i].slot_state == DVB_CA_SLOTSTATE_RUNNING) { + down_write(&ca->slot_info[i].sem); dvb_ringbuffer_flush(&ca->slot_info[i].rx_buffer); + up_write(&ca->slot_info[i].sem); } } @@ -1464,7 +1471,7 @@ static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table *wait) dprintk ("%s\n", __FUNCTION__); if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) { - up(&ca->slot_info[slot].sem); + up_read(&ca->slot_info[slot].sem); mask |= POLLIN; } @@ -1475,32 +1482,30 @@ static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table *wait) poll_wait(file, &ca->wait_queue, wait); if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) { - up(&ca->slot_info[slot].sem); + up_read(&ca->slot_info[slot].sem); mask |= POLLIN; } return mask; } - static struct file_operations dvb_ca_fops = { - .owner = THIS_MODULE, - .read = dvb_ca_en50221_io_read, - .write = dvb_ca_en50221_io_write, - .ioctl = dvb_ca_en50221_io_ioctl, - .open = dvb_ca_en50221_io_open, - .release = dvb_ca_en50221_io_release, - .poll = dvb_ca_en50221_io_poll, + .owner = THIS_MODULE, + .read = dvb_ca_en50221_io_read, + .write = dvb_ca_en50221_io_write, + .ioctl = dvb_ca_en50221_io_ioctl, + .open = dvb_ca_en50221_io_open, + .release= dvb_ca_en50221_io_release, + .poll = dvb_ca_en50221_io_poll, }; static struct dvb_device dvbdev_ca = { - .users = 1, - .readers = 1, - .writers = 1, - .fops = &dvb_ca_fops, + .users = 1, + .readers= 1, + .writers= 1, + .fops = &dvb_ca_fops, }; - /* ******************************************************************************** */ /* Initialisation/shutdown functions */ @@ -1558,7 +1563,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221* ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE; atomic_set(&ca->slot_info[i].camchange_count, 0); ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED; - init_MUTEX(&ca->slot_info[i].sem); + init_rwsem(&ca->slot_info[i].sem); } if (signal_pending(current)) { @@ -1604,7 +1609,7 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221* pubca) /* shutdown the thread if there was one */ if (ca->thread_pid) { if (kill_proc(ca->thread_pid, 0, 1) == -ESRCH) { - printk("dvb_ca_release: thread PID %d already died\n", ca->thread_pid); + printk("dvb_ca_release adapter %d: thread PID %d already died\n", ca->dvbdev->adapter->num, ca->thread_pid); } else { ca->exit = 1; mb(); @@ -1622,6 +1627,3 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221* pubca) pubca->private = NULL; } -MODULE_PARM(dvb_ca_en50221_debug,"i"); - -MODULE_PARM_DESC(dvb_ca_en50221_debug, "enable verbose debug messages"); diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h b/drivers/media/dvb/dvb-core/dvb_ca_en50221.h index 8458f7afdadb..882ca41a28dd 100644 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h +++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.h @@ -42,6 +42,9 @@ /* Structure describing a CA interface */ struct dvb_ca_en50221 { + /* NOTE: the read_*, write_* and poll_slot_status functions must use locks as + * they may be called from several threads at once */ + /* functions for accessing attribute memory on the CAM */ int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address); int (*write_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address, u8 value); diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c index 657d5579b16b..6b55e4910efa 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb/dvb-core/dvb_demux.c @@ -31,7 +31,6 @@ #include #include "dvb_demux.h" -#include "dvb_functions.h" #define NOBUFS /* @@ -570,24 +569,30 @@ static int dvb_demux_feed_find(struct dvb_demux_feed *feed) static void dvb_demux_feed_add(struct dvb_demux_feed *feed) { + spin_lock_irq(&feed->demux->lock); if (dvb_demux_feed_find(feed)) { printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n", __FUNCTION__, feed->type, feed->state, feed->pid); - return; + goto out; } list_add(&feed->list_head, &feed->demux->feed_list); +out: + spin_unlock_irq(&feed->demux->lock); } static void dvb_demux_feed_del(struct dvb_demux_feed *feed) { + spin_lock_irq(&feed->demux->lock); if (!(dvb_demux_feed_find(feed))) { printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n", __FUNCTION__, feed->type, feed->state, feed->pid); - return; + goto out; } list_del(&feed->list_head); +out: + spin_unlock_irq(&feed->demux->lock); } static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type, @@ -789,7 +794,7 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dmx_ts_feed *ts_ feed->pid = 0xffff; - if (feed->ts_type & TS_DECODER) + if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_TS_PES_OTHER) demux->pesfilter[feed->pes_type] = NULL; up(&demux->mutex); diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 94d6cfabf1ef..1e9b36ff5e63 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1,5 +1,6 @@ /* - * dvb-core.c: DVB core driver + * dvb_frontend.c: DVB frontend tuning interface/thread + * * * Copyright (C) 1999-2001 Ralph Metzler * Marcus Metzler @@ -31,13 +32,33 @@ #include #include #include +#include #include #include #include #include "dvb_frontend.h" #include "dvbdev.h" -#include "dvb_functions.h" + +static int dvb_frontend_debug; +static int dvb_shutdown_timeout = 5; +static int dvb_override_frequency_bending; +static int dvb_force_auto_inversion; +static int dvb_override_tune_delay; +static int do_frequency_bending; + +module_param_named(frontend_debug, dvb_frontend_debug, int, 0644); +MODULE_PARM_DESC(dvb_frontend_debug, "Turn on/off frontend core debugging (default:off)."); +module_param(dvb_shutdown_timeout, int, 0444); +MODULE_PARM_DESC(dvb_shutdown_timeout, "wait seconds after close() before suspending hardware"); +module_param(dvb_override_frequency_bending, int, 0444); +MODULE_PARM_DESC(dvb_override_frequency_bending, "0: normal (default), 1: never use frequency bending, 2: always use frequency bending"); +module_param(dvb_force_auto_inversion, int, 0444); +MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always"); +module_param(dvb_override_tune_delay, int, 0444); +MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt"); + +#define dprintk if (dvb_frontend_debug) printk #define FESTATE_IDLE 1 #define FESTATE_RETUNE 2 @@ -66,17 +87,6 @@ * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again. */ - -static int dvb_frontend_debug = 0; -static int dvb_shutdown_timeout = 5; -static int dvb_override_frequency_bending = 0; -static int dvb_force_auto_inversion = 0; -static int dvb_override_tune_delay = 0; - -static int do_frequency_bending = 0; - -#define dprintk if (dvb_frontend_debug) printk - #define MAX_EVENT 8 struct dvb_fe_events { @@ -95,6 +105,7 @@ struct dvb_frontend_data { struct dvb_device *dvbdev; struct dvb_frontend_parameters parameters; struct dvb_fe_events events; + struct module *module; struct semaphore sem; struct list_head list_head; wait_queue_head_t wait_queue; @@ -174,7 +185,7 @@ static void dvb_bend_frequency (struct dvb_frontend_data *this_fe, int recursive { struct list_head *entry; int stepsize = this_fe->info->frequency_stepsize; - int this_fe_adap_num = this_fe->frontend.i2c->adapter->num; + int this_fe_adap_num = this_fe->frontend.dvb_adapter->num; int frequency; if (!stepsize || recursive > 10) { @@ -198,7 +209,7 @@ static void dvb_bend_frequency (struct dvb_frontend_data *this_fe, int recursive fe = list_entry (entry, struct dvb_frontend_data, list_head); - if (fe->frontend.i2c->adapter->num != this_fe_adap_num) + if (fe->frontend.dvb_adapter->num != this_fe_adap_num) continue; f = fe->parameters.frequency; @@ -233,13 +244,10 @@ static void dvb_call_frontend_notifiers (struct dvb_frontend_data *fe, dprintk ("%s\n", __FUNCTION__); if (((s ^ fe->status) & FE_HAS_LOCK) && (s & FE_HAS_LOCK)) - dvb_delay (fe->info->notifier_delay); + msleep (fe->info->notifier_delay); fe->status = s; - if (!(s & FE_HAS_LOCK) && (fe->info->caps & FE_CAN_MUTE_TS)) - return; - /** * now tell the Demux about the TS status changes... */ @@ -333,8 +341,8 @@ static void dvb_frontend_init (struct dvb_frontend_data *fe) { struct dvb_frontend *frontend = &fe->frontend; - dprintk ("DVB: initialising frontend %i:%i (%s)...\n", - frontend->i2c->adapter->num, frontend->i2c->id, + dprintk ("DVB: initialising frontend %i (%s)...\n", + frontend->dvb_adapter->num, fe->info->name); dvb_frontend_internal_ioctl (frontend, FE_INIT, NULL); @@ -371,25 +379,26 @@ static int dvb_frontend_autotune(struct dvb_frontend_data *fe, int check_wrapped int original_inversion = fe->parameters.inversion; u32 original_frequency = fe->parameters.frequency; - // are we using autoinversion? - autoinversion = ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) && (fe->parameters.inversion == INVERSION_AUTO)); + /* are we using autoinversion? */ + autoinversion = ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) && + (fe->parameters.inversion == INVERSION_AUTO)); - // setup parameters correctly + /* setup parameters correctly */ while(!ready) { - // calculate the lnb_drift + /* calculate the lnb_drift */ fe->lnb_drift = fe->auto_step * fe->step_size; - // wrap the auto_step if we've exceeded the maximum drift + /* wrap the auto_step if we've exceeded the maximum drift */ if (fe->lnb_drift > fe->max_drift) { fe->auto_step = 0; fe->auto_sub_step = 0; fe->lnb_drift = 0; } - // perform inversion and +/- zigzag + /* perform inversion and +/- zigzag */ switch(fe->auto_sub_step) { case 0: - // try with the current inversion and current drift setting + /* try with the current inversion and current drift setting */ ready = 1; break; @@ -418,35 +427,36 @@ static int dvb_frontend_autotune(struct dvb_frontend_data *fe, int check_wrapped default: fe->auto_step++; - fe->auto_sub_step = -1; // it'll be incremented to 0 in a moment + fe->auto_sub_step = -1; /* it'll be incremented to 0 in a moment */ break; } if (!ready) fe->auto_sub_step++; } - // if this attempt would hit where we started, indicate a complete iteration has occurred - if ((fe->auto_step == fe->started_auto_step) && (fe->auto_sub_step == 0) && check_wrapped) { + /* if this attempt would hit where we started, indicate a complete + * iteration has occurred */ + if ((fe->auto_step == fe->started_auto_step) && + (fe->auto_sub_step == 0) && check_wrapped) { return 1; } - // perform frequency bending if necessary + /* perform frequency bending if necessary */ if ((dvb_override_frequency_bending != 1) && do_frequency_bending) dvb_bend_frequency(fe, 0); - // instrumentation - dprintk("%s: drift:%i bending:%i inversion:%i auto_step:%i auto_sub_step:%i started_auto_step:%i\n", - __FUNCTION__, fe->lnb_drift, fe->bending, fe->inversion, fe->auto_step, fe->auto_sub_step, - fe->started_auto_step); + dprintk("%s: drift:%i bending:%i inversion:%i auto_step:%i " + "auto_sub_step:%i started_auto_step:%i\n", + __FUNCTION__, fe->lnb_drift, fe->bending, fe->inversion, + fe->auto_step, fe->auto_sub_step, fe->started_auto_step); - // set the frontend itself + /* set the frontend itself */ fe->parameters.frequency += fe->lnb_drift + fe->bending; if (autoinversion) fe->parameters.inversion = fe->inversion; dvb_frontend_internal_ioctl (&fe->frontend, FE_SET_FRONTEND, &fe->parameters); fe->parameters.frequency = original_frequency; fe->parameters.inversion = original_inversion; - // normal return fe->auto_sub_step++; return 0; } @@ -490,10 +500,13 @@ static int dvb_frontend_thread (void *data) dprintk ("%s\n", __FUNCTION__); - snprintf (name, sizeof(name), "kdvb-fe-%i:%i", - fe->frontend.i2c->adapter->num, fe->frontend.i2c->id); + snprintf (name, sizeof(name), "kdvb-fe-%i", + fe->frontend.dvb_adapter->num); - dvb_kernel_thread_setup (name); + lock_kernel (); + daemonize (name); + sigfillset (¤t->blocked); + unlock_kernel (); dvb_call_frontend_notifiers (fe, 0); dvb_frontend_init (fe); @@ -511,65 +524,70 @@ static int dvb_frontend_thread (void *data) if (down_interruptible (&fe->sem)) break; - // if we've got no parameters, just keep idling + /* if we've got no parameters, just keep idling */ if (fe->state & FESTATE_IDLE) { delay = 3*HZ; quality = 0; continue; } - // get the frontend status + /* get the frontend status */ + if (fe->state & FESTATE_RETUNE) { + s = 0; + } else { dvb_frontend_internal_ioctl (&fe->frontend, FE_READ_STATUS, &s); - if (s != fe->status) + if (s != fe->status) { dvb_frontend_add_event (fe, s); - - // if we're not tuned, and we have a lock, move to the TUNED state + } + } + /* if we're not tuned, and we have a lock, move to the TUNED state */ if ((fe->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) { update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK); fe->state = FESTATE_TUNED; - // if we're tuned, then we have determined the correct inversion - if ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) && (fe->parameters.inversion == INVERSION_AUTO)) { + /* if we're tuned, then we have determined the correct inversion */ + if ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) && + (fe->parameters.inversion == INVERSION_AUTO)) { fe->parameters.inversion = fe->inversion; } continue; } - // if we are tuned already, check we're still locked + /* if we are tuned already, check we're still locked */ if (fe->state & FESTATE_TUNED) { update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK); - // we're tuned, and the lock is still good... - if (s & FE_HAS_LOCK) { + /* we're tuned, and the lock is still good... */ + if (s & FE_HAS_LOCK) continue; - } else { - // if we _WERE_ tuned, but now don't have a lock, need to zigzag + else { + /* if we _WERE_ tuned, but now don't have a lock, + * need to zigzag */ fe->state = FESTATE_ZIGZAG_FAST; fe->started_auto_step = fe->auto_step; check_wrapped = 0; - // fallthrough } } - // don't actually do anything if we're in the LOSTLOCK state, the frontend is set to - // FE_CAN_RECOVER, and the max_drift is 0 + /* don't actually do anything if we're in the LOSTLOCK state, + * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */ if ((fe->state & FESTATE_LOSTLOCK) && (fe->info->caps & FE_CAN_RECOVER) && (fe->max_drift == 0)) { update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK); continue; } - // don't do anything if we're in the DISEQC state, since this might be someone - // with a motorized dish controlled by DISEQC. If its actually a re-tune, there will - // be a SET_FRONTEND soon enough. + /* don't do anything if we're in the DISEQC state, since this + * might be someone with a motorized dish controlled by DISEQC. + * If its actually a re-tune, there will be a SET_FRONTEND soon enough. */ if (fe->state & FESTATE_DISEQC) { update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK); continue; } - // if we're in the RETUNE state, set everything up for a brand new scan, - // keeping the current inversion setting, as the next tune is _very_ likely - // to require the same + /* if we're in the RETUNE state, set everything up for a brand + * new scan, keeping the current inversion setting, as the next + * tune is _very_ likely to require the same */ if (fe->state & FESTATE_RETUNE) { fe->lnb_drift = 0; fe->auto_step = 0; @@ -578,35 +596,36 @@ static int dvb_frontend_thread (void *data) check_wrapped = 0; } - // fast zigzag. + /* fast zigzag. */ if ((fe->state & FESTATE_SEARCHING_FAST) || (fe->state & FESTATE_RETUNE)) { delay = fe->min_delay; - // peform a tune + /* peform a tune */ if (dvb_frontend_autotune(fe, check_wrapped)) { - // OK, if we've run out of trials at the fast speed. Drop back to - // slow for the _next_ attempt + /* OK, if we've run out of trials at the fast speed. + * Drop back to slow for the _next_ attempt */ fe->state = FESTATE_SEARCHING_SLOW; fe->started_auto_step = fe->auto_step; continue; } check_wrapped = 1; - // if we've just retuned, enter the ZIGZAG_FAST state. This ensures - // we cannot return from an FE_SET_FRONTEND ioctl before the first frontend - // tune occurs + /* if we've just retuned, enter the ZIGZAG_FAST state. + * This ensures we cannot return from an + * FE_SET_FRONTEND ioctl before the first frontend tune + * occurs */ if (fe->state & FESTATE_RETUNE) { fe->state = FESTATE_TUNING_FAST; wake_up_interruptible(&fe->wait_queue); } } - // slow zigzag + /* slow zigzag */ if (fe->state & FESTATE_SEARCHING_SLOW) { update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK); - // Note: don't bother checking for wrapping; we stay in this state - // until we get a lock + /* Note: don't bother checking for wrapping; we stay in this + * state until we get a lock */ dvb_frontend_autotune(fe, 0); } }; @@ -614,8 +633,6 @@ static int dvb_frontend_thread (void *data) if (dvb_shutdown_timeout) dvb_frontend_internal_ioctl (&fe->frontend, FE_SLEEP, NULL); - up (&fe->sem); - fe->thread_pid = 0; mb(); @@ -711,6 +728,11 @@ static int dvb_frontend_ioctl (struct inode *inode, struct file *file, if (!fe || !fe->frontend.ioctl || fe->exit) return -ENODEV; + if ((file->f_flags & O_ACCMODE) == O_RDONLY && + (_IOC_DIR(cmd) != _IOC_READ || cmd == FE_GET_EVENT || + cmd == FE_DISEQC_RECV_SLAVE_REPLY)) + return -EPERM; + if (down_interruptible (&fe->sem)) return -ERESTARTSYS; @@ -718,6 +740,7 @@ static int dvb_frontend_ioctl (struct inode *inode, struct file *file, case FE_DISEQC_SEND_MASTER_CMD: case FE_DISEQC_SEND_BURST: case FE_SET_TONE: + case FE_SET_VOLTAGE: if (fe->status) dvb_call_frontend_notifiers (fe, 0); dvb_frontend_internal_ioctl (&fe->frontend, cmd, parg); @@ -734,43 +757,48 @@ static int dvb_frontend_ioctl (struct inode *inode, struct file *file, memcpy(&fetunesettings.parameters, parg, sizeof (struct dvb_frontend_parameters)); - // force auto frequency inversion if requested + /* force auto frequency inversion if requested */ if (dvb_force_auto_inversion) { fe->parameters.inversion = INVERSION_AUTO; fetunesettings.parameters.inversion = INVERSION_AUTO; } - // get frontend-specific tuning settings - if (dvb_frontend_internal_ioctl(&fe->frontend, FE_GET_TUNE_SETTINGS, &fetunesettings) == 0) { + /* get frontend-specific tuning settings */ + if (dvb_frontend_internal_ioctl(&fe->frontend, FE_GET_TUNE_SETTINGS, + &fetunesettings) == 0) { fe->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000; fe->max_drift = fetunesettings.max_drift; fe->step_size = fetunesettings.step_size; } else { - // default values + /* default values */ switch(fe->info->type) { case FE_QPSK: - fe->min_delay = HZ/20; // default mindelay of 50ms + fe->min_delay = HZ/20; fe->step_size = fe->parameters.u.qpsk.symbol_rate / 16000; fe->max_drift = fe->parameters.u.qpsk.symbol_rate / 2000; break; case FE_QAM: - fe->min_delay = HZ/20; // default mindelay of 50ms - fe->step_size = 0; - fe->max_drift = 0; // don't want any zigzagging under DVB-C frontends + fe->min_delay = HZ/20; + fe->step_size = 0; /* no zigzag */ + fe->max_drift = 0; break; case FE_OFDM: - fe->min_delay = HZ/20; // default mindelay of 50ms + fe->min_delay = HZ/20; fe->step_size = fe->info->frequency_stepsize * 2; fe->max_drift = (fe->info->frequency_stepsize * 2) + 1; break; + case FE_ATSC: + printk("dvb-core: FE_ATSC not handled yet.\n"); + break; } } if (dvb_override_tune_delay > 0) { fe->min_delay = (dvb_override_tune_delay * HZ) / 1000; } + dvb_frontend_wakeup(fe); dvb_frontend_add_event (fe, 0); break; @@ -789,20 +817,13 @@ static int dvb_frontend_ioctl (struct inode *inode, struct file *file, if (err < 0) return err; - // Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't do it, it is done for it. + /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't + * do it, it is done for it. */ if ((cmd == FE_GET_INFO) && (err == 0)) { struct dvb_frontend_info* tmp = (struct dvb_frontend_info*) parg; tmp->caps |= FE_CAN_INVERSION_AUTO; } - // if the frontend has just been set, wait until the first tune has finished. - // This ensures the app doesn't start reading data too quickly, perhaps from the - // previous lock, which is REALLY CONFUSING TO DEBUG! - if ((cmd == FE_SET_FRONTEND) && (err == 0)) { - dvb_frontend_wakeup(fe); - err = wait_event_interruptible(fe->wait_queue, fe->state & ~FESTATE_RETUNE); - } - return err; } @@ -843,6 +864,11 @@ static int dvb_frontend_open (struct inode *inode, struct file *file) fe->events.eventr = fe->events.eventw = 0; } + if (!ret && fe->module) { + if (!try_module_get(fe->module)) + return -EINVAL; + } + return ret; } @@ -851,13 +877,19 @@ static int dvb_frontend_release (struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; struct dvb_frontend_data *fe = dvbdev->priv; + int ret = 0; dprintk ("%s\n", __FUNCTION__); if ((file->f_flags & O_ACCMODE) != O_RDONLY) fe->release_jiffies = jiffies; - return dvb_generic_release (inode, file); + ret = dvb_generic_release (inode, file); + + if (!ret && fe->module) + module_put(fe->module); + + return ret; } @@ -897,7 +929,7 @@ dvb_add_frontend_ioctls (struct dvb_adapter *adapter, fe = list_entry (entry, struct dvb_frontend_data, list_head); - if (fe->frontend.i2c->adapter == adapter && + if (fe->frontend.dvb_adapter == adapter && fe->frontend.before_ioctl == NULL && fe->frontend.after_ioctl == NULL) { @@ -931,7 +963,7 @@ dvb_remove_frontend_ioctls (struct dvb_adapter *adapter, fe = list_entry (entry, struct dvb_frontend_data, list_head); - if (fe->frontend.i2c->adapter == adapter && + if (fe->frontend.dvb_adapter == adapter && fe->frontend.before_ioctl == before_ioctl && fe->frontend.after_ioctl == after_ioctl) { @@ -992,7 +1024,7 @@ dvb_add_frontend_notifier (struct dvb_adapter *adapter, fe = list_entry (entry, struct dvb_frontend_data, list_head); - if (fe->frontend.i2c->adapter == adapter && + if (fe->frontend.dvb_adapter == adapter && fe->frontend.notifier_callback == NULL) { fe->frontend.notifier_callback = callback; @@ -1021,7 +1053,7 @@ dvb_remove_frontend_notifier (struct dvb_adapter *adapter, fe = list_entry (entry, struct dvb_frontend_data, list_head); - if (fe->frontend.i2c->adapter == adapter && + if (fe->frontend.dvb_adapter == adapter && fe->frontend.notifier_callback == callback) { fe->frontend.notifier_callback = NULL; @@ -1061,9 +1093,10 @@ static struct file_operations dvb_frontend_fops = { int dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg), - struct dvb_i2c_bus *i2c, + struct dvb_adapter *dvb_adapter, void *data, - struct dvb_frontend_info *info) + struct dvb_frontend_info *info, + struct module *module) { struct list_head *entry; struct dvb_frontend_data *fe; @@ -1093,9 +1126,10 @@ dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend, init_MUTEX (&fe->events.sem); fe->events.eventw = fe->events.eventr = 0; fe->events.overflow = 0; + fe->module = module; fe->frontend.ioctl = ioctl; - fe->frontend.i2c = i2c; + fe->frontend.dvb_adapter = dvb_adapter; fe->frontend.data = data; fe->info = info; fe->inversion = INVERSION_OFF; @@ -1107,7 +1141,7 @@ dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend, struct dvb_frontend_ioctl_data, list_head); - if (ioctl->adapter == i2c->adapter) { + if (ioctl->adapter == dvb_adapter) { fe->frontend.before_ioctl = ioctl->before_ioctl; fe->frontend.after_ioctl = ioctl->after_ioctl; fe->frontend.before_after_data = ioctl->before_after_data; @@ -1122,7 +1156,7 @@ dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend, struct dvb_frontend_notifier_data, list_head); - if (notifier->adapter == i2c->adapter) { + if (notifier->adapter == dvb_adapter) { fe->frontend.notifier_callback = notifier->callback; fe->frontend.notifier_data = notifier->data; break; @@ -1131,11 +1165,11 @@ dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend, list_add_tail (&fe->list_head, &frontend_list); - printk ("DVB: registering frontend %i:%i (%s)...\n", - fe->frontend.i2c->adapter->num, fe->frontend.i2c->id, + printk ("DVB: registering frontend %i (%s)...\n", + fe->frontend.dvb_adapter->num, fe->info->name); - dvb_register_device (i2c->adapter, &fe->dvbdev, &dvbdev_template, + dvb_register_device (dvb_adapter, &fe->dvbdev, &dvbdev_template, fe, DVB_DEVICE_FRONTEND); if ((info->caps & FE_NEEDS_BENDING) || (dvb_override_frequency_bending == 2)) @@ -1146,10 +1180,9 @@ dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend, return 0; } - -int dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend, +int dvb_unregister_frontend_new (int (*ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg), - struct dvb_i2c_bus *i2c) + struct dvb_adapter *dvb_adapter) { struct list_head *entry, *n; @@ -1162,7 +1195,7 @@ int dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend, fe = list_entry (entry, struct dvb_frontend_data, list_head); - if (fe->frontend.ioctl == ioctl && fe->frontend.i2c == i2c) { + if (fe->frontend.ioctl == ioctl && fe->frontend.dvb_adapter == dvb_adapter) { dvb_unregister_device (fe->dvbdev); list_del (entry); up (&frontend_mutex); @@ -1176,14 +1209,3 @@ int dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend, return -EINVAL; } -MODULE_PARM(dvb_frontend_debug,"i"); -MODULE_PARM(dvb_shutdown_timeout,"i"); -MODULE_PARM(dvb_override_frequency_bending,"i"); -MODULE_PARM(dvb_force_auto_inversion,"i"); -MODULE_PARM(dvb_override_tune_delay,"i"); - -MODULE_PARM_DESC(dvb_frontend_debug, "enable verbose debug messages"); -MODULE_PARM_DESC(dvb_shutdown_timeout, "wait seconds after close() before suspending hardware"); -MODULE_PARM_DESC(dvb_override_frequency_bending, "0: normal (default), 1: never use frequency bending, 2: always use frequency bending"); -MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always"); -MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt"); diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 8d8e21fa8395..505fd9b1e93d 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -31,14 +31,29 @@ #include #include #include +#include #include -#include "dvb_i2c.h" #include "dvbdev.h" - - +/* FIXME: Move to i2c-id.h */ +#define I2C_DRIVERID_DVBFE_ALPS_TDLB7 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_ALPS_TDMB7 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_AT76C651 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_CX24110 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_DST I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_DUMMY I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_L64781 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_MT312 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_MT352 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_NXT6000 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_SP887X I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_STV0299 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_TDA1004X I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_TDA8083 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_VES1820 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_VES1X93 I2C_DRIVERID_EXP2 /** * when before_ioctl is registered and returns value 0, ioctl and after_ioctl @@ -50,7 +65,7 @@ struct dvb_frontend { int (*ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg); int (*after_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg); void (*notifier_callback) (fe_status_t s, void *data); - struct dvb_i2c_bus *i2c; + struct dvb_adapter *dvb_adapter; void *before_after_data; /* can be used by hardware module... */ void *notifier_data; /* can be used by hardware module... */ void *data; /* can be used by hardware module... */ @@ -75,19 +90,21 @@ struct dvb_frontend_tune_settings { #define FE_SLEEP _IO('v', 80) #define FE_INIT _IO('v', 81) #define FE_GET_TUNE_SETTINGS _IOWR('v', 83, struct dvb_frontend_tune_settings) - +#define FE_REGISTER _IO ('v', 84) +#define FE_UNREGISTER _IO ('v', 85) extern int dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg), - struct dvb_i2c_bus *i2c, + struct dvb_adapter *dvb_adapter, void *data, - struct dvb_frontend_info *info); + struct dvb_frontend_info *info, + struct module *module); extern int -dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend, +dvb_unregister_frontend_new (int (*ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg), - struct dvb_i2c_bus *i2c); + struct dvb_adapter *dvb_adapter); /** diff --git a/drivers/media/dvb/dvb-core/dvb_functions.c b/drivers/media/dvb/dvb-core/dvb_functions.c deleted file mode 100644 index 2a39b2ef98e5..000000000000 --- a/drivers/media/dvb/dvb-core/dvb_functions.c +++ /dev/null @@ -1,89 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -void dvb_kernel_thread_setup (const char *thread_name) -{ - lock_kernel (); - - daemonize (thread_name); - - sigfillset (¤t->blocked); - - unlock_kernel (); -} - -/* if the miracle happens and "generic_usercopy()" is included into - the kernel, then this can vanish. please don't make the mistake and - define this as video_usercopy(). this will introduce a dependecy - to the v4l "videodev.o" module, which is unnecessary for some - cards (ie. the budget dvb-cards don't need the v4l module...) */ -int dvb_usercopy(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg)) -{ - char sbuf[128]; - void *mbuf = NULL; - void *parg = NULL; - int err = -EINVAL; - - /* Copy arguments into temp kernel buffer */ - switch (_IOC_DIR(cmd)) { - case _IOC_NONE: - /* - * For this command, the pointer is actually an integer - * argument. - */ - parg = (void *) arg; - break; - case _IOC_READ: /* some v4l ioctls are marked wrong ... */ - case _IOC_WRITE: - case (_IOC_WRITE | _IOC_READ): - if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { - parg = sbuf; - } else { - /* too big to allocate from stack */ - mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); - if (NULL == mbuf) - return -ENOMEM; - parg = mbuf; - } - - err = -EFAULT; - if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) - goto out; - break; - } - - /* call driver */ - if ((err = func(inode, file, cmd, parg)) == -ENOIOCTLCMD) - err = -EINVAL; - - if (err < 0) - goto out; - - /* Copy results into user buffer */ - switch (_IOC_DIR(cmd)) - { - case _IOC_READ: - case (_IOC_WRITE | _IOC_READ): - if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) - err = -EFAULT; - break; - } - -out: - if (mbuf) - kfree(mbuf); - - return err; -} - -EXPORT_SYMBOL(dvb_usercopy); -EXPORT_SYMBOL(dvb_kernel_thread_setup); diff --git a/drivers/media/dvb/dvb-core/dvb_functions.h b/drivers/media/dvb/dvb-core/dvb_functions.h deleted file mode 100644 index 294501e03d96..000000000000 --- a/drivers/media/dvb/dvb-core/dvb_functions.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * dvb_functions.h: isolate some Linux specific stuff from the dvb-core - * that can't be expressed as a one-liner - * in order to make porting to other environments easier - * - * Copyright (C) 2003 Convergence GmbH - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Lesser Public License - * as published by the Free Software Foundation; either version 2.1 - * 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef __DVB_FUNCTIONS_H__ -#define __DVB_FUNCTIONS_H__ - -/** - * a sleeping delay function, waits i ms - * - */ -static inline -void dvb_delay(int i) -{ - current->state=TASK_INTERRUPTIBLE; - schedule_timeout((HZ*i)/1000); -} - -/* we don't mess with video_usercopy() any more, -we simply define out own dvb_usercopy(), which will hopefull become -generic_usercopy() someday... */ - -extern int dvb_usercopy(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg)); - -extern void dvb_kernel_thread_setup (const char *thread_name); - -#endif - diff --git a/drivers/media/dvb/dvb-core/dvb_i2c.c b/drivers/media/dvb/dvb-core/dvb_i2c.c deleted file mode 100644 index 8bc8b5e7b30b..000000000000 --- a/drivers/media/dvb/dvb-core/dvb_i2c.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * dvb_i2c.h: simplified i2c interface for DVB adapters to get rid of i2c-core.c - * - * Copyright (C) 2002 Holger Waechtler for convergence integrated media GmbH - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * Or, point your browser to http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include -#include -#include - -#include "dvb_i2c.h" -#include "dvb_functions.h" - - -struct dvb_i2c_device { - struct list_head list_head; - struct module *owner; - int (*attach) (struct dvb_i2c_bus *i2c, void **data); - void (*detach) (struct dvb_i2c_bus *i2c, void *data); - void *data; -}; - -LIST_HEAD(dvb_i2c_buslist); -LIST_HEAD(dvb_i2c_devicelist); - -DECLARE_MUTEX(dvb_i2c_mutex); - -static int register_i2c_client (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev) -{ - struct dvb_i2c_device *client; - - if (!(client = kmalloc (sizeof (struct dvb_i2c_device), GFP_KERNEL))) - return -ENOMEM; - - client->detach = dev->detach; - client->owner = dev->owner; - client->data = dev->data; - - INIT_LIST_HEAD(&client->list_head); - - list_add_tail (&client->list_head, &i2c->client_list); - - return 0; -} - - -static void try_attach_device (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev) -{ - if (dev->owner) { - if (!try_module_get(dev->owner)) - return; - } - - if (dev->attach (i2c, &dev->data) == 0) { - register_i2c_client (i2c, dev); - } else { - if (dev->owner) - module_put (dev->owner); - } -} - - -static void detach_device (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev) -{ - dev->detach (i2c, dev->data); - - if (dev->owner) - module_put (dev->owner); -} - - -static void unregister_i2c_client_from_bus (struct dvb_i2c_device *dev, - struct dvb_i2c_bus *i2c) -{ - struct list_head *entry, *n; - - list_for_each_safe (entry, n, &i2c->client_list) { - struct dvb_i2c_device *client; - - client = list_entry (entry, struct dvb_i2c_device, list_head); - - if (client->detach == dev->detach) { - list_del (entry); - detach_device (i2c, dev); - } - } -} - - -static void unregister_i2c_client_from_all_busses (struct dvb_i2c_device *dev) -{ - struct list_head *entry, *n; - - list_for_each_safe (entry, n, &dvb_i2c_buslist) { - struct dvb_i2c_bus *i2c; - - i2c = list_entry (entry, struct dvb_i2c_bus, list_head); - - unregister_i2c_client_from_bus (dev, i2c); - } -} - - -static void unregister_all_clients_from_bus (struct dvb_i2c_bus *i2c) -{ - struct list_head *entry, *n; - - list_for_each_safe (entry, n, &(i2c->client_list)) { - struct dvb_i2c_device *dev; - - dev = list_entry (entry, struct dvb_i2c_device, list_head); - - unregister_i2c_client_from_bus (dev, i2c); - } -} - - -static void probe_device_on_all_busses (struct dvb_i2c_device *dev) -{ - struct list_head *entry; - - list_for_each (entry, &dvb_i2c_buslist) { - struct dvb_i2c_bus *i2c; - - i2c = list_entry (entry, struct dvb_i2c_bus, list_head); - - try_attach_device (i2c, dev); - } -} - - -static void probe_devices_on_bus (struct dvb_i2c_bus *i2c) -{ - struct list_head *entry; - - list_for_each (entry, &dvb_i2c_devicelist) { - struct dvb_i2c_device *dev; - - dev = list_entry (entry, struct dvb_i2c_device, list_head); - - try_attach_device (i2c, dev); - } -} - - -static struct dvb_i2c_bus* dvb_find_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c, - const struct i2c_msg msgs[], - int num), - struct dvb_adapter *adapter, - int id) -{ - struct list_head *entry; - - list_for_each (entry, &dvb_i2c_buslist) { - struct dvb_i2c_bus *i2c; - - i2c = list_entry (entry, struct dvb_i2c_bus, list_head); - - if (i2c->xfer == xfer && i2c->adapter == adapter && i2c->id == id) - return i2c; - } - - return NULL; -} - - -struct dvb_i2c_bus* -dvb_register_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c, - const struct i2c_msg *msgs, int num), - void *data, struct dvb_adapter *adapter, int id) -{ - struct dvb_i2c_bus *i2c; - - if (down_interruptible (&dvb_i2c_mutex)) - return NULL; - - if (!(i2c = kmalloc (sizeof (struct dvb_i2c_bus), GFP_KERNEL))) { - up (&dvb_i2c_mutex); - return NULL; - } - - INIT_LIST_HEAD(&i2c->list_head); - INIT_LIST_HEAD(&i2c->client_list); - - i2c->xfer = xfer; - i2c->data = data; - i2c->adapter = adapter; - i2c->id = id; - - probe_devices_on_bus (i2c); - - list_add_tail (&i2c->list_head, &dvb_i2c_buslist); - - up (&dvb_i2c_mutex); - - return i2c; -} - - -void dvb_unregister_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c, - const struct i2c_msg msgs[], int num), - struct dvb_adapter *adapter, int id) -{ - struct dvb_i2c_bus *i2c; - - down (&dvb_i2c_mutex); - - if ((i2c = dvb_find_i2c_bus (xfer, adapter, id))) { - unregister_all_clients_from_bus (i2c); - list_del (&i2c->list_head); - kfree (i2c); - } - - up (&dvb_i2c_mutex); -} - - -int dvb_register_i2c_device (struct module *owner, - int (*attach) (struct dvb_i2c_bus *i2c, void **data), - void (*detach) (struct dvb_i2c_bus *i2c, void *data)) -{ - struct dvb_i2c_device *entry; - - if (down_interruptible (&dvb_i2c_mutex)) - return -ERESTARTSYS; - - if (!(entry = kmalloc (sizeof (struct dvb_i2c_device), GFP_KERNEL))) { - up(&dvb_i2c_mutex); - return -ENOMEM; - } - - entry->owner = owner; - entry->attach = attach; - entry->detach = detach; - - INIT_LIST_HEAD(&entry->list_head); - - probe_device_on_all_busses (entry); - - list_add_tail (&entry->list_head, &dvb_i2c_devicelist); - - up (&dvb_i2c_mutex); - - return 0; -} - - -int dvb_unregister_i2c_device (int (*attach) (struct dvb_i2c_bus *i2c, void **data)) -{ - struct list_head *entry, *n; - - down (&dvb_i2c_mutex); - - list_for_each_safe (entry, n, &dvb_i2c_devicelist) { - struct dvb_i2c_device *dev; - - dev = list_entry (entry, struct dvb_i2c_device, list_head); - - if (dev->attach == attach) { - list_del (entry); - unregister_i2c_client_from_all_busses (dev); - kfree (entry); - up (&dvb_i2c_mutex); - return 0; - } - } - - up (&dvb_i2c_mutex); - - return -EINVAL; -} - - diff --git a/drivers/media/dvb/dvb-core/dvb_i2c.h b/drivers/media/dvb/dvb-core/dvb_i2c.h deleted file mode 100644 index 38f32d3e3f60..000000000000 --- a/drivers/media/dvb/dvb-core/dvb_i2c.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * dvb_i2c.h: i2c interface to get rid of i2c-core.c - * - * Copyright (C) 2002 Holger Waechtler for convergence integrated media GmbH - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 - * 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef _DVB_I2C_H_ -#define _DVB_I2C_H_ - -#include -#include - -#include "dvbdev.h" - - -struct dvb_i2c_bus { - struct list_head list_head; - int (*xfer) (struct dvb_i2c_bus *i2c, - const struct i2c_msg msgs[], - int num); - void *data; - struct dvb_adapter *adapter; - int id; - struct list_head client_list; -}; - - -extern struct dvb_i2c_bus* -dvb_register_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c, - const struct i2c_msg *msgs, int num), - void *data, - struct dvb_adapter *adapter, - int id); - -extern -void dvb_unregister_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c, - const struct i2c_msg msgs[], int num), - struct dvb_adapter *adapter, - int id); - - -extern int dvb_register_i2c_device (struct module *owner, - int (*attach) (struct dvb_i2c_bus *i2c, void **data), - void (*detach) (struct dvb_i2c_bus *i2c, void *data)); - -extern int dvb_unregister_i2c_device (int (*attach) (struct dvb_i2c_bus *i2c, void **data)); - -#endif - diff --git a/drivers/media/dvb/dvb-core/dvb_ksyms.c b/drivers/media/dvb/dvb-core/dvb_ksyms.c index 558b3f41ecb7..0cf48c77bf72 100644 --- a/drivers/media/dvb/dvb-core/dvb_ksyms.c +++ b/drivers/media/dvb/dvb-core/dvb_ksyms.c @@ -24,17 +24,12 @@ EXPORT_SYMBOL(dvbdmx_connect_frontend); EXPORT_SYMBOL(dvbdmx_disconnect_frontend); EXPORT_SYMBOL(dvb_register_frontend); -EXPORT_SYMBOL(dvb_unregister_frontend); +EXPORT_SYMBOL(dvb_unregister_frontend_new); EXPORT_SYMBOL(dvb_add_frontend_ioctls); EXPORT_SYMBOL(dvb_remove_frontend_ioctls); EXPORT_SYMBOL(dvb_add_frontend_notifier); EXPORT_SYMBOL(dvb_remove_frontend_notifier); -EXPORT_SYMBOL(dvb_register_i2c_bus); -EXPORT_SYMBOL(dvb_unregister_i2c_bus); -EXPORT_SYMBOL(dvb_register_i2c_device); -EXPORT_SYMBOL(dvb_unregister_i2c_device); - EXPORT_SYMBOL(dvb_net_init); EXPORT_SYMBOL(dvb_net_release); diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index ab18a9193fc4..18034e5a04f7 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -40,8 +40,6 @@ #include "dvb_demux.h" #include "dvb_net.h" -#include "dvb_functions.h" - static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt ) { diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 686ffc229eec..606c19d30bc9 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -25,22 +25,26 @@ #include #include #include +#include #include #include #include #include +#include #include "dvbdev.h" -#include "dvb_functions.h" -static int dvbdev_debug = 0; +static int dvbdev_debug; + +module_param(dvbdev_debug, int, 0644); +MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off)."); + #define dprintk if (dvbdev_debug) printk static LIST_HEAD(dvb_adapter_list); static DECLARE_MUTEX(dvbdev_register_lock); - -static char *dnames[] = { +static const char * const dnames[] = { "video", "audio", "sec", "frontend", "demux", "dvr", "ca", "net", "osd" }; @@ -49,6 +53,9 @@ static char *dnames[] = { #define DVB_MAX_IDS 4 #define nums2minor(num,type,id) ((num << 6) | (id << 4) | type) +struct class_simple *dvb_class; +EXPORT_SYMBOL(dvb_class); + static struct dvb_device* dvbdev_find_device (int minor) { struct list_head *entry; @@ -219,6 +226,9 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, S_IFCHR | S_IRUSR | S_IWUSR, "dvb/adapter%d/%s%d", adap->num, dnames[type], id); + class_simple_device_add(dvb_class, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)), + NULL, "dvb%d.%s%d", adap->num, dnames[type], id); + dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", adap->num, dnames[type], id, nums2minor(adap->num, type, id), nums2minor(adap->num, type, id)); @@ -235,6 +245,9 @@ void dvb_unregister_device(struct dvb_device *dvbdev) devfs_remove("dvb/adapter%d/%s%d", dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id); + class_simple_device_remove(MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num, + dvbdev->type, dvbdev->id))); + list_del(&dvbdev->list_head); kfree(dvbdev); } @@ -300,24 +313,95 @@ int dvb_register_adapter(struct dvb_adapter **padap, const char *name, struct mo int dvb_unregister_adapter(struct dvb_adapter *adap) { + devfs_remove("dvb/adapter%d", adap->num); + if (down_interruptible (&dvbdev_register_lock)) return -ERESTARTSYS; - devfs_remove("dvb/adapter%d", adap->num); list_del (&adap->list_head); up (&dvbdev_register_lock); kfree (adap); return 0; } +/* if the miracle happens and "generic_usercopy()" is included into + the kernel, then this can vanish. please don't make the mistake and + define this as video_usercopy(). this will introduce a dependecy + to the v4l "videodev.o" module, which is unnecessary for some + cards (ie. the budget dvb-cards don't need the v4l module...) */ +int dvb_usercopy(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct inode *inode, struct file *file, + unsigned int cmd, void *arg)) +{ + char sbuf[128]; + void *mbuf = NULL; + void *parg = NULL; + int err = -EINVAL; + + /* Copy arguments into temp kernel buffer */ + switch (_IOC_DIR(cmd)) { + case _IOC_NONE: + /* + * For this command, the pointer is actually an integer + * argument. + */ + parg = (void *) arg; + break; + case _IOC_READ: /* some v4l ioctls are marked wrong ... */ + case _IOC_WRITE: + case (_IOC_WRITE | _IOC_READ): + if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { + parg = sbuf; + } else { + /* too big to allocate from stack */ + mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); + if (NULL == mbuf) + return -ENOMEM; + parg = mbuf; + } + + err = -EFAULT; + if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) + goto out; + break; + } + + /* call driver */ + if ((err = func(inode, file, cmd, parg)) == -ENOIOCTLCMD) + err = -EINVAL; + + if (err < 0) + goto out; + + /* Copy results into user buffer */ + switch (_IOC_DIR(cmd)) + { + case _IOC_READ: + case (_IOC_WRITE | _IOC_READ): + if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) + err = -EFAULT; + break; + } + +out: + if (mbuf) + kfree(mbuf); + + return err; +} static int __init init_dvbdev(void) { int retval; + + if ((retval = register_chrdev(DVB_MAJOR,"DVB", &dvb_device_fops))) + printk("dvb-core: unable to get major %d\n", DVB_MAJOR); + devfs_mk_dir("dvb"); - retval = register_chrdev(DVB_MAJOR,"DVB", &dvb_device_fops); - if (retval) - printk("video_dev: unable to get major %d\n", DVB_MAJOR); + dvb_class = class_simple_create(THIS_MODULE, "dvb"); + if (IS_ERR(dvb_class)) + return PTR_ERR(dvb_class); return retval; } @@ -327,6 +411,7 @@ static void __exit exit_dvbdev(void) { unregister_chrdev(DVB_MAJOR, "DVB"); devfs_remove("dvb"); + class_simple_destroy(dvb_class); } module_init(init_dvbdev); @@ -336,6 +421,3 @@ MODULE_DESCRIPTION("DVB Core Driver"); MODULE_AUTHOR("Marcus Metzler, Ralph Metzler, Holger Waechtler"); MODULE_LICENSE("GPL"); -MODULE_PARM(dvbdev_debug,"i"); -MODULE_PARM_DESC(dvbdev_debug, "enable verbose debug messages"); - diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h index fc4700f05420..fcad5f21c605 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.h +++ b/drivers/media/dvb/dvb-core/dvbdev.h @@ -28,6 +28,7 @@ #include #include #include +#include #define DVB_MAJOR 212 @@ -92,5 +93,15 @@ extern int dvb_generic_open (struct inode *inode, struct file *file); extern int dvb_generic_release (struct inode *inode, struct file *file); extern int dvb_generic_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); + +/* we don't mess with video_usercopy() any more, +we simply define out own dvb_usercopy(), which will hopefully become +generic_usercopy() someday... */ + +extern int dvb_usercopy(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct inode *inode, struct file *file, + unsigned int cmd, void *arg)); + #endif /* #ifndef _DVBDEV_H_ */ diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index 51a69e389eae..0d59e6d76830 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -32,7 +32,8 @@ typedef enum fe_type { FE_QPSK, FE_QAM, - FE_OFDM + FE_OFDM, + FE_ATSC } fe_type_t; @@ -59,6 +60,8 @@ typedef enum fe_caps { FE_CAN_BANDWIDTH_AUTO = 0x40000, FE_CAN_GUARD_INTERVAL_AUTO = 0x80000, FE_CAN_HIERARCHY_AUTO = 0x100000, + FE_CAN_8VSB = 0x200000, + FE_CAN_16VSB = 0x400000, FE_NEEDS_BENDING = 0x20000000, // frontend requires frequency bending FE_CAN_RECOVER = 0x40000000, // frontend can recover from a cable unplug automatically FE_CAN_MUTE_TS = 0x80000000 // frontend can stop spurious TS data output -- cgit v1.2.3 From 29ad5b6cd793c7a0b8517df64a581483da1f95a3 Mon Sep 17 00:00:00 2001 From: Michael Hunold Date: Tue, 19 Oct 2004 18:22:10 -0700 Subject: [PATCH] DVB: misc driver updates - [DVB] av7110: convert MODULE_PARM() to module_param(), replace home-brewn waiting stuff in osd code with wait_event_interruptible_timeout() - [DVB] av7110: put a semaphore around osd calls to make sure they're properly serialized, timeout variable in arm_thread() must be int, not unsigned long - [DVB] av7110: add additional OSD window types (patch by Jeremy Jones), new ioctl OSD_GET_CAPABILITY/OSD_CAP_MEMSIZE; returns size of OSD memory - [DVB] av7110: put audio/video initialization into separate function init_av7110_av(); call this function after system initialization and after arm crash to restore the previous state; thanks to Soeren Sonnenburg for this patch. - [DVB] av7110, budget, ttusb-budget: remove dvb i2c remains, support kernel i2c - [DVB] av7110, budget: use msleep() instead of my_wait(), thanks to Kernel Janitors/Nishanth Aravamudan - [DVB] av7110, budget: fix videodev has no release callback - [DVB] av7110: more sparse annotiations - [DVB] budget: add support for TerraTec Cinergy 1200 DVB-S - [DVB] budget: fix race condition in irq handler - [DVB] skystar2, av7110, ttusb-budget, budget: make i2c client_(un)register() functions static Signed-off-by: Michael Hunold Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/b2c2/skystar2.c | 4 +- drivers/media/dvb/ttpci/av7110.c | 249 +++++++++++++--------- drivers/media/dvb/ttpci/av7110.h | 14 +- drivers/media/dvb/ttpci/av7110_av.c | 7 +- drivers/media/dvb/ttpci/av7110_ca.c | 5 - drivers/media/dvb/ttpci/av7110_hw.c | 243 ++++++++++++--------- drivers/media/dvb/ttpci/av7110_hw.h | 27 +-- drivers/media/dvb/ttpci/av7110_ir.c | 16 +- drivers/media/dvb/ttpci/av7110_v4l.c | 14 +- drivers/media/dvb/ttpci/budget-av.c | 47 ++-- drivers/media/dvb/ttpci/budget-ci.c | 49 +++-- drivers/media/dvb/ttpci/budget-core.c | 62 ++++-- drivers/media/dvb/ttpci/budget.c | 7 +- drivers/media/dvb/ttpci/budget.h | 8 +- drivers/media/dvb/ttpci/ttpci-eeprom.c | 23 +- drivers/media/dvb/ttpci/ttpci-eeprom.h | 5 +- drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 115 +++++++--- drivers/media/dvb/ttusb-dec/ttusb_dec.c | 40 ++-- include/linux/dvb/osd.h | 32 +++ 19 files changed, 569 insertions(+), 398 deletions(-) (limited to 'include/linux') diff --git a/drivers/media/dvb/b2c2/skystar2.c b/drivers/media/dvb/b2c2/skystar2.c index 642927f39cbf..056f375ff5f3 100644 --- a/drivers/media/dvb/b2c2/skystar2.c +++ b/drivers/media/dvb/b2c2/skystar2.c @@ -2236,7 +2236,7 @@ static int flexcop_diseqc_ioctl(struct dvb_frontend *fe, unsigned int cmd, void } -int client_register(struct i2c_client *client) +static int client_register(struct i2c_client *client) { struct adapter *adapter = (struct adapter*)i2c_get_adapdata(client->adapter); @@ -2247,7 +2247,7 @@ int client_register(struct i2c_client *client) return 0; } -int client_unregister(struct i2c_client *client) +static int client_unregister(struct i2c_client *client) { struct adapter *adapter = (struct adapter*)i2c_get_adapdata(client->adapter); diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 11e9ba7681d6..0f7e53447bc9 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -41,6 +41,7 @@ #include #include +#include #include #include #include @@ -50,18 +51,14 @@ #include #include #include +#include #include #include #include -#include "dvb_i2c.h" #include "dvb_frontend.h" -#include "dvb_functions.h" - - - #define DEBUG_VARIABLE av7110_debug #include "ttpci-eeprom.h" #include "av7110.h" @@ -70,26 +67,93 @@ #include "av7110_ca.h" #include "av7110_ipack.h" - -static void restart_feeds(struct av7110 *av7110); - -int av7110_debug = 0; - +static int av7110_debug; static int vidmode=CVBS_RGB_OUT; static int pids_off; static int adac=DVB_ADAC_TI; -static int hw_sections = 0; -static int rgb_on = 0; +static int hw_sections; +static int rgb_on; +static int volume = 255; + +module_param_named(debug, av7110_debug, int, 0644); +MODULE_PARM_DESC(av7110_debug, "Turn on/off debugging (default:off)."); +module_param(vidmode, int, 0444); +MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC"); +module_param(pids_off, int, 0444); +MODULE_PARM_DESC(pids_off,"clear video/audio/PCR PID filters when demux is closed"); +module_param(adac, int, 0444); +MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)"); +module_param(hw_sections, int, 0444); +MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware"); +module_param(rgb_on, int, 0444); +MODULE_PARM_DESC(rgb_on, "For Siemens DVB-C cards only: Enable RGB control" + " signal on SCART pin 16 to switch SCART video mode from CVBS to RGB"); +module_param(volume, int, 0444); +MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)"); + +static void restart_feeds(struct av7110 *av7110); int av7110_num = 0; +static void init_av7110_av(struct av7110 *av7110) +{ + struct saa7146_dev *dev=av7110->dev; + + /* set internal volume control to maximum */ + av7110->adac_type = DVB_ADAC_TI; + av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right); + + av7710_set_video_mode(av7110, vidmode); + + /* handle different card types */ + /* remaining inits according to card and frontend type */ + av7110->has_analog_tuner = 0; + av7110->current_input = 0; + if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) { + printk ("av7110(%d): Crystal audio DAC detected\n", + av7110->dvb_adapter->num); + av7110->adac_type = DVB_ADAC_CRYSTAL; + i2c_writereg(av7110, 0x20, 0x01, 0xd2); + i2c_writereg(av7110, 0x20, 0x02, 0x49); + i2c_writereg(av7110, 0x20, 0x03, 0x00); + i2c_writereg(av7110, 0x20, 0x04, 0x00); + + /** + * some special handling for the Siemens DVB-C cards... + */ + } else if (0 == av7110_init_analog_module(av7110)) { + /* done. */ + } + else if (dev->pci->subsystem_vendor == 0x110a) { + printk("av7110(%d): DVB-C w/o analog module detected\n", + av7110->dvb_adapter->num); + av7110->adac_type = DVB_ADAC_NONE; + } + else { + av7110->adac_type = adac; + printk("av7110(%d): adac type set to %d\n", + av7110->dvb_adapter->num, av7110->adac_type); + } + + if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP) { + // switch DVB SCART on + av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0); + av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1); + if (rgb_on) + saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16 + //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8 + } + + av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right); + av7110_setup_irc_config(av7110, 0); +} static void recover_arm(struct av7110 *av7110) { DEB_EE(("av7110: %p\n",av7110)); av7110_bootarm(av7110); - dvb_delay(100); + msleep(100); restart_feeds(av7110); av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config); } @@ -106,12 +170,16 @@ static void arm_error(struct av7110 *av7110) static int arm_thread(void *data) { struct av7110 *av7110 = data; - unsigned long timeout; u16 newloops = 0; + int timeout; DEB_EE(("av7110: %p\n",av7110)); - dvb_kernel_thread_setup ("arm_mon"); + lock_kernel (); + daemonize ("arm_mon"); + sigfillset (¤t->blocked); + unlock_kernel (); + av7110->arm_thread = current; while (1) { @@ -135,6 +203,9 @@ static int arm_thread(void *data) av7110->dvb_adapter->num); arm_error(av7110); + av7710_set_video_mode(av7110, vidmode); + + init_av7110_av(av7110); if (down_interruptible(&av7110->dcomlock)) break; @@ -638,6 +709,8 @@ static int dvb_osd_ioctl(struct inode *inode, struct file *file, if (cmd == OSD_SEND_CMD) return av7110_osd_cmd(av7110, (osd_cmd_t *) parg); + if (cmd == OSD_GET_CAPABILITY) + return av7110_osd_capability(av7110, (osd_cap_t *) parg); return -EINVAL; } @@ -1203,19 +1276,17 @@ static void dvb_unregister(struct av7110 *av7110) int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val) { u8 msg[2] = { reg, val }; - struct dvb_i2c_bus *i2c = av7110->i2c_bus; struct i2c_msg msgs; msgs.flags = 0; msgs.addr = id / 2; msgs.len = 2; msgs.buf = msg; - return i2c->xfer(i2c, &msgs, 1); + return i2c_transfer(&av7110->i2c_adap, &msgs, 1); } u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg) { - struct dvb_i2c_bus *i2c = av7110->i2c_bus; u8 mm1[] = {0x00}; u8 mm2[] = {0x00}; struct i2c_msg msgs[2]; @@ -1226,17 +1297,11 @@ u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg) mm1[0] = reg; msgs[0].len = 1; msgs[1].len = 1; msgs[0].buf = mm1; msgs[1].buf = mm2; - i2c->xfer(i2c, msgs, 2); + i2c_transfer(&av7110->i2c_adap, msgs, 2); return mm2[0]; } -static int master_xfer(struct dvb_i2c_bus *i2c, const struct i2c_msg msgs[], int num) -{ - struct saa7146_dev *dev = i2c->data; - return saa7146_i2c_transfer(dev, msgs, num, 6); -} - /**************************************************************************** * INITIALIZATION ****************************************************************************/ @@ -1310,27 +1375,66 @@ static int get_firmware(struct av7110* av7110) /* request the av7110 firmware, this will block until someone uploads it */ ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev); if (ret) { - printk("dvb-ttpci: cannot request firmware!\n"); + if (ret == -ENOENT) { + printk(KERN_ERR "dvb-ttpci: could not load firmware," + " file not found: dvb-ttpci-01.fw\n"); + printk(KERN_ERR "dvb-ttpci: usually this should be in" + " /usr/lib/hotplug/firmware\n"); + printk(KERN_ERR "dvb-ttpci: and can be downloaded here" + " http://www.linuxtv.org/download/dvb/firmware/\n"); + } else + printk(KERN_ERR "dvb-ttpci: cannot request firmware" + " (error %i)\n", ret); return -EINVAL; } + if (fw->size <= 200000) { printk("dvb-ttpci: this firmware is way too small.\n"); + release_firmware(fw); return -EINVAL; } + /* check if the firmware is available */ av7110->bin_fw = (unsigned char*) vmalloc(fw->size); if (NULL == av7110->bin_fw) { DEB_D(("out of memory\n")); + release_firmware(fw); return -ENOMEM; } + memcpy(av7110->bin_fw, fw->data, fw->size); av7110->size_fw = fw->size; if ((ret = check_firmware(av7110))) vfree(av7110->bin_fw); + + release_firmware(fw); return ret; } #endif + +static int client_register(struct i2c_client *client) +{ + struct saa7146_dev *dev = (struct saa7146_dev*)i2c_get_adapdata(client->adapter); + struct av7110 *av7110 = (struct av7110*)dev->ext_priv; + + /* fixme: check for "type" (ie. frontend type) */ + if (client->driver->command) + return client->driver->command(client, FE_REGISTER, av7110->dvb_adapter); + return 0; +} + +static int client_unregister(struct i2c_client *client) +{ + struct saa7146_dev *dev = (struct saa7146_dev*)i2c_get_adapdata(client->adapter); + struct av7110 *av7110 = (struct av7110*)dev->ext_priv; + + /* fixme: check for "type" (ie. frontend type) */ + if (client->driver->command) + return client->driver->command(client, FE_UNREGISTER, av7110->dvb_adapter); + return 0; +} + static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *pci_ext) { struct av7110 *av7110 = NULL; @@ -1361,18 +1465,26 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d get recognized before the main driver is fully loaded */ saa7146_write(dev, GPIO_CTRL, 0x500000); - saa7146_i2c_adapter_prepare(dev, NULL, 0, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */ + av7110->i2c_adap = (struct i2c_adapter) { + .client_register = client_register, + .client_unregister = client_unregister, +#ifdef I2C_ADAP_CLASS_TV_DIGITAL + .class = I2C_ADAP_CLASS_TV_DIGITAL, +#else + .class = I2C_CLASS_TV_DIGITAL, +#endif + }; + strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name)); - av7110->i2c_bus = dvb_register_i2c_bus (master_xfer, dev, - av7110->dvb_adapter, 0); + saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */ - if (!av7110->i2c_bus) { + if (i2c_add_adapter(&av7110->i2c_adap) < 0) { dvb_unregister_adapter (av7110->dvb_adapter); kfree(av7110); return -ENOMEM; } - ttpci_eeprom_parse_mac(av7110->i2c_bus); + ttpci_eeprom_parse_mac(&av7110->i2c_adap, av7110->dvb_adapter->proposed_mac); saa7146_write(dev, PCI_BT_V1, 0x1c00101f); saa7146_write(dev, BCS_CTRL, 0x80400040); @@ -1399,6 +1511,7 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d /* default OSD window */ av7110->osdwin=1; + sema_init(&av7110->osd_sema, 1); /* ARM "watchdog" */ init_waitqueue_head(&av7110->arm_wait); @@ -1443,54 +1556,12 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d goto err2; } - /* set internal volume control to maximum */ - av7110->adac_type = DVB_ADAC_TI; - av7110_set_volume(av7110, 0xff, 0xff); - - av7710_set_video_mode(av7110, vidmode); - - /* handle different card types */ - /* remaining inits according to card and frontend type */ - av7110->has_analog_tuner = 0; - av7110->current_input = 0; - if (i2c_writereg(av7110, 0x20, 0x00, 0x00)==1) { - printk ("av7110(%d): Crystal audio DAC detected\n", - av7110->dvb_adapter->num); - av7110->adac_type = DVB_ADAC_CRYSTAL; - i2c_writereg(av7110, 0x20, 0x01, 0xd2); - i2c_writereg(av7110, 0x20, 0x02, 0x49); - i2c_writereg(av7110, 0x20, 0x03, 0x00); - i2c_writereg(av7110, 0x20, 0x04, 0x00); + /* set initial volume in mixer struct */ + av7110->mixer.volume_left = volume; + av7110->mixer.volume_right = volume; - /** - * some special handling for the Siemens DVB-C cards... - */ - } else if (0 == av7110_init_analog_module(av7110)) { - /* done. */ - } - else if (dev->pci->subsystem_vendor == 0x110a) { - printk("av7110(%d): DVB-C w/o analog module detected\n", - av7110->dvb_adapter->num); - av7110->adac_type = DVB_ADAC_NONE; - } - else { - av7110->adac_type = adac; - printk("av7110(%d): adac type set to %d\n", - av7110->dvb_adapter->num, av7110->adac_type); - } + init_av7110_av(av7110); - if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP) { - // switch DVB SCART on - av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0); - av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1); - if (rgb_on) - saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16 - //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8 - } - - av7110_set_volume(av7110, 0xff, 0xff); - - av7110_setup_irc_config (av7110, 0); av7110_register(av7110); /* special case DVB-C: these cards have an analog tuner @@ -1510,13 +1581,12 @@ err3: av7110->arm_rmmod = 1; wake_up_interruptible(&av7110->arm_wait); while (av7110->arm_thread) - dvb_delay(1); + msleep(1); err2: av7110_ca_exit(av7110); av7110_av_exit(av7110); err: - dvb_unregister_i2c_bus (master_xfer,av7110->i2c_bus->adapter, - av7110->i2c_bus->id); + i2c_del_adapter(&av7110->i2c_adap); dvb_unregister_adapter (av7110->dvb_adapter); @@ -1546,7 +1616,7 @@ static int av7110_detach (struct saa7146_dev* saa) wake_up_interruptible(&av7110->arm_wait); while (av7110->arm_thread) - dvb_delay(1); + msleep(1); dvb_unregister(av7110); @@ -1563,7 +1633,8 @@ static int av7110_detach (struct saa7146_dev* saa) pci_free_consistent(saa->pci, 8192, av7110->debi_virt, av7110->debi_bus); - dvb_unregister_i2c_bus (master_xfer,av7110->i2c_bus->adapter, av7110->i2c_bus->id); + i2c_del_adapter(&av7110->i2c_adap); + dvb_unregister_adapter (av7110->dvb_adapter); av7110_num--; @@ -1602,7 +1673,7 @@ static struct saa7146_pci_extension_data x_var = { \ MAKE_AV7110_INFO(fs_1_5, "Siemens cable card PCI rev1.5"); MAKE_AV7110_INFO(fs_1_3, "Siemens/Technotrend/Hauppauge PCI rev1.3"); MAKE_AV7110_INFO(tt_1_6, "Technotrend/Hauppauge PCI rev1.3 or 1.6"); -MAKE_AV7110_INFO(tt_2_1, "Technotrend/Hauppauge PCI rev2.1"); +MAKE_AV7110_INFO(tt_2_1, "Technotrend/Hauppauge PCI rev2.1 or 2.2"); MAKE_AV7110_INFO(tt_t, "Technotrend/Hauppauge PCI DVB-T"); MAKE_AV7110_INFO(unkwn0, "Technotrend/Hauppauge PCI rev?(unknown0)?"); MAKE_AV7110_INFO(unkwn1, "Technotrend/Hauppauge PCI rev?(unknown1)?"); @@ -1684,15 +1755,3 @@ MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by " MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others"); MODULE_LICENSE("GPL"); -MODULE_PARM(av7110_debug,"i"); -MODULE_PARM(vidmode,"i"); -MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC"); -MODULE_PARM(pids_off,"i"); -MODULE_PARM_DESC(pids_off,"clear video/audio/PCR PID filters when demux is closed"); -MODULE_PARM(adac,"i"); -MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)"); -MODULE_PARM(hw_sections, "i"); -MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware"); -MODULE_PARM(rgb_on, "i"); -MODULE_PARM_DESC(rgb_on, "For Siemens DVB-C cards only: Enable RGB control" - " signal on SCART pin 16 to switch SCART video mode from CVBS to RGB"); diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h index c9485eeef55a..6a706fe96723 100644 --- a/drivers/media/dvb/ttpci/av7110.h +++ b/drivers/media/dvb/ttpci/av7110.h @@ -4,13 +4,12 @@ #include #include #include +#include #ifdef CONFIG_DEVFS_FS #include #endif -#include - #include #include #include @@ -26,6 +25,7 @@ #include "dvb_net.h" #include "dvb_ringbuffer.h" +#include #define MAXFILT 32 @@ -60,12 +60,13 @@ struct av7110 { struct dvb_device dvb_dev; struct dvb_net dvb_net; - struct video_device v4l_dev; - struct video_device vbi_dev; + struct video_device *v4l_dev; + struct video_device *vbi_dev; struct saa7146_dev *dev; - struct dvb_i2c_bus *i2c_bus; + struct i2c_adapter i2c_adap; + char *card_name; /* support for analog module of dvb-c */ @@ -127,7 +128,7 @@ struct av7110 { int osdwin; /* currently active window */ u16 osdbpp[8]; - + struct semaphore osd_sema; /* CA */ @@ -187,6 +188,7 @@ struct av7110 { struct dvb_ringbuffer ci_rbuffer; struct dvb_ringbuffer ci_wbuffer; + struct audio_mixer mixer; struct dvb_adapter *dvb_adapter; struct dvb_device *video_dev; diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c index b922851d8b45..f885c72dfc24 100644 --- a/drivers/media/dvb/ttpci/av7110_av.c +++ b/drivers/media/dvb/ttpci/av7110_av.c @@ -37,14 +37,10 @@ #include #include -#define DEBUG_VARIABLE av7110_debug -extern int av7110_debug; - #include "av7110.h" #include "av7110_hw.h" #include "av7110_av.h" #include "av7110_ipack.h" -#include "dvb_functions.h" /* MPEG-2 (ISO 13818 / H.222.0) stream types */ #define PROG_STREAM_MAP 0xBC @@ -292,6 +288,9 @@ int av7110_set_volume(struct av7110 *av7110, int volleft, int volright) DEB_EE(("av7110: %p\n", av7110)); + av7110->mixer.volume_left = volleft; + av7110->mixer.volume_right = volright; + switch (av7110->adac_type) { case DVB_ADAC_TI: volleft = (volleft * 256) / 1036; diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c index 2d169d63008a..bb666b7d454d 100644 --- a/drivers/media/dvb/ttpci/av7110_ca.c +++ b/drivers/media/dvb/ttpci/av7110_ca.c @@ -38,13 +38,8 @@ #include #include -#define DEBUG_VARIABLE av7110_debug -extern int av7110_debug; - -#include "dvb_i2c.h" #include "av7110.h" #include "av7110_hw.h" -#include "dvb_functions.h" void CI_handle(struct av7110 *av7110, u8 *data, u16 len) diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c index 054018b3fe78..2fc75bb79bb0 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.c +++ b/drivers/media/dvb/ttpci/av7110_hw.c @@ -38,12 +38,8 @@ #include #include -#define DEBUG_VARIABLE av7110_debug -extern int av7110_debug; - #include "av7110.h" #include "av7110_hw.h" -#include "dvb_functions.h" /**************************************************************************** * DEBI functions @@ -106,7 +102,7 @@ void av7110_reset_arm(struct av7110 *av7110) saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03)); saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTHI); - dvb_delay(30); /* the firmware needs some time to initialize */ + msleep(30); /* the firmware needs some time to initialize */ ARM_ResetMailBox(av7110); @@ -268,7 +264,7 @@ int av7110_bootarm(struct av7110 *av7110) return -1; } saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI); - dvb_delay(30); /* the firmware needs some time to initialize */ + msleep(30); /* the firmware needs some time to initialize */ //ARM_ClearIrq(av7110); ARM_ResetMailBox(av7110); @@ -302,7 +298,7 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) start = jiffies; while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) { - dvb_delay(1); + msleep(1); if (time_after(jiffies, start + ARM_WAIT_FREE)) { printk(KERN_ERR "%s: timeout waiting for COMMAND idle\n", __FUNCTION__); return -1; @@ -312,7 +308,7 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) #ifndef _NOHANDSHAKE start = jiffies; while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) { - dvb_delay(1); + msleep(1); if (time_after(jiffies, start + ARM_WAIT_SHAKE)) { printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); return -1; @@ -322,7 +318,7 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) start = jiffies; while (rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2) & OSDQFull) { - dvb_delay(1); + msleep(1); if (time_after(jiffies, start + ARM_WAIT_OSD)) { printk(KERN_ERR "%s: timeout waiting for !OSDQFull\n", __FUNCTION__); return -1; @@ -341,7 +337,7 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) #ifdef COM_DEBUG start = jiffies; while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) { - dvb_delay(1); + msleep(1); if (time_after(jiffies, start + ARM_WAIT_FREE)) { printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__); @@ -458,7 +454,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, start = jiffies; while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2)) { #ifdef _NOHANDSHAKE - dvb_delay(1); + msleep(1); #endif if (time_after(jiffies, start + ARM_WAIT_FREE)) { printk("%s: timeout waiting for COMMAND to complete\n", __FUNCTION__); @@ -470,7 +466,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, #ifndef _NOHANDSHAKE start = jiffies; while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) { - dvb_delay(1); + msleep(1); if (time_after(jiffies, start + ARM_WAIT_SHAKE)) { printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); up(&av7110->dcomlock); @@ -630,7 +626,7 @@ static int FlushText(struct av7110 *av7110) return -ERESTARTSYS; start = jiffies; while (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2)) { - dvb_delay(1); + msleep(1); if (time_after(jiffies, start + ARM_WAIT_OSD)) { printk(KERN_ERR "%s: timeout waiting for BUFF1_BASE == 0\n", __FUNCTION__); @@ -654,7 +650,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) start = jiffies; while (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2)) { - dvb_delay(1); + msleep(1); if (time_after(jiffies, start + ARM_WAIT_OSD)) { printk(KERN_ERR "%s: timeout waiting for BUFF1_BASE == 0\n", __FUNCTION__); @@ -665,7 +661,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) #ifndef _NOHANDSHAKE start = jiffies; while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2)) { - dvb_delay(1); + msleep(1); if (time_after(jiffies, start + ARM_WAIT_SHAKE)) { printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); @@ -721,7 +717,7 @@ static inline int DestroyOSDWindow(struct av7110 *av7110, u8 windownr) } static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr, - enum av7110_window_display_type disptype, + osd_raw_window_t disptype, u16 width, u16 height) { return av7110_fw_cmd(av7110, COMTYPE_OSD, WCreate, 4, @@ -732,8 +728,8 @@ static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr, static enum av7110_osd_palette_type bpp2pal[8] = { Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit }; -static enum av7110_window_display_type bpp2bit[8] = { - BITMAP1, BITMAP2, 0, BITMAP4, 0, 0, 0, BITMAP8 +static osd_raw_window_t bpp2bit[8] = { + OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8 }; static inline int LoadBitmap(struct av7110 *av7110, u16 format, @@ -743,32 +739,26 @@ static inline int LoadBitmap(struct av7110 *av7110, u16 format, int i; int d, delta; u8 c; - DECLARE_WAITQUEUE(wait, current); + int ret; DEB_EE(("av7110: %p\n", av7110)); - if (av7110->bmp_state == BMP_LOADING) { - add_wait_queue(&av7110->bmpq, &wait); - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - if (av7110->bmp_state != BMP_LOADING - || signal_pending(current)) - break; - schedule(); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&av7110->bmpq, &wait); - } - if (av7110->bmp_state == BMP_LOADING) + ret = wait_event_interruptible_timeout(av7110->bmpq, av7110->bmp_state != BMP_LOADING, HZ); + if (ret == -ERESTARTSYS || ret == 0) { + printk("dvb-ttpci: warning: timeout waiting in %s()\n", __FUNCTION__); + av7110->bmp_state = BMP_NONE; return -1; + } + BUG_ON (av7110->bmp_state == BMP_LOADING); + av7110->bmp_state = BMP_LOADING; - if (format == BITMAP8) { + if (format == OSD_BITMAP8) { bpp=8; delta = 1; - } else if (format == BITMAP4) { + } else if (format == OSD_BITMAP4) { bpp=4; delta = 2; - } else if (format == BITMAP2) { + } else if (format == OSD_BITMAP2) { bpp=2; delta = 4; - } else if (format == BITMAP1) { + } else if (format == OSD_BITMAP1) { bpp=1; delta = 8; } else { av7110->bmp_state = BMP_NONE; @@ -786,7 +776,7 @@ static inline int LoadBitmap(struct av7110 *av7110, u16 format, return -1; } } - if (format != BITMAP8) { + if (format != OSD_BITMAP8) { for (i = 0; i < dx * dy / delta; i++) { c = ((u8 *)av7110->bmpbuf)[1024 + i * delta + delta - 1]; for (d = delta - 2; d >= 0; d--) { @@ -802,27 +792,22 @@ static inline int LoadBitmap(struct av7110 *av7110, u16 format, static int BlitBitmap(struct av7110 *av7110, u16 win, u16 x, u16 y, u16 trans) { - DECLARE_WAITQUEUE(wait, current); + int ret; DEB_EE(("av7110: %p\n", av7110)); - if (av7110->bmp_state == BMP_NONE) + BUG_ON (av7110->bmp_state == BMP_NONE); + + ret = wait_event_interruptible_timeout(av7110->bmpq, av7110->bmp_state != BMP_LOADING, HZ); + if (ret == -ERESTARTSYS || ret == 0) { + printk("dvb-ttpci: warning: timeout waiting in %s()\n", __FUNCTION__); + av7110->bmp_state = BMP_NONE; return -1; - if (av7110->bmp_state == BMP_LOADING) { - add_wait_queue(&av7110->bmpq, &wait); - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - if (av7110->bmp_state != BMP_LOADING - || signal_pending(current)) - break; - schedule(); } - set_current_state(TASK_RUNNING); - remove_wait_queue(&av7110->bmpq, &wait); - } - if (av7110->bmp_state == BMP_LOADED) + + BUG_ON (av7110->bmp_state != BMP_LOADED); + return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, win, x, y, trans); - return -1; } static inline int ReleaseBitmap(struct av7110 *av7110) @@ -865,18 +850,22 @@ static void OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 bl color, ((blend >> 4) & 0x0f)); } -static int OSDSetPalette(struct av7110 *av7110, u32 *colors, u8 first, u8 last) +static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last) { int i; int length = last - first + 1; if (length * 4 > DATA_BUFF3_SIZE) - return -1; + return -EINVAL; for (i = 0; i < length; i++) { - u32 blend = (colors[i] & 0xF0000000) >> 4; - u32 yuv = blend ? RGB2YUV(colors[i] & 0xFF, (colors[i] >> 8) & 0xFF, - (colors[i] >> 16) & 0xFF) | blend : 0; + u32 color, blend, yuv; + + if (get_user(color, colors + i)) + return -EFAULT; + blend = (color & 0xF0000000) >> 4; + yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF, + (color >> 16) & 0xFF) | blend : 0; yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16); wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4); } @@ -922,10 +911,19 @@ static int OSDSetBlock(struct av7110 *av7110, int x0, int y0, int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc) { + int ret; + + ret = down_interruptible(&av7110->osd_sema); + if (ret) + return -ERESTARTSYS; + + /* stupid, but OSD functions don't provide a return code anyway */ + ret = 0; + switch (dc->cmd) { case OSD_Close: DestroyOSDWindow(av7110, av7110->osdwin); - return 0; + goto out; case OSD_Open: av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7; CreateOSDWindow(av7110, av7110->osdwin, @@ -935,90 +933,84 @@ int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc) MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0); SetColorBlend(av7110, av7110->osdwin); } - return 0; + goto out; case OSD_Show: MoveWindowRel(av7110, av7110->osdwin, 0, 0); - return 0; + goto out; case OSD_Hide: HideWindow(av7110, av7110->osdwin); - return 0; + goto out; case OSD_Clear: DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0); - return 0; + goto out; case OSD_Fill: DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color); - return 0; + goto out; case OSD_SetColor: OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1); - return 0; + goto out; case OSD_SetPalette: { - int len = dc->x0-dc->color+1; - void *buf; - if (len <= 0) - return 0; - - buf = kmalloc(len * 4, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - if (copy_from_user(buf, dc->data, len * 4)) { - kfree(buf); - return -EFAULT; + if (FW_VERSION(av7110->arm_app) >= 0x2618) { + ret = OSDSetPalette(av7110, (u32 *)dc->data, dc->color, dc->x0); + goto out; + } else { + int i, len = dc->x0-dc->color+1; + u8 *colors = (u8 *)dc->data; + u8 r, g, b, blend; + + for (i = 0; iarm_app) >= 0x2618) - OSDSetPalette(av7110, buf, dc->color, dc->x0); - else { - int i; - u8 *colors = buf; - - for (i = 0; icolor + i, - colors[i * 4], colors[i * 4 + 1], - colors[i * 4 + 2], colors[i * 4 + 3]); + OSDSetColor(av7110, dc->color + i, r, g, b, blend); } - kfree(buf); - return 0; + } + ret = 0; + goto out; } case OSD_SetTrans: - return 0; + goto out; case OSD_SetPixel: DrawLine(av7110, av7110->osdwin, dc->x0, dc->y0, 0, 0, dc->color); - return 0; + goto out; case OSD_GetPixel: - return 0; - + goto out; case OSD_SetRow: dc->y1 = dc->y0; /* fall through */ case OSD_SetBlock: OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data); - return 0; - + goto out; case OSD_FillRow: DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0, dc->x1-dc->x0+1, dc->y1, dc->color); - return 0; + goto out; case OSD_FillBlock: DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0, dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color); - return 0; + goto out; case OSD_Line: DrawLine(av7110, av7110->osdwin, dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color); - return 0; + goto out; case OSD_Query: - return 0; + goto out; case OSD_Test: - return 0; + goto out; case OSD_Text: { char textbuf[240]; - if (strncpy_from_user(textbuf, dc->data, 240) < 0) - return -EFAULT; + if (strncpy_from_user(textbuf, dc->data, 240) < 0) { + ret = -EFAULT; + goto out; + } textbuf[239] = 0; if (dc->x1 > 3) dc->x1 = 3; @@ -1026,16 +1018,55 @@ int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc) (u16) (dc->color & 0xffff), (u16) (dc->color >> 16)); FlushText(av7110); WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf); - return 0; + goto out; } case OSD_SetWindow: - if (dc->x0 < 1 || dc->x0 > 7) - return -EINVAL; + if (dc->x0 < 1 || dc->x0 > 7) { + ret = -EINVAL; + goto out; + } av7110->osdwin = dc->x0; - return 0; + goto out; case OSD_MoveWindow: MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0); SetColorBlend(av7110, av7110->osdwin); + goto out; + case OSD_OpenRaw: + if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) { + ret = -EINVAL; + goto out; + } + if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR) { + av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1; + } + else { + av7110->osdbpp[av7110->osdwin] = 0; + } + CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color, + dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1); + if (!dc->data) { + MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0); + SetColorBlend(av7110, av7110->osdwin); + } + goto out; + default: + ret = -EINVAL; + goto out; + } + +out: + up(&av7110->osd_sema); + return ret; +} + +int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap) +{ + switch (cap->cmd) { + case OSD_CAP_MEMSIZE: + if (FW_4M_SDRAM(av7110->arm_app)) + cap->val = 1000000; + else + cap->val = 92000; return 0; default: return -EINVAL; diff --git a/drivers/media/dvb/ttpci/av7110_hw.h b/drivers/media/dvb/ttpci/av7110_hw.h index 826ea877b29e..049f23f2c03e 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.h +++ b/drivers/media/dvb/ttpci/av7110_hw.h @@ -39,29 +39,6 @@ enum av7110_osd_palette_type Pal8Bit = 256 /* 256 colors for 16 bit palette */ }; -enum av7110_window_display_type { - BITMAP1, /* 1 bit bitmap */ - BITMAP2, /* 2 bit bitmap */ - BITMAP4, /* 4 bit bitmap */ - BITMAP8, /* 8 bit bitmap */ - BITMAP1HR, /* 1 Bit bitmap half resolution */ - BITMAP2HR, /* 2 bit bitmap half resolution */ - BITMAP4HR, /* 4 bit bitmap half resolution */ - BITMAP8HR, /* 8 bit bitmap half resolution */ - YCRCB422, /* 4:2:2 YCRCB Graphic Display */ - YCRCB444, /* 4:4:4 YCRCB Graphic Display */ - YCRCB444HR, /* 4:4:4 YCRCB graphic half resolution */ - VIDEOTSIZE, /* True Size Normal MPEG Video Display */ - VIDEOHSIZE, /* MPEG Video Display Half Resolution */ - VIDEOQSIZE, /* MPEG Video Display Quarter Resolution */ - VIDEODSIZE, /* MPEG Video Display Double Resolution */ - VIDEOTHSIZE, /* True Size MPEG Video Display Half Resolution */ - VIDEOTQSIZE, /* True Size MPEG Video Display Quarter Resolution*/ - VIDEOTDSIZE, /* True Size MPEG Video Display Double Resolution */ - VIDEONSIZE, /* Full Size MPEG Video Display */ - CURSOR /* Cursor */ -}; - /* switch defines */ #define SB_GPIO 3 #define SB_OFF SAA7146_GPIO_OUTLO /* SlowBlank off (TV-Mode) */ @@ -388,6 +365,7 @@ extern void av7110_reset_arm(struct av7110 *av7110); extern int av7110_bootarm(struct av7110 *av7110); extern int av7110_firmversion(struct av7110 *av7110); #define FW_CI_LL_SUPPORT(arm_app) ((arm_app) & 0x80000000) +#define FW_4M_SDRAM(arm_app) ((arm_app) & 0x40000000) #define FW_VERSION(arm_app) ((arm_app) & 0x0000FFFF) extern int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...); @@ -495,7 +473,7 @@ static int inline vidcom(struct av7110 *av7110, u32 com, u32 arg) static int inline audcom(struct av7110 *av7110, u32 com) { - return av7110_fw_cmd(av7110, COMTYPE_MISC, AV7110_FW_AUDIO_COMMAND, 4, + return av7110_fw_cmd(av7110, COMTYPE_MISC, AV7110_FW_AUDIO_COMMAND, 2, (com>>16), (com&0xffff)); } @@ -510,6 +488,7 @@ extern int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned #ifdef CONFIG_DVB_AV7110_OSD extern int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc); +extern int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap); #endif /* CONFIG_DVB_AV7110_OSD */ diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c index 22039beb41d1..f3fed48366cf 100644 --- a/drivers/media/dvb/ttpci/av7110_ir.c +++ b/drivers/media/dvb/ttpci/av7110_ir.c @@ -1,23 +1,21 @@ #include #include #include +#include #include #include #include #include "av7110.h" -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -#include "input_fake.h" -#endif - - #define UP_TIMEOUT (HZ/4) -static int av7110_ir_debug = 0; +static int av7110_ir_debug; -#define dprintk(x...) do { if (av7110_ir_debug) printk (x); } while (0) +module_param_named(debug_ir, av7110_ir_debug, int, 0644); +MODULE_PARM_DESC(av7110_ir_debug, "Turn on/off IR debugging (default:off)."); +#define dprintk(x...) do { if (av7110_ir_debug) printk (x); } while (0) static struct input_dev input_dev; @@ -205,6 +203,7 @@ int __init av7110_ir_init (void) void __exit av7110_ir_exit (void) { + del_timer_sync(&keyup_timer); remove_proc_entry ("av7110_ir", NULL); av7110_unregister_irc_handler (av7110_emit_key); input_unregister_device(&input_dev); @@ -213,6 +212,3 @@ void __exit av7110_ir_exit (void) //MODULE_AUTHOR("Holger Waechtler "); //MODULE_LICENSE("GPL"); -MODULE_PARM(av7110_ir_debug,"i"); -MODULE_PARM_DESC(av7110_ir_debug, "enable AV7110 IR receiver debug messages"); - diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c index fef348e130f6..7ef71f719d22 100644 --- a/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/drivers/media/dvb/ttpci/av7110_v4l.c @@ -35,23 +35,16 @@ #include #include -#define DEBUG_VARIABLE av7110_debug -extern int av7110_debug; - -#include "dvb_i2c.h" #include "av7110.h" #include "av7110_hw.h" #include "av7110_av.h" -#include "dvb_functions.h" - int msp_writereg(struct av7110 *av7110, u8 dev, u16 reg, u16 val) { u8 msg[5] = { dev, reg >> 8, reg & 0xff, val >> 8 , val & 0xff }; - struct dvb_i2c_bus *i2c = av7110->i2c_bus; struct i2c_msg msgs = { .flags = 0, .addr = 0x40, .len = 5, .buf = msg }; - if (i2c->xfer(i2c, &msgs, 1) != 1) { + if (i2c_transfer(&av7110->i2c_adap, &msgs, 1) != 1) { printk("av7110(%d): %s(%u = %u) failed\n", av7110->dvb_adapter->num, __FUNCTION__, reg, val); return -EIO; @@ -63,13 +56,12 @@ int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val) { u8 msg1[3] = { dev, reg >> 8, reg & 0xff }; u8 msg2[2]; - struct dvb_i2c_bus *i2c = av7110->i2c_bus; struct i2c_msg msgs[2] = { { .flags = 0, .addr = 0x40, .len = 3, .buf = msg1 }, { .flags = I2C_M_RD, .addr = 0x40, .len = 2, .buf = msg2 } }; - if (i2c->xfer(i2c, msgs, 2) != 2) { + if (i2c_transfer(&av7110->i2c_adap, &msgs[0], 2) != 2) { printk("av7110(%d): %s(%u) failed\n", av7110->dvb_adapter->num, __FUNCTION__, reg); return -EIO; @@ -517,7 +509,7 @@ int av7110_init_analog_module(struct av7110 *av7110) printk("av7110(%d): DVB-C analog module detected, initializing MSP3400\n", av7110->dvb_adapter->num); av7110->adac_type = DVB_ADAC_MSP; - dvb_delay(100); // the probing above resets the msp... + msleep(100); // the probing above resets the msp... msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1); msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2); printk("av7110(%d): MSP3400 version 0x%04x 0x%04x\n", diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 6203be434c98..b324839d49b5 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -30,14 +30,12 @@ * the project's page is at http://www.linuxtv.org/dvb/ */ -#include - #include "budget.h" -#include "dvb_functions.h" +#include struct budget_av { struct budget budget; - struct video_device vd; + struct video_device *vd; int cur_input; int has_saa7113; }; @@ -47,7 +45,7 @@ struct budget_av { ****************************************************************************/ -static u8 i2c_readreg (struct dvb_i2c_bus *i2c, u8 id, u8 reg) +static u8 i2c_readreg (struct i2c_adapter *i2c, u8 id, u8 reg) { u8 mm1[] = {0x00}; u8 mm2[] = {0x00}; @@ -60,12 +58,12 @@ static u8 i2c_readreg (struct dvb_i2c_bus *i2c, u8 id, u8 reg) msgs[0].len = 1; msgs[1].len = 1; msgs[0].buf = mm1; msgs[1].buf = mm2; - i2c->xfer(i2c, msgs, 2); + i2c_transfer(i2c, msgs, 2); return mm2[0]; } -static int i2c_readregs(struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 *buf, u8 len) +static int i2c_readregs(struct i2c_adapter *i2c, u8 id, u8 reg, u8 *buf, u8 len) { u8 mm1[] = { reg }; struct i2c_msg msgs[2] = { @@ -73,13 +71,14 @@ static int i2c_readregs(struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 *buf, u8 len) { .addr = id/2, .flags = I2C_M_RD, .buf = buf, .len = len } }; - if (i2c->xfer(i2c, msgs, 2) != 2) + if (i2c_transfer(i2c, msgs, 2) != 2) return -EIO; + return 0; } -static int i2c_writereg (struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 val) +static int i2c_writereg (struct i2c_adapter *i2c, u8 id, u8 reg, u8 val) { u8 msg[2]={ reg, val }; struct i2c_msg msgs; @@ -88,7 +87,7 @@ static int i2c_writereg (struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 val) msgs.addr=id/2; msgs.len=2; msgs.buf=msg; - return i2c->xfer (i2c, &msgs, 1); + return i2c_transfer(i2c, &msgs, 1); } @@ -127,7 +126,7 @@ static int saa7113_init (struct budget_av *budget_av) struct budget *budget = &budget_av->budget; const u8 *data = saa7113_tab; - if (i2c_writereg (budget->i2c_bus, 0x4a, 0x01, 0x08) != 1) { + if (i2c_writereg (&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) { DEB_D(("saa7113: not found on KNC card\n")); return -ENODEV; } @@ -135,12 +134,12 @@ static int saa7113_init (struct budget_av *budget_av) INFO(("saa7113: detected and initializing\n")); while (*data != 0xff) { - i2c_writereg(budget->i2c_bus, 0x4a, *data, *(data+1)); + i2c_writereg(&budget->i2c_adap, 0x4a, *data, *(data+1)); data += 2; } DEB_D(("saa7113: status=%02x\n", - i2c_readreg(budget->i2c_bus, 0x4a, 0x1f))); + i2c_readreg(&budget->i2c_adap, 0x4a, 0x1f))); return 0; } @@ -154,11 +153,11 @@ static int saa7113_setinput (struct budget_av *budget_av, int input) return -ENODEV; if (input == 1) { - i2c_writereg(budget->i2c_bus, 0x4a, 0x02, 0xc7); - i2c_writereg(budget->i2c_bus, 0x4a, 0x09, 0x80); + i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc7); + i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x80); } else if (input == 0) { - i2c_writereg(budget->i2c_bus, 0x4a, 0x02, 0xc0); - i2c_writereg(budget->i2c_bus, 0x4a, 0x09, 0x00); + i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc0); + i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x00); } else return -EINVAL; @@ -177,7 +176,7 @@ static int budget_av_detach (struct saa7146_dev *dev) if ( 1 == budget_av->has_saa7113 ) { saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO); - dvb_delay(200); + msleep(200); saa7146_unregister_device (&budget_av->vd, dev); } @@ -201,7 +200,7 @@ static int budget_av_attach (struct saa7146_dev* dev, DEB_EE(("dev: %p\n",dev)); - if (bi->type != BUDGET_KNC1) { + if (bi->type != BUDGET_KNC1 && bi->type != BUDGET_CIN1200) { return -ENODEV; } @@ -210,13 +209,13 @@ static int budget_av_attach (struct saa7146_dev* dev, memset(budget_av, 0, sizeof(struct budget_av)); + dev->ext_priv = budget_av; + if ((err = ttpci_budget_init(&budget_av->budget, dev, info))) { kfree(budget_av); return err; } - dev->ext_priv = budget_av; - /* knc1 initialization */ saa7146_write(dev, DD1_STREAM_B, 0x04000000); saa7146_write(dev, DD1_INIT, 0x07000600); @@ -225,7 +224,7 @@ static int budget_av_attach (struct saa7146_dev* dev, //test_knc_ci(av7110); saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI); - dvb_delay(500); + msleep(500); if ( 0 == saa7113_init(budget_av) ) { budget_av->has_saa7113 = 1; @@ -259,7 +258,7 @@ static int budget_av_attach (struct saa7146_dev* dev, saa7146_write(dev, PCI_BT_V1, 0x1c00101f); mac = budget_av->budget.dvb_adapter->proposed_mac; - if (i2c_readregs(budget_av->budget.i2c_bus, 0xa0, 0x30, mac, 6)) { + if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) { printk("KNC1-%d: Could not read MAC from KNC1 card\n", budget_av->budget.dvb_adapter->num); memset(mac, 0, 6); @@ -361,9 +360,11 @@ static struct saa7146_extension budget_extension; MAKE_BUDGET_INFO(knc1, "KNC1 DVB-S", BUDGET_KNC1); +MAKE_BUDGET_INFO(cin1200, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200); static struct pci_device_id pci_tbl [] = { MAKE_EXTENSION_PCI(knc1, 0x1131, 0x4f56), + MAKE_EXTENSION_PCI(cin1200, 0x153b, 0x1154), { .vendor = 0, } diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 30c806599196..5e217e833772 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -38,13 +38,8 @@ #include #include -#include "dvb_functions.h" #include "dvb_ca_en50221.h" -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -#include "input_fake.h" -#endif - #define DEBIADDR_IR 0x1234 #define DEBIADDR_CICONTROL 0x0000 #define DEBIADDR_CIVERSION 0x4000 @@ -79,14 +74,15 @@ static u32 budget_debiread (struct budget_ci* budget_ci, u32 config, int addr, i { struct saa7146_dev *saa = budget_ci->budget.dev; u32 result = 0; + unsigned long flags; if (count > 4 || count <= 0) return 0; - spin_lock(&budget_ci->debilock); + spin_lock_irqsave(&budget_ci->debilock, flags); if (saa7146_wait_for_debi_done(saa) < 0) { - spin_unlock(&budget_ci->debilock); + spin_unlock_irqrestore(&budget_ci->debilock, flags); return 0; } @@ -101,21 +97,22 @@ static u32 budget_debiread (struct budget_ci* budget_ci, u32 config, int addr, i result = saa7146_read(saa, 0x88); result &= (0xffffffffUL >> ((4 - count) * 8)); - spin_unlock(&budget_ci->debilock); + spin_unlock_irqrestore(&budget_ci->debilock, flags); return result; } static u8 budget_debiwrite (struct budget_ci* budget_ci, u32 config, int addr, int count, u32 value) { struct saa7146_dev *saa = budget_ci->budget.dev; + unsigned long flags; if (count > 4 || count <= 0) return 0; - spin_lock(&budget_ci->debilock); + spin_lock_irqsave(&budget_ci->debilock, flags); if (saa7146_wait_for_debi_done(saa) < 0) { - spin_unlock(&budget_ci->debilock); + spin_unlock_irqrestore(&budget_ci->debilock, flags); return 0; } @@ -128,7 +125,7 @@ static u8 budget_debiwrite (struct budget_ci* budget_ci, u32 config, int addr, i saa7146_wait_for_debi_done(saa); - spin_unlock(&budget_ci->debilock); + spin_unlock_irqrestore(&budget_ci->debilock, flags); return 0; } @@ -326,7 +323,7 @@ static int ciintf_slot_reset(struct dvb_ca_en50221* ca, int slot) { saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); budget_ci->slot_status = SLOTSTATUS_RESET; budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, 0); - dvb_delay(1); + msleep(1); budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, CICONTROL_RESET); saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI); @@ -372,14 +369,13 @@ static void ciintf_interrupt (unsigned long data) // ensure we don't get spurious IRQs during initialisation if (!budget_ci->budget.ci_present) return; + // read the CAM status flags = budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1); + if (flags & CICONTROL_CAMDETECT) { - // always set the GPIO mode back to "normal", in case the card is - // yanked at an inopportune moment + // GPIO should be set to trigger on falling edge if a CAM is present saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO); - if (flags & CICONTROL_CAMDETECT) { - if (budget_ci->slot_status & SLOTSTATUS_NONE) { // CAM insertion IRQ budget_ci->slot_status = SLOTSTATUS_PRESENT; @@ -395,7 +391,15 @@ static void ciintf_interrupt (unsigned long data) dvb_ca_en50221_frda_irq(&budget_ci->ca, 0); } } else { + + // trigger on rising edge if a CAM is not present - when a CAM is inserted, we + // only want to get the IRQ when it sets READY. If we trigger on the falling edge, + // the CAM might not actually be ready yet. + saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); + + // generate a CAM removal IRQ if we haven't already if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) { + // CAM removal IRQ budget_ci->slot_status = SLOTSTATUS_NONE; dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, DVB_CA_EN50221_CAMCHANGE_REMOVED); } @@ -446,7 +450,11 @@ static int ciintf_init(struct budget_ci* budget_ci) // Setup CI slot IRQ tasklet_init (&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci); + if (budget_ci->slot_status != SLOTSTATUS_NONE) { saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO); + } else { + saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); + } saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03); budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, CICONTROL_RESET); @@ -475,7 +483,7 @@ static void ciintf_deinit(struct budget_ci* budget_ci) saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); tasklet_kill(&budget_ci->ciintf_irq_tasklet); budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, 0); - dvb_delay(1); + msleep(1); budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, CICONTROL_RESET); // disable TS data stream to CI interface @@ -520,20 +528,19 @@ static int budget_ci_attach (struct saa7146_dev* dev, spin_lock_init(&budget_ci->debilock); budget_ci->budget.ci_present = 0; + dev->ext_priv = budget_ci; + if ((err = ttpci_budget_init (&budget_ci->budget, dev, info))) { kfree (budget_ci); return err; } - dev->ext_priv = budget_ci; - tasklet_init (&budget_ci->msp430_irq_tasklet, msp430_ir_interrupt, (unsigned long) budget_ci); msp430_ir_init (budget_ci); - // UNCOMMENT TO TEST CI INTERFACE -// ciintf_init(budget_ci); + ciintf_init(budget_ci); return 0; } diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c index 15cf7442217b..4a0fea87a119 100644 --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/dvb/ttpci/budget-core.c @@ -34,10 +34,15 @@ * the project's page is at http://www.linuxtv.org/dvb/ */ +#include + #include "budget.h" #include "ttpci-eeprom.h" -int budget_debug = 0; +int budget_debug; + +module_param_named(debug, budget_debug, int, 0644); +MODULE_PARM_DESC(budget_debug, "Turn on/off budget debugging (default:off)."); /**************************************************************************** * TT budget / WinTV Nova @@ -258,13 +263,26 @@ static void budget_unregister(struct budget *budget) dvb_dmx_release(&budget->demux); } - -static int master_xfer (struct dvb_i2c_bus *i2c, const struct i2c_msg msgs[], int num) +/* fixme: can this be unified among all saa7146 based dvb cards? */ +static int client_register(struct i2c_client *client) { - struct saa7146_dev *dev = i2c->data; - return saa7146_i2c_transfer(dev, msgs, num, 6); + struct saa7146_dev *dev = (struct saa7146_dev*)i2c_get_adapdata(client->adapter); + struct budget *budget = (struct budget*)dev->ext_priv; + + if (client->driver->command) + return client->driver->command(client, FE_REGISTER, budget->dvb_adapter); + return 0; } +static int client_unregister(struct i2c_client *client) +{ + struct saa7146_dev *dev = (struct saa7146_dev*)i2c_get_adapdata(client->adapter); + struct budget *budget = (struct budget*)dev->ext_priv; + + if (client->driver->command) + return client->driver->command(client, FE_UNREGISTER, budget->dvb_adapter); + return 0; +} int ttpci_budget_init (struct budget *budget, struct saa7146_dev* dev, @@ -301,17 +319,27 @@ int ttpci_budget_init (struct budget *budget, if (bi->type != BUDGET_FS_ACTIVY) saa7146_write(dev, GPIO_CTRL, 0x500000); /* GPIO 3 = 1 */ - saa7146_i2c_adapter_prepare(dev, NULL, 0, SAA7146_I2C_BUS_BIT_RATE_120); - - budget->i2c_bus = dvb_register_i2c_bus (master_xfer, dev, - budget->dvb_adapter, 0); - - if (!budget->i2c_bus) { + budget->i2c_adap = (struct i2c_adapter) { + .client_register = client_register, + .client_unregister = client_unregister, +#ifdef I2C_ADAP_CLASS_TV_DIGITAL + .class = I2C_ADAP_CLASS_TV_DIGITAL, +#else + .class = I2C_CLASS_TV_DIGITAL, +#endif + }; + + strlcpy(budget->i2c_adap.name, budget->card->name, sizeof(budget->i2c_adap.name)); + + saa7146_i2c_adapter_prepare(dev, &budget->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); + strcpy(budget->i2c_adap.name, budget->card->name); + + if (i2c_add_adapter(&budget->i2c_adap) < 0) { dvb_unregister_adapter (budget->dvb_adapter); return -ENOMEM; } - ttpci_eeprom_parse_mac(budget->i2c_bus); + ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter->proposed_mac); if( NULL == (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci,length,&budget->pt))) { ret = -ENOMEM; @@ -334,12 +362,11 @@ int ttpci_budget_init (struct budget *budget, return 0; } err: + i2c_del_adapter(&budget->i2c_adap); + if (budget->grabbing) vfree(budget->grabbing); - dvb_unregister_i2c_bus (master_xfer,budget->i2c_bus->adapter, - budget->i2c_bus->id); - dvb_unregister_adapter (budget->dvb_adapter); return ret; @@ -354,8 +381,7 @@ int ttpci_budget_deinit (struct budget *budget) budget_unregister (budget); - dvb_unregister_i2c_bus (master_xfer, budget->i2c_bus->adapter, - budget->i2c_bus->id); + i2c_del_adapter(&budget->i2c_adap); dvb_unregister_adapter (budget->dvb_adapter); @@ -402,7 +428,5 @@ EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler); EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port); EXPORT_SYMBOL_GPL(budget_debug); -MODULE_PARM(budget_debug,"i"); MODULE_LICENSE("GPL"); - diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index fbf1d5a6df72..21aacb748788 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -35,7 +35,6 @@ */ #include "budget.h" -#include "dvb_functions.h" static void Set22K (struct budget *budget, int state) { @@ -100,7 +99,7 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long udelay(12500); saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); } - dvb_delay(20); + msleep(20); } return 0; @@ -202,6 +201,8 @@ static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_ DEB_EE(("dev:%p, info:%p, budget:%p\n",dev,info,budget)); + dev->ext_priv = budget; + if ((err = ttpci_budget_init (budget, dev, info))) { printk("==> failed\n"); kfree (budget); @@ -215,8 +216,6 @@ static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_ dvb_add_frontend_ioctls (budget->dvb_adapter, budget_diseqc_ioctl, NULL, budget); - dev->ext_priv = budget; - return 0; } diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h index 6be1d3bcdf7e..f0a15da1110a 100644 --- a/drivers/media/dvb/ttpci/budget.h +++ b/drivers/media/dvb/ttpci/budget.h @@ -1,9 +1,6 @@ #ifndef __BUDGET_DVB__ #define __BUDGET_DVB__ -#include - -#include "dvb_i2c.h" #include "dvb_frontend.h" #include "dvbdev.h" #include "demux.h" @@ -12,6 +9,8 @@ #include "dvb_filter.h" #include "dvb_net.h" +#include + extern int budget_debug; struct budget_info { @@ -28,7 +27,7 @@ struct budget { struct saa7146_dev *dev; - struct dvb_i2c_bus *i2c_bus; + struct i2c_adapter i2c_adap; struct budget_info *card; unsigned char *grabbing; @@ -79,6 +78,7 @@ static struct saa7146_pci_extension_data x_var = { \ #define BUDGET_KNC1 2 #define BUDGET_PATCH 3 #define BUDGET_FS_ACTIVY 4 +#define BUDGET_CIN1200 5 #define BUDGET_VIDEO_PORTA 0 #define BUDGET_VIDEO_PORTB 1 diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.c b/drivers/media/dvb/ttpci/ttpci-eeprom.c index a17c828fdde9..0659c53f9464 100644 --- a/drivers/media/dvb/ttpci/ttpci-eeprom.c +++ b/drivers/media/dvb/ttpci/ttpci-eeprom.c @@ -35,9 +35,8 @@ #include #include #include +#include -#include "dvb_i2c.h" -#include "dvb_functions.h" #if 1 #define dprintk(x...) do { printk(x); } while (0) @@ -85,7 +84,7 @@ static int getmac_tt(u8 * decodedMAC, u8 * encodedMAC) return 0; } -static int ttpci_eeprom_read_encodedMAC(struct dvb_i2c_bus *i2c, u8 * encodedMAC) +static int ttpci_eeprom_read_encodedMAC(struct i2c_adapter *adapter, u8 * encodedMAC) { int ret; u8 b0[] = { 0xcc }; @@ -97,7 +96,7 @@ static int ttpci_eeprom_read_encodedMAC(struct dvb_i2c_bus *i2c, u8 * encodedMAC /* dprintk("%s\n", __FUNCTION__); */ - ret = i2c->xfer(i2c, msg, 2); + ret = i2c_transfer(adapter, msg, 2); if (ret != 2) /* Assume EEPROM isn't there */ return (-ENODEV); @@ -106,36 +105,34 @@ static int ttpci_eeprom_read_encodedMAC(struct dvb_i2c_bus *i2c, u8 * encodedMAC } -int ttpci_eeprom_parse_mac(struct dvb_i2c_bus *i2c) +int ttpci_eeprom_parse_mac(struct i2c_adapter *adapter, u8 *proposed_mac) { int ret, i; u8 encodedMAC[20]; u8 decodedMAC[6]; - ret = ttpci_eeprom_read_encodedMAC(i2c, encodedMAC); + ret = ttpci_eeprom_read_encodedMAC(adapter, encodedMAC); if (ret != 0) { /* Will only be -ENODEV */ dprintk("Couldn't read from EEPROM: not there?\n"); - memset(i2c->adapter->proposed_mac, 0, 6); + memset(proposed_mac, 0, 6); return ret; } ret = getmac_tt(decodedMAC, encodedMAC); if( ret != 0 ) { - dprintk("%s adapter %i failed MAC signature check\n", - i2c->adapter->name, i2c->adapter->num); + dprintk("adapter failed MAC signature check\n"); dprintk("encoded MAC from EEPROM was " ); for(i=0; i<19; i++) { dprintk( "%.2x:", encodedMAC[i]); } dprintk("%.2x\n", encodedMAC[19]); - memset(i2c->adapter->proposed_mac, 0, 6); + memset(proposed_mac, 0, 6); return ret; } - memcpy(i2c->adapter->proposed_mac, decodedMAC, 6); - dprintk("%s adapter %i has MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", - i2c->adapter->name, i2c->adapter->num, + memcpy(proposed_mac, decodedMAC, 6); + dprintk("adapter has MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", decodedMAC[0], decodedMAC[1], decodedMAC[2], decodedMAC[3], decodedMAC[4], decodedMAC[5]); return 0; diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.h b/drivers/media/dvb/ttpci/ttpci-eeprom.h index 48df7ce53f3c..e2dc6cfe205c 100644 --- a/drivers/media/dvb/ttpci/ttpci-eeprom.h +++ b/drivers/media/dvb/ttpci/ttpci-eeprom.h @@ -25,8 +25,9 @@ #ifndef __TTPCI_EEPROM_H__ #define __TTPCI_EEPROM_H__ -#include "dvb_i2c.h" +#include +#include -extern int ttpci_eeprom_parse_mac(struct dvb_i2c_bus *i2c); +extern int ttpci_eeprom_parse_mac(struct i2c_adapter *adapter, u8 *propsed_mac); #endif diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index cc14ec76d43b..537c7eccdebb 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -28,8 +29,6 @@ #include #include -#include "dvb_functions.h" - /* TTUSB_HWSECTIONS: the DSP supports filtering in hardware, however, since the "muxstream" @@ -49,7 +48,10 @@ this unless the device doesn't load at all. > 2 for bandwidth statistics. */ -static int debug = 0; +static int debug; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); #define dprintk(x...) do { if (debug) printk(KERN_DEBUG x); } while (0) @@ -80,6 +82,8 @@ struct ttusb { struct dvb_adapter *adapter; struct usb_device *dev; + struct i2c_adapter i2c_adap; + int disconnecting; int iso_streaming; @@ -242,10 +246,9 @@ static int ttusb_i2c_msg(struct ttusb *ttusb, return rcv_len; } -static int ttusb_i2c_xfer(struct dvb_i2c_bus *i2c, const struct i2c_msg msg[], - int num) +static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg msg[], int num) { - struct ttusb *ttusb = i2c->data; + struct ttusb *ttusb = i2c_get_adapdata(adapter); int i = 0; int inc; @@ -514,7 +517,7 @@ static int ttusb_set_tone(struct ttusb *ttusb, fe_sec_tone_mode_t tone) static int ttusb_lnb_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) { - struct ttusb *ttusb = fe->i2c->data; + struct ttusb *ttusb = fe->before_after_data; switch (cmd) { case FE_SET_VOLTAGE: @@ -787,7 +790,7 @@ static void ttusb_iso_irq(struct urb *urb, struct pt_regs *ptregs) ttusb_process_frame(ttusb, data, len); } } - usb_submit_urb(urb, GFP_KERNEL); + usb_submit_urb(urb, GFP_ATOMIC); } static void ttusb_free_iso_urbs(struct ttusb *ttusb) @@ -822,7 +825,7 @@ static int ttusb_alloc_iso_urbs(struct ttusb *ttusb) if (! (urb = - usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_KERNEL))) { + usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_ATOMIC))) { ttusb_free_iso_urbs(ttusb); return -ENOMEM; } @@ -880,7 +883,7 @@ static int ttusb_start_iso_xfer(struct ttusb *ttusb) } for (i = 0; i < ISO_BUF_COUNT; i++) { - if ((err = usb_submit_urb(ttusb->iso_urb[i], GFP_KERNEL))) { + if ((err = usb_submit_urb(ttusb->iso_urb[i], GFP_ATOMIC))) { ttusb_stop_iso_xfer(ttusb); printk ("%s: failed urb submission (%i: err = %i)!\n", @@ -1068,6 +1071,38 @@ static struct file_operations stc_fops = { }; #endif +u32 functionality(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm ttusb_dec_algo = { + .name = "ttusb dec i2c algorithm", + .id = I2C_ALGO_BIT, + .master_xfer = master_xfer, + .functionality = functionality, +}; + +static int client_register(struct i2c_client *client) +{ + struct ttusb *ttusb = (struct ttusb*)i2c_get_adapdata(client->adapter); + + if (client->driver->command) + return client->driver->command(client, FE_REGISTER, ttusb->adapter); + + return 0; +} + +static int client_unregister(struct i2c_client *client) +{ + struct ttusb *ttusb = (struct ttusb*)i2c_get_adapdata(client->adapter); + + if (client->driver->command) + return client->driver->command(client, FE_UNREGISTER, ttusb->adapter); + + return 0; +} + static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev; @@ -1078,17 +1113,6 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i udev = interface_to_usbdev(intf); - /* Device has already been reset; its configuration was chosen. - * If this fault happens, use a hotplug script to choose the - * right configuration (write bConfigurationValue in sysfs). - */ - if (udev->actconfig->desc.bConfigurationValue != 1) { - dev_err(&intf->dev, "device config is #%d, need #1\n", - udev->actconfig->desc.bConfigurationValue); - return -ENODEV; - } - - if (intf->altsetting->desc.bInterfaceNumber != 1) return -ENODEV; if (!(ttusb = kmalloc(sizeof(struct ttusb), GFP_KERNEL))) @@ -1117,7 +1141,29 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE); - dvb_register_i2c_bus(ttusb_i2c_xfer, ttusb, ttusb->adapter, 0); + /* i2c */ + memset(&ttusb->i2c_adap, 0, sizeof(struct i2c_adapter)); + strcpy(ttusb->i2c_adap.name, "TTUSB DEC"); + + i2c_set_adapdata(&ttusb->i2c_adap, ttusb); + +#ifdef I2C_ADAP_CLASS_TV_DIGITAL + ttusb->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL; +#else + ttusb->i2c_adap.class = I2C_CLASS_TV_DIGITAL; +#endif + ttusb->i2c_adap.algo = &ttusb_dec_algo; + ttusb->i2c_adap.algo_data = NULL; + ttusb->i2c_adap.id = I2C_ALGO_BIT; + ttusb->i2c_adap.client_register = client_register; + ttusb->i2c_adap.client_unregister = client_unregister; + + result = i2c_add_adapter(&ttusb->i2c_adap); + if (result) { + dvb_unregister_adapter (ttusb->adapter); + return result; + } + dvb_add_frontend_ioctls(ttusb->adapter, ttusb_lnb_ioctl, NULL, ttusb); @@ -1137,9 +1183,10 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i ttusb->dvb_demux.write_to_decoder = NULL; if ((result = dvb_dmx_init(&ttusb->dvb_demux)) < 0) { - printk("ttusb_dvb: dvb_dmx_init failed (errno = %d)\n", - result); - goto err; + printk("ttusb_dvb: dvb_dmx_init failed (errno = %d)\n", result); + i2c_del_adapter(&ttusb->i2c_adap); + dvb_unregister_adapter (ttusb->adapter); + return -ENODEV; } //FIXME dmxdev (nur WAS?) ttusb->dmxdev.filternum = ttusb->dvb_demux.filternum; @@ -1150,15 +1197,20 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i printk("ttusb_dvb: dvb_dmxdev_init failed (errno = %d)\n", result); dvb_dmx_release(&ttusb->dvb_demux); - goto err; + i2c_del_adapter(&ttusb->i2c_adap); + dvb_unregister_adapter (ttusb->adapter); + return -ENODEV; } - if (dvb_net_init - (ttusb->adapter, &ttusb->dvbnet, &ttusb->dvb_demux.dmx)) { + if (dvb_net_init(ttusb->adapter, &ttusb->dvbnet, &ttusb->dvb_demux.dmx)) { printk("ttusb_dvb: dvb_net_init failed!\n"); + dvb_dmxdev_release(&ttusb->dmxdev); + dvb_dmx_release(&ttusb->dvb_demux); + i2c_del_adapter(&ttusb->i2c_adap); + dvb_unregister_adapter (ttusb->adapter); + return -ENODEV; } - err: #if 0 ttusb->stc_devfs_handle = devfs_register(ttusb->adapter->devfs_handle, TTUSB_BUDGET_NAME, @@ -1187,7 +1239,7 @@ static void ttusb_disconnect(struct usb_interface *intf) dvb_dmxdev_release(&ttusb->dmxdev); dvb_dmx_release(&ttusb->dvb_demux); - dvb_unregister_i2c_bus(ttusb_i2c_xfer, ttusb->adapter, 0); + i2c_del_adapter(&ttusb->i2c_adap); dvb_unregister_adapter(ttusb->adapter); ttusb_free_iso_urbs(ttusb); @@ -1234,9 +1286,6 @@ static void __exit ttusb_exit(void) module_init(ttusb_init); module_exit(ttusb_exit); -MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, "Debug or not"); - MODULE_AUTHOR("Holger Waechtler "); MODULE_DESCRIPTION("TTUSB DVB Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index cc48a65e8b14..ec31f21f264b 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -22,10 +22,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #if defined(CONFIG_CRC32) || defined(CONFIG_CRC32_MODULE) @@ -37,13 +39,17 @@ #include "dmxdev.h" #include "dvb_demux.h" -#include "dvb_i2c.h" #include "dvb_filter.h" #include "dvb_frontend.h" #include "dvb_net.h" -static int debug = 0; -static int output_pva = 0; +static int debug; +static int output_pva; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); +module_param(output_pva, int, 0444); +MODULE_PARM_DESC(output_pva, "Output PVA from dvr device (default:off)"); #define dprintk if (debug) printk @@ -95,7 +101,6 @@ struct ttusb_dec { struct dmxdev dmxdev; struct dvb_demux demux; struct dmx_frontend frontend; - struct dvb_i2c_bus i2c_bus; struct dvb_net dvb_net; struct dvb_frontend_info *frontend_info; int (*frontend_ioctl) (struct dvb_frontend *, unsigned int, void *); @@ -1100,7 +1105,7 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec) &dec->iso_dma_handle); memset(dec->iso_buffer, 0, - sizeof(ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT))); + ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT)); for (i = 0; i < ISO_BUF_COUNT; i++) { struct urb *urb; @@ -1600,7 +1605,7 @@ static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe, p->u.qam.symbol_rate); dprintk(" inversion->%d\n", p->inversion); - freq = htonl(p->frequency * 1000 + + freq = htonl(p->frequency + (dec->hi_band ? LOF_HI : LOF_LO)); memcpy(&b[4], &freq, sizeof(u32)); sym_rate = htonl(p->u.qam.symbol_rate); @@ -1628,9 +1633,18 @@ static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe, dprintk("%s: FE_INIT\n", __FUNCTION__); break; - case FE_DISEQC_SEND_MASTER_CMD: + case FE_DISEQC_SEND_MASTER_CMD: { + u8 b[] = { 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 }; + struct dvb_diseqc_master_cmd *cmd = arg; + memcpy(&b[4], cmd->msg, cmd->msg_len); dprintk("%s: FE_DISEQC_SEND_MASTER_CMD\n", __FUNCTION__); + ttusb_dec_send_command(dec, 0x72, + sizeof(b) - (6 - cmd->msg_len), b, + NULL, NULL); break; + } case FE_DISEQC_SEND_BURST: dprintk("%s: FE_DISEQC_SEND_BURST\n", __FUNCTION__); @@ -1669,15 +1683,13 @@ static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe, static void ttusb_dec_init_frontend(struct ttusb_dec *dec) { - dec->i2c_bus.adapter = dec->adapter; - - dvb_register_frontend(dec->frontend_ioctl, &dec->i2c_bus, (void *)dec, - dec->frontend_info); + int ret; + ret = dvb_register_frontend(dec->frontend_ioctl, dec->adapter, dec, dec->frontend_info, THIS_MODULE); } static void ttusb_dec_exit_frontend(struct ttusb_dec *dec) { - dvb_unregister_frontend(dec->frontend_ioctl, &dec->i2c_bus); + dvb_unregister_frontend_new(dec->frontend_ioctl, dec->adapter); } static void ttusb_dec_init_filters(struct ttusb_dec *dec) @@ -1840,7 +1852,3 @@ MODULE_DESCRIPTION(DRIVER_NAME); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(usb, ttusb_dec_table); -MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, "Debug level"); -MODULE_PARM(output_pva, "i"); -MODULE_PARM_DESC(output_pva, "Output PVA from dvr device"); diff --git a/include/linux/dvb/osd.h b/include/linux/dvb/osd.h index cdaff25eccc3..d236deac80f1 100644 --- a/include/linux/dvb/osd.h +++ b/include/linux/dvb/osd.h @@ -94,6 +94,7 @@ typedef enum { OSD_Text, // (x0,y0,size,color,text) OSD_SetWindow, // (x0) set window with number 0 Date: Tue, 19 Oct 2004 18:24:43 -0700 Subject: [PATCH] nfsd4: reference count stateowners Reference-counting the nfsd4 stateowner structs will let us fix a race and simplify some of the xdr code a bit, and may also help us make the nfsd4 locking a little more fine-grained in the future. Signed-off-by: J. Bruce Fields Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/nfs4state.c | 27 ++++++++++++++------------- include/linux/nfsd/state.h | 16 ++++++++++++++++ 2 files changed, 30 insertions(+), 13 deletions(-) (limited to 'include/linux') diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 1ca8ce8f6680..3885d97b48d0 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -833,6 +833,17 @@ release_all_files(void) } } +/* should use a slab cache */ +void +nfs4_free_stateowner(struct kref *kref) +{ + struct nfs4_stateowner *sop = + container_of(kref, struct nfs4_stateowner, so_ref); + kfree(sop->so_owner.data); + kfree(sop); + free_sowner++; +} + static inline struct nfs4_stateowner * alloc_stateowner(struct xdr_netobj *owner) { @@ -842,6 +853,7 @@ alloc_stateowner(struct xdr_netobj *owner) if ((sop->so_owner.data = kmalloc(owner->len, GFP_KERNEL))) { memcpy(sop->so_owner.data, owner->data, owner->len); sop->so_owner.len = owner->len; + kref_init(&sop->so_ref); return sop; } kfree(sop); @@ -849,17 +861,6 @@ alloc_stateowner(struct xdr_netobj *owner) return NULL; } -/* should use a slab cache */ -static void -free_stateowner(struct nfs4_stateowner *sop) { - if (sop) { - kfree(sop->so_owner.data); - kfree(sop); - sop = NULL; - free_sowner++; - } -} - static struct nfs4_stateowner * alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, struct nfsd4_open *open) { struct nfs4_stateowner *sop; @@ -932,7 +933,7 @@ release_stateowner(struct nfs4_stateowner *sop) { unhash_stateowner(sop); list_del(&sop->so_close_lru); - free_stateowner(sop); + nfs4_put_stateowner(sop); } static inline void @@ -1460,7 +1461,7 @@ nfs4_laundromat(void) dprintk("NFSD: purging unused open stateowner (so_id %d)\n", sop->so_id); list_del(&sop->so_close_lru); - free_stateowner(sop); + nfs4_put_stateowner(sop); } if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT) clientid_val = NFSD_LAUNDROMAT_MINTIMEOUT; diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h index 97d84c887853..a56399b985a4 100644 --- a/include/linux/nfsd/state.h +++ b/include/linux/nfsd/state.h @@ -38,6 +38,7 @@ #define _NFSD4_STATE_H #include +#include #include #define NFS4_OPAQUE_LIMIT 1024 @@ -168,6 +169,7 @@ struct nfs4_replay { * reaped by laundramat thread after lease period. */ struct nfs4_stateowner { + struct kref so_ref; struct list_head so_idhash; /* hash by so_id */ struct list_head so_strhash; /* hash by op_name */ struct list_head so_perclient; /* nfs4_client->cl_perclient */ @@ -248,4 +250,18 @@ extern void nfs4_lock_state(void); extern void nfs4_unlock_state(void); extern int nfs4_in_grace(void); extern int nfs4_check_open_reclaim(clientid_t *clid); +extern void nfs4_free_stateowner(struct kref *kref); + +static inline void +nfs4_put_stateowner(struct nfs4_stateowner *so) +{ + kref_put(&so->so_ref, nfs4_free_stateowner); +} + +static inline void +nfs4_get_stateowner(struct nfs4_stateowner *so) +{ + kref_get(&so->so_ref); +} + #endif /* NFSD4_STATE_H */ -- cgit v1.2.3 From 7b7e07a026a089e49bba8f1fc7f06da2180c24a2 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Tue, 19 Oct 2004 18:25:26 -0700 Subject: [PATCH] nfsd4: fix race in xdr encoding of lock_denied response. We take a reference on the stateowner, and copy the clientid, instead of just hoping no one destroys the stateowner before we reference it in nfsd4_encode_lock_denied. Signed-off-by: J. Bruce Fields Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/nfs4state.c | 5 ++++- fs/nfsd/nfs4xdr.c | 3 ++- include/linux/nfsd/xdr4.h | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index fcf49fe08460..440695e625cb 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1949,8 +1949,11 @@ nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny) unsigned int hval = lockownerid_hashval(sop->so_id); deny->ld_sop = NULL; - if (nfs4_verify_lock_stateowner(sop, hval)) + if (nfs4_verify_lock_stateowner(sop, hval)) { + kref_get(&sop->so_ref); deny->ld_sop = sop; + deny->ld_clientid = sop->so_client->cl_clientid; + } deny->ld_start = fl->fl_start; deny->ld_length = ~(u64)0; if (fl->fl_end != ~(u64)0) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 67cbaa9cb050..76cd74eddbeb 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1994,9 +1994,10 @@ nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denie WRITE64(ld->ld_length); WRITE32(ld->ld_type); if (ld->ld_sop) { - WRITEMEM(&ld->ld_sop->so_client->cl_clientid, 8); + WRITEMEM(&ld->ld_clientid, 8); WRITE32(ld->ld_sop->so_owner.len); WRITEMEM(ld->ld_sop->so_owner.data, ld->ld_sop->so_owner.len); + kref_put(&ld->ld_sop->so_ref, nfs4_free_stateowner); } else { /* non - nfsv4 lock in conflict, no clientid nor owner */ WRITE64((u64)0); /* clientid */ WRITE32(0); /* length of owner name */ diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h index bf94561ca623..d629b5e55d90 100644 --- a/include/linux/nfsd/xdr4.h +++ b/include/linux/nfsd/xdr4.h @@ -116,6 +116,7 @@ struct nfsd4_link { }; struct nfsd4_lock_denied { + clientid_t ld_clientid; struct nfs4_stateowner *ld_sop; u64 ld_start; u64 ld_length; -- cgit v1.2.3 From 1ea5482bee2b6fdd0ef6a416c7648865ecaec806 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Tue, 19 Oct 2004 18:26:11 -0700 Subject: [PATCH] nfsd: set OPEN_RESULT_LOCKTYPE_POSIX in open() We should set the OPEN_RESULT_LOCKTYPE_POSIX flag in the return to open, to indicate that we support locking. Signed-off-by: Andy Adamson Signed-off-by: J. Bruce Fields Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/nfs4state.c | 2 +- include/linux/nfs4.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 5a044f0746a8..b217d554d247 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1384,7 +1384,7 @@ out: /* * To finish the open response, we just need to set the rflags. */ - open->op_rflags = 0; + open->op_rflags = NFS4_OPEN_RESULT_LOCKTYPE_POSIX; if (!open->op_stateowner->so_confirmed) open->op_rflags |= NFS4_OPEN_RESULT_CONFIRM; diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index 96974ab10f27..5ca8a8d8ccdf 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h @@ -35,6 +35,7 @@ #define NFS4_FH_VOL_RENAME 0x0008 #define NFS4_OPEN_RESULT_CONFIRM 0x0002 +#define NFS4_OPEN_RESULT_LOCKTYPE_POSIX 0x0004 #define NFS4_SHARE_ACCESS_READ 0x0001 #define NFS4_SHARE_ACCESS_WRITE 0x0002 -- cgit v1.2.3 From c363ca85e1d786d4f593fd8b224756e42c756b19 Mon Sep 17 00:00:00 2001 From: William Lee Irwin III Date: Tue, 19 Oct 2004 18:28:00 -0700 Subject: [PATCH] vm: introduce remap_pfn_range() to replace remap_page_range() This patch introduces remap_pfn_range(), destined to replace remap_page_range(), to which all callers of remap_page_range() are converted in the sequel. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm.h | 11 +++++++++-- mm/memory.c | 19 ++++++++----------- mm/nommu.c | 2 +- 3 files changed, 18 insertions(+), 14 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mm.h b/include/linux/mm.h index 158ee1c501f0..1538a9dd4f62 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -758,8 +758,15 @@ extern struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned lon extern struct page * vmalloc_to_page(void *addr); extern struct page * follow_page(struct mm_struct *mm, unsigned long address, int write); -extern int remap_page_range(struct vm_area_struct *vma, unsigned long from, - unsigned long to, unsigned long size, pgprot_t prot); +int remap_pfn_range(struct vm_area_struct *, unsigned long, + unsigned long, unsigned long, pgprot_t); + +static inline __deprecated /* since 25 Sept 2004 -- wli */ +int remap_page_range(struct vm_area_struct *vma, unsigned long uvaddr, + unsigned long paddr, unsigned long size, pgprot_t prot) +{ + return remap_pfn_range(vma, uvaddr, paddr >> PAGE_SHIFT, size, prot); +} #ifdef CONFIG_PROC_FS void __vm_stat_account(struct mm_struct *, unsigned long, struct file *, long); diff --git a/mm/memory.c b/mm/memory.c index c43881bbd00d..556ed18f7f2e 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -918,16 +918,14 @@ int zeromap_page_range(struct vm_area_struct *vma, unsigned long address, unsign * in null mappings (currently treated as "copy-on-access") */ static inline void remap_pte_range(pte_t * pte, unsigned long address, unsigned long size, - unsigned long phys_addr, pgprot_t prot) + unsigned long pfn, pgprot_t prot) { unsigned long end; - unsigned long pfn; address &= ~PMD_MASK; end = address + size; if (end > PMD_SIZE) end = PMD_SIZE; - pfn = phys_addr >> PAGE_SHIFT; do { BUG_ON(!pte_none(*pte)); if (!pfn_valid(pfn) || PageReserved(pfn_to_page(pfn))) @@ -939,7 +937,7 @@ static inline void remap_pte_range(pte_t * pte, unsigned long address, unsigned } static inline int remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size, - unsigned long phys_addr, pgprot_t prot) + unsigned long pfn, pgprot_t prot) { unsigned long base, end; @@ -948,12 +946,12 @@ static inline int remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned lo end = address + size; if (end > PGDIR_SIZE) end = PGDIR_SIZE; - phys_addr -= address; + pfn -= address >> PAGE_SHIFT; do { pte_t * pte = pte_alloc_map(mm, pmd, base + address); if (!pte) return -ENOMEM; - remap_pte_range(pte, base + address, end - address, address + phys_addr, prot); + remap_pte_range(pte, base + address, end - address, pfn + (address >> PAGE_SHIFT), prot); pte_unmap(pte); address = (address + PMD_SIZE) & PMD_MASK; pmd++; @@ -962,7 +960,7 @@ static inline int remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned lo } /* Note: this is only safe if the mm semaphore is held when called. */ -int remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long phys_addr, unsigned long size, pgprot_t prot) +int remap_pfn_range(struct vm_area_struct *vma, unsigned long from, unsigned long pfn, unsigned long size, pgprot_t prot) { int error = 0; pgd_t * dir; @@ -970,7 +968,7 @@ int remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned lo unsigned long end = from + size; struct mm_struct *mm = vma->vm_mm; - phys_addr -= from; + pfn -= from >> PAGE_SHIFT; dir = pgd_offset(mm, from); flush_cache_range(vma, beg, end); if (from >= end) @@ -982,7 +980,7 @@ int remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned lo error = -ENOMEM; if (!pmd) break; - error = remap_pmd_range(mm, pmd, from, end - from, phys_addr + from, prot); + error = remap_pmd_range(mm, pmd, from, end - from, pfn + (from >> PAGE_SHIFT), prot); if (error) break; from = (from + PGDIR_SIZE) & PGDIR_MASK; @@ -995,8 +993,7 @@ int remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned lo spin_unlock(&mm->page_table_lock); return error; } - -EXPORT_SYMBOL(remap_page_range); +EXPORT_SYMBOL(remap_pfn_range); /* * Do pte_mkwrite, but only if the vma says VM_WRITE. We do this when diff --git a/mm/nommu.c b/mm/nommu.c index 68e6b32dea6a..f749f023e565 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -560,7 +560,7 @@ struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr) return NULL; } -int remap_page_range(struct vm_area_struct *vma, unsigned long from, +int remap_pfn_range(struct vm_area_struct *vma, unsigned long from, unsigned long to, unsigned long size, pgprot_t prot) { return -EPERM; -- cgit v1.2.3 From d38948f6fbf8a003a6384db00c62d601dab6285b Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 19 Oct 2004 18:29:31 -0700 Subject: [PATCH] disk stats preempt safety The per-cpu disk stats are being updated in a non-preempt-safe manner in a couple of places. The patch introduces introduces preempt and non-preempt versions of the statistics code and updates the block code to use the appropriate ones. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/ll_rw_blk.c | 20 ++++++++++---------- include/linux/genhd.h | 27 +++++++++++++++++++++------ 2 files changed, 31 insertions(+), 16 deletions(-) (limited to 'include/linux') diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 3ba6430899df..40dff89509de 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -2058,13 +2058,13 @@ void drive_stat_acct(struct request *rq, int nr_sectors, int new_io) return; if (rw == READ) { - disk_stat_add(rq->rq_disk, read_sectors, nr_sectors); + __disk_stat_add(rq->rq_disk, read_sectors, nr_sectors); if (!new_io) - disk_stat_inc(rq->rq_disk, read_merges); + __disk_stat_inc(rq->rq_disk, read_merges); } else if (rw == WRITE) { - disk_stat_add(rq->rq_disk, write_sectors, nr_sectors); + __disk_stat_add(rq->rq_disk, write_sectors, nr_sectors); if (!new_io) - disk_stat_inc(rq->rq_disk, write_merges); + __disk_stat_inc(rq->rq_disk, write_merges); } if (new_io) { disk_round_stats(rq->rq_disk); @@ -2110,12 +2110,12 @@ void disk_round_stats(struct gendisk *disk) { unsigned long now = jiffies; - disk_stat_add(disk, time_in_queue, + __disk_stat_add(disk, time_in_queue, disk->in_flight * (now - disk->stamp)); disk->stamp = now; if (disk->in_flight) - disk_stat_add(disk, io_ticks, (now - disk->stamp_idle)); + __disk_stat_add(disk, io_ticks, (now - disk->stamp_idle)); disk->stamp_idle = now; } @@ -2982,12 +2982,12 @@ void end_that_request_last(struct request *req) unsigned long duration = jiffies - req->start_time; switch (rq_data_dir(req)) { case WRITE: - disk_stat_inc(disk, writes); - disk_stat_add(disk, write_ticks, duration); + __disk_stat_inc(disk, writes); + __disk_stat_add(disk, write_ticks, duration); break; case READ: - disk_stat_inc(disk, reads); - disk_stat_add(disk, read_ticks, duration); + __disk_stat_inc(disk, reads); + __disk_stat_add(disk, read_ticks, duration); break; } disk_round_stats(disk); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 749992dc71b7..0692f7778f4f 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -129,13 +129,14 @@ struct gendisk { /* * Macros to operate on percpu disk statistics: - * Since writes to disk_stats are serialised through the queue_lock, - * smp_processor_id() should be enough to get to the per_cpu versions - * of statistics counters + * + * The __ variants should only be called in critical sections. The full + * variants disable/enable preemption. */ #ifdef CONFIG_SMP -#define disk_stat_add(gendiskp, field, addnd) \ +#define __disk_stat_add(gendiskp, field, addnd) \ (per_cpu_ptr(gendiskp->dkstats, smp_processor_id())->field += addnd) + #define disk_stat_read(gendiskp, field) \ ({ \ typeof(gendiskp->dkstats->field) res = 0; \ @@ -159,7 +160,8 @@ static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { } #else -#define disk_stat_add(gendiskp, field, addnd) (gendiskp->dkstats.field += addnd) +#define __disk_stat_add(gendiskp, field, addnd) \ + (gendiskp->dkstats.field += addnd) #define disk_stat_read(gendiskp, field) (gendiskp->dkstats.field) static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { @@ -167,8 +169,21 @@ static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { } #endif -#define disk_stat_inc(gendiskp, field) disk_stat_add(gendiskp, field, 1) +#define disk_stat_add(gendiskp, field, addnd) \ + do { \ + preempt_disable(); \ + __disk_stat_add(gendiskp, field, addnd); \ + preempt_enable(); \ + } while (0) + +#define __disk_stat_dec(gendiskp, field) __disk_stat_add(gendiskp, field, -1) #define disk_stat_dec(gendiskp, field) disk_stat_add(gendiskp, field, -1) + +#define __disk_stat_inc(gendiskp, field) __disk_stat_add(gendiskp, field, 1) +#define disk_stat_inc(gendiskp, field) disk_stat_add(gendiskp, field, 1) + +#define __disk_stat_sub(gendiskp, field, subnd) \ + __disk_stat_add(gendiskp, field, -subnd) #define disk_stat_sub(gendiskp, field, subnd) \ disk_stat_add(gendiskp, field, -subnd) -- cgit v1.2.3 From 26d784977a0a78038f934cd2fb3ce35975d0ebee Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 19 Oct 2004 18:30:01 -0700 Subject: [PATCH] move struct k_itimer out of linux/sched.h I don't know why struct k_itimer was ever declared in sched.h; perhaps at one time it was referenced by something else there. There is no need for it now. This patch moves the struct where it belongs, in linux/posix-timers.h. It has zero effect on anything except keeping the source easier to read. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/posix-timers.h | 20 ++++++++++++++++++++ include/linux/sched.h | 20 -------------------- 2 files changed, 20 insertions(+), 20 deletions(-) (limited to 'include/linux') diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index ec4910e37c65..1e6c5e90089f 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -4,6 +4,26 @@ #include #include +/* POSIX.1b interval timer structure. */ +struct k_itimer { + struct list_head list; /* free/ allocate list */ + spinlock_t it_lock; + clockid_t it_clock; /* which timer type */ + timer_t it_id; /* timer id */ + int it_overrun; /* overrun on pending signal */ + int it_overrun_last; /* overrun on last delivered signal */ + int it_requeue_pending; /* waiting to requeue this timer */ + int it_sigev_notify; /* notify word of sigevent struct */ + int it_sigev_signo; /* signo word of sigevent struct */ + sigval_t it_sigev_value; /* value word of sigevent struct */ + unsigned long it_incr; /* interval specified in jiffies */ + struct task_struct *it_process; /* process to send signal to */ + struct timer_list it_timer; + struct sigqueue *sigq; /* signal queue entry. */ + struct list_head abs_timer_entry; /* clock abs_timer_list */ + struct timespec wall_to_prev; /* wall_to_monotonic used when set */ +}; + struct k_clock_abs { struct list_head list; spinlock_t lock; diff --git a/include/linux/sched.h b/include/linux/sched.h index 1c556975b2dd..04c8d47e8654 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -375,26 +375,6 @@ typedef struct prio_array prio_array_t; struct backing_dev_info; struct reclaim_state; -/* POSIX.1b interval timer structure. */ -struct k_itimer { - struct list_head list; /* free/ allocate list */ - spinlock_t it_lock; - clockid_t it_clock; /* which timer type */ - timer_t it_id; /* timer id */ - int it_overrun; /* overrun on pending signal */ - int it_overrun_last; /* overrun on last delivered signal */ - int it_requeue_pending; /* waiting to requeue this timer */ - int it_sigev_notify; /* notify word of sigevent struct */ - int it_sigev_signo; /* signo word of sigevent struct */ - sigval_t it_sigev_value; /* value word of sigevent struct */ - unsigned long it_incr; /* interval specified in jiffies */ - struct task_struct *it_process; /* process to send signal to */ - struct timer_list it_timer; - struct sigqueue *sigq; /* signal queue entry. */ - struct list_head abs_timer_entry; /* clock abs_timer_list */ - struct timespec wall_to_prev; /* wall_to_monotonic used when set */ -}; - #ifdef CONFIG_SCHEDSTATS struct sched_info { /* cumulative counters */ -- cgit v1.2.3 From cdb16df9d3f41be07e35dbff6d4a0e453fdd6cf9 Mon Sep 17 00:00:00 2001 From: "Michael A. Halcrow" Date: Tue, 19 Oct 2004 18:30:12 -0700 Subject: [PATCH] BSD Secure Levels LSM: add time hooks I have received positive feedback from various individuals who have applied my BSD Secure Levels LSM patch, and so at this point I am submitting it to you with a request to merge it in. Nothing has changed in this patch since when I last posted it to the LKML, so I am not re-sending it there. This first patch adds hooks to catch attempts to set the system clock back. Signed-off-by: Michael A. Halcrow Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/mips/kernel/sysirix.c | 10 ++++++++-- arch/ppc64/kernel/time.c | 17 +++++++++++------ include/linux/security.h | 19 +++++++++++++++++++ kernel/time.c | 18 +++++++++++++----- security/capability.c | 1 + security/commoncap.c | 16 +++++++++++----- security/dummy.c | 8 ++++++++ 7 files changed, 71 insertions(+), 18 deletions(-) (limited to 'include/linux') diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c index 4ddbeed9d53e..88be7ef79eef 100644 --- a/arch/mips/kernel/sysirix.c +++ b/arch/mips/kernel/sysirix.c @@ -619,8 +619,14 @@ asmlinkage int irix_getgid(struct pt_regs *regs) asmlinkage int irix_stime(int value) { - if (!capable(CAP_SYS_TIME)) - return -EPERM; + int err; + struct timespec tv; + + tv.tv_sec = value; + tv.tv_nsec = 0; + err = security_settime(&tv, NULL); + if (err) + return err; write_seqlock_irq(&xtime_lock); xtime.tv_sec = value; diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c index 66fe6f6711b5..aea2c5cfa84e 100644 --- a/arch/ppc64/kernel/time.c +++ b/arch/ppc64/kernel/time.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -434,9 +435,7 @@ long ppc64_sys32_stime(int __user * tptr) { int value; struct timespec myTimeval; - - if (!capable(CAP_SYS_TIME)) - return -EPERM; + int err; if (get_user(value, tptr)) return -EFAULT; @@ -444,6 +443,10 @@ long ppc64_sys32_stime(int __user * tptr) myTimeval.tv_sec = value; myTimeval.tv_nsec = 0; + err = security_settime(&myTimeval, NULL); + if (err) + return err; + do_settimeofday(&myTimeval); return 0; @@ -459,9 +462,7 @@ long ppc64_sys_stime(long __user * tptr) { long value; struct timespec myTimeval; - - if (!capable(CAP_SYS_TIME)) - return -EPERM; + int err; if (get_user(value, tptr)) return -EFAULT; @@ -469,6 +470,10 @@ long ppc64_sys_stime(long __user * tptr) myTimeval.tv_sec = value; myTimeval.tv_nsec = 0; + err = security_settime(&myTimeval, NULL); + if (err) + return err; + do_settimeofday(&myTimeval); return 0; diff --git a/include/linux/security.h b/include/linux/security.h index ab0941c9fca7..c1792f3fb6ca 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -40,6 +40,7 @@ struct ctl_table; * as the default capabilities functions */ extern int cap_capable (struct task_struct *tsk, int cap); +extern int cap_settime (struct timespec *ts, struct timezone *tz); extern int cap_ptrace (struct task_struct *parent, struct task_struct *child); extern int cap_capget (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); extern int cap_capset_check (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); @@ -1001,6 +1002,12 @@ struct swap_info_struct; * See the syslog(2) manual page for an explanation of the @type values. * @type contains the type of action. * Return 0 if permission is granted. + * @settime: + * Check permission to change the system time. + * struct timespec and timezone are defined in include/linux/time.h + * @ts contains new time + * @tz contains new timezone + * Return 0 if permission is granted. * @vm_enough_memory: * Check permissions for allocating a new virtual mapping. * @pages contains the number of pages. @@ -1036,6 +1043,7 @@ struct security_operations { int (*quotactl) (int cmds, int type, int id, struct super_block * sb); int (*quota_on) (struct file * f); int (*syslog) (int type); + int (*settime) (struct timespec *ts, struct timezone *tz); int (*vm_enough_memory) (long pages); int (*bprm_alloc_security) (struct linux_binprm * bprm); @@ -1291,6 +1299,12 @@ static inline int security_syslog(int type) return security_ops->syslog(type); } +static inline int security_settime(struct timespec *ts, struct timezone *tz) +{ + return security_ops->settime(ts, tz); +} + + static inline int security_vm_enough_memory(long pages) { return security_ops->vm_enough_memory(pages); @@ -1963,6 +1977,11 @@ static inline int security_syslog(int type) return cap_syslog(type); } +static inline int security_settime(struct timespec *ts, struct timezone *tz) +{ + return cap_settime(ts, tz); +} + static inline int security_vm_enough_memory(long pages) { return cap_vm_enough_memory(pages); diff --git a/kernel/time.c b/kernel/time.c index 0b4797fa3d30..52b273c7ccac 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -32,6 +32,8 @@ #include #include #include +#include + #include #include @@ -78,13 +80,17 @@ asmlinkage long sys_time(int __user * tloc) asmlinkage long sys_stime(time_t __user *tptr) { struct timespec tv; + int err; - if (!capable(CAP_SYS_TIME)) - return -EPERM; if (get_user(tv.tv_sec, tptr)) return -EFAULT; tv.tv_nsec = 0; + + err = security_settime(&tv, NULL); + if (err) + return err; + do_settimeofday(&tv); return 0; } @@ -146,10 +152,12 @@ inline static void warp_clock(void) int do_sys_settimeofday(struct timespec *tv, struct timezone *tz) { static int firsttime = 1; + int error = 0; + + error = security_settime(tv, tz); + if (error) + return error; - if (!capable(CAP_SYS_TIME)) - return -EPERM; - if (tz) { /* SMP safe, global irq locking makes it work. */ sys_tz = *tz; diff --git a/security/capability.c b/security/capability.c index 532023c652ca..ec18d6075625 100644 --- a/security/capability.c +++ b/security/capability.c @@ -30,6 +30,7 @@ static struct security_operations capability_ops = { .capset_check = cap_capset_check, .capset_set = cap_capset_set, .capable = cap_capable, + .settime = cap_settime, .netlink_send = cap_netlink_send, .netlink_recv = cap_netlink_recv, diff --git a/security/commoncap.c b/security/commoncap.c index ed0d6136f6fc..6890914525dc 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -27,20 +27,25 @@ int cap_capable (struct task_struct *tsk, int cap) { /* Derived from include/linux/sched.h:capable. */ - if (cap_raised (tsk->cap_effective, cap)) + if (cap_raised(tsk->cap_effective, cap)) return 0; - else + return -EPERM; +} + +int cap_settime(struct timespec *ts, struct timezone *tz) +{ + if (!capable(CAP_SYS_TIME)) return -EPERM; + return 0; } int cap_ptrace (struct task_struct *parent, struct task_struct *child) { /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */ if (!cap_issubset (child->cap_permitted, current->cap_permitted) && - !capable (CAP_SYS_PTRACE)) + !capable(CAP_SYS_PTRACE)) return -EPERM; - else - return 0; + return 0; } int cap_capget (struct task_struct *target, kernel_cap_t *effective, @@ -373,6 +378,7 @@ int cap_vm_enough_memory(long pages) } EXPORT_SYMBOL(cap_capable); +EXPORT_SYMBOL(cap_settime); EXPORT_SYMBOL(cap_ptrace); EXPORT_SYMBOL(cap_capget); EXPORT_SYMBOL(cap_capset_check); diff --git a/security/dummy.c b/security/dummy.c index 0ce9f22d6c8c..c20c28ac1f00 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -104,6 +104,13 @@ static int dummy_syslog (int type) return 0; } +static int dummy_settime(struct timespec *ts, struct timezone *tz) +{ + if (!capable(CAP_SYS_TIME)) + return -EPERM; + return 0; +} + /* * Check that a process has enough memory to allocate a new virtual * mapping. 0 means there is enough memory for the allocation to @@ -897,6 +904,7 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, quota_on); set_to_dummy_if_null(ops, sysctl); set_to_dummy_if_null(ops, syslog); + set_to_dummy_if_null(ops, settime); set_to_dummy_if_null(ops, vm_enough_memory); set_to_dummy_if_null(ops, bprm_alloc_security); set_to_dummy_if_null(ops, bprm_free_security); -- cgit v1.2.3 From 40d799554739e50ad8f03690ef8880766f5c9891 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 19 Oct 2004 18:30:53 -0700 Subject: [PATCH] register_chrdev_region(), alloc_chrdev_region() const char A couple chrdev routines take a constant string and should be declared with const char *. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/char_dev.c | 5 +++-- include/linux/fs.h | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/fs/char_dev.c b/fs/char_dev.c index a1fd846920d3..a4d07d3ee954 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -153,7 +153,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct) return cd; } -int register_chrdev_region(dev_t from, unsigned count, char *name) +int register_chrdev_region(dev_t from, unsigned count, const char *name) { struct char_device_struct *cd; dev_t to = from + count; @@ -178,7 +178,8 @@ fail: return PTR_ERR(cd); } -int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, char *name) +int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, + const char *name) { struct char_device_struct *cd; cd = __register_chrdev_region(0, baseminor, count, name); diff --git a/include/linux/fs.h b/include/linux/fs.h index 6768655fd11d..5657f00fedef 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1270,8 +1270,8 @@ extern int bd_claim(struct block_device *, void *); extern void bd_release(struct block_device *); /* fs/char_dev.c */ -extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, char *); -extern int register_chrdev_region(dev_t, unsigned, char *); +extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *); +extern int register_chrdev_region(dev_t, unsigned, const char *); extern int register_chrdev(unsigned int, const char *, struct file_operations *); extern int unregister_chrdev(unsigned int, const char *); -- cgit v1.2.3 From bb82e8a53042a91688fd819d0c475a1c9a2b982a Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Tue, 19 Oct 2004 18:31:19 -0700 Subject: [PATCH] Posix compliant cpu clocks POSIX clocks are to be implemented in the following way according to V3 of the Single Unix Specification: 1. CLOCK_PROCESS_CPUTIME_ID Implementations shall also support the special clockid_t value CLOCK_PROCESS_CPUTIME_ID, which represents the CPU-time clock of the calling process when invoking one of the clock_*() or timer_*() functions. For these clock IDs, the values returned by clock_gettime() and specified by clock_settime() represent the amount of execution time of the process associated with the clock. 2. CLOCK_THREAD_CPUTIME_ID Implementations shall also support the special clockid_t value CLOCK_THREAD_CPUTIME_ID, which represents the CPU-time clock of the calling thread when invoking one of the clock_*() or timer_*() functions. For these clock IDs, the values returned by clock_gettime() and specified by clock_settime() shall represent the amount of execution time of the thread associated with the clock. These times mentioned are CPU processing times and not the time that has passed since the startup of a process. Glibc currently provides its own implementation of these two clocks which is designed to return the time that passed since the startup of a process or a thread. Moreover Glibc's clocks are bound to CPU timers which is problematic when the frequency of the clock changes or the process is moved to a different processor whose cpu timer may not be fully synchronized to the cpu timer of the current CPU. This patchset results in a both clocks working reliably. The patch also implements the access to other the thread and process clocks of linux processes by using negative clockid's: 1. For CLOCK_PROCESS_CPUTIME_ID: -pid 2. For CLOCK_THREAD_CPUTIME_ID: -(pid + PID_MAX_LIMIT) This allows clock_getcpuclockid(pid) to return -pid and pthread_getcpuiclock(pid) to return -(pid + PID_MAX_LIMIT) to allow access to the corresponding clocks. Todo: - The timer API to generate events by a non tick based timer is not usable in its current state. The posix timer API seems to be only useful at this point to define clock_get/set. Need to revise this. - Implement timed interrupts in mmtimer after API is revised. The mmtimer patch is unchanged from V6 and stays as is in 2.6.9-rc3-mm2. But I expect to update the driver as soon as the interface to setup hardware timer interrupts is usable. Single Thread Testing CLOCK_THREAD_CPUTIME_ID= 0.494140878 resolution= 0.000976563 CLOCK_PROCESS_CPUTIME_ID= 0.494140878 resolution= 0.000976563 Multi Thread Testing Starting Thread: 0 1 2 3 4 5 6 7 8 9 Joining Thread: 0 1 2 3 4 5 6 7 8 9 0 Cycles= 0 Thread= 0.000000000ns Process= 0.495117441ns 1 Cycles=1000000 Thread= 0.140625072ns Process= 2.523438792ns 2 Cycles=2000000 Thread= 0.966797370ns Process= 8.512699671ns 3 Cycles=3000000 Thread= 0.806641038ns Process= 7.561527309ns 4 Cycles=4000000 Thread= 1.865235330ns Process= 12.891608163ns 5 Cycles=5000000 Thread= 1.604493009ns Process= 11.528326215ns 6 Cycles=6000000 Thread= 2.086915131ns Process= 13.500983475ns 7 Cycles=7000000 Thread= 2.245118337ns Process= 13.947272766ns 8 Cycles=8000000 Thread= 1.604493009ns Process= 12.252935961ns 9 Cycles=9000000 Thread= 2.160157356ns Process= 13.977546219ns Clock status at the end of the timer tests: Gettimeofday() = 1097084999.489938000 CLOCK_REALTIME= 1097084999.490116229 resolution= 0.000000040 CLOCK_MONOTONIC= 177.071675109 resolution= 0.000000040 CLOCK_PROCESS_CPUTIME_ID= 13.978522782 resolution= 0.000976563 CLOCK_THREAD_CPUTIME_ID= 0.497070567 resolution= 0.000976563 CLOCK_SGI_CYCLE= 229.967982280 resolution= 0.000000040 PROCESS clock of 1 (init)= 4.833986850 resolution= 0.000976563 THREAD clock of 1 (init)= 0.009765630 resolution= 0.000976563 Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/posix-timers.h | 19 +++++- include/linux/time.h | 7 ++- kernel/posix-timers.c | 146 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 153 insertions(+), 19 deletions(-) (limited to 'include/linux') diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index 1e6c5e90089f..e7c08acbe796 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -33,9 +33,10 @@ struct k_clock { struct k_clock_abs *abs_struct; int (*clock_set) (struct timespec * tp); int (*clock_get) (struct timespec * tp); - int (*nsleep) (int flags, - struct timespec * new_setting, - struct itimerspec * old_setting); + int (*timer_create) (int which_clock, struct sigevent __user *timer_event_spec, + timer_t __user * created_timer_id); + int (*nsleep) (int which_clock, int flags, + struct timespec * t); int (*timer_set) (struct k_itimer * timr, int flags, struct itimerspec * new_setting, struct itimerspec * old_setting); @@ -43,6 +44,17 @@ struct k_clock { void (*timer_get) (struct k_itimer * timr, struct itimerspec * cur_setting); }; + +void register_posix_clock(int clock_id, struct k_clock *new_clock); + +/* Error handlers for timer_create, nanosleep and settime */ +int do_posix_clock_notimer_create(int which_clock, + struct sigevent __user *time_event_spec, + timer_t __user *created_timer_id); + +int do_posix_clock_nonanosleep(int which_clock, int flags, struct timespec * t); +int do_posix_clock_nosettime(struct timespec *tp); + struct now_struct { unsigned long jiffies; }; @@ -62,3 +74,4 @@ struct now_struct { } \ }while (0) #endif + diff --git a/include/linux/time.h b/include/linux/time.h index ae174b8ab036..320681c9bc81 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -157,7 +157,12 @@ struct itimerval { #define CLOCK_REALTIME_HR 4 #define CLOCK_MONOTONIC_HR 5 -#define MAX_CLOCKS 6 +/* + * The IDs of various hardware clocks + */ + + +#define MAX_CLOCKS 16 #define CLOCKS_MASK (CLOCK_REALTIME | CLOCK_MONOTONIC | \ CLOCK_REALTIME_HR | CLOCK_MONOTONIC_HR) #define CLOCKS_MONO (CLOCK_MONOTONIC & CLOCK_MONOTONIC_HR) diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index c2dc4f89da41..4a3f7cd9bfdc 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -10,6 +10,10 @@ * 2004-06-01 Fix CLOCK_REALTIME clock/timer TIMER_ABSTIME bug. * Copyright (C) 2004 Boris Hu * + * 2004-07-27 Provide POSIX compliant clocks + * CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID. + * by Christoph Lameter + * * 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 @@ -134,18 +138,10 @@ static spinlock_t idr_lock = SPIN_LOCK_UNLOCKED; * resolution. Here we define the standard CLOCK_REALTIME as a * 1/HZ resolution clock. * - * CPUTIME & THREAD_CPUTIME: We are not, at this time, definding these - * two clocks (and the other process related clocks (Std - * 1003.1d-1999). The way these should be supported, we think, - * is to use large negative numbers for the two clocks that are - * pinned to the executing process and to use -pid for clocks - * pinned to particular pids. Calls which supported these clock - * ids would split early in the function. - * * RESOLUTION: Clock resolution is used to round up timer and interval * times, NOT to report clock times, which are reported with as * much resolution as the system can muster. In some cases this - * resolution may depend on the underlaying clock hardware and + * resolution may depend on the underlying clock hardware and * may not be quantifiable until run time, and only then is the * necessary code is written. The standard says we should say * something about this issue in the documentation... @@ -163,7 +159,7 @@ static spinlock_t idr_lock = SPIN_LOCK_UNLOCKED; * * At this time all functions EXCEPT clock_nanosleep can be * redirected by the CLOCKS structure. Clock_nanosleep is in - * there, but the code ignors it. + * there, but the code ignores it. * * Permissions: It is assumed that the clock_settime() function defined * for each clock will take care of permission checks. Some @@ -193,12 +189,12 @@ static struct k_clock_abs abs_list = {.list = LIST_HEAD_INIT(abs_list.list), #define p_timer_del(clock,a) \ if_clock_do((clock)->timer_del, do_timer_delete, (a)) -void register_posix_clock(int clock_id, struct k_clock *new_clock); static int do_posix_gettime(struct k_clock *clock, struct timespec *tp); static u64 do_posix_clock_monotonic_gettime_parts( struct timespec *tp, struct timespec *mo); int do_posix_clock_monotonic_gettime(struct timespec *tp); -int do_posix_clock_monotonic_settime(struct timespec *tp); +static int do_posix_clock_process_gettime(struct timespec *tp); +static int do_posix_clock_thread_gettime(struct timespec *tp); static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags); static inline void unlock_timer(struct k_itimer *timr, unsigned long flags) @@ -217,11 +213,27 @@ static __init int init_posix_timers(void) struct k_clock clock_monotonic = {.res = CLOCK_REALTIME_RES, .abs_struct = NULL, .clock_get = do_posix_clock_monotonic_gettime, - .clock_set = do_posix_clock_monotonic_settime + .clock_set = do_posix_clock_nosettime + }; + struct k_clock clock_thread = {.res = CLOCK_REALTIME_RES, + .abs_struct = NULL, + .clock_get = do_posix_clock_thread_gettime, + .clock_set = do_posix_clock_nosettime, + .timer_create = do_posix_clock_notimer_create, + .nsleep = do_posix_clock_nonanosleep + }; + struct k_clock clock_process = {.res = CLOCK_REALTIME_RES, + .abs_struct = NULL, + .clock_get = do_posix_clock_process_gettime, + .clock_set = do_posix_clock_nosettime, + .timer_create = do_posix_clock_notimer_create, + .nsleep = do_posix_clock_nonanosleep }; register_posix_clock(CLOCK_REALTIME, &clock_realtime); register_posix_clock(CLOCK_MONOTONIC, &clock_monotonic); + register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &clock_process); + register_posix_clock(CLOCK_THREAD_CPUTIME_ID, &clock_thread); posix_timers_cache = kmem_cache_create("posix_timers_cache", sizeof (struct k_itimer), 0, 0, NULL, NULL); @@ -573,6 +585,10 @@ sys_timer_create(clockid_t which_clock, !posix_clocks[which_clock].res) return -EINVAL; + if (posix_clocks[which_clock].timer_create) + return posix_clocks[which_clock].timer_create(which_clock, + timer_event_spec, created_timer_id); + new_timer = alloc_posix_timer(); if (unlikely(!new_timer)) return -EAGAIN; @@ -1218,16 +1234,87 @@ int do_posix_clock_monotonic_gettime(struct timespec *tp) return 0; } -int do_posix_clock_monotonic_settime(struct timespec *tp) +int do_posix_clock_nosettime(struct timespec *tp) { return -EINVAL; } +int do_posix_clock_notimer_create(int which_clock, + struct sigevent __user *timer_event_spec, + timer_t __user *created_timer_id) { + return -EINVAL; +} + +int do_posix_clock_nonanosleep(int which_lock, int flags,struct timespec * t) { +/* Single Unix specficiation says to return ENOTSUP but we do not have that */ + return -EINVAL; +} + +static unsigned long process_ticks(task_t *p) { + unsigned long ticks; + task_t *t; + + spin_lock(&p->sighand->siglock); + /* The signal structure is shared between all threads */ + ticks = p->signal->utime + p->signal->stime; + + /* Add up the cpu time for all the still running threads of this process */ + t = p; + do { + ticks += t->utime + t->stime; + t = next_thread(t); + } while (t != p); + + spin_unlock(&p->sighand->siglock); + return ticks; +} + +static inline unsigned long thread_ticks(task_t *p) { + return p->utime + current->stime; +} + +/* + * Single Unix Specification V3: + * + * Implementations shall also support the special clockid_t value + * CLOCK_THREAD_CPUTIME_ID, which represents the CPU-time clock of the calling + * thread when invoking one of the clock_*() or timer_*() functions. For these + * clock IDs, the values returned by clock_gettime() and specified by + * clock_settime() shall represent the amount of execution time of the thread + * associated with the clock. + */ +static int do_posix_clock_thread_gettime(struct timespec *tp) +{ + jiffies_to_timespec(thread_ticks(current), tp); + return 0; +} + +/* + * Single Unix Specification V3: + * + * Implementations shall also support the special clockid_t value + * CLOCK_PROCESS_CPUTIME_ID, which represents the CPU-time clock of the + * calling process when invoking one of the clock_*() or timer_*() functions. + * For these clock IDs, the values returned by clock_gettime() and specified + * by clock_settime() represent the amount of execution time of the process + * associated with the clock. + */ + +static int do_posix_clock_process_gettime(struct timespec *tp) +{ + jiffies_to_timespec(process_ticks(current), tp); + return 0; +} + asmlinkage long sys_clock_settime(clockid_t which_clock, const struct timespec __user *tp) { struct timespec new_tp; + /* Cannot set process specific clocks */ + if (which_clock<0) + return -EINVAL; + if ((unsigned) which_clock >= MAX_CLOCKS || !posix_clocks[which_clock].res) return -EINVAL; @@ -1245,6 +1332,29 @@ sys_clock_gettime(clockid_t which_clock, struct timespec __user *tp) struct timespec rtn_tp; int error = 0; + /* Process process specific clocks */ + if (which_clock < 0) { + task_t *t; + int pid = -which_clock; + + if (pid < PID_MAX_LIMIT) { + if ((t = find_task_by_pid(pid))) { + jiffies_to_timespec(process_ticks(t), tp); + return 0; + } + return -EINVAL; + } + if (pid < 2*PID_MAX_LIMIT) { + if ((t = find_task_by_pid(pid - PID_MAX_LIMIT))) { + jiffies_to_timespec(thread_ticks(t), tp); + return 0; + } + return -EINVAL; + } + /* More process specific clocks could follow here */ + return -EINVAL; + } + if ((unsigned) which_clock >= MAX_CLOCKS || !posix_clocks[which_clock].res) return -EINVAL; @@ -1263,6 +1373,9 @@ sys_clock_getres(clockid_t which_clock, struct timespec __user *tp) { struct timespec rtn_tp; + /* All process clocks have the resolution of CLOCK_PROCESS_CPUTIME_ID */ + if (which_clock < 0 ) which_clock = CLOCK_PROCESS_CPUTIME_ID; + if ((unsigned) which_clock >= MAX_CLOCKS || !posix_clocks[which_clock].res) return -EINVAL; @@ -1409,7 +1522,10 @@ sys_clock_nanosleep(clockid_t which_clock, int flags, if ((unsigned) t.tv_nsec >= NSEC_PER_SEC || t.tv_sec < 0) return -EINVAL; - ret = do_clock_nanosleep(which_clock, flags, &t); + if (posix_clocks[which_clock].nsleep) + ret = posix_clocks[which_clock].nsleep(which_clock, flags, &t); + else + ret = do_clock_nanosleep(which_clock, flags, &t); /* * Do this here as do_clock_nanosleep does not have the real address */ -- cgit v1.2.3 From 6d338e926dd72fc697323d3271a4859fd15a54d2 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Tue, 19 Oct 2004 18:31:31 -0700 Subject: [PATCH] Posix compliant cpu clocks V6: mmtimer provides CLOCK_SGI_CYCLE * Add CLOCK_SGI_CYCLE provided by drivers/char/mmtimer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/mmtimer.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/time.h | 1 + 2 files changed, 45 insertions(+) (limited to 'include/linux') diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index 0dd1ba7eec61..d5fdf41b9eaa 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c @@ -25,6 +25,8 @@ #include #include #include +#include + #include #include #include @@ -178,6 +180,45 @@ static struct miscdevice mmtimer_miscdev = { &mmtimer_fops }; +static struct timespec sgi_clock_offset; +static int sgi_clock_period; + +static int sgi_clock_get(struct timespec *tp) { + u64 nsec; + + nsec = readq(RTC_COUNTER_ADDR) * sgi_clock_period + + sgi_clock_offset.tv_nsec; + tp->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &tp->tv_nsec) + + sgi_clock_offset.tv_sec; + return 0; +}; + +static int sgi_clock_set(struct timespec *tp) { + + u64 nsec; + u64 rem; + + nsec = readq(RTC_COUNTER_ADDR) * sgi_clock_period; + + sgi_clock_offset.tv_sec = tp->tv_sec - div_long_long_rem(nsec, NSEC_PER_SEC, &rem); + + if (rem <= tp->tv_nsec) + sgi_clock_offset.tv_nsec = tp->tv_sec - rem; + else { + sgi_clock_offset.tv_nsec = tp->tv_sec + NSEC_PER_SEC - rem; + sgi_clock_offset.tv_sec--; + } + return 0; +} + +static struct k_clock sgi_clock = { + .res = 0, + .clock_set = sgi_clock_set, + .clock_get = sgi_clock_get, + .timer_create = do_posix_clock_notimer_create, + .nsleep = do_posix_clock_nonanosleep +}; + /** * mmtimer_init - device initialization routine * @@ -207,6 +248,9 @@ static int __init mmtimer_init(void) return -1; } + sgi_clock_period = sgi_clock.res = NSEC_PER_SEC / sn_rtc_cycles_per_second; + register_posix_clock(CLOCK_SGI_CYCLE, &sgi_clock); + printk(KERN_INFO "%s: v%s, %ld MHz\n", MMTIMER_DESC, MMTIMER_VERSION, sn_rtc_cycles_per_second/(unsigned long)1E6); diff --git a/include/linux/time.h b/include/linux/time.h index 320681c9bc81..0814ed4a4586 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -162,6 +162,7 @@ struct itimerval { */ +#define CLOCK_SGI_CYCLE 10 #define MAX_CLOCKS 16 #define CLOCKS_MASK (CLOCK_REALTIME | CLOCK_MONOTONIC | \ CLOCK_REALTIME_HR | CLOCK_MONOTONIC_HR) -- cgit v1.2.3 From f07dd65162ad02746da92362a467f4e1645dc649 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Tue, 19 Oct 2004 18:35:52 -0700 Subject: [PATCH] mips: added missing definition and fixed typo This patch had added missing definition and had fixed typo for VRC4173. Cc: Ralf Baechle Signed-off-by: Yoichi Yuasa Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/mips/vr41xx/common/vrc4173.c | 5 ++++- include/linux/pci_ids.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/arch/mips/vr41xx/common/vrc4173.c b/arch/mips/vr41xx/common/vrc4173.c index 0bbad1e8c177..080ad4000ada 100644 --- a/arch/mips/vr41xx/common/vrc4173.c +++ b/arch/mips/vr41xx/common/vrc4173.c @@ -56,6 +56,9 @@ MODULE_LICENSE("GPL"); #define VRC4173_SYSINT1REG 0x060 #define VRC4173_MSYSINT1REG 0x06c +#define VRC4173_MPIUINTREG 0x06e +#define VRC4173_MAIUINTREG 0x070 +#define VRC4173_MKIUINTREG 0x072 #define VRC4173_SELECTREG 0x09e #define SEL3 0x0008 @@ -329,7 +332,7 @@ void vrc4173_enable_piuint(uint16_t mask) spin_unlock_irqrestore(&desc->lock, flags); } -EXPORT_SYMBOL(vrc4173_eanble_piuint); +EXPORT_SYMBOL(vrc4173_enable_piuint); void vrc4173_disable_piuint(uint16_t mask) { diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index d6e4a6ef3eb5..f2cdec811f1f 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -569,6 +569,7 @@ #define PCI_DEVICE_ID_NEC_PCX2 0x0046 /* PowerVR */ #define PCI_DEVICE_ID_NEC_NILE4 0x005a #define PCI_DEVICE_ID_NEC_VRC5476 0x009b +#define PCI_DEVICE_ID_NEC_VRC4173 0x00a5 #define PCI_DEVICE_ID_NEC_VRC5477_AC97 0x00a6 #define PCI_DEVICE_ID_NEC_PC9821CS01 0x800c /* PC-9821-CS01 */ #define PCI_DEVICE_ID_NEC_PC9821NRB06 0x800d /* PC-9821NR-B06 */ -- cgit v1.2.3 From 2850479a63f2505e8d6fdac8e111bbdf82f1bfb9 Mon Sep 17 00:00:00 2001 From: Matt Domsch Date: Tue, 19 Oct 2004 18:36:22 -0700 Subject: [PATCH] EDD: use EXTENDED READ command, add CONFIG_EDD_SKIP_MBR Some controller BIOSes have problems with the legacy int13 fn02 READ SECTORS command. int13 fn42 EXTENDED READ is used in preference by most boot loaders today, so lets use that. If EXTENDED READ fails or isn't supported, fall back to READ SECTORS. This hopefully resolves the three reports of BIOSes which would either long-pause (30+ seconds) or hang completely on the legacy READ SECTORS command. This also adds CONFIG_EDD_SKIP_MBR to eliminate reading the MBR on each BIOS-presented disk, in case there are further problems in this area. Signed-off-by: Matt Domsch Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/boot/edd.S | 126 ++++++++++++++++++++++++++++++++++++++++------- drivers/firmware/Kconfig | 11 +++++ include/linux/edd.h | 4 ++ 3 files changed, 123 insertions(+), 18 deletions(-) (limited to 'include/linux') diff --git a/arch/i386/boot/edd.S b/arch/i386/boot/edd.S index 889790693bcd..61af26a4bee6 100644 --- a/arch/i386/boot/edd.S +++ b/arch/i386/boot/edd.S @@ -7,20 +7,66 @@ * and Andrew Wilks September 2003, June 2004 * legacy CHS retreival by Patrick J. LoPresti * March 2004 + * Use EXTENDED READ calls if possible, Matt Domsch, October 2004 */ #include #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) -# Read the first sector of each BIOS disk device and store the 4-byte signature -edd_mbr_sig_start: movb $0, (EDD_MBR_SIG_NR_BUF) # zero value at EDD_MBR_SIG_NR_BUF +#ifndef CONFIG_EDD_SKIP_MBR + xorl %edx, %edx movb $0x80, %dl # from device 80 - movw $EDD_MBR_SIG_BUF, %bx # store buffer ptr in bx -edd_mbr_sig_read: - movl $0xFFFFFFFF, %eax - movl %eax, (%bx) # assume failure - pushw %bx + +edd_mbr_check_ext: + xorl %eax, %eax + xorl %ebx, %ebx + xorl %ecx, %ecx + movb $CHECKEXTENSIONSPRESENT, %ah # Function 41 + movw $EDDMAGIC1, %bx # magic + pushw %dx # work around buggy BIOSes + stc # work around buggy BIOSes + int $0x13 # make the call + sti # work around buggy BIOSes + popw %dx + jc edd_start # no more BIOS devices + cmpw $EDDMAGIC2, %bx # is magic right? + jne edd_mbr_sig_next # nope, next... + testw $FIXEDDISKSUBSET, %cx # EXTENDED READ supported? + jz edd_mbr_read_sectors # nope, use READ SECTORS + +edd_mbr_extended_read: +# Fill out the device address packet here, make the fn42 call + xorl %eax, %eax + xorl %ebx, %ebx + xorl %ecx, %ecx + subw $EDD_DEV_ADDR_PACKET_LEN, %sp # put packet on stack + pushw %si + movw %sp, %si + movl $0, (%si) # zero out packet + movl $0, 4(%si) + movl $0, 8(%si) + movl $0, 12(%si) + movb $EDD_DEV_ADDR_PACKET_LEN, (%si) # length of packet + movb $1, 2(%si) # move 1 sector + movw $EDDBUF, 4(%si) # into EDDBUF + movw %ds, 6(%si) # EDDBUF seg is ds + movb $EXTENDEDREAD, %ah + pushw %dx # work around buggy BIOSes + stc # work around buggy BIOSes + int $0x13 + sti # work around buggy BIOSes + popw %dx + popw %si + addw $EDD_DEV_ADDR_PACKET_LEN, %sp # remove packet from stack + jnc edd_mbr_store_sig + # otherwise, fall through to the legacy read function + +edd_mbr_read_sectors: +# Read the first sector of each BIOS disk device and store the 4-byte signature + xorl %eax, %eax + xorl %ebx, %ebx + xorl %ecx, %ecx movb $READ_SECTORS, %ah movb $1, %al # read 1 sector movb $0, %dh # at head 0 @@ -28,23 +74,31 @@ edd_mbr_sig_read: pushw %es pushw %ds popw %es - movw $EDDBUF, %bx # disk's data goes into EDDBUF - pushw %dx # work around buggy BIOSes - stc # work around buggy BIOSes + movw $EDDBUF, %bx # disk's data goes into EDDBUF + pushw %dx # work around buggy BIOSes + stc # work around buggy BIOSes int $0x13 - sti # work around buggy BIOSes + sti # work around buggy BIOSes popw %dx popw %es - popw %bx jc edd_mbr_sig_done # on failure, we're done. + +edd_mbr_store_sig: + xorl %ebx, %ebx # clear ebx + movb %dl, %bl # copy drive number to ebx + sub $0x80, %bl # subtract 80h from drive number + shlw $2, %bx # multiply by 4 + addw $EDD_MBR_SIG_BUF, %bx # add to sig_buf + # bx now points to the right sig slot movl (EDDBUF+EDD_MBR_SIG_OFFSET), %eax # read sig out of the MBR movl %eax, (%bx) # store success incb (EDD_MBR_SIG_NR_BUF) # note that we stored something +edd_mbr_sig_next: incb %dl # increment to next device - addw $4, %bx # increment sig buffer ptr cmpb $EDD_MBR_SIG_MAX, (EDD_MBR_SIG_NR_BUF) # Out of space? - jb edd_mbr_sig_read # keep looping + jb edd_mbr_check_ext # keep looping edd_mbr_sig_done: +#endif # Do the BIOS Enhanced Disk Drive calls # This consists of two calls: @@ -77,12 +131,35 @@ edd_start: movw $EDDBUF+EDDEXTSIZE, %si # in ds:si, fn41 results # kept just before that movb $0, (EDDNR) # zero value at EDDNR + xorl %edx, %edx movb $0x80, %dl # BIOS device 0x80 edd_check_ext: + pushw %di # zero out this edd_info block + pushw %es + movw %ds, %ax + movw %ax, %es + movw %si, %ax + subw $EDDEXTSIZE, %ax + movw %ax, %di + movl $EDDEXTSIZE+EDDPARMSIZE, %ecx + xorl %eax, %eax + cld + rep + stosb + popw %es + popw %di + + xorl %eax, %eax + xorl %ebx, %ebx + xorl %ecx, %ecx movb $CHECKEXTENSIONSPRESENT, %ah # Function 41 movw $EDDMAGIC1, %bx # magic + pushw %dx # work around buggy BIOSes + stc # work around buggy BIOSes int $0x13 # make the call + sti # work around buggy BIOSes + popw %dx jc edd_done # no more BIOS devices cmpw $EDDMAGIC2, %bx # is magic right? @@ -93,25 +170,38 @@ edd_check_ext: movw %cx, %ds:-6(%si) # store extensions incb (EDDNR) # note that we stored something + testw $GET_DEVICE_PARAMETERS_SUPPORTED, %cx + jz edd_get_legacy_chs # nope, skip fn48 + edd_get_device_params: + xorl %eax, %eax + xorl %ebx, %ebx + xorl %ecx, %ecx movw $EDDPARMSIZE, %ds:(%si) # put size - movw $0x0, %ds:2(%si) # work around buggy BIOSes movb $GETDEVICEPARAMETERS, %ah # Function 48 + pushw %dx # work around buggy BIOSes + stc # work around buggy BIOSes int $0x13 # make the call + sti # work around buggy BIOSes + popw %dx # Don't check for fail return # it doesn't matter. edd_get_legacy_chs: - xorw %ax, %ax + xorl %eax, %eax + xorl %ebx, %ebx + xorl %ecx, %ecx movw %ax, %ds:-4(%si) movw %ax, %ds:-2(%si) - # Ralf Brown's Interrupt List says to set ES:DI to + # Ralf Brown's Interrupt List says to set ES:DI to # 0000h:0000h "to guard against BIOS bugs" - pushw %es + pushw %es movw %ax, %es movw %ax, %di pushw %dx # legacy call clobbers %dl movb $LEGACYGETDEVICEPARAMETERS, %ah # Function 08 + stc # work around buggy BIOSes int $0x13 # make the call + sti # work around buggy BIOSes jc edd_legacy_done # failed movb %cl, %al # Low 6 bits are max andb $0x3F, %al # sector number diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 4607ddd4693e..b88322c91528 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -18,6 +18,17 @@ config EDD obscure configurations. Most disk controller BIOS vendors do not yet implement this feature. +config EDD_SKIP_MBR + bool "EDD: Skip Master Boot Record read" + depends on EDD + default n + help + Most controller BIOSs properly implement real-mode legacy + READ SECTORS commands. A few don't. + + If your controller hangs during the kernel's real-mode + startup routine, say Y here. + config EFI_VARS tristate "EFI Variable Support via sysfs" depends on EFI diff --git a/include/linux/edd.h b/include/linux/edd.h index 5f93881106fa..242600817a8d 100644 --- a/include/linux/edd.h +++ b/include/linux/edd.h @@ -37,14 +37,18 @@ #define EDDEXTSIZE 8 /* change these if you muck with the structures */ #define EDDPARMSIZE 74 #define CHECKEXTENSIONSPRESENT 0x41 +#define EXTENDEDREAD 0x42 #define GETDEVICEPARAMETERS 0x48 #define LEGACYGETDEVICEPARAMETERS 0x08 #define EDDMAGIC1 0x55AA #define EDDMAGIC2 0xAA55 +#define FIXEDDISKSUBSET 0x0001 +#define GET_DEVICE_PARAMETERS_SUPPORTED 0x0007 #define READ_SECTORS 0x02 /* int13 AH=0x02 is READ_SECTORS command */ #define EDD_MBR_SIG_OFFSET 0x1B8 /* offset of signature in the MBR */ +#define EDD_DEV_ADDR_PACKET_LEN 0x10 /* for int13 fn42 */ #define EDD_MBR_SIG_BUF 0x290 /* addr in boot params */ #define EDD_MBR_SIG_MAX 16 /* max number of signatures to store */ #define EDD_MBR_SIG_NR_BUF 0x1ea /* addr of number of MBR signtaures at EDD_MBR_SIG_BUF -- cgit v1.2.3 From 1caf076bd632994f89979fcc1584c3457a04ddcd Mon Sep 17 00:00:00 2001 From: Hideo Aoki Date: Tue, 19 Oct 2004 18:36:36 -0700 Subject: [PATCH] vm thrashing control tuning This patch adds "swap_token_timeout" parameter in /proc/sys/vm. The parameter means expired time of token. Unit of the value is HZ, and the default value is the same as current SWAP_TOKEN_TIMEOUT (i.e. HZ * 300). Signed-off-by: Hideo Aoki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/filesystems/proc.txt | 8 ++++++++ Documentation/sysctl/vm.txt | 2 +- include/linux/swap.h | 1 + include/linux/sysctl.h | 1 + kernel/sysctl.c | 11 +++++++++++ mm/thrash.c | 5 +++-- 6 files changed, 25 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 686c4acbc06d..9b507722d9fe 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -1295,6 +1295,14 @@ block_dump block_dump enables block I/O debugging when set to a nonzero value. More information on block I/O debugging is in Documentation/laptop-mode.txt. +swap_token_timeout +------------------ + +This file contains valid hold time of swap out protection token. The Linux +VM has token based thrashing control mechanism and uses the token to prevent +unnecessary page faults in thrashing situation. The unit of the value is +second. The value would be useful to tune thrashing behavior. + 2.5 /proc/sys/dev - Device specific parameters ---------------------------------------------- diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index 57c6fbc84d11..2f1aae32a5d9 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt @@ -31,7 +31,7 @@ Currently, these files are in /proc/sys/vm: dirty_ratio, dirty_background_ratio, dirty_expire_centisecs, dirty_writeback_centisecs, vfs_cache_pressure, laptop_mode, -block_dump: +block_dump, swap_token_timeout: See Documentation/filesystems/proc.txt diff --git a/include/linux/swap.h b/include/linux/swap.h index 371e8260c577..b0f07148e0eb 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -230,6 +230,7 @@ extern spinlock_t swaplock; /* linux/mm/thrash.c */ extern struct mm_struct * swap_token_mm; +extern unsigned long swap_token_default_timeout; extern void grab_swap_token(void); extern void __put_swap_token(struct mm_struct *); diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 8db31f8d17ff..129ff0ac8a15 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -167,6 +167,7 @@ enum VM_HUGETLB_GROUP=25, /* permitted hugetlb group */ VM_VFS_CACHE_PRESSURE=26, /* dcache/icache reclaim pressure */ VM_LEGACY_VA_LAYOUT=27, /* legacy/compatibility virtual address space layout */ + VM_SWAP_TOKEN_TIMEOUT=28, /* default time for token time out */ }; diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 80bf15f035cd..fed8d5a8aa62 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -783,6 +783,7 @@ static ctl_table vm_table[] = { .strategy = &sysctl_intvec, .extra1 = &zero, }, +#ifdef CONFIG_SWAP { .ctl_name = VM_VFS_CACHE_PRESSURE, .procname = "vfs_cache_pressure", @@ -805,6 +806,15 @@ static ctl_table vm_table[] = { .extra1 = &zero, }, #endif + { + .ctl_name = VM_SWAP_TOKEN_TIMEOUT, + .procname = "swap_token_timeout", + .data = &swap_token_default_timeout, + .maxlen = sizeof(swap_token_default_timeout), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + .strategy = &sysctl_jiffies, + }, { .ctl_name = 0 } }; @@ -915,6 +925,7 @@ static ctl_table fs_table[] = { .mode = 0644, .proc_handler = &proc_dointvec, }, +#endif { .ctl_name = 0 } }; diff --git a/mm/thrash.c b/mm/thrash.c index 7183937b24e5..b6b7360a8b34 100644 --- a/mm/thrash.c +++ b/mm/thrash.c @@ -20,6 +20,7 @@ struct mm_struct * swap_token_mm = &init_mm; #define SWAP_TOKEN_CHECK_INTERVAL (HZ * 2) #define SWAP_TOKEN_TIMEOUT (HZ * 300) +unsigned long swap_token_default_timeout = SWAP_TOKEN_TIMEOUT; /* * Take the token away if the process had no page faults @@ -75,10 +76,10 @@ void grab_swap_token(void) if ((reason = should_release_swap_token(mm))) { unsigned long eligible = jiffies; if (reason == SWAP_TOKEN_TIMED_OUT) { - eligible += SWAP_TOKEN_TIMEOUT; + eligible += swap_token_default_timeout; } mm->swap_token_time = eligible; - swap_token_timeout = jiffies + SWAP_TOKEN_TIMEOUT; + swap_token_timeout = jiffies + swap_token_default_timeout; swap_token_mm = current->mm; } spin_unlock(&swap_token_lock); -- cgit v1.2.3 From 1184aeda646af14b91609552436f722e12117e0b Mon Sep 17 00:00:00 2001 From: Matt Domsch Date: Tue, 19 Oct 2004 18:37:33 -0700 Subject: [PATCH] modules: put srcversion checksum in each modinfo section Separate the module source and header checksum into a separate modinfo field srcversion. With CONFIG_MODULE_SRCVERSION_ALL=y, put srcversion into every module, not just those with MODULE_VERSION("something"). Patch by Rusty Russell, trivial merging and testing by Matt Domsch Signed-off-by: Matt Domsch Signed-off-by: Rusty Russell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/module.h | 6 ++-- init/Kconfig | 12 ++++++++ scripts/Makefile.modpost | 1 + scripts/mod/modpost.c | 65 ++++++++++++++++++++++++++++++++++++--- scripts/mod/modpost.h | 10 +++--- scripts/mod/sumversion.c | 80 +++++++++--------------------------------------- 6 files changed, 96 insertions(+), 78 deletions(-) (limited to 'include/linux') diff --git a/include/linux/module.h b/include/linux/module.h index e5d2d6112f4b..f557855b02dd 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -141,11 +141,9 @@ extern struct module __this_module; customizations, eg "rh3" or "rusty1". Using this automatically adds a checksum of the .c files and the - local headers to the end. Use MODULE_VERSION("") if you want just - this. Macro includes room for this. + local headers in "srcversion". */ -#define MODULE_VERSION(_version) \ - MODULE_INFO(version, _version "\0xxxxxxxxxxxxxxxxxxxxxxxx") +#define MODULE_VERSION(_version) MODULE_INFO(version, _version) /* Given an address, look for it in the exception tables */ const struct exception_table_entry *search_exception_tables(unsigned long add); diff --git a/init/Kconfig b/init/Kconfig index 0d8b1bfc2e8c..6dcf85f3d796 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -389,6 +389,18 @@ config MODVERSIONS make them incompatible with the kernel you are running. If unsure, say N. +config MODULE_SRCVERSION_ALL + bool "Source checksum for all modules" + depends on MODULES + help + Modules which contain a MODULE_VERSION get an extra "srcversion" + field inserting into their modinfo section, which contains a + sum of the source files which made it. This helps maintainers + see exactly which source was used to build a module (since + others sometimes change the module source without updating + the version). With this option, such a "srcversion" field + will be created for all modules. If unsure, say N. + config KMOD bool "Automatic kernel module loading" depends on MODULES diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index b3d31b559ad8..94b550e21be8 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -52,6 +52,7 @@ _modpost: $(modules) quiet_cmd_modpost = MODPOST cmd_modpost = scripts/mod/modpost \ $(if $(CONFIG_MODVERSIONS),-m) \ + $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,) \ $(if $(KBUILD_EXTMOD),-i,-o) $(symverfile) \ $(filter-out FORCE,$^) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 2a174e504c22..db094659fb1e 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1,7 +1,7 @@ /* Postprocess module symbol versions * * Copyright 2003 Kai Germaschewski - * 2002-2003 Rusty Russell, IBM Corporation + * Copyright 2002-2004 Rusty Russell, IBM Corporation * * Based in part on module-init-tools/depmod.c,file2alias * @@ -18,6 +18,8 @@ int modversions = 0; /* Warn about undefined symbols? (do so if we have vmlinux) */ int have_vmlinux = 0; +/* Is CONFIG_MODULE_SRCVERSION_ALL set? */ +static int all_versions = 0; void fatal(const char *fmt, ...) @@ -397,10 +399,44 @@ is_vmlinux(const char *modname) return strcmp(myname, "vmlinux") == 0; } +/* Parse tag=value strings from .modinfo section */ +static char *next_string(char *string, unsigned long *secsize) +{ + /* Skip non-zero chars */ + while (string[0]) { + string++; + if ((*secsize)-- <= 1) + return NULL; + } + + /* Skip any zero padding. */ + while (!string[0]) { + string++; + if ((*secsize)-- <= 1) + return NULL; + } + return string; +} + +static char *get_modinfo(void *modinfo, unsigned long modinfo_len, + const char *tag) +{ + char *p; + unsigned int taglen = strlen(tag); + unsigned long size = modinfo_len; + + for (p = modinfo; p; p = next_string(p, &size)) { + if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=') + return p + taglen + 1; + } + return NULL; +} + void read_symbols(char *modname) { const char *symname; + char *version; struct module *mod; struct elf_info info = { }; Elf_Sym *sym; @@ -424,8 +460,15 @@ read_symbols(char *modname) handle_modversions(mod, &info, sym, symname); handle_moddevtable(mod, &info, sym, symname); } - maybe_frob_version(modname, info.modinfo, info.modinfo_len, - (void *)info.modinfo - (void *)info.hdr); + + version = get_modinfo(info.modinfo, info.modinfo_len, "version"); + if (version) + maybe_frob_rcs_version(modname, version, info.modinfo, + version - (char *)info.hdr); + if (version || (all_versions && !is_vmlinux(modname))) + get_src_version(modname, mod->srcversion, + sizeof(mod->srcversion)-1); + parse_elf_finish(&info); /* Our trick to get versioning for struct_module - it's @@ -570,6 +613,16 @@ add_depends(struct buffer *b, struct module *mod, struct module *modules) buf_printf(b, "\";\n"); } +void +add_srcversion(struct buffer *b, struct module *mod) +{ + if (mod->srcversion[0]) { + buf_printf(b, "\n"); + buf_printf(b, "MODULE_INFO(srcversion, \"%s\");\n", + mod->srcversion); + } +} + void write_if_changed(struct buffer *b, const char *fname) { @@ -691,7 +744,7 @@ main(int argc, char **argv) char *dump_read = NULL, *dump_write = NULL; int opt; - while ((opt = getopt(argc, argv, "i:mo:")) != -1) { + while ((opt = getopt(argc, argv, "i:mo:a")) != -1) { switch(opt) { case 'i': dump_read = optarg; @@ -702,6 +755,9 @@ main(int argc, char **argv) case 'o': dump_write = optarg; break; + case 'a': + all_versions = 1; + break; default: exit(1); } @@ -724,6 +780,7 @@ main(int argc, char **argv) add_versions(&buf, mod); add_depends(&buf, mod, modules); add_moddevtable(&buf, mod); + add_srcversion(&buf, mod); sprintf(fname, "%s.mod.c", mod->name); write_if_changed(&buf, fname); diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 4871343e192a..eb8815ae209e 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -77,6 +77,7 @@ struct module { int has_init; int has_cleanup; struct buffer dev_table_buf; + char srcversion[25]; }; struct elf_info { @@ -95,10 +96,11 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, void add_moddevtable(struct buffer *buf, struct module *mod); -void maybe_frob_version(const char *modfilename, - void *modinfo, - unsigned long modinfo_len, - unsigned long modinfo_offset); +void maybe_frob_rcs_version(const char *modfilename, + char *version, + void *modinfo, + unsigned long modinfo_offset); +void get_src_version(const char *modname, char sum[], unsigned sumlen); void *grab_file(const char *filename, unsigned long *size); char* get_next_line(unsigned long *pos, void *file, unsigned long size); diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c index bf07479c8630..6ece36794c0d 100644 --- a/scripts/mod/sumversion.c +++ b/scripts/mod/sumversion.c @@ -9,39 +9,6 @@ #include #include "modpost.h" -/* Parse tag=value strings from .modinfo section */ -static char *next_string(char *string, unsigned long *secsize) -{ - /* Skip non-zero chars */ - while (string[0]) { - string++; - if ((*secsize)-- <= 1) - return NULL; - } - - /* Skip any zero padding. */ - while (!string[0]) { - string++; - if ((*secsize)-- <= 1) - return NULL; - } - return string; -} - -static char *get_modinfo(void *modinfo, unsigned long modinfo_len, - const char *tag) -{ - char *p; - unsigned int taglen = strlen(tag); - unsigned long size = modinfo_len; - - for (p = modinfo; p; p = next_string(p, &size)) { - if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=') - return p + taglen + 1; - } - return NULL; -} - /* * Stolen form Cryptographic API. * @@ -408,11 +375,11 @@ out: return ret; } -static int get_version(const char *modname, char sum[]) +/* Calc and record src checksum. */ +void get_src_version(const char *modname, char sum[], unsigned sumlen) { void *file; unsigned long len; - int ret = 0; struct md4_ctx md; char *sources, *end, *fname; const char *basename; @@ -432,7 +399,7 @@ static int get_version(const char *modname, char sum[]) if (!file) { fprintf(stderr, "Warning: could not find versions for %s\n", filelist); - return 0; + return; } sources = strchr(file, '\n'); @@ -457,12 +424,9 @@ static int get_version(const char *modname, char sum[]) goto release; } - /* sum is of form \0. */ - md4_final_ascii(&md, sum, 1 + strlen(sum+1)); - ret = 1; + md4_final_ascii(&md, sum, sumlen); release: release_file(file, len); - return ret; } static void write_version(const char *filename, const char *sum, @@ -492,12 +456,12 @@ out: close(fd); } -void strip_rcs_crap(char *version) +static int strip_rcs_crap(char *version) { unsigned int len, full_len; if (strncmp(version, "$Revision", strlen("$Revision")) != 0) - return; + return 0; /* Space for version string follows. */ full_len = strlen(version) + strlen(version + strlen(version) + 1) + 2; @@ -518,31 +482,15 @@ void strip_rcs_crap(char *version) len++; memmove(version + len, version + strlen(version), full_len - strlen(version)); + return 1; } -/* If the modinfo contains a "version" value, then set this. */ -void maybe_frob_version(const char *modfilename, - void *modinfo, - unsigned long modinfo_len, - unsigned long modinfo_offset) +/* Clean up RCS-style version numbers. */ +void maybe_frob_rcs_version(const char *modfilename, + char *version, + void *modinfo, + unsigned long version_offset) { - char *version, *csum; - - version = get_modinfo(modinfo, modinfo_len, "version"); - if (!version) - return; - - /* RCS $Revision gets stripped out. */ - strip_rcs_crap(version); - - /* Check against double sumversion */ - if (strchr(version, ' ')) - return; - - /* Version contains embedded NUL: second half has space for checksum */ - csum = version + strlen(version); - *(csum++) = ' '; - if (get_version(modfilename, csum)) - write_version(modfilename, version, - modinfo_offset + (version - (char *)modinfo)); + if (strip_rcs_crap(version)) + write_version(modfilename, version, version_offset); } -- cgit v1.2.3 From 551107ca34a5e350c3bcaf20b76301db0cf3a242 Mon Sep 17 00:00:00 2001 From: "Paolo \\'Blaisorblade\\' Giarrusso" Date: Tue, 19 Oct 2004 18:38:30 -0700 Subject: [PATCH] use container_of() for rb_entry() Use, in the rb_entry definition, the container_of macro instead of reinventing the wheel; compared to using offset_of() as I did in the prev. version, it has type safety checking. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/rbtree.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h index 3ae0c6e140af..4b7cc4fe366d 100644 --- a/include/linux/rbtree.h +++ b/include/linux/rbtree.h @@ -113,8 +113,7 @@ struct rb_root }; #define RB_ROOT (struct rb_root) { NULL, } -#define rb_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) +#define rb_entry(ptr, type, member) container_of(ptr, type, member) extern void rb_insert_color(struct rb_node *, struct rb_root *); extern void rb_erase(struct rb_node *, struct rb_root *); -- cgit v1.2.3 From eb293c3e9cdd84f5ae1ab052af76d523cbbabcbe Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 19 Oct 2004 18:39:25 -0700 Subject: [PATCH] #include -> #include There's no reason to directly #include since it's available on all architectures and also included by #include . This patch changes #include to #include . Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DocBook/kernel-hacking.tmpl | 2 +- arch/alpha/kernel/irq.c | 2 +- arch/alpha/kernel/signal.c | 2 +- arch/alpha/kernel/smp.c | 2 +- arch/alpha/kernel/sys_alcor.c | 2 +- arch/alpha/kernel/sys_cabriolet.c | 2 +- arch/alpha/kernel/sys_dp264.c | 2 +- arch/alpha/kernel/sys_eb64p.c | 2 +- arch/alpha/kernel/sys_eiger.c | 2 +- arch/alpha/kernel/sys_marvel.c | 2 +- arch/alpha/kernel/sys_mikasa.c | 2 +- arch/alpha/kernel/sys_nautilus.c | 2 +- arch/alpha/kernel/sys_noritake.c | 2 +- arch/alpha/kernel/sys_rx164.c | 2 +- arch/alpha/kernel/sys_sx164.c | 2 +- arch/alpha/kernel/sys_titan.c | 2 +- arch/alpha/kernel/sys_wildfire.c | 2 +- arch/arm/vfp/vfpdouble.c | 2 +- arch/arm/vfp/vfpsingle.c | 2 +- arch/arm26/machine/small_page.c | 2 +- arch/cris/arch-v10/drivers/ethernet.c | 2 +- arch/cris/arch-v10/drivers/serial.c | 2 +- arch/cris/kernel/irq.c | 2 +- arch/i386/kernel/i8259.c | 2 +- arch/ia64/hp/common/sba_iommu.c | 2 +- arch/ia64/hp/sim/simeth.c | 2 +- arch/ia64/kernel/irq.c | 2 +- arch/ia64/kernel/irq_ia64.c | 2 +- arch/ia64/kernel/perfmon.c | 2 +- arch/ia64/kernel/smp.c | 2 +- arch/ia64/kernel/smpboot.c | 2 +- arch/ia64/lib/bitop.c | 2 +- arch/ia64/mm/init.c | 2 +- arch/ia64/sn/kernel/sn2/sn2_smp.c | 2 +- arch/m32r/kernel/irq.c | 2 +- arch/m32r/mm/init.c | 2 +- arch/m68k/sun3/mmu_emu.c | 2 +- arch/mips/au1000/common/au1xxx_irqmap.c | 2 +- arch/mips/au1000/common/irq.c | 2 +- arch/mips/au1000/csb250/irqmap.c | 2 +- arch/mips/au1000/db1x00/irqmap.c | 2 +- arch/mips/au1000/hydrogen3/irqmap.c | 2 +- arch/mips/au1000/mtx-1/irqmap.c | 2 +- arch/mips/au1000/pb1000/irqmap.c | 2 +- arch/mips/au1000/pb1100/irqmap.c | 2 +- arch/mips/au1000/pb1500/irqmap.c | 2 +- arch/mips/au1000/pb1550/irqmap.c | 2 +- arch/mips/au1000/xxs1500/irqmap.c | 2 +- arch/mips/baget/irq.c | 2 +- arch/mips/gt64120/ev64120/irq.c | 2 +- arch/mips/gt64120/momenco_ocelot/irq.c | 2 +- arch/mips/ite-boards/generic/irq.c | 2 +- arch/mips/jmr3927/rbhma3100/irq.c | 2 +- arch/mips/kernel/signal.c | 2 +- arch/mips/kernel/signal32.c | 2 +- arch/mips/kernel/signal_n32.c | 2 +- arch/mips/momentum/ocelot_c/irq.c | 2 +- arch/mips/momentum/ocelot_g/irq.c | 2 +- arch/mips/pmc-sierra/yosemite/irq.c | 2 +- arch/mips/sgi-ip27/ip27-irq.c | 2 +- arch/mips/sgi-ip32/ip32-irq.c | 1 - arch/mips/tx4927/common/tx4927_irq.c | 2 +- arch/mips/tx4927/common/tx4927_setup.c | 2 +- arch/parisc/kernel/smp.c | 2 +- arch/ppc/4xx_io/serial_sicc.c | 2 +- arch/ppc/8260_io/enet.c | 2 +- arch/ppc/8260_io/fcc_enet.c | 2 +- arch/ppc/8xx_io/enet.c | 2 +- arch/ppc/8xx_io/fec.c | 2 +- arch/ppc/kernel/bitops.c | 2 +- arch/ppc/kernel/irq.c | 2 +- arch/ppc/kernel/ppc_htab.c | 2 +- arch/ppc/kernel/ppc_ksyms.c | 2 +- arch/ppc/platforms/pmac_setup.c | 2 +- arch/ppc/syslib/prom.c | 2 +- arch/ppc/syslib/prom_init.c | 2 +- arch/ppc/xmon/start.c | 4 +--- arch/ppc/xmon/xmon.c | 2 +- arch/ppc64/kernel/LparData.c | 2 +- arch/ppc64/kernel/bitops.c | 2 +- arch/ppc64/kernel/iommu.c | 2 +- arch/ppc64/kernel/irq.c | 2 +- arch/ppc64/kernel/lmb.c | 2 +- arch/ppc64/kernel/pmac_setup.c | 3 +-- arch/ppc64/kernel/ppc_ksyms.c | 2 +- arch/ppc64/kernel/prom.c | 2 +- arch/ppc64/kernel/prom_init.c | 2 +- arch/ppc64/kernel/ras.c | 2 +- arch/ppc64/kernel/rtas-proc.c | 2 +- arch/sh/boards/bigsur/irq.c | 2 +- arch/sh/boards/bigsur/setup.c | 2 +- arch/sh/kernel/cpu/irq_imask.c | 2 +- arch/sh/kernel/irq.c | 2 +- arch/sh64/kernel/irq.c | 2 +- arch/sh64/kernel/irq_intc.c | 6 +++--- arch/sparc/kernel/signal.c | 2 +- arch/sparc/lib/bitext.c | 2 +- arch/sparc/mm/io-unit.c | 2 +- arch/sparc64/kernel/signal.c | 2 +- arch/sparc64/kernel/signal32.c | 2 +- arch/sparc64/kernel/unaligned.c | 2 +- arch/sparc64/lib/find_bit.c | 2 +- arch/v850/kernel/fpga85e2c.c | 2 +- arch/x86_64/kernel/i8259.c | 2 +- arch/x86_64/kernel/pci-gart.c | 2 +- arch/x86_64/kernel/setup64.c | 2 +- arch/x86_64/lib/bitops.c | 2 +- arch/x86_64/lib/bitstr.c | 2 +- drivers/acorn/block/fd1772.c | 2 +- drivers/block/z2ram.c | 2 +- drivers/bluetooth/bt3c_cs.c | 2 +- drivers/bluetooth/btuart_cs.c | 2 +- drivers/bluetooth/dtl1_cs.c | 2 +- drivers/char/amiserial.c | 2 +- drivers/char/cyclades.c | 2 +- drivers/char/ec3104_keyb.c | 2 +- drivers/char/hpet.c | 2 +- drivers/char/ip2main.c | 2 +- drivers/char/moxa.c | 2 +- drivers/char/mwave/3780i.c | 2 +- drivers/char/n_hdlc.c | 2 +- drivers/char/n_tty.c | 2 +- drivers/char/pcmcia/synclink_cs.c | 2 +- drivers/char/pcxx.c | 2 +- drivers/char/pty.c | 2 +- drivers/char/qtronix.c | 2 +- drivers/char/rocket.c | 2 +- drivers/char/serial167.c | 2 +- drivers/char/synclink.c | 2 +- drivers/char/synclinkmp.c | 2 +- drivers/char/tipar.c | 2 +- drivers/char/tty_io.c | 2 +- drivers/char/tty_ioctl.c | 2 +- drivers/char/vt.c | 2 +- drivers/char/watchdog/ixp2000_wdt.c | 2 +- drivers/char/watchdog/ixp4xx_wdt.c | 2 +- drivers/fc4/soc.c | 2 +- drivers/fc4/socal.c | 2 +- drivers/ide/ide-default.c | 2 +- drivers/ide/ide-floppy.c | 2 +- drivers/ide/ide-iops.c | 2 +- drivers/ide/ide-lib.c | 2 +- drivers/ide/ide-tape.c | 2 +- drivers/ide/ide-taskfile.c | 2 +- drivers/ide/ide.c | 2 +- drivers/input/serio/q40kbd.c | 2 +- drivers/isdn/i4l/isdn_bsdcomp.c | 2 +- drivers/macintosh/macserial.c | 2 +- drivers/md/raid5.c | 2 +- drivers/md/raid6main.c | 2 +- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 2 +- drivers/media/dvb/frontends/at76c651.c | 5 +---- drivers/media/dvb/ttpci/av7110_ir.c | 2 +- drivers/net/3c501.c | 2 +- drivers/net/3c505.c | 2 +- drivers/net/3c507.c | 2 +- drivers/net/3c509.c | 2 +- drivers/net/3c515.c | 2 +- drivers/net/3c523.c | 2 +- drivers/net/3c527.c | 2 +- drivers/net/3c59x.c | 2 +- drivers/net/7990.c | 2 +- drivers/net/82596.c | 2 +- drivers/net/8390.c | 2 +- drivers/net/a2065.c | 2 +- drivers/net/appletalk/cops.c | 2 +- drivers/net/appletalk/ltpc.c | 2 +- drivers/net/ariadne.c | 2 +- drivers/net/arm/am79c961a.c | 2 +- drivers/net/arm/ether1.c | 2 +- drivers/net/arm/ether3.c | 2 +- drivers/net/arm/etherh.c | 2 +- drivers/net/at1700.c | 2 +- drivers/net/atari_bionet.c | 2 +- drivers/net/atari_pamsnet.c | 2 +- drivers/net/atarilance.c | 2 +- drivers/net/atp.c | 2 +- drivers/net/au1000_eth.c | 2 +- drivers/net/bagetlance.c | 2 +- drivers/net/bonding/bond_main.c | 2 +- drivers/net/cs89x0.c | 2 +- drivers/net/defxx.c | 2 +- drivers/net/depca.c | 2 +- drivers/net/dgrs.c | 2 +- drivers/net/dl2k.h | 2 +- drivers/net/e1000/e1000.h | 2 +- drivers/net/eepro.c | 2 +- drivers/net/eepro100.c | 2 +- drivers/net/eexpress.c | 2 +- drivers/net/epic100.c | 2 +- drivers/net/eth16i.c | 2 +- drivers/net/ewrk3.c | 2 +- drivers/net/fealnx.c | 2 +- drivers/net/fec.c | 2 +- drivers/net/fec_8xx/fec_8xx-netta.c | 2 +- drivers/net/fec_8xx/fec_main.c | 2 +- drivers/net/fec_8xx/fec_mii.c | 2 +- drivers/net/fmv18x.c | 2 +- drivers/net/gt96100eth.c | 2 +- drivers/net/hamachi.c | 2 +- drivers/net/hamradio/6pack.c | 2 +- drivers/net/hamradio/baycom_par.c | 2 +- drivers/net/hamradio/hdlcdrv.c | 2 +- drivers/net/hamradio/mkiss.c | 2 +- drivers/net/hamradio/scc.c | 2 +- drivers/net/hamradio/yam.c | 2 +- drivers/net/hp100.c | 2 +- drivers/net/hydra.c | 2 +- drivers/net/ibm_emac/ibm_emac_core.c | 2 +- drivers/net/ibmlana.c | 2 +- drivers/net/irda/au1k_ir.c | 2 +- drivers/net/irda/irport.c | 2 +- drivers/net/isa-skeleton.c | 2 +- drivers/net/ixgb/ixgb.h | 2 +- drivers/net/jazzsonic.c | 2 +- drivers/net/lance.c | 2 +- drivers/net/lasi_82596.c | 2 +- drivers/net/lp486e.c | 2 +- drivers/net/mac8390.c | 2 +- drivers/net/macsonic.c | 2 +- drivers/net/mv643xx_eth.c | 2 +- drivers/net/myri_sbus.c | 2 +- drivers/net/natsemi.c | 2 +- drivers/net/ne2.c | 2 +- drivers/net/ni5010.c | 2 +- drivers/net/ni52.c | 2 +- drivers/net/ni65.c | 2 +- drivers/net/pcmcia/3c574_cs.c | 2 +- drivers/net/pcmcia/3c589_cs.c | 2 +- drivers/net/pcmcia/axnet_cs.c | 2 +- drivers/net/pcmcia/nmclan_cs.c | 2 +- drivers/net/pcmcia/xirc2ps_cs.c | 2 +- drivers/net/pcnet32.c | 2 +- drivers/net/plip.c | 2 +- drivers/net/sb1000.c | 2 +- drivers/net/sb1250-mac.c | 2 +- drivers/net/seeq8005.c | 2 +- drivers/net/sgiseeq.c | 2 +- drivers/net/sis900.c | 2 +- drivers/net/sk98lin/h/skdrv1st.h | 2 +- drivers/net/sk98lin/skge.c | 2 +- drivers/net/sk_g16.c | 2 +- drivers/net/sk_mca.c | 2 +- drivers/net/skfp/skfddi.c | 2 +- drivers/net/slip.c | 2 +- drivers/net/smc9194.c | 2 +- drivers/net/sun3_82586.c | 2 +- drivers/net/sun3lance.c | 2 +- drivers/net/sunbmac.c | 2 +- drivers/net/sundance.c | 2 +- drivers/net/sungem.c | 2 +- drivers/net/sunhme.c | 2 +- drivers/net/sunlance.c | 2 +- drivers/net/sunqe.c | 2 +- drivers/net/tc35815.c | 2 +- drivers/net/tokenring/3c359.c | 2 +- drivers/net/tokenring/lanstreamer.c | 2 +- drivers/net/tokenring/olympic.c | 2 +- drivers/net/tokenring/smctr.c | 2 +- drivers/net/tokenring/tms380tr.c | 2 +- drivers/net/tulip/de4x5.c | 2 +- drivers/net/tulip/dmfe.c | 2 +- drivers/net/tulip/winbond-840.c | 2 +- drivers/net/tulip/xircom_cb.c | 2 +- drivers/net/typhoon.c | 2 +- drivers/net/via-rhine.c | 2 +- drivers/net/wan/dlci.c | 2 +- drivers/net/wan/hd6457x.c | 2 +- drivers/net/wan/lmc/lmc_main.c | 2 +- drivers/net/wan/lmc/lmc_media.c | 2 +- drivers/net/wan/lmc/lmc_proto.c | 2 +- drivers/net/wan/sdla.c | 2 +- drivers/net/wan/x25_asy.c | 2 +- drivers/net/wireless/airo.c | 2 +- drivers/net/wireless/arlan.h | 2 +- drivers/net/wireless/netwave_cs.c | 2 +- drivers/net/wireless/strip.c | 2 +- drivers/net/wireless/wavelan.p.h | 2 +- drivers/net/wireless/wavelan_cs.p.h | 2 +- drivers/net/yellowfin.c | 2 +- drivers/net/znet.c | 2 +- drivers/pcmcia/i82365.c | 2 +- drivers/pcmcia/tcic.c | 2 +- drivers/s390/net/ctcmain.c | 2 +- drivers/s390/net/netiucv.c | 2 +- drivers/s390/net/qeth.h | 3 ++- drivers/sbus/char/aurora.c | 2 +- drivers/scsi/NCR53c406a.c | 2 +- drivers/scsi/arm/acornscsi.c | 2 +- drivers/scsi/atari_scsi.c | 2 +- drivers/scsi/ultrastor.c | 2 +- drivers/serial/68328serial.c | 2 +- drivers/serial/8250_pci.c | 2 +- drivers/serial/8250_pnp.c | 2 +- drivers/serial/icom.c | 2 +- drivers/serial/mcfserial.c | 2 +- drivers/serial/pmac_zilog.c | 2 +- drivers/serial/sh-sci.c | 2 +- drivers/tc/zs.c | 2 +- drivers/usb/host/uhci-hcd.c | 2 +- drivers/usb/net/catc.c | 2 +- drivers/zorro/zorro.c | 2 +- fs/adfs/super.c | 2 +- fs/autofs/inode.c | 2 +- fs/autofs4/inode.c | 2 +- fs/buffer.c | 2 +- fs/coda/sysctl.c | 2 +- fs/devfs/base.c | 2 +- fs/devfs/util.c | 2 +- fs/eventpoll.c | 2 +- fs/ext3/ialloc.c | 2 +- fs/file.c | 3 +-- fs/jfs/jfs_incore.h | 2 +- fs/minix/bitmap.c | 2 +- fs/partitions/devfs.c | 2 +- fs/proc/generic.c | 2 +- fs/proc/proc_tty.c | 2 +- fs/proc/root.c | 2 +- fs/qnx4/bitmap.c | 3 +-- fs/udf/balloc.c | 2 +- fs/ufs/balloc.c | 2 +- fs/ufs/cylinder.c | 2 +- fs/ufs/ialloc.c | 2 +- fs/ufs/super.c | 2 +- include/linux/idr.h | 2 +- include/linux/mtd/gen_probe.h | 2 +- include/net/pkt_act.h | 2 +- kernel/rcupdate.c | 2 +- lib/bitmap.c | 2 +- net/core/dev.c | 2 +- net/core/dev_mcast.c | 2 +- net/core/link_watch.c | 2 +- net/core/pktgen.c | 2 +- net/econet/af_econet.c | 2 +- net/ipv4/devinet.c | 2 +- net/ipv4/fib_frontend.c | 2 +- net/ipv4/fib_hash.c | 2 +- net/ipv4/fib_rules.c | 2 +- net/ipv4/fib_semantics.c | 2 +- net/ipv4/route.c | 2 +- net/irda/irlan/irlan_client.c | 2 +- net/irda/irlan/irlan_common.c | 2 +- net/irda/irlan/irlan_provider.c | 2 +- net/netlink/netlink_dev.c | 2 +- net/sched/act_api.c | 2 +- net/sched/cls_api.c | 2 +- net/sched/cls_fw.c | 2 +- net/sched/cls_route.c | 2 +- net/sched/cls_rsvp.c | 2 +- net/sched/cls_rsvp6.c | 2 +- net/sched/cls_u32.c | 2 +- net/sched/estimator.c | 2 +- net/sched/gact.c | 2 +- net/sched/police.c | 2 +- net/sched/sch_api.c | 2 +- net/sched/sch_cbq.c | 2 +- net/sched/sch_fifo.c | 2 +- net/sched/sch_generic.c | 2 +- net/sched/sch_gred.c | 2 +- net/sched/sch_htb.c | 2 +- net/sched/sch_netem.c | 2 +- net/sched/sch_prio.c | 2 +- net/sched/sch_red.c | 2 +- net/sched/sch_sfq.c | 2 +- net/sched/sch_tbf.c | 2 +- net/sched/sch_teql.c | 2 +- sound/pci/bt87x.c | 2 +- 367 files changed, 369 insertions(+), 377 deletions(-) (limited to 'include/linux') diff --git a/Documentation/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl index cd1bc1574613..1e8219d85255 100644 --- a/Documentation/DocBook/kernel-hacking.tmpl +++ b/Documentation/DocBook/kernel-hacking.tmpl @@ -888,7 +888,7 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress)); The second class of atomic operations is atomic bit operations on a long, defined in - include/asm/bitops.h. These + include/linux/bitops.h. These operations generally take a pointer to the bit pattern, and a bit number: 0 is the least significant bit. set_bit(), clear_bit() diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index 199435fb9640..b6114f5c0d2b 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -26,10 +26,10 @@ #include #include #include +#include #include #include -#include #include /* diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 94ff1b330ce4..974329cf0e5b 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -19,8 +19,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 6d4d09c43912..04a4d366b2a6 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -33,7 +34,6 @@ #include #include -#include #include #include #include diff --git a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c index 6852eeedf93b..145dcde143ae 100644 --- a/arch/alpha/kernel/sys_alcor.c +++ b/arch/alpha/kernel/sys_alcor.c @@ -16,12 +16,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c index c3f9dbc1ecc0..8e3374d34c95 100644 --- a/arch/alpha/kernel/sys_cabriolet.c +++ b/arch/alpha/kernel/sys_cabriolet.c @@ -16,12 +16,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c index 10973586f592..6e334292bbcd 100644 --- a/arch/alpha/kernel/sys_dp264.c +++ b/arch/alpha/kernel/sys_dp264.c @@ -19,12 +19,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/alpha/kernel/sys_eb64p.c b/arch/alpha/kernel/sys_eb64p.c index 32d9c350b2c2..61a79c354f0b 100644 --- a/arch/alpha/kernel/sys_eb64p.c +++ b/arch/alpha/kernel/sys_eb64p.c @@ -15,12 +15,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/alpha/kernel/sys_eiger.c b/arch/alpha/kernel/sys_eiger.c index f98be3e85b62..bd6e5f0e43c7 100644 --- a/arch/alpha/kernel/sys_eiger.c +++ b/arch/alpha/kernel/sys_eiger.c @@ -15,12 +15,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c index 52873d5fc824..804727853d25 100644 --- a/arch/alpha/kernel/sys_marvel.c +++ b/arch/alpha/kernel/sys_marvel.c @@ -10,12 +10,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/alpha/kernel/sys_mikasa.c b/arch/alpha/kernel/sys_mikasa.c index a55c109f5c86..d78a0daa6168 100644 --- a/arch/alpha/kernel/sys_mikasa.c +++ b/arch/alpha/kernel/sys_mikasa.c @@ -15,12 +15,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c index dd3bdedb71f2..c0d696efec5b 100644 --- a/arch/alpha/kernel/sys_nautilus.c +++ b/arch/alpha/kernel/sys_nautilus.c @@ -32,12 +32,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/alpha/kernel/sys_noritake.c b/arch/alpha/kernel/sys_noritake.c index 02363fa79962..65061f5d7410 100644 --- a/arch/alpha/kernel/sys_noritake.c +++ b/arch/alpha/kernel/sys_noritake.c @@ -16,12 +16,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/alpha/kernel/sys_rx164.c b/arch/alpha/kernel/sys_rx164.c index dfe16bc122ff..58404243057b 100644 --- a/arch/alpha/kernel/sys_rx164.c +++ b/arch/alpha/kernel/sys_rx164.c @@ -14,12 +14,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/alpha/kernel/sys_sx164.c b/arch/alpha/kernel/sys_sx164.c index 3ee73b68efd4..94ad68b7c0ae 100644 --- a/arch/alpha/kernel/sys_sx164.c +++ b/arch/alpha/kernel/sys_sx164.c @@ -14,12 +14,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c index 4466af674bc0..147058fae0c1 100644 --- a/arch/alpha/kernel/sys_titan.c +++ b/arch/alpha/kernel/sys_titan.c @@ -19,12 +19,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/alpha/kernel/sys_wildfire.c b/arch/alpha/kernel/sys_wildfire.c index 959e8d7dffc3..57be096764a0 100644 --- a/arch/alpha/kernel/sys_wildfire.c +++ b/arch/alpha/kernel/sys_wildfire.c @@ -12,12 +12,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c index 54649c1ee43d..3a4df3ffad3e 100644 --- a/arch/arm/vfp/vfpdouble.c +++ b/arch/arm/vfp/vfpdouble.c @@ -31,7 +31,7 @@ * =========================================================================== */ #include -#include +#include #include #include diff --git a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c index 92aa8412709e..265de1dee1e9 100644 --- a/arch/arm/vfp/vfpsingle.c +++ b/arch/arm/vfp/vfpsingle.c @@ -31,7 +31,7 @@ * =========================================================================== */ #include -#include +#include #include #include diff --git a/arch/arm26/machine/small_page.c b/arch/arm26/machine/small_page.c index 3cbeffa01718..78e9198c2e60 100644 --- a/arch/arm26/machine/small_page.c +++ b/arch/arm26/machine/small_page.c @@ -24,8 +24,8 @@ #include #include #include +#include -#include #include #define PEDANTIC diff --git a/arch/cris/arch-v10/drivers/ethernet.c b/arch/cris/arch-v10/drivers/ethernet.c index 2b9d9b7163f5..2e6a34135ece 100644 --- a/arch/cris/arch-v10/drivers/ethernet.c +++ b/arch/cris/arch-v10/drivers/ethernet.c @@ -222,13 +222,13 @@ #include #include #include +#include #include /* DMA and register descriptions */ #include /* LED_* I/O functions */ #include #include #include -#include #include #include diff --git a/arch/cris/arch-v10/drivers/serial.c b/arch/cris/arch-v10/drivers/serial.c index 272795de9f5b..5881533878d1 100644 --- a/arch/cris/arch-v10/drivers/serial.c +++ b/arch/cris/arch-v10/drivers/serial.c @@ -435,7 +435,7 @@ static char *serial_version = "$Revision: 1.20 $"; #include #include #include -#include +#include #include #include diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c index bb8d2e4e7a9c..2a9ed1806764 100644 --- a/arch/cris/kernel/irq.c +++ b/arch/cris/kernel/irq.c @@ -36,9 +36,9 @@ #include #include #include +#include #include -#include /* Defined in arch specific irq.c */ extern void arch_setup_irq(int irq); diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c index dec7ebf49a48..686a95bd0bd7 100644 --- a/arch/i386/kernel/i8259.c +++ b/arch/i386/kernel/i8259.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -17,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c index e50c446e0f4f..64295162dcb2 100644 --- a/arch/ia64/hp/common/sba_iommu.c +++ b/arch/ia64/hp/common/sba_iommu.c @@ -33,13 +33,13 @@ #include #include #include +#include /* hweight64() */ #include /* ia64_get_itc() */ #include #include /* PAGE_OFFSET */ #include #include /* wmb() */ -#include /* hweight64() */ #include diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c index 3c9c3072b68c..45d69f4d3c72 100644 --- a/arch/ia64/hp/sim/simeth.c +++ b/arch/ia64/hp/sim/simeth.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index f779d97a43a7..b3afd073b9dc 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -43,13 +43,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 335d827ceb9f..946df2d55836 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -30,8 +30,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 8561f8dcffba..4c8043b74c88 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -38,8 +38,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c index 14134f2e3952..4041bb3bdfd2 100644 --- a/arch/ia64/kernel/smp.c +++ b/arch/ia64/kernel/smp.c @@ -29,9 +29,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index f0dd8c3dc67e..0a0bf975199c 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -29,9 +29,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/ia64/lib/bitop.c b/arch/ia64/lib/bitop.c index 1c6ee49fd3cf..d509e204c238 100644 --- a/arch/ia64/lib/bitop.c +++ b/arch/ia64/lib/bitop.c @@ -2,7 +2,7 @@ #include #include #include -#include +#include /* * Find next zero bit in a bitmap reasonably efficiently.. diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 3bfbb7dc1f31..f7c6ddbf4ca3 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -19,9 +19,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c index 29a6915fadd1..5fa8f1f1a066 100644 --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -28,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/m32r/kernel/irq.c b/arch/m32r/kernel/irq.c index ba135773308a..74ab2ec74e59 100644 --- a/arch/m32r/kernel/irq.c +++ b/arch/m32r/kernel/irq.c @@ -42,12 +42,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c index a290e3793caf..b6a5aaceaadf 100644 --- a/arch/m32r/mm/init.c +++ b/arch/m32r/mm/init.c @@ -18,9 +18,9 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/arch/m68k/sun3/mmu_emu.c b/arch/m68k/sun3/mmu_emu.c index 0d9876190af0..5ced6d3c9926 100644 --- a/arch/m68k/sun3/mmu_emu.c +++ b/arch/m68k/sun3/mmu_emu.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -21,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/mips/au1000/common/au1xxx_irqmap.c b/arch/mips/au1000/common/au1xxx_irqmap.c index afac7edd2f58..2043ec5205c7 100644 --- a/arch/mips/au1000/common/au1xxx_irqmap.c +++ b/arch/mips/au1000/common/au1xxx_irqmap.c @@ -39,8 +39,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c index 5104328f7d74..989b7b5bb2b0 100644 --- a/arch/mips/au1000/common/irq.c +++ b/arch/mips/au1000/common/irq.c @@ -41,8 +41,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/au1000/csb250/irqmap.c b/arch/mips/au1000/csb250/irqmap.c index d7fbda4921bb..5cb1166be35c 100644 --- a/arch/mips/au1000/csb250/irqmap.c +++ b/arch/mips/au1000/csb250/irqmap.c @@ -39,8 +39,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/au1000/db1x00/irqmap.c b/arch/mips/au1000/db1x00/irqmap.c index cbae591f022a..8f6ef0dbe1f8 100644 --- a/arch/mips/au1000/db1x00/irqmap.c +++ b/arch/mips/au1000/db1x00/irqmap.c @@ -40,8 +40,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/au1000/hydrogen3/irqmap.c b/arch/mips/au1000/hydrogen3/irqmap.c index a335c90bdec5..6eacaa0daa49 100644 --- a/arch/mips/au1000/hydrogen3/irqmap.c +++ b/arch/mips/au1000/hydrogen3/irqmap.c @@ -39,8 +39,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/au1000/mtx-1/irqmap.c b/arch/mips/au1000/mtx-1/irqmap.c index 720bc759d62d..51fcc2cbe0af 100644 --- a/arch/mips/au1000/mtx-1/irqmap.c +++ b/arch/mips/au1000/mtx-1/irqmap.c @@ -39,8 +39,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/au1000/pb1000/irqmap.c b/arch/mips/au1000/pb1000/irqmap.c index 215b07a6d0d9..4950c33a4bdc 100644 --- a/arch/mips/au1000/pb1000/irqmap.c +++ b/arch/mips/au1000/pb1000/irqmap.c @@ -39,8 +39,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/au1000/pb1100/irqmap.c b/arch/mips/au1000/pb1100/irqmap.c index 6333deb601e1..bfb389e7e17c 100644 --- a/arch/mips/au1000/pb1100/irqmap.c +++ b/arch/mips/au1000/pb1100/irqmap.c @@ -39,8 +39,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/au1000/pb1500/irqmap.c b/arch/mips/au1000/pb1500/irqmap.c index 79c4e0fd6ef5..476e25001681 100644 --- a/arch/mips/au1000/pb1500/irqmap.c +++ b/arch/mips/au1000/pb1500/irqmap.c @@ -39,8 +39,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/au1000/pb1550/irqmap.c b/arch/mips/au1000/pb1550/irqmap.c index 4f692163b9c9..889d4949ee76 100644 --- a/arch/mips/au1000/pb1550/irqmap.c +++ b/arch/mips/au1000/pb1550/irqmap.c @@ -39,8 +39,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/au1000/xxs1500/irqmap.c b/arch/mips/au1000/xxs1500/irqmap.c index d751f48a69d9..954800a0ab52 100644 --- a/arch/mips/au1000/xxs1500/irqmap.c +++ b/arch/mips/au1000/xxs1500/irqmap.c @@ -39,8 +39,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/baget/irq.c b/arch/mips/baget/irq.c index 3dcc16efd08a..341562d6eca0 100644 --- a/arch/mips/baget/irq.c +++ b/arch/mips/baget/irq.c @@ -18,8 +18,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/gt64120/ev64120/irq.c b/arch/mips/gt64120/ev64120/irq.c index 537eab3fd314..656aaeb8bf2a 100644 --- a/arch/mips/gt64120/ev64120/irq.c +++ b/arch/mips/gt64120/ev64120/irq.c @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/mips/gt64120/momenco_ocelot/irq.c b/arch/mips/gt64120/momenco_ocelot/irq.c index 6812277807bf..d04c62b073d9 100644 --- a/arch/mips/gt64120/momenco_ocelot/irq.c +++ b/arch/mips/gt64120/momenco_ocelot/irq.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/mips/ite-boards/generic/irq.c b/arch/mips/ite-boards/generic/irq.c index 4be10d820687..941590ec70ce 100644 --- a/arch/mips/ite-boards/generic/irq.c +++ b/arch/mips/ite-boards/generic/irq.c @@ -47,8 +47,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c index 4ab85b5b2b4d..abb2ba632670 100644 --- a/arch/mips/jmr3927/rbhma3100/irq.c +++ b/arch/mips/jmr3927/rbhma3100/irq.c @@ -45,8 +45,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 325705fcc5c1..025faa57be56 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -20,9 +20,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index a449a5651c42..e12e1dbd15fe 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -19,9 +19,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c index d2f8b8cf67e0..4a61749221f0 100644 --- a/arch/mips/kernel/signal_n32.c +++ b/arch/mips/kernel/signal_n32.c @@ -26,9 +26,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/mips/momentum/ocelot_c/irq.c b/arch/mips/momentum/ocelot_c/irq.c index 13dd8bd74041..dd10713e174b 100644 --- a/arch/mips/momentum/ocelot_c/irq.c +++ b/arch/mips/momentum/ocelot_c/irq.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/mips/momentum/ocelot_g/irq.c b/arch/mips/momentum/ocelot_g/irq.c index 7d838c132c89..c5adfa6d8231 100644 --- a/arch/mips/momentum/ocelot_g/irq.c +++ b/arch/mips/momentum/ocelot_g/irq.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/mips/pmc-sierra/yosemite/irq.c b/arch/mips/pmc-sierra/yosemite/irq.c index e8b7ed63eaa0..df38a4209d04 100644 --- a/arch/mips/pmc-sierra/yosemite/irq.c +++ b/arch/mips/pmc-sierra/yosemite/irq.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 917c1ee7aef2..6678b903c074 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -20,8 +20,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c index 75846d6e8154..3d7b04c66ade 100644 --- a/arch/mips/sgi-ip32/ip32-irq.c +++ b/arch/mips/sgi-ip32/ip32-irq.c @@ -20,7 +20,6 @@ #include #include -#include #include #include #include diff --git a/arch/mips/tx4927/common/tx4927_irq.c b/arch/mips/tx4927/common/tx4927_irq.c index bf59409eea36..c89dd5f94d93 100644 --- a/arch/mips/tx4927/common/tx4927_irq.c +++ b/arch/mips/tx4927/common/tx4927_irq.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/mips/tx4927/common/tx4927_setup.c b/arch/mips/tx4927/common/tx4927_setup.c index 73d188ff6a46..88d02973d132 100644 --- a/arch/mips/tx4927/common/tx4927_setup.c +++ b/arch/mips/tx4927/common/tx4927_setup.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 9def95a4313b..ddc53e1bf044 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -33,10 +33,10 @@ #include #include #include +#include #include #include -#include #include #include #include /* for flush_tlb_all() proto/macro */ diff --git a/arch/ppc/4xx_io/serial_sicc.c b/arch/ppc/4xx_io/serial_sicc.c index f0728f3c0e7b..0e7ba9ecba26 100644 --- a/arch/ppc/4xx_io/serial_sicc.c +++ b/arch/ppc/4xx_io/serial_sicc.c @@ -51,12 +51,12 @@ #include #include #include +#include #include #include #include #include -#include #include diff --git a/arch/ppc/8260_io/enet.c b/arch/ppc/8260_io/enet.c index 3f8aa419771e..ac6d55fe2235 100644 --- a/arch/ppc/8260_io/enet.c +++ b/arch/ppc/8260_io/enet.c @@ -39,11 +39,11 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c index 41ca12432d8e..a38487b11503 100644 --- a/arch/ppc/8260_io/fcc_enet.c +++ b/arch/ppc/8260_io/fcc_enet.c @@ -34,12 +34,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c index 8ddef1c5cf11..3508f31b6d3b 100644 --- a/arch/ppc/8xx_io/enet.c +++ b/arch/ppc/8xx_io/enet.c @@ -38,11 +38,11 @@ #include #include #include +#include #include #include #include -#include #include #include diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c index 5c7c914f84ea..30ea33a5fbb4 100644 --- a/arch/ppc/8xx_io/fec.c +++ b/arch/ppc/8xx_io/fec.c @@ -44,6 +44,7 @@ #include #include #include +#include #ifdef CONFIG_FEC_PACKETHOOK #include #endif @@ -52,7 +53,6 @@ #include #include #include -#include #include #include diff --git a/arch/ppc/kernel/bitops.c b/arch/ppc/kernel/bitops.c index c00bad67db41..7f53d193968b 100644 --- a/arch/ppc/kernel/bitops.c +++ b/arch/ppc/kernel/bitops.c @@ -3,7 +3,7 @@ */ #include -#include +#include /* * If the bitops are not inlined in bitops.h, they are defined here. diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c index 168dcd718546..7b842826c88a 100644 --- a/arch/ppc/kernel/irq.c +++ b/arch/ppc/kernel/irq.c @@ -47,9 +47,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c index d8e027fd4849..b5cd7e411e65 100644 --- a/arch/ppc/kernel/ppc_htab.c +++ b/arch/ppc/kernel/ppc_htab.c @@ -21,9 +21,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index 44114bac11d0..85b47a7f4a15 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -23,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c index 79fc295143eb..513952331986 100644 --- a/arch/ppc/platforms/pmac_setup.c +++ b/arch/ppc/platforms/pmac_setup.c @@ -51,13 +51,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c index 1ddb0c0eb8bb..1b23f1e23ae3 100644 --- a/arch/ppc/syslib/prom.c +++ b/arch/ppc/syslib/prom.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -31,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c index ac4c8b158041..3d6ea5ee8f6f 100644 --- a/arch/ppc/syslib/prom_init.c +++ b/arch/ppc/syslib/prom_init.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -26,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c index d88096739064..bbe463913e74 100644 --- a/arch/ppc/xmon/start.c +++ b/arch/ppc/xmon/start.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -21,9 +22,6 @@ #include #include #include -#ifdef CONFIG_SMP -#include -#endif static volatile unsigned char *sccc, *sccd; unsigned int TXRDY, RXRDY, DLAB; diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c index e7fe8d4c25ee..9976e7cb5b0d 100644 --- a/arch/ppc/xmon/xmon.c +++ b/arch/ppc/xmon/xmon.c @@ -8,10 +8,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c index 73d919bf858e..4400095f9501 100644 --- a/arch/ppc64/kernel/LparData.c +++ b/arch/ppc64/kernel/LparData.c @@ -11,11 +11,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/ppc64/kernel/bitops.c b/arch/ppc64/kernel/bitops.c index 6b24b0219090..ae329e8b4acb 100644 --- a/arch/ppc64/kernel/bitops.c +++ b/arch/ppc64/kernel/bitops.c @@ -4,7 +4,7 @@ #include #include -#include +#include #include unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, diff --git a/arch/ppc64/kernel/iommu.c b/arch/ppc64/kernel/iommu.c index d5d64d1d7258..3c476ee1d89e 100644 --- a/arch/ppc64/kernel/iommu.c +++ b/arch/ppc64/kernel/iommu.c @@ -33,12 +33,12 @@ #include #include #include +#include #include #include #include #include #include -#include #define DBG(...) diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c index 55e5387123ec..9410bbf260d3 100644 --- a/arch/ppc64/kernel/irq.c +++ b/arch/ppc64/kernel/irq.c @@ -42,9 +42,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/ppc64/kernel/lmb.c b/arch/ppc64/kernel/lmb.c index 56a26eec0b1a..56d7ba87fe60 100644 --- a/arch/ppc64/kernel/lmb.c +++ b/arch/ppc64/kernel/lmb.c @@ -13,12 +13,12 @@ #include #include #include +#include #include #include #include #include #include -#include struct lmb lmb; diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c index 3d1de0f9bf83..49fb81444522 100644 --- a/arch/ppc64/kernel/pmac_setup.c +++ b/arch/ppc64/kernel/pmac_setup.c @@ -53,13 +53,12 @@ #include #include #include +#include #include #include #include #include -#include -#include #include #include #include diff --git a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c index 3732fe0482a2..cf543e042665 100644 --- a/arch/ppc64/kernel/ppc_ksyms.c +++ b/arch/ppc64/kernel/ppc_ksyms.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -28,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index f121ffbc2069..f9eec2a5405b 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -43,7 +44,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index f62bda79e102..2add2f88d440 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -42,7 +43,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc64/kernel/ras.c b/arch/ppc64/kernel/ras.c index 75ced99c5d7c..06f69b37fe34 100644 --- a/arch/ppc64/kernel/ras.c +++ b/arch/ppc64/kernel/ras.c @@ -37,9 +37,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c index bd75066cc047..c857aa14d6b2 100644 --- a/arch/ppc64/kernel/rtas-proc.c +++ b/arch/ppc64/kernel/rtas-proc.c @@ -22,9 +22,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/sh/boards/bigsur/irq.c b/arch/sh/boards/bigsur/irq.c index 082472448611..c188fc32dc9a 100644 --- a/arch/sh/boards/bigsur/irq.c +++ b/arch/sh/boards/bigsur/irq.c @@ -29,10 +29,10 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/arch/sh/boards/bigsur/setup.c b/arch/sh/boards/bigsur/setup.c index 9cb329269260..e69be05195f5 100644 --- a/arch/sh/boards/bigsur/setup.c +++ b/arch/sh/boards/bigsur/setup.c @@ -29,10 +29,10 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/arch/sh/kernel/cpu/irq_imask.c b/arch/sh/kernel/cpu/irq_imask.c index be2c82385d97..f76901e732fb 100644 --- a/arch/sh/kernel/cpu/irq_imask.c +++ b/arch/sh/kernel/cpu/irq_imask.c @@ -18,10 +18,10 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 73ec3365d0d0..9a7d936263fd 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -31,10 +31,10 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/arch/sh64/kernel/irq.c b/arch/sh64/kernel/irq.c index 7d0f422e1133..b0f138f545a8 100644 --- a/arch/sh64/kernel/irq.c +++ b/arch/sh64/kernel/irq.c @@ -30,9 +30,9 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/arch/sh64/kernel/irq_intc.c b/arch/sh64/kernel/irq_intc.c index 4062ae55e1ae..43f88f3a78b0 100644 --- a/arch/sh64/kernel/irq_intc.c +++ b/arch/sh64/kernel/irq_intc.c @@ -20,12 +20,12 @@ #include #include #include +#include /* this includes also #include -#include /* this includes also #include #include diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c index 276860da53bd..7f677a39c1a9 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal.c @@ -20,9 +20,9 @@ #include #include #include /* do_coredum */ +#include #include -#include #include #include #include diff --git a/arch/sparc/lib/bitext.c b/arch/sparc/lib/bitext.c index f375c8e361df..1e711bb665b7 100644 --- a/arch/sparc/lib/bitext.c +++ b/arch/sparc/lib/bitext.c @@ -10,9 +10,9 @@ */ #include +#include #include -#include /** * bit_map_string_get - find and set a bit string in bit map. diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c index 7eddc56b749f..40b36f0b3307 100644 --- a/arch/sparc/mm/io-unit.c +++ b/arch/sparc/mm/io-unit.c @@ -11,6 +11,7 @@ #include #include #include /* pte_offset_map => kmap_atomic */ +#include #include #include @@ -19,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index d81bfab517f0..aa298d31d33c 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -23,9 +23,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 63d9cec39754..ab266049499e 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -20,9 +20,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c index 646a788fa9d2..8a9d3b6bfe5c 100644 --- a/arch/sparc64/kernel/unaligned.c +++ b/arch/sparc64/kernel/unaligned.c @@ -19,8 +19,8 @@ #include #include #include +#include #include -#include /* #define DEBUG_MNA */ diff --git a/arch/sparc64/lib/find_bit.c b/arch/sparc64/lib/find_bit.c index 5852614492bb..27545fbf5da7 100644 --- a/arch/sparc64/lib/find_bit.c +++ b/arch/sparc64/lib/find_bit.c @@ -1,4 +1,4 @@ -#include +#include /** * find_next_bit - find the next set bit in a memory region diff --git a/arch/v850/kernel/fpga85e2c.c b/arch/v850/kernel/fpga85e2c.c index 17e3dbafc371..af2e804b7283 100644 --- a/arch/v850/kernel/fpga85e2c.c +++ b/arch/v850/kernel/fpga85e2c.c @@ -20,11 +20,11 @@ #include #include #include +#include #include #include #include -#include #include "mach.h" diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c index f5d084a990d3..7929a2e534a6 100644 --- a/arch/x86_64/kernel/i8259.c +++ b/arch/x86_64/kernel/i8259.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -19,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c index ca608a2a0aaf..bf2d2d0bf5d2 100644 --- a/arch/x86_64/kernel/pci-gart.c +++ b/arch/x86_64/kernel/pci-gart.c @@ -22,10 +22,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c index b7f2bfa57c55..8c68b5d34cf6 100644 --- a/arch/x86_64/kernel/setup64.c +++ b/arch/x86_64/kernel/setup64.c @@ -11,11 +11,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/x86_64/lib/bitops.c b/arch/x86_64/lib/bitops.c index 6060dd9084aa..994d766503dd 100644 --- a/arch/x86_64/lib/bitops.c +++ b/arch/x86_64/lib/bitops.c @@ -1,5 +1,5 @@ #include -#include +#include #undef find_first_zero_bit #undef find_next_zero_bit diff --git a/arch/x86_64/lib/bitstr.c b/arch/x86_64/lib/bitstr.c index e7ce82a0a332..24676609a6ac 100644 --- a/arch/x86_64/lib/bitstr.c +++ b/arch/x86_64/lib/bitstr.c @@ -1,5 +1,5 @@ #include -#include +#include /* Find string of zero bits in a bitmap */ unsigned long diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c index 0e7a399d2470..9cc2e8436b45 100644 --- a/drivers/acorn/block/fd1772.c +++ b/drivers/acorn/block/fd1772.c @@ -138,9 +138,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index 958a5e1f70c7..8dc889498306 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c @@ -32,9 +32,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index d67d0385f20b..305e030eb447 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -39,8 +39,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index b44fa7dd38c3..f039c84e8218 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -38,8 +38,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 79ec1ce7841d..91e0a2edf720 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -38,8 +38,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index bcf906bb24ff..b657ac4ff7cc 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -85,13 +85,13 @@ static char *serial_version = "4.30"; #include #include #include +#include #include #include #include -#include #include #include diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 46002d5bada1..d3fd1c9c9301 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -652,12 +652,12 @@ static char rcsid[] = #include #include #include +#include #include #include #include #include -#include #define CY_LOCK(info,flags) \ do { \ diff --git a/drivers/char/ec3104_keyb.c b/drivers/char/ec3104_keyb.c index b3289d9d23f5..452d45c7b13b 100644 --- a/drivers/char/ec3104_keyb.c +++ b/drivers/char/ec3104_keyb.c @@ -43,9 +43,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index e8ad7da73f6f..7ee8a1d70ee8 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -28,13 +28,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c index e0cbd7552eb8..3d3ae6856bbd 100644 --- a/drivers/char/ip2main.c +++ b/drivers/char/ip2main.c @@ -112,11 +112,11 @@ #include #include #include +#include #include #include #include -#include #include #include diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 11373907f29f..36b90e087031 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c @@ -50,10 +50,10 @@ #include #include #include +#include #include #include -#include #include #define MOXA_VERSION "5.1k" diff --git a/drivers/char/mwave/3780i.c b/drivers/char/mwave/3780i.c index 8832ed21d412..0dee98b146fb 100644 --- a/drivers/char/mwave/3780i.c +++ b/drivers/char/mwave/3780i.c @@ -52,11 +52,11 @@ #include #include #include +#include #include #include #include #include -#include #include "smapi.h" #include "mwavedd.h" #include "3780i.h" diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index 3e10c700d685..0a684d8cc112 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c @@ -103,9 +103,9 @@ #include /* used in new tty drivers */ #include /* used in new tty drivers */ #include +#include #include -#include #include #include diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 5a3be050e7bf..3bca97c2ae45 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -44,10 +44,10 @@ #include #include #include +#include #include #include -#include /* number of characters left in xmit buffer before select has we have room */ #define WAKEUP_CHARS 256 diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index f334dbfcf21f..522de1ec92c4 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -65,7 +65,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/char/pcxx.c b/drivers/char/pcxx.c index 97fd9da9c5ef..d489a1322e0d 100644 --- a/drivers/char/pcxx.c +++ b/drivers/char/pcxx.c @@ -65,6 +65,7 @@ #include #include #include +#include #ifndef MODULE #include /* We only need it for parsing the "digi="-line */ @@ -73,7 +74,6 @@ #include #include #include -#include #include #define VERSION "1.6.3" diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 9826bbd0f67a..2e0eda2d40bf 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include /* These are global because they are accessed in tty_io.c */ diff --git a/drivers/char/qtronix.c b/drivers/char/qtronix.c index 4698af2d62e3..e0bb00f3c05d 100644 --- a/drivers/char/qtronix.c +++ b/drivers/char/qtronix.c @@ -79,7 +79,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 9f13fad3fc11..4a0840ed50c9 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -91,7 +91,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index b2538a6b85b0..028044f79045 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -59,10 +59,10 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index edf89fffe4e1..84224b99353f 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -97,7 +97,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 9ccce79fdf4e..cb4de2ebb15e 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -63,7 +63,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c index 48d7a7cc0c2b..2fd2901ffc45 100644 --- a/drivers/char/tipar.c +++ b/drivers/char/tipar.c @@ -55,7 +55,7 @@ #include #include #include -#include +#include #include /* DevFs support */ #include /* Our code depend on parport */ #include diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 9d5e4ba9dc25..b27ae629e6e2 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -93,10 +93,10 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 830c665a3bd5..d1060b2d5579 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -19,9 +19,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/char/vt.c b/drivers/char/vt.c index cffa77b92629..185d19ab1214 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -101,11 +101,11 @@ #include #include #include +#include #include #include #include -#include #include "console_macros.h" diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c index ebcaf79ce8bc..ab659d37b4d2 100644 --- a/drivers/char/watchdog/ixp2000_wdt.c +++ b/drivers/char/watchdog/ixp2000_wdt.c @@ -25,9 +25,9 @@ #include #include #include +#include #include -#include #include #ifdef CONFIG_WATCHDOG_NOWAYOUT diff --git a/drivers/char/watchdog/ixp4xx_wdt.c b/drivers/char/watchdog/ixp4xx_wdt.c index a6781dede6c8..eb13091b8b15 100644 --- a/drivers/char/watchdog/ixp4xx_wdt.c +++ b/drivers/char/watchdog/ixp4xx_wdt.c @@ -22,9 +22,9 @@ #include #include #include +#include #include -#include #include #ifdef CONFIG_WATCHDOG_NOWAYOUT diff --git a/drivers/fc4/soc.c b/drivers/fc4/soc.c index 3f8b4c15115d..392e216696d9 100644 --- a/drivers/fc4/soc.c +++ b/drivers/fc4/soc.c @@ -32,7 +32,7 @@ static char *version = #include #include #include -#include +#include #include #include #include diff --git a/drivers/fc4/socal.c b/drivers/fc4/socal.c index 5ee4dda53743..162985ca9d57 100644 --- a/drivers/fc4/socal.c +++ b/drivers/fc4/socal.c @@ -27,8 +27,8 @@ static char *version = #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/ide/ide-default.c b/drivers/ide/ide-default.c index ef6e2c8c21d3..a6bea5d0de03 100644 --- a/drivers/ide/ide-default.c +++ b/drivers/ide/ide-default.c @@ -23,13 +23,13 @@ #include #include #include +#include #include #include #include #include #include -#include #define IDEDEFAULT_VERSION "0.9.newide" /* diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 3b092c387193..39819daed56c 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -97,13 +97,13 @@ #include #include #include +#include #include #include #include #include #include -#include /* * The following are used to debug the driver. diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index c104120ae669..d2316daebd38 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -23,12 +23,12 @@ #include #include #include +#include #include #include #include #include -#include /* * Conventional PIO operations for ATA devices diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index b2fa5eccdcad..8acad305be8b 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -15,12 +15,12 @@ #include #include #include +#include #include #include #include #include -#include /* * IDE library routines. These are plug in code that most diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 3ec7ff671c65..82e471ffd713 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -442,13 +442,13 @@ #include #include #include +#include #include #include #include #include #include -#include /* * partition diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 4a8019475c02..c7eea8dd31a3 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -44,12 +44,12 @@ #include #include #include +#include #include #include #include #include -#include #define DEBUG_TASKFILE 0 /* unset when fixed */ diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 5f0a43527219..75baad1eafca 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -153,12 +153,12 @@ #include #include #include +#include #include #include #include #include -#include /* default maximum number of failures */ diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c index 7d5ecce92346..a56ea2b73f12 100644 --- a/drivers/input/serio/q40kbd.c +++ b/drivers/input/serio/q40kbd.c @@ -36,8 +36,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/drivers/isdn/i4l/isdn_bsdcomp.c b/drivers/isdn/i4l/isdn_bsdcomp.c index fd80b86388a9..baf4bcad9bf9 100644 --- a/drivers/isdn/i4l/isdn_bsdcomp.c +++ b/drivers/isdn/i4l/isdn_bsdcomp.c @@ -68,9 +68,9 @@ #include #include /* used in new tty drivers */ #include /* used in new tty drivers */ +#include #include -#include #include #include diff --git a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c index a3a5372f7aeb..e35a141adaa6 100644 --- a/drivers/macintosh/macserial.c +++ b/drivers/macintosh/macserial.c @@ -32,6 +32,7 @@ #include #endif #include +#include #include #include @@ -40,7 +41,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index d1f54a9ad324..e5f6bb754f5a 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include /* diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index aea1a1be5845..b6050c837bb6 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include "raid6.h" diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index e33fdd99b3d3..f53ce50411a2 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -19,7 +19,7 @@ * */ -#include +#include #include #include #include diff --git a/drivers/media/dvb/frontends/at76c651.c b/drivers/media/dvb/frontends/at76c651.c index 0dceacee31d5..d221723ac909 100644 --- a/drivers/media/dvb/frontends/at76c651.c +++ b/drivers/media/dvb/frontends/at76c651.c @@ -35,10 +35,7 @@ #include #include #include - -#if defined(__powerpc__) -#include -#endif +#include #include "dvb_frontend.h" diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c index f3fed48366cf..32292be4bacc 100644 --- a/drivers/media/dvb/ttpci/av7110_ir.c +++ b/drivers/media/dvb/ttpci/av7110_ir.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "av7110.h" diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c index 0c99115637bf..7628bda82c91 100644 --- a/drivers/net/3c501.c +++ b/drivers/net/3c501.c @@ -124,9 +124,9 @@ static const char version[] = #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c index 3aa8409fe5f9..6bff013a941d 100644 --- a/drivers/net/3c505.c +++ b/drivers/net/3c505.c @@ -107,9 +107,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c index 4866a09c0708..8c2a06bfefc7 100644 --- a/drivers/net/3c507.c +++ b/drivers/net/3c507.c @@ -59,8 +59,8 @@ static const char version[] = #include #include #include +#include -#include #include #include #include diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index b053f53bb13e..7d25f2e36fc7 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -90,9 +90,9 @@ static int max_interrupt_work = 10; #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c index bcdc0d60846a..7dca6e585e66 100644 --- a/drivers/net/3c515.c +++ b/drivers/net/3c515.c @@ -72,9 +72,9 @@ static int max_interrupt_work = 20; #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index 1902f792199e..0a5df59d46fd 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -104,10 +104,10 @@ #include #include #include +#include #include #include -#include #include #include "3c523.h" diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c index a39c446c3429..15550b1442f8 100644 --- a/drivers/net/3c527.c +++ b/drivers/net/3c527.c @@ -102,11 +102,11 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Richard Procter #include #include +#include #include #include #include -#include #include #include diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index adcbf6853357..5b45341d3a6a 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -257,8 +257,8 @@ static int vortex_debug = 1; #include #include #include +#include #include /* For NR_IRQS only. */ -#include #include #include diff --git a/drivers/net/7990.c b/drivers/net/7990.c index 0e5aec0d57d1..a18ecab20637 100644 --- a/drivers/net/7990.c +++ b/drivers/net/7990.c @@ -32,9 +32,9 @@ #include /* Used for the temporal inet entries and routing */ #include +#include #include -#include #include #include #include diff --git a/drivers/net/82596.c b/drivers/net/82596.c index c835712edef9..33bcdf612cba 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -53,8 +53,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/drivers/net/8390.c b/drivers/net/8390.c index 04dcacda870d..c89a61289401 100644 --- a/drivers/net/8390.c +++ b/drivers/net/8390.c @@ -58,9 +58,9 @@ static const char version[] = #include #include #include +#include #include #include -#include #include #include #include diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index 0d95f0bf964c..8e538a6d7d97 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -52,8 +52,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c index 925dd04774fa..00bb1b2ae4a0 100644 --- a/drivers/net/appletalk/cops.c +++ b/drivers/net/appletalk/cops.c @@ -69,9 +69,9 @@ static const char *version = #include /* For udelay() */ #include #include +#include #include -#include #include #include diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c index 70a7a181b8d8..118503bc3823 100644 --- a/drivers/net/appletalk/ltpc.c +++ b/drivers/net/appletalk/ltpc.c @@ -227,9 +227,9 @@ static int dma; #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index 10a94c54427e..9fe93acfc8ef 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c @@ -47,8 +47,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index a6d42aa9fac5..9b659e3c8d67 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -28,9 +28,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c index fb401b27c3b1..6118f09c63cf 100644 --- a/drivers/net/arm/ether1.c +++ b/drivers/net/arm/ether1.c @@ -48,9 +48,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c index d054876b9673..e0d22a31ea12 100644 --- a/drivers/net/arm/ether3.c +++ b/drivers/net/arm/ether3.c @@ -64,9 +64,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index d861c54a7766..f3f1a483f8ca 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c @@ -44,9 +44,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c index a3e7e63c39a6..0dcf27a51dd6 100644 --- a/drivers/net/at1700.c +++ b/drivers/net/at1700.c @@ -56,9 +56,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/atari_bionet.c b/drivers/net/atari_bionet.c index 92a2ec2e51da..1798ce7262c9 100644 --- a/drivers/net/atari_bionet.c +++ b/drivers/net/atari_bionet.c @@ -97,6 +97,7 @@ static char version[] = #include #include #include +#include #include #include @@ -105,7 +106,6 @@ static char version[] = #include #include #include -#include #include #include #include diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c index c74e5866293a..81c362c8cb97 100644 --- a/drivers/net/atari_pamsnet.c +++ b/drivers/net/atari_pamsnet.c @@ -88,9 +88,9 @@ static char *version = #include #include #include +#include #include #include -#include #include #include #include diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c index e462e2fca538..a5dfb1276c2d 100644 --- a/drivers/net/atarilance.c +++ b/drivers/net/atarilance.c @@ -56,12 +56,12 @@ static char version[] = "atarilance.c: v1.3 04/04/96 " #include #include #include +#include #include #include #include #include -#include #include /* Debug level: diff --git a/drivers/net/atp.c b/drivers/net/atp.c index fd2e033fecc1..662e40f30031 100644 --- a/drivers/net/atp.c +++ b/drivers/net/atp.c @@ -141,9 +141,9 @@ static int xcvr[NUM_UNITS]; /* The data transfer mode. */ #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index afcdcffc7847..3328ed511bf8 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -36,10 +36,10 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/drivers/net/bagetlance.c b/drivers/net/bagetlance.c index e62ad3ad6e58..55a0f66f6cf8 100644 --- a/drivers/net/bagetlance.c +++ b/drivers/net/bagetlance.c @@ -25,9 +25,9 @@ static char *version = "bagetlance.c: v1.1 11/10/98\n"; #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6917b665b65a..e1097f90c883 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -491,8 +491,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 3ce3237b1686..e8c74071fed3 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -135,9 +135,9 @@ #include #include #include +#include #include -#include #include #if ALLOW_DMA #include diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index 85d1bb3a9865..c7ef439ea1de 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -207,9 +207,9 @@ #include #include #include +#include #include -#include #include #include "defxx.h" diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 5d62a032b8c8..49ebfbe6cff8 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -255,9 +255,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c index 639aa7508502..779af1727eef 100644 --- a/drivers/net/dgrs.c +++ b/drivers/net/dgrs.c @@ -97,8 +97,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/drivers/net/dl2k.h b/drivers/net/dl2k.h index d46367392595..6e75482d75f2 100644 --- a/drivers/net/dl2k.h +++ b/drivers/net/dl2k.h @@ -28,8 +28,8 @@ #include #include #include +#include #include /* Processor type for cache alignment. */ -#include #include #include #include diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 1951644a9afc..30c7d5433b69 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -54,7 +54,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index 9f5ea60758b1..3f05a33e7c69 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c @@ -145,9 +145,9 @@ static const char version[] = #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 13850a3177c0..e02b6aec703a 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -102,8 +102,8 @@ static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1}; #include #include #include +#include -#include #include #include #include diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c index 1880fc0ba665..8d0585f7841b 100644 --- a/drivers/net/eexpress.c +++ b/drivers/net/eexpress.c @@ -115,9 +115,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index ec327ad3a33f..459013762bd8 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -133,7 +133,7 @@ static int rx_copybreak; #include #include #include -#include +#include #include #include diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c index 5a9ae260f3d6..39f678270705 100644 --- a/drivers/net/eth16i.c +++ b/drivers/net/eth16i.c @@ -160,9 +160,9 @@ static char *version = #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c index ccc8c52669e3..8f995141b518 100644 --- a/drivers/net/ewrk3.c +++ b/drivers/net/ewrk3.c @@ -161,8 +161,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index 9112ca037315..fddc5360fd1c 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -85,9 +85,9 @@ static int full_duplex[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; #include #include #include +#include #include /* Processor type for cache alignment. */ -#include #include #include diff --git a/drivers/net/fec.c b/drivers/net/fec.c index b9e59da66b56..645122086a94 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -39,9 +39,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/fec_8xx/fec_8xx-netta.c b/drivers/net/fec_8xx/fec_8xx-netta.c index 7d73661aa367..29c275e1d566 100644 --- a/drivers/net/fec_8xx/fec_8xx-netta.c +++ b/drivers/net/fec_8xx/fec_8xx-netta.c @@ -21,12 +21,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include diff --git a/drivers/net/fec_8xx/fec_main.c b/drivers/net/fec_8xx/fec_main.c index 1bf15eed626a..b4f3a9f8a535 100644 --- a/drivers/net/fec_8xx/fec_main.c +++ b/drivers/net/fec_8xx/fec_main.c @@ -30,12 +30,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/drivers/net/fec_8xx/fec_mii.c b/drivers/net/fec_8xx/fec_mii.c index 700233655e52..8fd1495fafe2 100644 --- a/drivers/net/fec_8xx/fec_mii.c +++ b/drivers/net/fec_8xx/fec_mii.c @@ -30,12 +30,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include diff --git a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c index f0b6f9c9dcfb..04c748523471 100644 --- a/drivers/net/fmv18x.c +++ b/drivers/net/fmv18x.c @@ -51,9 +51,9 @@ static const char version[] = #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/gt96100eth.c b/drivers/net/gt96100eth.c index a41ccc452007..b6f1e8be445b 100644 --- a/drivers/net/gt96100eth.c +++ b/drivers/net/gt96100eth.c @@ -44,9 +44,9 @@ #include #include #include +#include #include -#include #include #define DESC_BE 1 diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index 7dda9988e13b..9b885efadf00 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -170,10 +170,10 @@ static int tx_params[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; #include #include #include +#include #include #include /* Processor type for cache alignment. */ -#include #include #include #include diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index e6dba5623add..738cef65b728 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c index 4bd7c09656d8..77f29fdde8ef 100644 --- a/drivers/net/hamradio/baycom_par.c +++ b/drivers/net/hamradio/baycom_par.c @@ -83,9 +83,9 @@ #include #include #include +#include #include -#include #include /* --------------------------------------------------------------------- */ diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c index 86deb52100be..8e115b5a6a11 100644 --- a/drivers/net/hamradio/hdlcdrv.c +++ b/drivers/net/hamradio/hdlcdrv.c @@ -51,7 +51,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index e2a28b562446..d51712a17fd3 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c index 2049556d1764..8da1948026c6 100644 --- a/drivers/net/hamradio/scc.c +++ b/drivers/net/hamradio/scc.c @@ -173,6 +173,7 @@ #include #include #include +#include #include @@ -180,7 +181,6 @@ #include #include #include -#include #include "z8530.h" diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index c516e7156ca1..acae5949a9ea 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c @@ -50,7 +50,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index 675ad8f523db..2392d4523a3d 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -114,8 +114,8 @@ #include /* for CONFIG_PCI */ #include #include +#include -#include #include #include "hp100.h" diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c index fecaec10291d..6e0ca7340a8f 100644 --- a/drivers/net/hydra.c +++ b/drivers/net/hydra.c @@ -23,8 +23,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c index 6b0328fbc97b..a68b29245b90 100644 --- a/drivers/net/ibm_emac/ibm_emac_core.c +++ b/drivers/net/ibm_emac/ibm_emac_core.c @@ -40,9 +40,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c index 0aa0a826128c..e58b31c918a9 100644 --- a/drivers/net/ibmlana.c +++ b/drivers/net/ibmlana.c @@ -88,9 +88,9 @@ History: #include #include #include +#include #include -#include #include #define _IBM_LANA_DRIVER_ diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c index c5af0cb78905..a02a2a25aa07 100644 --- a/drivers/net/irda/au1k_ir.c +++ b/drivers/net/irda/au1k_ir.c @@ -28,9 +28,9 @@ #include #include #include +#include #include -#include #include #include #if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c index 6ad80edb2efa..c2c26b605357 100644 --- a/drivers/net/irda/irport.c +++ b/drivers/net/irda/irport.c @@ -51,9 +51,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c index 650943395087..50bebb55e9ee 100644 --- a/drivers/net/isa-skeleton.c +++ b/drivers/net/isa-skeleton.c @@ -55,9 +55,9 @@ static const char *version = #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h index 24311a57a376..d5c6f477f916 100644 --- a/drivers/net/ixgb/ixgb.h +++ b/drivers/net/ixgb/ixgb.h @@ -50,7 +50,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c index 8624bfc4905b..7046c4395266 100644 --- a/drivers/net/jazzsonic.c +++ b/drivers/net/jazzsonic.c @@ -27,10 +27,10 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/drivers/net/lance.c b/drivers/net/lance.c index f04d0a82cf3b..87acad34266f 100644 --- a/drivers/net/lance.c +++ b/drivers/net/lance.c @@ -56,8 +56,8 @@ static const char version[] = "lance.c:v1.15ac 1999/11/13 dplatt@3do.com, becker #include #include #include +#include -#include #include #include diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index b315acb14362..188562f70130 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -83,8 +83,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c index c87d90a837fb..70be2a9e3820 100644 --- a/drivers/net/lp486e.c +++ b/drivers/net/lp486e.c @@ -70,8 +70,8 @@ All other communication is through memory! #include #include #include +#include -#include #include #include diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index 0a8094eb3061..c4d742f67013 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c @@ -32,9 +32,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c index e67bf67f122f..a4dde8181d25 100644 --- a/drivers/net/macsonic.c +++ b/drivers/net/macsonic.c @@ -42,10 +42,10 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 41d38b3b3b4f..362fee325e0a 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -49,7 +49,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index c5f95959ccbe..d85e04bd7490 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -22,6 +22,7 @@ static char version[] = #include #include #include +#include #include #include @@ -29,7 +30,6 @@ static char version[] = #include #include -#include #include #include #include diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 41d93758bb3c..5bb12dc93496 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -159,8 +159,8 @@ #include #include #include +#include #include /* Processor type for cache alignment. */ -#include #include #include #include diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c index 5d690c9f1d25..4fe6e7574855 100644 --- a/drivers/net/ne2.c +++ b/drivers/net/ne2.c @@ -74,9 +74,9 @@ static const char *version = "ne2.c:v0.91 Nov 16 1998 Wim Dumon #include #include +#include #include -#include #include #include diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c index 8124ad671698..2ab01a5d1d22 100644 --- a/drivers/net/ni5010.c +++ b/drivers/net/ni5010.c @@ -59,7 +59,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c index 234709ded746..a76c8575ccff 100644 --- a/drivers/net/ni52.c +++ b/drivers/net/ni52.c @@ -115,7 +115,7 @@ static int fifo=0x8; /* don't change */ #include #include #include -#include +#include #include #include diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c index c43c4cf9e837..fd58f0d9e644 100644 --- a/drivers/net/ni65.c +++ b/drivers/net/ni65.c @@ -73,8 +73,8 @@ #include #include #include +#include -#include #include #include diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 7c4ed0ddd12a..b5c99d2f37b6 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -84,6 +84,7 @@ earlier 3Com products. #include #include #include +#include #include #include @@ -97,7 +98,6 @@ earlier 3Com products. #include #include #include -#include /*====================================================================*/ diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 2e0135dad547..970ed7bb596f 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -50,7 +51,6 @@ #include #include #include -#include /* To minimize the size of the driver source I only define operating constants if they are used several times. You'll need the manual diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 0d9a06f8c561..3029129ae650 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -936,7 +936,7 @@ module_exit(exit_axnet_cs); static const char *version_8390 = "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@scyld.com)\n"; -#include +#include #include #include #include diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 947dad4ca55a..0ec78c327343 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -144,6 +144,7 @@ Include Files #include #include #include +#include #include #include @@ -155,7 +156,6 @@ Include Files #include #include #include -#include /* ---------------------------------------------------------------------------- Defines diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 5be2ba3b03e8..25c2fc991405 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -79,6 +79,7 @@ #include #include #include +#include #include #include @@ -89,7 +90,6 @@ #include #include -#include #include #ifndef MANFID_COMPAQ diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index a0af06c18a23..74d9062dc1c9 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -47,8 +47,8 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n"; #include #include #include +#include -#include #include #include #include diff --git a/drivers/net/plip.c b/drivers/net/plip.c index 937b6198c229..3dd010328f16 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -109,11 +109,11 @@ static const char version[] = "NET3 PLIP version 2.4-parport gniibe@mri.co.jp\n" #include #include #include +#include #include #include -#include #include #include #include diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c index 03f28fdc0629..dcc64eb8dc4a 100644 --- a/drivers/net/sb1000.c +++ b/drivers/net/sb1000.c @@ -50,8 +50,8 @@ static char version[] = "sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net)\n"; #include #include #include +#include -#include #include #include #include diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index e0f88fbd33f5..1534679529d2 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -68,8 +68,8 @@ static int int_timeout = 0; #include #include #include +#include #include /* Processor type for cache alignment. */ -#include #include #include diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c index 0f237b54d5b3..d9fd93004730 100644 --- a/drivers/net/seeq8005.c +++ b/drivers/net/seeq8005.c @@ -45,9 +45,9 @@ static const char version[] = #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index b71f45f5cb58..4385cd1677a0 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c @@ -19,11 +19,11 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 8ddf9d02f973..7bb0e9019d3c 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -64,9 +64,9 @@ #include #include #include +#include #include /* Processor type for cache alignment. */ -#include #include #include /* User space memory access functions */ diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h index 21d807390738..e65a19f8794a 100644 --- a/drivers/net/sk98lin/h/skdrv1st.h +++ b/drivers/net/sk98lin/h/skdrv1st.h @@ -66,8 +66,8 @@ typedef struct s_AC SK_AC; #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 58775e61963d..5db59c43f6a2 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -72,8 +72,8 @@ * * * + * * - * * * * diff --git a/drivers/net/sk_g16.c b/drivers/net/sk_g16.c index bc71b55a99c0..425012d48f07 100644 --- a/drivers/net/sk_g16.c +++ b/drivers/net/sk_g16.c @@ -72,10 +72,10 @@ static const char rcsid[] = "$Id: sk_g16.c,v 1.1 1994/06/30 16:25:15 root Exp $" #include #include #include +#include #include #include -#include #include "sk_g16.h" diff --git a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c index 2039f22338fc..07b980281666 100644 --- a/drivers/net/sk_mca.c +++ b/drivers/net/sk_mca.c @@ -97,9 +97,9 @@ History: #include #include #include +#include #include -#include #include #define _SK_MCA_DRIVER_ diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c index 8308bcc14ac6..e9ef28cbbd29 100644 --- a/drivers/net/skfp/skfddi.c +++ b/drivers/net/skfp/skfddi.c @@ -83,9 +83,9 @@ static const char *boot_msg = #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 0c1995bc2848..01c2c3e1d102 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -60,7 +60,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c index f5071b047315..de31ab71384c 100644 --- a/drivers/net/smc9194.c +++ b/drivers/net/smc9194.c @@ -72,8 +72,8 @@ static const char version[] = #include #include #include +#include -#include #include #include "smc9194.h" diff --git a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c index 053fcaf1c9e2..d5a58fb30d3a 100644 --- a/drivers/net/sun3_82586.c +++ b/drivers/net/sun3_82586.c @@ -39,7 +39,7 @@ static int fifo=0x8; /* don't change */ #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c index 6faef842db46..1f43bbfbc1c7 100644 --- a/drivers/net/sun3lance.c +++ b/drivers/net/sun3lance.c @@ -36,10 +36,10 @@ static char *version = "sun3lance.c: v1.2 1/12/2001 Sam Creasey (sammy@sammy.ne #include #include #include +#include #include #include -#include #include #include #include diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 25d35022bdb8..025dcd867eaa 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -22,9 +22,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 42f665496524..776403daf634 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -162,9 +162,9 @@ static char *media[MAX_UNITS]; #include #include #include +#include #include #include /* Processor type for cache alignment. */ -#include #include #include #include diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index eab667c7b1c6..85c1e1e5e89b 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -37,9 +37,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 0a11b5627804..525b9ca61972 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -36,9 +36,9 @@ static char version[] = #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index 6e4bb5781fe9..d2d34594bae7 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -94,9 +94,9 @@ static char lancestr[] = "LANCE"; #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index 1ed3ff5b3519..37ef1b82a6cb 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -27,9 +27,9 @@ static char version[] = #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index 952ef81775fb..c2ec9fd8c31d 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -49,9 +49,9 @@ static const char *version = #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c index a50df64b212c..47d7d6d4ca64 100644 --- a/drivers/net/tokenring/3c359.c +++ b/drivers/net/tokenring/3c359.c @@ -61,12 +61,12 @@ #include #include #include +#include #include #include #include -#include #include "3c359.h" diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c index dcf7f3e8ce93..63005ae6a418 100644 --- a/drivers/net/tokenring/lanstreamer.c +++ b/drivers/net/tokenring/lanstreamer.c @@ -120,12 +120,12 @@ #include #include #include +#include #include #include #include -#include #include "lanstreamer.h" diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index 1ec45b2b9f4c..eed699bafbc8 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -99,12 +99,12 @@ #include #include #include +#include #include #include #include -#include #include "olympic.h" diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c index 599057ac316f..1331fd1d8f90 100644 --- a/drivers/net/tokenring/smctr.c +++ b/drivers/net/tokenring/smctr.c @@ -49,9 +49,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c index 9d121890b6fb..df43b449e429 100644 --- a/drivers/net/tokenring/tms380tr.c +++ b/drivers/net/tokenring/tms380tr.c @@ -96,9 +96,9 @@ static const char version[] = "tms380tr.c: v1.10 30/12/2002 by Christoph Goos, A #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index 05e8947f9047..7afae1f70483 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -467,8 +467,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index 7353f28ccc34..dfcb1657a0ac 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -86,9 +86,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 7174a278bddd..5bf05492a0ec 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -130,9 +130,9 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; #include #include #include +#include #include #include /* Processor type for cache alignment. */ -#include #include #include diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index 6e65890391a6..1555d632266d 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c @@ -28,9 +28,9 @@ #include #include #include +#include #include -#include #include #ifdef DEBUG diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index d22567ede974..d763bf6d310f 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -115,8 +115,8 @@ static const int multicast_filter_limit = 32; #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 33c3137c016e..5a011ee958b9 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -193,8 +193,8 @@ static const int multicast_filter_limit = 32; #include #include #include +#include #include /* Processor type for cache alignment. */ -#include #include #include #include diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c index bad0d418580b..6e1ec5bf22fc 100644 --- a/drivers/net/wan/dlci.c +++ b/drivers/net/wan/dlci.c @@ -45,11 +45,11 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/drivers/net/wan/hd6457x.c b/drivers/net/wan/hd6457x.c index c98d7eca5c92..c96f5aaf4529 100644 --- a/drivers/net/wan/hd6457x.c +++ b/drivers/net/wan/hd6457x.c @@ -38,9 +38,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index b9800715d739..f88d9b64eafa 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -56,11 +56,11 @@ #include #include #include +#include #include #include /* Processor type for cache alignment. */ -#include #include #include #include diff --git a/drivers/net/wan/lmc/lmc_media.c b/drivers/net/wan/lmc/lmc_media.c index 2aca8dc986f1..f55ce76b00ed 100644 --- a/drivers/net/wan/lmc/lmc_media.c +++ b/drivers/net/wan/lmc/lmc_media.c @@ -16,11 +16,11 @@ #include #include #include +#include #include #include /* Processor type for cache alignment. */ -#include #include #include diff --git a/drivers/net/wan/lmc/lmc_proto.c b/drivers/net/wan/lmc/lmc_proto.c index bb9f1eab7cdb..74876c0073e8 100644 --- a/drivers/net/wan/lmc/lmc_proto.c +++ b/drivers/net/wan/lmc/lmc_proto.c @@ -36,11 +36,11 @@ #include #include #include +#include #include #include /* Processor type for cache alignment. */ -#include #include #include #include diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c index 12598181abed..f0ed00ef06fe 100644 --- a/drivers/net/wan/sdla.c +++ b/drivers/net/wan/sdla.c @@ -51,9 +51,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 467ad7b8cd86..c29233115d3f 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 4246f6b8b656..0360693eb6fc 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -35,9 +35,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/drivers/net/wireless/arlan.h b/drivers/net/wireless/arlan.h index a48af699c9c5..e499f4b52a51 100644 --- a/drivers/net/wireless/arlan.h +++ b/drivers/net/wireless/arlan.h @@ -19,8 +19,8 @@ #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 13641142bf77..15708eb78521 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -54,6 +54,7 @@ #include #include #include +#include #ifdef CONFIG_NET_RADIO #include #if WIRELESS_EXT > 12 @@ -70,7 +71,6 @@ #include #include -#include #include #include diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index 7f44588cb6e7..69c92876f7fd 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c @@ -85,9 +85,9 @@ static const char StripVersion[] = "1.3A-STUART.CHESHIRE"; #include #include #include +#include #include #include -#include # include #include diff --git a/drivers/net/wireless/wavelan.p.h b/drivers/net/wireless/wavelan.p.h index 24e66a8c2de1..475add67f5bf 100644 --- a/drivers/net/wireless/wavelan.p.h +++ b/drivers/net/wireless/wavelan.p.h @@ -377,8 +377,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h index 381876f542a7..0c18af262494 100644 --- a/drivers/net/wireless/wavelan_cs.p.h +++ b/drivers/net/wireless/wavelan_cs.p.h @@ -428,10 +428,10 @@ #include #include #include +#include #include #include #include -#include #include #include diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 53fb0e88235c..9c2d0752ab90 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -124,10 +124,10 @@ static int gx_fix; #include #include #include +#include #include #include /* Processor type for cache alignment. */ #include -#include #include /* These identify the driver base version and may not be removed. */ diff --git a/drivers/net/znet.c b/drivers/net/znet.c index 9ebd5ea34b88..d26121fa61df 100644 --- a/drivers/net/znet.c +++ b/drivers/net/znet.c @@ -98,9 +98,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index fd404eee5c6f..56ced25d993c 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c @@ -48,9 +48,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c index 0bb9017d0b77..a651309eb84f 100644 --- a/drivers/pcmcia/tcic.c +++ b/drivers/pcmcia/tcic.c @@ -45,9 +45,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index 6a1cb3f86be9..ba0348a5fe06 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -65,7 +66,6 @@ #include #include #include -#include #include #include diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index e95272f1a03e..16e8e69afb10 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -58,7 +59,6 @@ #include #include -#include #include #include "iucv.h" diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 063430d3f2bc..56f0923c3219 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h @@ -15,7 +15,8 @@ #include -#include +#include + #include #include #include diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c index 1ff81bec8741..db4c1c2b799c 100644 --- a/drivers/sbus/char/aurora.c +++ b/drivers/sbus/char/aurora.c @@ -60,12 +60,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c index c407e8643bab..c685d546f838 100644 --- a/drivers/scsi/NCR53c406a.c +++ b/drivers/scsi/NCR53c406a.c @@ -46,9 +46,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c index e5e86962f0d1..24dd0b890dd2 100644 --- a/drivers/scsi/arm/acornscsi.c +++ b/drivers/scsi/arm/acornscsi.c @@ -142,8 +142,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index c3d8bc82eb74..af8adb629b33 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -91,6 +91,7 @@ #include #include #include +#include #include #include @@ -99,7 +100,6 @@ #include #include #include -#include #include "scsi.h" #include diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c index cb0a05d56722..3d0a0f2f7f89 100644 --- a/drivers/scsi/ultrastor.c +++ b/drivers/scsi/ultrastor.c @@ -137,9 +137,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 6dd522466d34..299c2bcea221 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c @@ -34,12 +34,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 2d69c47e61db..ef536ae16861 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -24,8 +24,8 @@ #include #include #include +#include -#include #include #include diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index efa91660adcd..5c8f1fbd5040 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -25,8 +25,8 @@ #include #include #include +#include -#include #include #include diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c index c15c8a0aac58..df71e2370f97 100644 --- a/drivers/serial/icom.c +++ b/drivers/serial/icom.c @@ -54,13 +54,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include "icom.h" diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index 7f1b9ee7e03f..46bcd19f2c45 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c @@ -34,13 +34,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 72586594be4c..bda0c8088fac 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -53,11 +53,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index b44e820a6d8b..ad5b776d779b 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -41,6 +41,7 @@ #include #include #include +#include #ifdef CONFIG_CPU_FREQ #include @@ -51,7 +52,6 @@ #include #include #include -#include #include diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c index c5befc9af125..74aea012129c 100644 --- a/drivers/tc/zs.c +++ b/drivers/tc/zs.c @@ -55,6 +55,7 @@ #include #include #include +#include #ifdef CONFIG_SERIAL_CONSOLE #include #endif @@ -63,7 +64,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 95dce5995859..b9f57d391a34 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -51,8 +51,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c index 920fbd6608e5..decd7ab1c7fe 100644 --- a/drivers/usb/net/catc.c +++ b/drivers/usb/net/catc.c @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #undef DEBUG diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c index c10bc4bcd383..6d70b40d3fa5 100644 --- a/drivers/zorro/zorro.c +++ b/drivers/zorro/zorro.c @@ -15,8 +15,8 @@ #include #include #include +#include #include -#include #include #include "zorro.h" diff --git a/fs/adfs/super.c b/fs/adfs/super.c index 87e8694509f7..243963228d10 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c @@ -19,8 +19,8 @@ #include #include #include +#include -#include #include #include diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index a50096dd1595..579e432794a8 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include "autofs_i.h" #include diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 3b8e34a7aeb1..72f579c47ca8 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include "autofs_i.h" #include diff --git a/fs/buffer.c b/fs/buffer.c index 2a75b3f9efe4..d4027fca46bc 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include static int fsync_buffers_list(spinlock_t *lock, struct list_head *list); static void invalidate_bh_lrus(void); diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c index fd98626ba280..5b71f47e27dd 100644 --- a/fs/coda/sysctl.c +++ b/fs/coda/sysctl.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/fs/devfs/base.c b/fs/devfs/base.c index 65e299a2d97e..22e3cf0852aa 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -677,13 +677,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include #define DEVFS_VERSION "2004-01-31" diff --git a/fs/devfs/util.c b/fs/devfs/util.c index 06a2d827e3e5..db06d388c9ac 100644 --- a/fs/devfs/util.c +++ b/fs/devfs/util.c @@ -71,7 +71,7 @@ #include #include #include -#include +#include int devfs_register_tape(const char *name) { diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 7d6a12f66a6f..b11ab1a9ceee 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index a3ca0238635a..e6bcf5fac48d 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c @@ -22,8 +22,8 @@ #include #include #include +#include -#include #include #include "xattr.h" diff --git a/fs/file.c b/fs/file.c index d40c4028fab2..862a89c3dffe 100644 --- a/fs/file.c +++ b/fs/file.c @@ -12,8 +12,7 @@ #include #include #include - -#include +#include /* diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h index 5496bfb149cf..2357d95c2a90 100644 --- a/fs/jfs/jfs_incore.h +++ b/fs/jfs/jfs_incore.h @@ -21,7 +21,7 @@ #include #include -#include +#include #include "jfs_types.h" #include "jfs_xtree.h" #include "jfs_dtree.h" diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c index daae633cc43d..4a4a74326959 100644 --- a/fs/minix/bitmap.c +++ b/fs/minix/bitmap.c @@ -14,7 +14,7 @@ #include "minix.h" #include #include -#include +#include static int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 }; diff --git a/fs/partitions/devfs.c b/fs/partitions/devfs.c index 9b4d03742c87..87f50444fd39 100644 --- a/fs/partitions/devfs.c +++ b/fs/partitions/devfs.c @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 72febc00fa3b..e0e72ec5b978 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -18,8 +18,8 @@ #include #include #include +#include #include -#include static ssize_t proc_file_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos); diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c index 93cbcbaf6f0c..e4e2f6b5e9c1 100644 --- a/fs/proc/proc_tty.c +++ b/fs/proc/proc_tty.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include static int tty_ldiscs_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data); diff --git a/fs/proc/root.c b/fs/proc/root.c index 76779d4e5a75..aef148f099a2 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver; diff --git a/fs/qnx4/bitmap.c b/fs/qnx4/bitmap.c index 72327856f893..ea634dc47b92 100644 --- a/fs/qnx4/bitmap.c +++ b/fs/qnx4/bitmap.c @@ -21,8 +21,7 @@ #include #include #include - -#include +#include int qnx4_new_block(struct super_block *sb) { diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index 235418f35f65..cddb733d20fb 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include "udf_i.h" #include "udf_sb.h" diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 9195c9dfa803..997640c99c7d 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include "swab.h" diff --git a/fs/ufs/cylinder.c b/fs/ufs/cylinder.c index 105a695aad8f..14abb8b835f7 100644 --- a/fs/ufs/cylinder.c +++ b/fs/ufs/cylinder.c @@ -13,8 +13,8 @@ #include #include #include +#include -#include #include #include "swab.h" diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index 767cb8fbbebf..ed6e546fc4fb 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include "swab.h" diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 4ff38a0ab44a..7bcd4fc8d651 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -66,10 +66,10 @@ #include #include +#include #include -#include #include #include diff --git a/include/linux/idr.h b/include/linux/idr.h index 1b0c1e6d1e2d..ca3b7e462576 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h @@ -9,7 +9,7 @@ * tables. */ #include -#include +#include #if BITS_PER_LONG == 32 # define IDR_BITS 5 diff --git a/include/linux/mtd/gen_probe.h b/include/linux/mtd/gen_probe.h index 2d66b33f805d..f6208098660c 100644 --- a/include/linux/mtd/gen_probe.h +++ b/include/linux/mtd/gen_probe.h @@ -10,7 +10,7 @@ #include #include #include -#include +#include struct chip_probe { char *name; diff --git a/include/net/pkt_act.h b/include/net/pkt_act.h index e7e7da355012..7c30074c4a6f 100644 --- a/include/net/pkt_act.h +++ b/include/net/pkt_act.h @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index 1b16bfc7d1ee..80cac1cd0859 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/lib/bitmap.c b/lib/bitmap.c index 8ffd202dcdd6..f7414e7fd046 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include /* diff --git a/net/core/dev.c b/net/core/dev.c index 5ab736ff0087..88fffb4be34b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -74,7 +74,7 @@ #include #include -#include +#include #include #include #include diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index e8ce25b759ee..db098ff3cd6a 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/core/link_watch.c b/net/core/link_watch.c index 6dd61ea39b2d..0a84b0d8db74 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 1d1c5451f303..6cd292a83719 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -74,8 +74,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index fc31ae1209d1..03890eeb7fc4 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -40,10 +40,10 @@ #include #include #include +#include #include #include -#include static struct proto_ops econet_ops; static struct hlist_head econet_sklist; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 19eb795a1140..bda63766b6ab 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -31,7 +31,7 @@ #include #include -#include +#include #include #include #include diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index f13e797c32e8..4ccd02f535f7 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c index 8aa5b76f4653..21e11b49d742 100644 --- a/net/ipv4/fib_hash.c +++ b/net/ipv4/fib_hash.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index ee19a7e7a881..e4b3af075657 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index e2a772d3bc4c..ec1f08872f1d 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 455cc0e77549..fd023db82df9 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -65,7 +65,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c index b849ecd541f5..fbd7bf12fb44 100644 --- a/net/irda/irlan/irlan_client.c +++ b/net/irda/irlan/irlan_client.c @@ -33,10 +33,10 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c index e6599074e8af..032ab40f913a 100644 --- a/net/irda/irlan/irlan_common.c +++ b/net/irda/irlan/irlan_common.c @@ -37,9 +37,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/net/irda/irlan/irlan_provider.c b/net/irda/irlan/irlan_provider.c index abf11e4a1bbc..2793c54f3462 100644 --- a/net/irda/irlan/irlan_provider.c +++ b/net/irda/irlan/irlan_provider.c @@ -33,9 +33,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/net/netlink/netlink_dev.c b/net/netlink/netlink_dev.c index 72059f182a40..59f53de4b86b 100644 --- a/net/netlink/netlink_dev.c +++ b/net/netlink/netlink_dev.c @@ -28,8 +28,8 @@ #include #include #include +#include -#include #include #include diff --git a/net/sched/act_api.c b/net/sched/act_api.c index b189f5a28b39..a1243f0c062e 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include #include diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 71c85ad84ec8..b66754d04cdc 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include #include diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index 3ef250827a59..4d8438a59e1f 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index c2165492a3c3..0762c74ae574 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/sched/cls_rsvp.c b/net/sched/cls_rsvp.c index 05a937b59032..69a56e921171 100644 --- a/net/sched/cls_rsvp.c +++ b/net/sched/cls_rsvp.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/sched/cls_rsvp6.c b/net/sched/cls_rsvp6.c index 85ed7b400bb4..9a0dac539f78 100644 --- a/net/sched/cls_rsvp6.c +++ b/net/sched/cls_rsvp6.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index bfe785eb0f57..372e36efe54c 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -31,7 +31,7 @@ #include #include -#include +#include #include #include #include diff --git a/net/sched/estimator.c b/net/sched/estimator.c index 17eb0798bd31..f39a5187a75c 100644 --- a/net/sched/estimator.c +++ b/net/sched/estimator.c @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include #include diff --git a/net/sched/gact.c b/net/sched/gact.c index 5607f5e8cd83..b1d4addd956a 100644 --- a/net/sched/gact.c +++ b/net/sched/gact.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include #include diff --git a/net/sched/police.c b/net/sched/police.c index 12bd44006537..cb30e8ea9fef 100644 --- a/net/sched/police.c +++ b/net/sched/police.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include #include diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 5da7b7312642..7818886af89d 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -42,7 +43,6 @@ #include #include #include -#include static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, u32 clid, struct Qdisc *old, struct Qdisc *new); diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 2ae73826d6cf..1a73822c8a93 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c index b089924177f8..06acf4d7320d 100644 --- a/net/sched/sch_fifo.c +++ b/net/sched/sch_fifo.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 2516dd92a0f1..c91c4e4962a0 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include #include diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 375c6c2fb996..aaf611899b25 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 61c8fa4db608..6f0fdc77fed2 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index d29df1cabf59..72fd04a6ae78 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index 6961f081170f..2c8bf5e3ed04 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index e98f79bdb435..6be9a7779a3f 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index ac668b08ebe9..160786fc3351 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index a1df30471451..9f3699d2ccbe 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index dd169094aa2e..f358692716cc 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 85c825b8ad00..67bccddaa383 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -27,8 +27,8 @@ #include #include #include +#include #include -#include #include #include #include -- cgit v1.2.3 From 6902800445f4bfd224e82c7c3df74e48e925c001 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Tue, 19 Oct 2004 18:40:03 -0700 Subject: [PATCH] Remove redundant AND from swp_type() There is a useless AND in swp_type() function. We just shifted right SWP_TYPE_SHIFT() bits the value from the swp_entry_t, and then we AND it with "(1 << 5) - 1" (which is a mask corresponding to the number of bits used by "type"). Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/swapops.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/swapops.h b/include/linux/swapops.h index 0cfc704d0565..d4c7db35e708 100644 --- a/include/linux/swapops.h +++ b/include/linux/swapops.h @@ -30,8 +30,7 @@ static inline swp_entry_t swp_entry(unsigned long type, pgoff_t offset) */ static inline unsigned swp_type(swp_entry_t entry) { - return (entry.val >> SWP_TYPE_SHIFT(entry)) & - ((1 << MAX_SWAPFILES_SHIFT) - 1); + return (entry.val >> SWP_TYPE_SHIFT(entry)); } /* -- cgit v1.2.3 From 3fe5f54e696e7af4e38fbb7ba6079dcc22875bce Mon Sep 17 00:00:00 2001 From: Manfred Spraul Date: Tue, 19 Oct 2004 18:40:18 -0700 Subject: [PATCH] slab: reduce fragmentation due to kmem_cache_alloc_node Attached is a patch that fixes the fragmentation that Badri noticed with kmem_cache_alloc_node. kmem_cache_alloc_node tries to allocate memory from a given node. The current implementation contains two bugs: - the node aware code was used even for !CONFIG_NUMA systems. Fix: inline function that redefines kmem_cache_alloc_node as kmem_cache_alloc for !CONFIG_NUMA. - the code always allocated a new slab for each new allocation. This caused severe fragmentation. Fix: walk the slabp lists and search for a matching page instead of allocating a new page. - the patch also adds a new statistics field for node-local allocs. They should be rare - the codepath is quite slow, especially compared to the normal kmem_cache_alloc. Signed-Off-By: Manfred Spraul Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/slab.h | 7 ++++ mm/slab.c | 111 +++++++++++++++++++++++++++++---------------------- 2 files changed, 71 insertions(+), 47 deletions(-) (limited to 'include/linux') diff --git a/include/linux/slab.h b/include/linux/slab.h index e51014cb24a0..7c81a7863b99 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -61,7 +61,14 @@ extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned lo extern int kmem_cache_destroy(kmem_cache_t *); extern int kmem_cache_shrink(kmem_cache_t *); extern void *kmem_cache_alloc(kmem_cache_t *, int); +#ifdef CONFIG_NUMA extern void *kmem_cache_alloc_node(kmem_cache_t *, int); +#else +static inline void *kmem_cache_alloc_node(kmem_cache_t *cachep, int node) +{ + return kmem_cache_alloc(cachep, GFP_KERNEL); +} +#endif extern void kmem_cache_free(kmem_cache_t *, void *); extern unsigned int kmem_cache_size(kmem_cache_t *); diff --git a/mm/slab.c b/mm/slab.c index 3b00d4499b3e..958d22d78383 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -327,6 +327,7 @@ struct kmem_cache_s { unsigned long reaped; unsigned long errors; unsigned long max_freeable; + unsigned long node_allocs; atomic_t allochit; atomic_t allocmiss; atomic_t freehit; @@ -361,6 +362,7 @@ struct kmem_cache_s { (x)->high_mark = (x)->num_active; \ } while (0) #define STATS_INC_ERR(x) ((x)->errors++) +#define STATS_INC_NODEALLOCS(x) ((x)->node_allocs++) #define STATS_SET_FREEABLE(x, i) \ do { if ((x)->max_freeable < i) \ (x)->max_freeable = i; \ @@ -378,6 +380,7 @@ struct kmem_cache_s { #define STATS_INC_REAPED(x) do { } while (0) #define STATS_SET_HIGH(x) do { } while (0) #define STATS_INC_ERR(x) do { } while (0) +#define STATS_INC_NODEALLOCS(x) do { } while (0) #define STATS_SET_FREEABLE(x, i) \ do { } while (0) @@ -1747,7 +1750,7 @@ static void set_slab_attr(kmem_cache_t *cachep, struct slab *slabp, void *objp) * Grow (by 1) the number of slabs within a cache. This is called by * kmem_cache_alloc() when there are no active objs left in a cache. */ -static int cache_grow (kmem_cache_t * cachep, int flags) +static int cache_grow (kmem_cache_t * cachep, int flags, int nodeid) { struct slab *slabp; void *objp; @@ -1798,7 +1801,7 @@ static int cache_grow (kmem_cache_t * cachep, int flags) /* Get mem for the objs. */ - if (!(objp = kmem_getpages(cachep, flags, -1))) + if (!(objp = kmem_getpages(cachep, flags, nodeid))) goto failed; /* Get slab management. */ @@ -2032,7 +2035,7 @@ alloc_done: if (unlikely(!ac->avail)) { int x; - x = cache_grow(cachep, flags); + x = cache_grow(cachep, flags, -1); // cache_grow can reenable interrupts, then ac could change. ac = ac_data(cachep); @@ -2313,6 +2316,7 @@ out: return 0; } +#ifdef CONFIG_NUMA /** * kmem_cache_alloc_node - Allocate an object on the specified node * @cachep: The cache to allocate from. @@ -2325,69 +2329,80 @@ out: */ void *kmem_cache_alloc_node(kmem_cache_t *cachep, int nodeid) { - size_t offset; + int loop; void *objp; struct slab *slabp; kmem_bufctl_t next; - /* The main algorithms are not node aware, thus we have to cheat: - * We bypass all caches and allocate a new slab. - * The following code is a streamlined copy of cache_grow(). - */ + for (loop = 0;;loop++) { + struct list_head *q; - /* Get colour for the slab, and update the next value. */ - spin_lock_irq(&cachep->spinlock); - offset = cachep->colour_next; - cachep->colour_next++; - if (cachep->colour_next >= cachep->colour) - cachep->colour_next = 0; - offset *= cachep->colour_off; - spin_unlock_irq(&cachep->spinlock); + objp = NULL; + check_irq_on(); + spin_lock_irq(&cachep->spinlock); + /* walk through all partial and empty slab and find one + * from the right node */ + list_for_each(q,&cachep->lists.slabs_partial) { + slabp = list_entry(q, struct slab, list); + + if (page_to_nid(virt_to_page(slabp->s_mem)) == nodeid || + loop > 2) + goto got_slabp; + } + list_for_each(q, &cachep->lists.slabs_free) { + slabp = list_entry(q, struct slab, list); - /* Get mem for the objs. */ - if (!(objp = kmem_getpages(cachep, GFP_KERNEL, nodeid))) - goto failed; + if (page_to_nid(virt_to_page(slabp->s_mem)) == nodeid || + loop > 2) + goto got_slabp; + } + spin_unlock_irq(&cachep->spinlock); - /* Get slab management. */ - if (!(slabp = alloc_slabmgmt(cachep, objp, offset, GFP_KERNEL))) - goto opps1; + local_irq_disable(); + if (!cache_grow(cachep, GFP_KERNEL, nodeid)) { + local_irq_enable(); + return NULL; + } + local_irq_enable(); + } +got_slabp: + /* found one: allocate object */ + check_slabp(cachep, slabp); + check_spinlock_acquired(cachep); - set_slab_attr(cachep, slabp, objp); - cache_init_objs(cachep, slabp, SLAB_CTOR_CONSTRUCTOR); + STATS_INC_ALLOCED(cachep); + STATS_INC_ACTIVE(cachep); + STATS_SET_HIGH(cachep); + STATS_INC_NODEALLOCS(cachep); - /* The first object is ours: */ objp = slabp->s_mem + slabp->free*cachep->objsize; + slabp->inuse++; next = slab_bufctl(slabp)[slabp->free]; #if DEBUG slab_bufctl(slabp)[slabp->free] = BUFCTL_FREE; #endif slabp->free = next; - - /* add the remaining objects into the cache */ - spin_lock_irq(&cachep->spinlock); check_slabp(cachep, slabp); - STATS_INC_GROWN(cachep); - /* Make slab active. */ - if (slabp->free == BUFCTL_END) { - list_add_tail(&slabp->list, &(list3_data(cachep)->slabs_full)); - } else { - list_add_tail(&slabp->list, - &(list3_data(cachep)->slabs_partial)); - list3_data(cachep)->free_objects += cachep->num-1; - } + + /* move slabp to correct slabp list: */ + list_del(&slabp->list); + if (slabp->free == BUFCTL_END) + list_add(&slabp->list, &cachep->lists.slabs_full); + else + list_add(&slabp->list, &cachep->lists.slabs_partial); + + list3_data(cachep)->free_objects--; spin_unlock_irq(&cachep->spinlock); + objp = cache_alloc_debugcheck_after(cachep, GFP_KERNEL, objp, __builtin_return_address(0)); return objp; -opps1: - kmem_freepages(cachep, objp); -failed: - return NULL; - } EXPORT_SYMBOL(kmem_cache_alloc_node); +#endif + /** * kmalloc - allocate memory * @size: how many bytes of memory are required. @@ -2812,15 +2827,16 @@ static void *s_start(struct seq_file *m, loff_t *pos) * without _too_ many complaints. */ #if STATS - seq_puts(m, "slabinfo - version: 2.0 (statistics)\n"); + seq_puts(m, "slabinfo - version: 2.1 (statistics)\n"); #else - seq_puts(m, "slabinfo - version: 2.0\n"); + seq_puts(m, "slabinfo - version: 2.1\n"); #endif seq_puts(m, "# name "); seq_puts(m, " : tunables "); seq_puts(m, " : slabdata "); #if STATS - seq_puts(m, " : globalstat "); + seq_puts(m, " : globalstat " + " "); seq_puts(m, " : cpustat "); #endif seq_putc(m, '\n'); @@ -2911,10 +2927,11 @@ static int s_show(struct seq_file *m, void *p) unsigned long errors = cachep->errors; unsigned long max_freeable = cachep->max_freeable; unsigned long free_limit = cachep->free_limit; + unsigned long node_allocs = cachep->node_allocs; - seq_printf(m, " : globalstat %7lu %6lu %5lu %4lu %4lu %4lu %4lu", + seq_printf(m, " : globalstat %7lu %6lu %5lu %4lu %4lu %4lu %4lu %4lu", allocs, high, grown, reaped, errors, - max_freeable, free_limit); + max_freeable, free_limit, node_allocs); } /* cpu stats */ { -- cgit v1.2.3 From fc29938dabf736b88f7f2ae3e18efbb01b1fbcb8 Mon Sep 17 00:00:00 2001 From: Ed Schouten Date: Tue, 19 Oct 2004 18:40:45 -0700 Subject: [PATCH] lockd: remove hardcoded maximum NLM cookie length At the moment, the NLM cookie length is fixed to 8 bytes, while 1024 is the theoretical maximum. FreeBSD uses 16 bytes, Mac OS X uses 20 bytes. Therefore we need to make the length dynamic (which I set to 32 bytes). This patch is based on an old patch for Linux 2.4.23-pre9, which I changed to patch properly (also added some stylish NIPQUAD fixes). From: Neil Brown Further lockd tidyups. - NIPQUAD everywhere that is appropriate - use XDR_QUADLEN in more places as appropriate - discard QUADLEN which is a lockd-specific version of XDR_QUADLEN Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/lockd/host.c | 6 +----- fs/lockd/mon.c | 4 +--- fs/lockd/svc4proc.c | 8 ++++---- fs/lockd/svclock.c | 16 +++++++-------- fs/lockd/svcproc.c | 8 ++++---- fs/lockd/xdr.c | 49 ++++++++++++++++++++++++++++++++++++--------- fs/lockd/xdr4.c | 10 ++++----- include/linux/lockd/debug.h | 9 +++++++++ include/linux/lockd/xdr.h | 10 ++++----- 9 files changed, 76 insertions(+), 44 deletions(-) (limited to 'include/linux') diff --git a/fs/lockd/host.c b/fs/lockd/host.c index fc4f414a8c5f..54f25ae2ad64 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c @@ -104,11 +104,7 @@ nlm_lookup_host(int server, struct sockaddr_in *sin, memset(host, 0, sizeof(*host)); addr = sin->sin_addr.s_addr; - sprintf(host->h_name, "%d.%d.%d.%d", - (unsigned char) (ntohl(addr) >> 24), - (unsigned char) (ntohl(addr) >> 16), - (unsigned char) (ntohl(addr) >> 8), - (unsigned char) (ntohl(addr) >> 0)); + sprintf(host->h_name, "%u.%u.%u.%u", NIPQUAD(addr)); host->h_addr = *sin; host->h_addr.sin_port = 0; /* ouch! */ diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index de204b36bc34..a9f08284cf2d 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -140,7 +140,6 @@ static u32 * xdr_encode_common(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) { char buffer[20]; - u32 addr = ntohl(argp->addr); /* * Use the dotted-quad IP address of the remote host as @@ -148,8 +147,7 @@ xdr_encode_common(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) * hostname first for whatever remote hostname it receives, * so this works alright. */ - sprintf(buffer, "%d.%d.%d.%d", (addr>>24) & 0xff, (addr>>16) & 0xff, - (addr>>8) & 0xff, (addr) & 0xff); + sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(argp->addr)); if (!(p = xdr_encode_string(p, buffer)) || !(p = xdr_encode_string(p, system_utsname.nodename))) return ERR_PTR(-EIO); diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index 3afa2659b21d..489670e21769 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c @@ -546,10 +546,10 @@ struct nlm_void { int dummy; }; .pc_ressize = sizeof(struct nlm_##rest), \ .pc_xdrressize = respsize, \ } -#define Ck (1+8) /* cookie */ -#define No (1+1024/4) /* netobj */ -#define St 1 /* status */ -#define Rg 4 /* range (offset + length) */ +#define Ck (1+XDR_QUADLEN(NLM_MAXCOOKIELEN)) /* cookie */ +#define No (1+1024/4) /* netobj */ +#define St 1 /* status */ +#define Rg 4 /* range (offset + length) */ struct svc_procedure nlmsvc_procedures4[] = { PROC(null, void, void, void, void, 1), PROC(test, testargs, testres, args, res, Ck+St+2+No+Rg), diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 80e7cc4d44a2..de3f50afa424 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -112,11 +112,11 @@ nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock, int remove) (long long)lock->fl.fl_end, lock->fl.fl_type); for (head = &nlm_blocked; (block = *head) != 0; head = &block->b_next) { fl = &block->b_call.a_args.lock.fl; - dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%x\n", + dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n", block->b_file, fl->fl_pid, (long long)fl->fl_start, (long long)fl->fl_end, fl->fl_type, - *(unsigned int*)(block->b_call.a_args.cookie.data)); + nlmdbg_cookie2a(&block->b_call.a_args.cookie)); if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) { if (remove) { *head = block->b_next; @@ -584,13 +584,13 @@ nlmsvc_grant_callback(struct rpc_task *task) struct sockaddr_in *peer_addr = RPC_PEERADDR(task->tk_client); dprintk("lockd: GRANT_MSG RPC callback\n"); - dprintk("callback: looking for cookie %x, host (%08x)\n", - *(unsigned int *)(call->a_args.cookie.data), - ntohl(peer_addr->sin_addr.s_addr)); + dprintk("callback: looking for cookie %s, host (%u.%u.%u.%u)\n", + nlmdbg_cookie2a(&call->a_args.cookie), + NIPQUAD(peer_addr->sin_addr.s_addr)); if (!(block = nlmsvc_find_block(&call->a_args.cookie, peer_addr))) { - dprintk("lockd: no block for cookie %x, host (%08x)\n", - *(u32 *)(call->a_args.cookie.data), - ntohl(peer_addr->sin_addr.s_addr)); + dprintk("lockd: no block for cookie %s, host (%u.%u.%u.%u)\n", + nlmdbg_cookie2a(&call->a_args.cookie), + NIPQUAD(peer_addr->sin_addr.s_addr)); return; } diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 3eca6cfdbdd6..757e344cf200 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -571,10 +571,10 @@ struct nlm_void { int dummy; }; .pc_xdrressize = respsize, \ } -#define Ck (1+8) /* cookie */ -#define St 1 /* status */ -#define No (1+1024/4) /* Net Obj */ -#define Rg 2 /* range - offset + size */ +#define Ck (1+XDR_QUADLEN(NLM_MAXCOOKIELEN)) /* cookie */ +#define St 1 /* status */ +#define No (1+1024/4) /* Net Obj */ +#define Rg 2 /* range - offset + size */ struct svc_procedure nlmsvc_procedures[] = { PROC(null, void, void, void, void, 1), diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c index a76c496a5f0d..f01e9c0d2677 100644 --- a/fs/lockd/xdr.c +++ b/fs/lockd/xdr.c @@ -55,16 +55,16 @@ static inline u32 *nlm_decode_cookie(u32 *p, struct nlm_cookie *c) c->len=4; memset(c->data, 0, 4); /* hockeypux brain damage */ } - else if(len<=8) + else if(len<=NLM_MAXCOOKIELEN) { c->len=len; memcpy(c->data, p, len); - p+=(len+3)>>2; + p+=XDR_QUADLEN(len); } else { printk(KERN_NOTICE - "lockd: bad cookie size %d (only cookies under 8 bytes are supported.)\n", len); + "lockd: bad cookie size %d (only cookies under %d bytes are supported.)\n", len, NLM_MAXCOOKIELEN); return NULL; } return p; @@ -75,7 +75,7 @@ nlm_encode_cookie(u32 *p, struct nlm_cookie *c) { *p++ = htonl(c->len); memcpy(p, c->data, c->len); - p+=(c->len+3)>>2; + p+=XDR_QUADLEN(c->len); return p; } @@ -86,7 +86,7 @@ nlm_decode_fh(u32 *p, struct nfs_fh *f) if ((len = ntohl(*p++)) != NFS2_FHSIZE) { printk(KERN_NOTICE - "lockd: bad fhandle size %x (should be %d)\n", + "lockd: bad fhandle size %d (should be %d)\n", len, NFS2_FHSIZE); return NULL; } @@ -512,11 +512,11 @@ nlmclt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) * Buffer requirements for NLM */ #define NLM_void_sz 0 -#define NLM_cookie_sz 3 /* 1 len , 2 data */ -#define NLM_caller_sz 1+QUADLEN(sizeof(system_utsname.nodename)) -#define NLM_netobj_sz 1+QUADLEN(XDR_MAX_NETOBJ) -/* #define NLM_owner_sz 1+QUADLEN(NLM_MAXOWNER) */ -#define NLM_fhandle_sz 1+QUADLEN(NFS2_FHSIZE) +#define NLM_cookie_sz 1+XDR_QUADLEN(NLM_MAXCOOKIELEN) +#define NLM_caller_sz 1+XDR_QUADLEN(sizeof(system_utsname.nodename)) +#define NLM_netobj_sz 1+XDR_QUADLEN(XDR_MAX_NETOBJ) +/* #define NLM_owner_sz 1+XDR_QUADLEN(NLM_MAXOWNER) */ +#define NLM_fhandle_sz 1+XDR_QUADLEN(NFS2_FHSIZE) #define NLM_lock_sz 3+NLM_caller_sz+NLM_netobj_sz+NLM_fhandle_sz #define NLM_holder_sz 4+NLM_netobj_sz @@ -604,3 +604,32 @@ struct rpc_program nlm_program = { .stats = &nlm_stats, }; +#ifdef RPC_DEBUG +const char *nlmdbg_cookie2a(const struct nlm_cookie *cookie) +{ + /* + * We can get away with a static buffer because we're only + * called with BKL held. + */ + static char buf[2*NLM_MAXCOOKIELEN+1]; + int i; + int len = sizeof(buf); + char *p = buf; + + len--; /* allow for trailing \0 */ + if (len < 3) + return "???"; + for (i = 0 ; i < cookie->len ; i++) { + if (len < 2) { + strcpy(p-3, "..."); + break; + } + sprintf(p, "%02x", cookie->data[i]); + p += 2; + len -= 2; + } + *p = '\0'; + + return buf; +} +#endif diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c index 10562d31f073..ae4d6b426c62 100644 --- a/fs/lockd/xdr4.c +++ b/fs/lockd/xdr4.c @@ -56,16 +56,16 @@ nlm4_decode_cookie(u32 *p, struct nlm_cookie *c) c->len=4; memset(c->data, 0, 4); /* hockeypux brain damage */ } - else if(len<=8) + else if(len<=NLM_MAXCOOKIELEN) { c->len=len; memcpy(c->data, p, len); - p+=(len+3)>>2; + p+=XDR_QUADLEN(len); } else { printk(KERN_NOTICE - "lockd: bad cookie size %d (only cookies under 8 bytes are supported.)\n", len); + "lockd: bad cookie size %d (only cookies under %d bytes are supported.)\n", len, NLM_MAXCOOKIELEN); return NULL; } return p; @@ -76,7 +76,7 @@ nlm4_encode_cookie(u32 *p, struct nlm_cookie *c) { *p++ = htonl(c->len); memcpy(p, c->data, c->len); - p+=(c->len+3)>>2; + p+=XDR_QUADLEN(c->len); return p; } @@ -515,7 +515,7 @@ nlm4clt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) * Buffer requirements for NLM */ #define NLM4_void_sz 0 -#define NLM4_cookie_sz 3 /* 1 len , 2 data */ +#define NLM4_cookie_sz 1+XDR_QUADLEN(NLM_MAXCOOKIELEN) #define NLM4_caller_sz 1+XDR_QUADLEN(NLM_MAXSTRLEN) #define NLM4_netobj_sz 1+XDR_QUADLEN(XDR_MAX_NETOBJ) /* #define NLM4_owner_sz 1+XDR_QUADLEN(NLM4_MAXOWNER) */ diff --git a/include/linux/lockd/debug.h b/include/linux/lockd/debug.h index 5b6961d739d4..34b2b7f33c3b 100644 --- a/include/linux/lockd/debug.h +++ b/include/linux/lockd/debug.h @@ -45,4 +45,13 @@ #define NLMDBG_ALL 0x7fff +/* + * Support for printing NLM cookies in dprintk() + */ +#ifdef RPC_DEBUG +struct nlm_cookie; +/* Call this function with the BKL held (it uses a static buffer) */ +extern const char *nlmdbg_cookie2a(const struct nlm_cookie *); +#endif + #endif /* LINUX_LOCKD_DEBUG_H */ diff --git a/include/linux/lockd/xdr.h b/include/linux/lockd/xdr.h index ef14dbd2a67c..d7a5cc4cfa97 100644 --- a/include/linux/lockd/xdr.h +++ b/include/linux/lockd/xdr.h @@ -13,10 +13,9 @@ #include #include +#define NLM_MAXCOOKIELEN 32 #define NLM_MAXSTRLEN 1024 -#define QUADLEN(len) (((len) + 3) >> 2) - #define nlm_granted __constant_htonl(NLM_LCK_GRANTED) #define nlm_lck_denied __constant_htonl(NLM_LCK_DENIED) #define nlm_lck_denied_nolocks __constant_htonl(NLM_LCK_DENIED_NOLOCKS) @@ -33,13 +32,14 @@ struct nlm_lock { }; /* - * NLM cookies. Technically they can be 1K, Nobody uses over 8 bytes - * however. + * NLM cookies. Technically they can be 1K, but Linux only uses 8 bytes. + * FreeBSD uses 16, Apple Mac OS X 10.3 uses 20. Therefore we set it to + * 32 bytes. */ struct nlm_cookie { - unsigned char data[8]; + unsigned char data[NLM_MAXCOOKIELEN]; unsigned int len; }; -- cgit v1.2.3 From 93d435ff3f2af47ac4918b9383cee662a9c6d081 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Tue, 19 Oct 2004 18:42:56 -0700 Subject: [PATCH] reiserfs: support for REISERFS_UNSUPPORTED_OPT notation This patch adds a REISERFS_UNSUPPORTED_OPT flag to denote when a mount option is allowable, but is unsupported in the running configuration. This allows the potential for the set of mount options to be consistent, regardless of what features the kernel is compiled with. Rather than failing the mount, a warning is issued and the mount succeeds. Signed-off-by: Jeff Mahoney Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/super.c | 10 ++++++++-- include/linux/reiserfs_fs_sb.h | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 3e7d7e0845e8..b96aa702660e 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -662,8 +662,14 @@ static int reiserfs_getopt ( struct super_block * s, char ** cur, opt_desc_t * o for (opt = opts; opt->option_name; opt ++) { if (!strncmp (p, opt->option_name, strlen (opt->option_name))) { if (bit_flags) { - *bit_flags &= ~opt->clrmask; - *bit_flags |= opt->setmask; + if (opt->clrmask == (1 << REISERFS_UNSUPPORTED_OPT)) + reiserfs_warning (s, "%s not supported.", p); + else + *bit_flags &= ~opt->clrmask; + if (opt->setmask == (1 << REISERFS_UNSUPPORTED_OPT)) + reiserfs_warning (s, "%s not supported.", p); + else + *bit_flags |= opt->setmask; } break; } diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h index 891418bb525a..ba465f763066 100644 --- a/include/linux/reiserfs_fs_sb.h +++ b/include/linux/reiserfs_fs_sb.h @@ -467,6 +467,7 @@ enum reiserfs_mount_options { REISERFS_TEST2, REISERFS_TEST3, REISERFS_TEST4, + REISERFS_UNSUPPORTED_OPT, }; #define reiserfs_r5_hash(s) (REISERFS_SB(s)->s_mount_opt & (1 << FORCE_R5_HASH)) -- cgit v1.2.3 From 8f8d338eaa6af102c8ba69d9913b9f2cc84db8ba Mon Sep 17 00:00:00 2001 From: "William A. Adamson" Date: Tue, 19 Oct 2004 18:43:24 -0700 Subject: [PATCH] nfs4 lease: add a lock manager copy lock callback The following patches provide an interface to the lease subsystem in the current VFS locking code. NFSv4 delegations and Samba op-locks share most architecture features. The version 4 NFS server delegation implementation should use leases to co-ordinate behavior between local, Samba, and NFS access. The main design points are - Seperate the fcntl interface from the file_lock FL_LEASE processing in fcntl_setlease, creating __setlease() called by fcntl_setlease() - Add new lock_manager callbacks to enable lease properties to be set, leases to be broken, and leases to be cleaned up: with default callbacks preserving the current fcntl_setlease properties. - Add a new interface, setlease() which also calls __setlease(), and remove_lease() for kernel lease managers (e.g. the v4 NFS server) This patch: Add a lock manager copy lock callback to locks_copy_lock() so that nfsd can set lease properties. Signed-off-by: Andy Adamson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/locks.c | 2 ++ include/linux/fs.h | 1 + 2 files changed, 3 insertions(+) (limited to 'include/linux') diff --git a/fs/locks.c b/fs/locks.c index efdea3c64a41..a4db50872a4b 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -228,6 +228,8 @@ void locks_copy_lock(struct file_lock *new, struct file_lock *fl) new->fl_lmops = fl->fl_lmops; if (fl->fl_ops && fl->fl_ops->fl_copy_lock) fl->fl_ops->fl_copy_lock(new, fl); + if (fl->fl_lmops && fl->fl_lmops->fl_copy_lock) + fl->fl_lmops->fl_copy_lock(new, fl); } EXPORT_SYMBOL(locks_copy_lock); diff --git a/include/linux/fs.h b/include/linux/fs.h index 5657f00fedef..e9b3d55ce6d8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -633,6 +633,7 @@ struct file_lock_operations { struct lock_manager_operations { int (*fl_compare_owner)(struct file_lock *, struct file_lock *); void (*fl_notify)(struct file_lock *); /* unblock callback */ + void (*fl_copy_lock)(struct file_lock *, struct file_lock *); }; /* that will die - we need it for nfs_lock_info */ -- cgit v1.2.3 From 6a0ddd1535f56ffb61951ae45fbb0ca45da61754 Mon Sep 17 00:00:00 2001 From: "William A. Adamson" Date: Tue, 19 Oct 2004 18:43:39 -0700 Subject: [PATCH] nfs4 lease: add a lock manager release private callback Add a lock manager release private callback to locks_free_lock() for lock manger lease clean-up. Signed-off-by: Andy Adamson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/locks.c | 7 ++++++- include/linux/fs.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/fs/locks.c b/fs/locks.c index a4db50872a4b..caa9b466cd91 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -173,7 +173,12 @@ static inline void locks_free_lock(struct file_lock *fl) fl->fl_ops->fl_release_private(fl); fl->fl_ops = NULL; } - fl->fl_lmops = NULL; + + if (fl->fl_lmops) { + if (fl->fl_lmops->fl_release_private) + fl->fl_lmops->fl_release_private(fl); + fl->fl_lmops = NULL; + } kmem_cache_free(filelock_cache, fl); } diff --git a/include/linux/fs.h b/include/linux/fs.h index e9b3d55ce6d8..2177ae562927 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -634,6 +634,7 @@ struct lock_manager_operations { int (*fl_compare_owner)(struct file_lock *, struct file_lock *); void (*fl_notify)(struct file_lock *); /* unblock callback */ void (*fl_copy_lock)(struct file_lock *, struct file_lock *); + void (*fl_release_private)(struct file_lock *); }; /* that will die - we need it for nfs_lock_info */ -- cgit v1.2.3 From 67db781f6ef69e017f28ddbb3ffa48fb87a9ec9c Mon Sep 17 00:00:00 2001 From: "William A. Adamson" Date: Tue, 19 Oct 2004 18:43:51 -0700 Subject: [PATCH] nfs4 lease: add a lock manager break callback - Add a lock manager break callback to break_lease() for lock managers to initiate breaking a lease. - Move the break_lease() kill_fasync() call to a default lock manager fl_break callback Signed-off-by: Andy Adamson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/locks.c | 15 ++++++++++++++- include/linux/fs.h | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/fs/locks.c b/fs/locks.c index caa9b466cd91..70a3df0d930d 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -391,6 +391,16 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl, } #endif +/* default lease lock manager operations */ +static void lease_break_callback(struct file_lock *fl) +{ + kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG); +} + +struct lock_manager_operations lease_manager_ops = { + .fl_break = lease_break_callback, +}; + /* Allocate a file_lock initialised to this type of lease */ static int lease_alloc(struct file *filp, int type, struct file_lock **flp) { @@ -1127,7 +1137,10 @@ int __break_lease(struct inode *inode, unsigned int mode) if (fl->fl_type != future) { fl->fl_type = future; fl->fl_break_time = break_time; - kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG); + if (fl->fl_lmops && fl->fl_lmops->fl_break) + fl->fl_lmops->fl_break(fl); + else /* lease must have lmops break callback */ + BUG(); } } diff --git a/include/linux/fs.h b/include/linux/fs.h index 2177ae562927..9e9befdd0289 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -635,6 +635,7 @@ struct lock_manager_operations { void (*fl_notify)(struct file_lock *); /* unblock callback */ void (*fl_copy_lock)(struct file_lock *, struct file_lock *); void (*fl_release_private)(struct file_lock *); + void (*fl_break)(struct file_lock *); }; /* that will die - we need it for nfs_lock_info */ -- cgit v1.2.3 From d744ecf3d4b0ba6f3e13b5ae07087f44d6be6f7b Mon Sep 17 00:00:00 2001 From: "William A. Adamson" Date: Tue, 19 Oct 2004 18:45:03 -0700 Subject: [PATCH] nfs4 lease: export setlease Export setlease(), a direct interface to __setlease() used by nfsd Signed-off-by: Andy Adamson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/locks.c | 33 +++++++++++++++++++++++++++++++++ include/linux/fs.h | 1 + 2 files changed, 34 insertions(+) (limited to 'include/linux') diff --git a/fs/locks.c b/fs/locks.c index 3f296007d48d..43ced9dee14c 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1342,6 +1342,39 @@ out: return error; } + /** + * setlease - sets a lease on an open file + * @filp: file pointer + * @arg: type of lease to obtain + * @lease: file_lock to use + * + * Call this to establish a lease on the file. + * The fl_lmops fl_break function is required by break_lease + */ + +int setlease(struct file *filp, long arg, struct file_lock **lease) +{ + struct dentry *dentry = filp->f_dentry; + struct inode *inode = dentry->d_inode; + int error; + + if ((current->fsuid != inode->i_uid) && !capable(CAP_LEASE)) + return -EACCES; + if (!S_ISREG(inode->i_mode)) + return -EINVAL; + error = security_file_lock(filp, arg); + if (error) + return error; + + lock_kernel(); + error = __setlease(filp, arg, lease); + unlock_kernel(); + + return error; +} + +EXPORT_SYMBOL(setlease); + /** * fcntl_setlease - sets a lease on an open file * @fd: open file descriptor diff --git a/include/linux/fs.h b/include/linux/fs.h index 9e9befdd0289..b6569ec04ff4 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -701,6 +701,7 @@ extern int posix_locks_deadlock(struct file_lock *, struct file_lock *); extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl); extern int __break_lease(struct inode *inode, unsigned int flags); extern void lease_get_mtime(struct inode *, struct timespec *time); +extern int setlease(struct file *, long, struct file_lock **); extern int lock_may_read(struct inode *, loff_t start, unsigned long count); extern int lock_may_write(struct inode *, loff_t start, unsigned long count); extern void steal_locks(fl_owner_t from); -- cgit v1.2.3 From 1cb697f8418561df220a3c68a9ffc68771ee5204 Mon Sep 17 00:00:00 2001 From: "William A. Adamson" Date: Tue, 19 Oct 2004 18:45:19 -0700 Subject: [PATCH] nfs4 lease: export remove_lease Export remove_lease(), an interface to time_out_leases() with an fl_break_time in the past. needed by nfsd Signed-off-by: Andy Adamson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/locks.c | 20 ++++++++++++++++++++ include/linux/fs.h | 1 + 2 files changed, 21 insertions(+) (limited to 'include/linux') diff --git a/fs/locks.c b/fs/locks.c index 43ced9dee14c..fd6e88bb9890 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1090,6 +1090,26 @@ static void time_out_leases(struct inode *inode) } } + /** +* remove_lease - let time_out_leases remove the lease. +* @@file_lock: the lease to remove +*/ +void remove_lease(struct file_lock *fl) +{ + if (!IS_LEASE(fl)) + return; + + lock_kernel(); + + fl->fl_type = F_UNLCK | F_INPROGRESS; + fl->fl_break_time = jiffies - 10; + time_out_leases(fl->fl_file->f_dentry->d_inode); + + unlock_kernel(); +} + +EXPORT_SYMBOL(remove_lease); + /** * __break_lease - revoke all outstanding leases on file * @inode: the inode of the file to return diff --git a/include/linux/fs.h b/include/linux/fs.h index b6569ec04ff4..4a9463c662ed 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -702,6 +702,7 @@ extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl); extern int __break_lease(struct inode *inode, unsigned int flags); extern void lease_get_mtime(struct inode *, struct timespec *time); extern int setlease(struct file *, long, struct file_lock **); +extern void remove_lease(struct file_lock *); extern int lock_may_read(struct inode *, loff_t start, unsigned long count); extern int lock_may_write(struct inode *, loff_t start, unsigned long count); extern void steal_locks(fl_owner_t from); -- cgit v1.2.3 From a9ce970684c1365b6bc9a46e8fb35ccfe1a9928f Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 20 Oct 2004 03:05:52 -0700 Subject: [PATCH] i2o: missing bits from merge A couple of functions got themselves lost. cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/i2o.h | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'include/linux') diff --git a/include/linux/i2o.h b/include/linux/i2o.h index 3481de9c5837..f571709b0443 100644 --- a/include/linux/i2o.h +++ b/include/linux/i2o.h @@ -501,6 +501,45 @@ static inline void i2o_flush_reply(struct i2o_controller *c, u32 m) I2O_REPLY_WRITE32(c, m); }; +/** + * i2o_out_to_virt - Turn an I2O message to a virtual address + * @c: controller + * @m: message engine value + * + * Turn a receive message from an I2O controller bus address into + * a Linux virtual address. The shared page frame is a linear block + * so we simply have to shift the offset. This function does not + * work for sender side messages as they are ioremap objects + * provided by the I2O controller. + */ +static inline struct i2o_message *i2o_msg_out_to_virt(struct i2o_controller *c, + u32 m) +{ + if (unlikely + (m < c->out_queue.phys + || m >= c->out_queue.phys + c->out_queue.len)) + BUG(); + + return c->out_queue.virt + (m - c->out_queue.phys); +}; + +/** + * i2o_msg_in_to_virt - Turn an I2O message to a virtual address + * @c: controller + * @m: message engine value + * + * Turn a send message from an I2O controller bus address into + * a Linux virtual address. The shared page frame is a linear block + * so we simply have to shift the offset. This function does not + * work for receive side messages as they are kmalloc objects + * in a different pool. + */ +static inline struct i2o_message *i2o_msg_in_to_virt(struct i2o_controller *c, + u32 m) +{ + return c->in_queue.virt + m; +}; + /** * i2o_dma_alloc - Allocate DMA memory * @dev: struct device pointer to the PCI device of the I2O controller -- cgit v1.2.3 From 2e879618c240b379990b34d2dda709605a5dc6ae Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 20 Oct 2004 21:08:34 +0200 Subject: [ide] always allocate hwif->sg_table Allocate hwif->sg_table in hwif_init() so it can also be used for PIO. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/arm/icside.c | 27 +-------------------------- drivers/ide/ide-dma.c | 11 ++--------- drivers/ide/ide-probe.c | 10 ++++++++++ drivers/ide/ide.c | 3 +++ drivers/ide/pci/sgiioc4.c | 9 +-------- drivers/ide/ppc/pmac.c | 10 ++-------- include/linux/ide.h | 1 + 7 files changed, 20 insertions(+), 51 deletions(-) (limited to 'include/linux') diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index 330167da7290..a24120ef0c6b 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -206,8 +206,6 @@ static void icside_maskproc(ide_drive_t *drive, int mask) * here, but we rely on the main IDE driver spotting that both * interfaces use the same IRQ, which should guarantee this. */ -#define NR_ENTRIES 256 -#define TABLE_SIZE (NR_ENTRIES * 8) static void icside_build_sglist(ide_drive_t *drive, struct request *rq) { @@ -527,7 +525,7 @@ static int icside_dma_lostirq(ide_drive_t *drive) return 1; } -static int icside_dma_init(ide_hwif_t *hwif) +static void icside_dma_init(ide_hwif_t *hwif) { int autodma = 0; @@ -537,11 +535,6 @@ static int icside_dma_init(ide_hwif_t *hwif) printk(" %s: SG-DMA", hwif->name); - hwif->sg_table = kmalloc(sizeof(struct scatterlist) * NR_ENTRIES, - GFP_KERNEL); - if (!hwif->sg_table) - goto failed; - hwif->atapi_dma = 1; hwif->mwdma_mask = 7; /* MW0..2 */ hwif->swdma_mask = 7; /* SW0..2 */ @@ -569,24 +562,9 @@ static int icside_dma_init(ide_hwif_t *hwif) hwif->drives[1].autodma = hwif->autodma; printk(" capable%s\n", hwif->autodma ? ", auto-enable" : ""); - - return 1; - -failed: - printk(" disabled, unable to allocate DMA table\n"); - return 0; -} - -static void icside_dma_exit(ide_hwif_t *hwif) -{ - if (hwif->sg_table) { - kfree(hwif->sg_table); - hwif->sg_table = NULL; - } } #else #define icside_dma_init(hwif) (0) -#define icside_dma_exit(hwif) do { } while (0) #endif static ide_hwif_t *icside_find_hwif(unsigned long dataport) @@ -811,9 +789,6 @@ static void __devexit icside_remove(struct expansion_card *ec) case ICS_TYPE_V6: /* FIXME: tell IDE to stop using the interface */ - icside_dma_exit(state->hwif[1]); - icside_dma_exit(state->hwif[0]); - if (ec->dma != NO_DMA) free_dma(ec->dma); diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index d041da5674e0..499a8d1a142f 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -810,10 +810,6 @@ int ide_release_dma_engine (ide_hwif_t *hwif) hwif->dmatable_dma); hwif->dmatable_cpu = NULL; } - if (hwif->sg_table) { - kfree(hwif->sg_table); - hwif->sg_table = NULL; - } return 1; } @@ -846,15 +842,12 @@ int ide_allocate_dma_engine (ide_hwif_t *hwif) hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev, PRD_ENTRIES * PRD_BYTES, &hwif->dmatable_dma); - hwif->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES, - GFP_KERNEL); - if ((hwif->dmatable_cpu) && (hwif->sg_table)) + if (hwif->dmatable_cpu) return 0; - printk(KERN_ERR "%s: -- Error, unable to allocate%s%s table(s).\n", + printk(KERN_ERR "%s: -- Error, unable to allocate%s DMA table(s).\n", (hwif->dmatable_cpu == NULL) ? " CPU" : "", - (hwif->sg_table == NULL) ? " SG DMA" : " DMA", hwif->cds->name); ide_release_dma_engine(hwif); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 61c72a700014..f8a9d269a567 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1246,6 +1246,16 @@ static int hwif_init(ide_hwif_t *hwif) if (register_blkdev(hwif->major, hwif->name)) return 0; + if (!hwif->sg_max_nents) + hwif->sg_max_nents = PRD_ENTRIES; + + hwif->sg_table = kmalloc(sizeof(struct scatterlist)*hwif->sg_max_nents, + GFP_KERNEL); + if (!hwif->sg_table) { + printk(KERN_ERR "%s: unable to allocate SG table.\n", hwif->name); + goto out; + } + if (alloc_disks(hwif) < 0) goto out; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 5f0a43527219..0a934d4b25f1 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -712,6 +712,8 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->INSW = tmp_hwif->INSW; hwif->INSL = tmp_hwif->INSL; + hwif->sg_max_nents = tmp_hwif->sg_max_nents; + hwif->mmio = tmp_hwif->mmio; hwif->rqsize = tmp_hwif->rqsize; hwif->no_lba48 = tmp_hwif->no_lba48; @@ -900,6 +902,7 @@ void ide_unregister(unsigned int index) hwif->drives[i].disk = NULL; put_disk(disk); } + kfree(hwif->sg_table); unregister_blkdev(hwif->major, hwif->name); spin_lock_irq(&ide_lock); diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 5187bb1e9af0..4fa129925cc9 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -404,11 +404,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) if (!hwif->dmatable_cpu) goto dma_alloc_failure; - hwif->sg_table = - kmalloc(sizeof (struct scatterlist) * IOC4_PRD_ENTRIES, GFP_KERNEL); - - if (!hwif->sg_table) - goto dma_sgalloc_failure; + hwif->sg_max_nents = IOC4_PRD_ENTRIES; hwif->dma_base2 = (unsigned long) pci_alloc_consistent(hwif->pci_dev, @@ -421,9 +417,6 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) return; dma_base2alloc_failure: - kfree(hwif->sg_table); - -dma_sgalloc_failure: pci_free_consistent(hwif->pci_dev, IOC4_PRD_ENTRIES * IOC4_PRD_BYTES, hwif->dmatable_cpu, hwif->dmatable_dma); diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 11672c2c1131..784080210c90 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -1241,6 +1241,8 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) hwif->noprobe = 0; #endif /* CONFIG_PMAC_PBOOK */ + hwif->sg_max_nents = MAX_DCMDS; + #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC /* has a DBDMA controller channel */ if (pmif->dma_regs) @@ -2064,14 +2066,6 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) return; } - hwif->sg_table = kmalloc(sizeof(struct scatterlist) * MAX_DCMDS, - GFP_KERNEL); - if (hwif->sg_table == NULL) { - pci_free_consistent( hwif->pci_dev, - (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), - pmif->dma_table_cpu, hwif->dmatable_dma); - return; - } hwif->ide_dma_off_quietly = &__ide_dma_off_quietly; hwif->ide_dma_on = &__ide_dma_on; hwif->ide_dma_check = &pmac_ide_dma_check; diff --git a/include/linux/ide.h b/include/linux/ide.h index c05eb8673a4e..2fddaa5f5f42 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -920,6 +920,7 @@ typedef struct hwif_s { dma_addr_t dmatable_dma; /* Scatter-gather list used to build the above */ struct scatterlist *sg_table; + int sg_max_nents; /* Maximum number of entries in it */ int sg_nents; /* Current number of entries in it */ int sg_dma_direction; /* dma transfer direction */ -- cgit v1.2.3 From 680b896870a7c47dc7210424f12367fc5a8663d2 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 20 Oct 2004 22:48:28 +0200 Subject: [ide] sg PIO for taskfile requests Use scatterlists for taskfile based PIO transfers instead of directly walking rq->[bio,cbio] lists. If CONFIG_IDE_TASKFILE_IO is defined this code will be used for fs requests. ide_pio_sector() is based on ata_pio_sector() from libata-core.c so kudos to Jeff. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-disk.c | 7 +-- drivers/ide/ide-io.c | 36 ++++++++++++ drivers/ide/ide-taskfile.c | 144 ++++++++++++++++++++------------------------- include/linux/ide.h | 36 +++--------- 4 files changed, 110 insertions(+), 113 deletions(-) (limited to 'include/linux') diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 70e93aa031cb..f35ab894b070 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -516,6 +516,9 @@ static u8 get_command(ide_drive_t *drive, struct request *rq, ide_task_t *task) dma = 0; } + if (!dma) + ide_init_sg_cmd(drive, rq); + if (rq_data_dir(rq) == READ) { task->command_type = IDE_DRIVE_TASK_IN; if (dma) @@ -779,10 +782,6 @@ ide_startstop_t idedisk_error (ide_drive_t *drive, const char *msg, u8 stat) ide_end_drive_cmd(drive, stat, err); return ide_stopped; } -#ifdef CONFIG_IDE_TASKFILE_IO - /* make rq completion pointers new submission pointers */ - blk_rq_prep_restart(rq); -#endif if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */ diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index d20cd1eb537a..d0458c79c21f 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -674,6 +675,31 @@ ide_startstop_t do_special (ide_drive_t *drive) EXPORT_SYMBOL(do_special); +static void ide_map_sg(ide_drive_t *drive, struct request *rq) +{ + ide_hwif_t *hwif = drive->hwif; + struct scatterlist *sg = hwif->sg_table; + + if ((rq->flags & REQ_DRIVE_TASKFILE) == 0) { + hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); + } else { + sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE); + hwif->sg_nents = 1; + } +} + +void ide_init_sg_cmd(ide_drive_t *drive, struct request *rq) +{ + ide_hwif_t *hwif = drive->hwif; + + hwif->nsect = hwif->nleft = rq->nr_sectors; + hwif->cursg = hwif->cursg_ofs = 0; + + ide_map_sg(drive, rq); +} + +EXPORT_SYMBOL_GPL(ide_init_sg_cmd); + /** * execute_drive_command - issue special drive command * @drive: the drive to issue th command on @@ -697,6 +723,16 @@ ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq) hwif->data_phase = args->data_phase; + switch (hwif->data_phase) { + case TASKFILE_MULTI_OUT: + case TASKFILE_OUT: + case TASKFILE_MULTI_IN: + case TASKFILE_IN: + ide_init_sg_cmd(drive, rq); + default: + break; + } + if (args->tf_out_flags.all != 0) return flagged_taskfile(drive, args); return do_rw_taskfile(drive, args); diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 4a8019475c02..9d70e5c9ff05 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -5,7 +5,7 @@ * Copyright (C) 2000-2002 Andre Hedrick * Copyright (C) 2001-2002 Klaus Smolin * IBM Storage Technology Division - * Copyright (C) 2003 Bartlomiej Zolnierkiewicz + * Copyright (C) 2003-2004 Bartlomiej Zolnierkiewicz * * The big the bad and the ugly. * @@ -253,73 +253,6 @@ ide_startstop_t task_no_data_intr (ide_drive_t *drive) EXPORT_SYMBOL(task_no_data_intr); -static void task_buffer_sectors(ide_drive_t *drive, struct request *rq, - unsigned nsect, unsigned rw) -{ - char *buf = rq->buffer + blk_rq_offset(rq); - - rq->sector += nsect; - rq->current_nr_sectors -= nsect; - rq->nr_sectors -= nsect; - __task_sectors(drive, buf, nsect, rw); -} - -static inline void task_buffer_multi_sectors(ide_drive_t *drive, - struct request *rq, unsigned rw) -{ - unsigned int msect = drive->mult_count, nsect; - - nsect = rq->current_nr_sectors; - if (nsect > msect) - nsect = msect; - - task_buffer_sectors(drive, rq, nsect, rw); -} - -#ifdef CONFIG_IDE_TASKFILE_IO -static void task_sectors(ide_drive_t *drive, struct request *rq, - unsigned nsect, unsigned rw) -{ - if (rq->cbio) { /* fs request */ - rq->errors = 0; - task_bio_sectors(drive, rq, nsect, rw); - } else /* task request */ - task_buffer_sectors(drive, rq, nsect, rw); -} - -static inline void task_bio_multi_sectors(ide_drive_t *drive, - struct request *rq, unsigned rw) -{ - unsigned int nsect, msect = drive->mult_count; - - do { - nsect = rq->current_nr_sectors; - if (nsect > msect) - nsect = msect; - - task_bio_sectors(drive, rq, nsect, rw); - - if (!rq->nr_sectors) - msect = 0; - else - msect -= nsect; - } while (msect); -} - -static void task_multi_sectors(ide_drive_t *drive, - struct request *rq, unsigned rw) -{ - if (rq->cbio) { /* fs request */ - rq->errors = 0; - task_bio_multi_sectors(drive, rq, rw); - } else /* task request */ - task_buffer_multi_sectors(drive, rq, rw); -} -#else -# define task_sectors(d, rq, nsect, rw) task_buffer_sectors(d, rq, nsect, rw) -# define task_multi_sectors(d, rq, rw) task_buffer_multi_sectors(d, rq, rw) -#endif /* CONFIG_IDE_TASKFILE_IO */ - static u8 wait_drive_not_busy(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); @@ -340,16 +273,65 @@ static u8 wait_drive_not_busy(ide_drive_t *drive) return stat; } +static void ide_pio_sector(ide_drive_t *drive, unsigned int write) +{ + ide_hwif_t *hwif = drive->hwif; + struct scatterlist *sg = hwif->sg_table; + struct page *page; +#ifdef CONFIG_HIGHMEM + unsigned long flags; +#endif + u8 *buf; + + page = sg[hwif->cursg].page; +#ifdef CONFIG_HIGHMEM + local_irq_save(flags); +#endif + buf = kmap_atomic(page, KM_BIO_SRC_IRQ) + + sg[hwif->cursg].offset + (hwif->cursg_ofs * SECTOR_SIZE); + + hwif->nleft--; + hwif->cursg_ofs++; + + if ((hwif->cursg_ofs * SECTOR_SIZE) == sg[hwif->cursg].length) { + hwif->cursg++; + hwif->cursg_ofs = 0; + } + + /* do the actual data transfer */ + if (write) + taskfile_output_data(drive, buf, SECTOR_WORDS); + else + taskfile_input_data(drive, buf, SECTOR_WORDS); + + kunmap_atomic(page, KM_BIO_SRC_IRQ); +#ifdef CONFIG_HIGHMEM + local_irq_restore(flags); +#endif +} + +static void ide_pio_multi(ide_drive_t *drive, unsigned int write) +{ + unsigned int nsect; + + nsect = min_t(unsigned int, drive->hwif->nleft, drive->mult_count); + while (nsect--) + ide_pio_sector(drive, write); +} + static inline void ide_pio_datablock(ide_drive_t *drive, struct request *rq, unsigned int write) { + if (rq->bio) /* fs request */ + rq->errors = 0; + switch (drive->hwif->data_phase) { case TASKFILE_MULTI_IN: case TASKFILE_MULTI_OUT: - task_multi_sectors(drive, rq, write); + ide_pio_multi(drive, write); break; default: - task_sectors(drive, rq, 1, write); + ide_pio_sector(drive, write); break; } } @@ -359,18 +341,19 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, const char *s, u8 stat) { if (rq->bio) { - int sectors = rq->hard_nr_sectors - rq->nr_sectors; + ide_hwif_t *hwif = drive->hwif; + int sectors = hwif->nsect - hwif->nleft; - switch (drive->hwif->data_phase) { + switch (hwif->data_phase) { case TASKFILE_IN: - if (rq->nr_sectors) + if (hwif->nleft) break; /* fall through */ case TASKFILE_OUT: sectors--; break; case TASKFILE_MULTI_IN: - if (rq->nr_sectors) + if (hwif->nleft) break; /* fall through */ case TASKFILE_MULTI_OUT: @@ -407,8 +390,9 @@ static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) */ ide_startstop_t task_in_intr (ide_drive_t *drive) { + ide_hwif_t *hwif = drive->hwif; struct request *rq = HWGROUP(drive)->rq; - u8 stat = HWIF(drive)->INB(IDE_STATUS_REG); + u8 stat = hwif->INB(IDE_STATUS_REG); if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { if (stat & (ERR_STAT | DRQ_STAT)) @@ -421,7 +405,7 @@ ide_startstop_t task_in_intr (ide_drive_t *drive) ide_pio_datablock(drive, rq, 0); /* If it was the last datablock check status and finish transfer. */ - if (!rq->nr_sectors) { + if (!hwif->nleft) { stat = wait_drive_not_busy(drive); if (!OK_STAT(stat, 0, BAD_R_STAT)) return task_error(drive, rq, __FUNCTION__, stat); @@ -441,18 +425,18 @@ EXPORT_SYMBOL(task_in_intr); */ ide_startstop_t task_out_intr (ide_drive_t *drive) { + ide_hwif_t *hwif = drive->hwif; struct request *rq = HWGROUP(drive)->rq; - u8 stat; + u8 stat = hwif->INB(IDE_STATUS_REG); - stat = HWIF(drive)->INB(IDE_STATUS_REG); if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat)) return task_error(drive, rq, __FUNCTION__, stat); /* Deal with unexpected ATA data phase. */ - if (((stat & DRQ_STAT) == 0) ^ !rq->nr_sectors) + if (((stat & DRQ_STAT) == 0) ^ !hwif->nleft) return task_error(drive, rq, __FUNCTION__, stat); - if (!rq->nr_sectors) { + if (!hwif->nleft) { task_end_request(drive, rq, stat); return ide_stopped; } diff --git a/include/linux/ide.h b/include/linux/ide.h index 2fddaa5f5f42..d8b6b870b352 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -927,6 +927,11 @@ typedef struct hwif_s { /* data phase of the active command (currently only valid for PIO/DMA) */ int data_phase; + unsigned int nsect; + unsigned int nleft; + unsigned int cursg; + unsigned int cursg_ofs; + int mmio; /* hosts iomio (0) or custom (2) select */ int rqsize; /* max sectors per request */ int irq; /* our irq number */ @@ -1370,35 +1375,6 @@ extern void atapi_output_bytes(ide_drive_t *, void *, u32); extern void taskfile_input_data(ide_drive_t *, void *, u32); extern void taskfile_output_data(ide_drive_t *, void *, u32); -#define IDE_PIO_IN 0 -#define IDE_PIO_OUT 1 - -static inline void __task_sectors(ide_drive_t *drive, char *buf, - unsigned nsect, unsigned rw) -{ - /* - * IRQ can happen instantly after reading/writing - * last sector of the datablock. - */ - if (rw == IDE_PIO_OUT) - taskfile_output_data(drive, buf, nsect * SECTOR_WORDS); - else - taskfile_input_data(drive, buf, nsect * SECTOR_WORDS); -} - -#ifdef CONFIG_IDE_TASKFILE_IO -static inline void task_bio_sectors(ide_drive_t *drive, struct request *rq, - unsigned nsect, unsigned rw) -{ - unsigned long flags; - char *buf = rq_map_buffer(rq, &flags); - - process_that_request_first(rq, nsect); - __task_sectors(drive, buf, nsect, rw); - rq_unmap_buffer(buf, &flags); -} -#endif /* CONFIG_IDE_TASKFILE_IO */ - extern int drive_is_ready(ide_drive_t *); extern int wait_for_ready(ide_drive_t *, int /* timeout */); @@ -1529,6 +1505,8 @@ typedef struct ide_pci_device_s { extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); extern void ide_setup_pci_devices(struct pci_dev *, struct pci_dev *, ide_pci_device_t *); +void ide_init_sg_cmd(ide_drive_t *, struct request *); + #define BAD_DMA_DRIVE 0 #define GOOD_DMA_DRIVE 1 -- cgit v1.2.3 From c1379b8c815a4c13cfdebd886e1aac114152ab34 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 20 Oct 2004 22:52:39 +0200 Subject: [ide] sg PIO for fs requests Convert CONFIG_IDE_TASKFILE_IO=n code to use scatterlists for PIO transfers. Fixes longstanding 'data integrity on error' issue and makes barriers work with PIO. Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/block/biodoc.txt | 3 +- arch/cris/arch-v10/drivers/ide.c | 4 +- drivers/ide/ide-disk.c | 218 ++++++++++----------------------------- drivers/ide/ide-dma.c | 4 +- drivers/ide/ide-io.c | 7 +- drivers/ide/ide-taskfile.c | 18 ++-- drivers/ide/pci/sgiioc4.c | 1 + drivers/ide/ppc/pmac.c | 4 +- include/linux/ide.h | 27 ++--- 9 files changed, 88 insertions(+), 198 deletions(-) (limited to 'include/linux') diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index f24dbcaca492..6dd274d7e1cf 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt @@ -1172,8 +1172,7 @@ PIO drivers (or drivers that need to revert to PIO transfer once in a while (IDE for example)), where the CPU is doing the actual data transfer a virtual mapping is needed. If the driver supports highmem I/O, (Sec 1.1, (ii) ) it needs to use __bio_kmap_atomic and bio_kmap_irq to -temporarily map a bio into the virtual address space. See how IDE handles -this with ide_map_buffer. +temporarily map a bio into the virtual address space. 8. Prior/Related/Impacted patches diff --git a/arch/cris/arch-v10/drivers/ide.c b/arch/cris/arch-v10/drivers/ide.c index cd9c0fa9899f..473e4d133202 100644 --- a/arch/cris/arch-v10/drivers/ide.c +++ b/arch/cris/arch-v10/drivers/ide.c @@ -297,8 +297,10 @@ static int e100_dma_setup(ide_drive_t *drive) } /* set up the Etrax DMA descriptors */ - if (e100_ide_build_dmatable(drive)) + if (e100_ide_build_dmatable(drive)) { + ide_map_sg(drive, rq); return 1; + } return 0; } diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index f35ab894b070..10bd2368f95f 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -128,55 +128,30 @@ static int lba_capacity_is_ok (struct hd_driveid *id) static ide_startstop_t read_intr (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - u32 i = 0, nsect = 0, msect = drive->mult_count; - struct request *rq; - unsigned long flags; + struct request *rq = hwif->hwgroup->rq; u8 stat; - char *to; /* new way for dealing with premature shared PCI interrupts */ if (!OK_STAT(stat=hwif->INB(IDE_STATUS_REG),DATA_READY,BAD_R_STAT)) { if (stat & (ERR_STAT|DRQ_STAT)) { - return DRIVER(drive)->error(drive, "read_intr", stat); + return task_error(drive, rq, __FUNCTION__, stat); } /* no data yet, so wait for another interrupt */ ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); return ide_started; } - -read_next: - rq = HWGROUP(drive)->rq; - if (msect) { - if ((nsect = rq->current_nr_sectors) > msect) - nsect = msect; - msect -= nsect; - } else - nsect = 1; - to = ide_map_buffer(rq, &flags); - taskfile_input_data(drive, to, nsect * SECTOR_WORDS); -#ifdef DEBUG - printk("%s: read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n", - drive->name, rq->sector, rq->sector+nsect-1, - (unsigned long) rq->buffer+(nsect<<9), rq->nr_sectors-nsect); -#endif - ide_unmap_buffer(rq, to, &flags); - rq->sector += nsect; + + if (drive->mult_count) + ide_pio_multi(drive, 0); + else + ide_pio_sector(drive, 0); rq->errors = 0; - i = (rq->nr_sectors -= nsect); - if (((long)(rq->current_nr_sectors -= nsect)) <= 0) - ide_end_request(drive, 1, rq->hard_cur_sectors); - /* - * Another BH Page walker and DATA INTEGRITY Questioned on ERROR. - * If passed back up on multimode read, BAD DATA could be ACKED - * to FILE SYSTEMS above ... - */ - if (i > 0) { - if (msect) - goto read_next; - ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); - return ide_started; + if (!hwif->nleft) { + ide_end_request(drive, 1, hwif->nsect); + return ide_stopped; } - return ide_stopped; + ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); + return ide_started; } /* @@ -187,106 +162,27 @@ static ide_startstop_t write_intr (ide_drive_t *drive) ide_hwgroup_t *hwgroup = HWGROUP(drive); ide_hwif_t *hwif = HWIF(drive); struct request *rq = hwgroup->rq; - u32 i = 0; u8 stat; if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), DRIVE_READY, drive->bad_wstat)) { - printk("%s: write_intr error1: nr_sectors=%ld, stat=0x%02x\n", - drive->name, rq->nr_sectors, stat); + printk("%s: write_intr error1: nr_sectors=%u, stat=0x%02x\n", + drive->name, hwif->nleft, stat); } else { -#ifdef DEBUG - printk("%s: write: sector %ld, buffer=0x%08lx, remaining=%ld\n", - drive->name, rq->sector, (unsigned long) rq->buffer, - rq->nr_sectors-1); -#endif - if ((rq->nr_sectors == 1) ^ ((stat & DRQ_STAT) != 0)) { - rq->sector++; + if ((hwif->nleft == 0) ^ ((stat & DRQ_STAT) != 0)) { rq->errors = 0; - i = --rq->nr_sectors; - --rq->current_nr_sectors; - if (((long)rq->current_nr_sectors) <= 0) - ide_end_request(drive, 1, rq->hard_cur_sectors); - if (i > 0) { - unsigned long flags; - char *to = ide_map_buffer(rq, &flags); - taskfile_output_data(drive, to, SECTOR_WORDS); - ide_unmap_buffer(rq, to, &flags); - ide_set_handler(drive, &write_intr, WAIT_CMD, NULL); - return ide_started; + if (!hwif->nleft) { + ide_end_request(drive, 1, hwif->nsect); + return ide_stopped; } - return ide_stopped; + ide_pio_sector(drive, 1); + ide_set_handler(drive, &write_intr, WAIT_CMD, NULL); + return ide_started; } /* the original code did this here (?) */ return ide_stopped; } - return DRIVER(drive)->error(drive, "write_intr", stat); -} - -/* - * ide_multwrite() transfers a block of up to mcount sectors of data - * to a drive as part of a disk multiple-sector write operation. - * - * Note that we may be called from two contexts - __ide_do_rw_disk() context - * and IRQ context. The IRQ can happen any time after we've output the - * full "mcount" number of sectors, so we must make sure we update the - * state _before_ we output the final part of the data! - * - * The update and return to BH is a BLOCK Layer Fakey to get more data - * to satisfy the hardware atomic segment. If the hardware atomic segment - * is shorter or smaller than the BH segment then we should be OKAY. - * This is only valid if we can rewind the rq->current_nr_sectors counter. - */ -static void ide_multwrite(ide_drive_t *drive, unsigned int mcount) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - struct request *rq = &hwgroup->wrq; - - do { - char *buffer; - int nsect = rq->current_nr_sectors; - unsigned long flags; - - if (nsect > mcount) - nsect = mcount; - mcount -= nsect; - buffer = ide_map_buffer(rq, &flags); - - rq->sector += nsect; - rq->nr_sectors -= nsect; - rq->current_nr_sectors -= nsect; - - /* Do we move to the next bh after this? */ - if (!rq->current_nr_sectors) { - struct bio *bio = rq->bio; - - /* - * only move to next bio, when we have processed - * all bvecs in this one. - */ - if (++bio->bi_idx >= bio->bi_vcnt) { - bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments; - bio = bio->bi_next; - } - - /* end early early we ran out of requests */ - if (!bio) { - mcount = 0; - } else { - rq->bio = bio; - rq->nr_cbio_segments = bio_segments(bio); - rq->current_nr_sectors = bio_cur_sectors(bio); - rq->hard_cur_sectors = rq->current_nr_sectors; - } - } - - /* - * Ok, we're all setup for the interrupt - * re-entering us on the last transfer. - */ - taskfile_output_data(drive, buffer, nsect<<7); - ide_unmap_buffer(rq, buffer, &flags); - } while (mcount); + return task_error(drive, rq, __FUNCTION__, stat); } /* @@ -294,42 +190,29 @@ static void ide_multwrite(ide_drive_t *drive, unsigned int mcount) */ static ide_startstop_t multwrite_intr (ide_drive_t *drive) { - ide_hwgroup_t *hwgroup = HWGROUP(drive); ide_hwif_t *hwif = HWIF(drive); - struct request *rq = &hwgroup->wrq; - struct bio *bio = rq->bio; + struct request *rq = hwif->hwgroup->rq; u8 stat; stat = hwif->INB(IDE_STATUS_REG); if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat)) { if (stat & DRQ_STAT) { - /* - * The drive wants data. Remember rq is the copy - * of the request - */ - if (rq->nr_sectors) { - ide_multwrite(drive, drive->mult_count); + /* The drive wants data. */ + if (hwif->nleft) { + ide_pio_multi(drive, 1); ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL); return ide_started; } } else { - /* - * If the copy has all the blocks completed then - * we can end the original request. - */ - if (!rq->nr_sectors) { /* all done? */ - bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments; - rq = hwgroup->rq; - ide_end_request(drive, 1, rq->nr_sectors); + if (!hwif->nleft) { /* all done? */ + ide_end_request(drive, 1, hwif->nsect); return ide_stopped; } } - bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments; /* the original code did this here (?) */ return ide_stopped; } - bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments; - return DRIVER(drive)->error(drive, "multwrite_intr", stat); + return task_error(drive, rq, __FUNCTION__, stat); } /* @@ -352,6 +235,11 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector dma = 0; } + if (!dma) { + ide_init_sg_cmd(drive, rq); + ide_map_sg(drive, rq); + } + if (IDE_CONTROL_REG) hwif->OUTB(drive->ctl, IDE_CONTROL_REG); @@ -435,20 +323,32 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector return ide_started; } /* fallback to PIO */ + ide_init_sg_cmd(drive, rq); } if (rq_data_dir(rq) == READ) { - command = ((drive->mult_count) ? - ((lba48) ? WIN_MULTREAD_EXT : WIN_MULTREAD) : - ((lba48) ? WIN_READ_EXT : WIN_READ)); + + if (drive->mult_count) { + hwif->data_phase = TASKFILE_MULTI_IN; + command = lba48 ? WIN_MULTREAD_EXT : WIN_MULTREAD; + } else { + hwif->data_phase = TASKFILE_IN; + command = lba48 ? WIN_READ_EXT : WIN_READ; + } + ide_execute_command(drive, command, &read_intr, WAIT_CMD, NULL); return ide_started; } else { ide_startstop_t startstop; - command = ((drive->mult_count) ? - ((lba48) ? WIN_MULTWRITE_EXT : WIN_MULTWRITE) : - ((lba48) ? WIN_WRITE_EXT : WIN_WRITE)); + if (drive->mult_count) { + hwif->data_phase = TASKFILE_MULTI_OUT; + command = lba48 ? WIN_MULTWRITE_EXT : WIN_MULTWRITE; + } else { + hwif->data_phase = TASKFILE_OUT; + command = lba48 ? WIN_WRITE_EXT : WIN_WRITE; + } + hwif->OUTB(command, IDE_COMMAND_REG); if (ide_wait_stat(&startstop, drive, DATA_READY, @@ -461,17 +361,11 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector if (!drive->unmask) local_irq_disable(); if (drive->mult_count) { - ide_hwgroup_t *hwgroup = HWGROUP(drive); - - hwgroup->wrq = *rq; /* scratchpad */ ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL); - ide_multwrite(drive, drive->mult_count); + ide_pio_multi(drive, 1); } else { - unsigned long flags; - char *to = ide_map_buffer(rq, &flags); ide_set_handler(drive, &write_intr, WAIT_CMD, NULL); - taskfile_output_data(drive, to, SECTOR_WORDS); - ide_unmap_buffer(rq, to, &flags); + ide_pio_sector(drive, 1); } return ide_started; } @@ -516,8 +410,10 @@ static u8 get_command(ide_drive_t *drive, struct request *rq, ide_task_t *task) dma = 0; } - if (!dma) + if (!dma) { ide_init_sg_cmd(drive, rq); + ide_map_sg(drive, rq); + } if (rq_data_dir(rq) == READ) { task->command_type = IDE_DRIVE_TASK_IN; diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 499a8d1a142f..8157fb812d74 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -610,8 +610,10 @@ int ide_dma_setup(ide_drive_t *drive) reading = 1 << 3; /* fall back to pio! */ - if (!ide_build_dmatable(drive, rq)) + if (!ide_build_dmatable(drive, rq)) { + ide_map_sg(drive, rq); return 1; + } /* PRD table */ hwif->OUTL(hwif->dmatable_dma, hwif->dma_prdtable); diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index d0458c79c21f..5663a6644e11 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -675,7 +675,7 @@ ide_startstop_t do_special (ide_drive_t *drive) EXPORT_SYMBOL(do_special); -static void ide_map_sg(ide_drive_t *drive, struct request *rq) +void ide_map_sg(ide_drive_t *drive, struct request *rq) { ide_hwif_t *hwif = drive->hwif; struct scatterlist *sg = hwif->sg_table; @@ -688,14 +688,14 @@ static void ide_map_sg(ide_drive_t *drive, struct request *rq) } } +EXPORT_SYMBOL_GPL(ide_map_sg); + void ide_init_sg_cmd(ide_drive_t *drive, struct request *rq) { ide_hwif_t *hwif = drive->hwif; hwif->nsect = hwif->nleft = rq->nr_sectors; hwif->cursg = hwif->cursg_ofs = 0; - - ide_map_sg(drive, rq); } EXPORT_SYMBOL_GPL(ide_init_sg_cmd); @@ -729,6 +729,7 @@ ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq) case TASKFILE_MULTI_IN: case TASKFILE_IN: ide_init_sg_cmd(drive, rq); + ide_map_sg(drive, rq); default: break; } diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 9d70e5c9ff05..41dab5656281 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -273,7 +273,7 @@ static u8 wait_drive_not_busy(ide_drive_t *drive) return stat; } -static void ide_pio_sector(ide_drive_t *drive, unsigned int write) +void ide_pio_sector(ide_drive_t *drive, unsigned int write) { ide_hwif_t *hwif = drive->hwif; struct scatterlist *sg = hwif->sg_table; @@ -310,7 +310,9 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write) #endif } -static void ide_pio_multi(ide_drive_t *drive, unsigned int write) +EXPORT_SYMBOL_GPL(ide_pio_sector); + +void ide_pio_multi(ide_drive_t *drive, unsigned int write) { unsigned int nsect; @@ -319,6 +321,8 @@ static void ide_pio_multi(ide_drive_t *drive, unsigned int write) ide_pio_sector(drive, write); } +EXPORT_SYMBOL_GPL(ide_pio_multi); + static inline void ide_pio_datablock(ide_drive_t *drive, struct request *rq, unsigned int write) { @@ -336,9 +340,8 @@ static inline void ide_pio_datablock(ide_drive_t *drive, struct request *rq, } } -#ifdef CONFIG_IDE_TASKFILE_IO -static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, - const char *s, u8 stat) +ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, + const char *s, u8 stat) { if (rq->bio) { ide_hwif_t *hwif = drive->hwif; @@ -367,9 +370,8 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, } return drive->driver->error(drive, s, stat); } -#else -# define task_error(d, rq, s, stat) drive->driver->error(d, s, stat) -#endif + +EXPORT_SYMBOL_GPL(task_error); static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) { diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 4fa129925cc9..9edeea2f4c5b 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -577,6 +577,7 @@ static int sgiioc4_ide_dma_setup(ide_drive_t *drive) if (!(count = sgiioc4_build_dma_table(drive, rq, ddir))) { /* try PIO instead of DMA */ + ide_map_sg(drive, rq); return 1; } diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 784080210c90..33a169041770 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -1885,8 +1885,10 @@ pmac_ide_dma_setup(ide_drive_t *drive) return 1; ata4 = (pmif->kind == controller_kl_ata4); - if (!pmac_ide_build_dmatable(drive, rq)) + if (!pmac_ide_build_dmatable(drive, rq)) { + ide_map_sg(drive, rq); return 1; + } /* Apple adds 60ns to wrDataSetup on reads */ if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) { diff --git a/include/linux/ide.h b/include/linux/ide.h index d8b6b870b352..a5482c0bcd0b 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -789,27 +789,6 @@ typedef struct ide_drive_s { struct gendisk *disk; } ide_drive_t; -/* - * mapping stuff, prepare for highmem... - * - * temporarily mapping a (possible) highmem bio for PIO transfer - */ -#ifndef CONFIG_IDE_TASKFILE_IO - -#define ide_rq_offset(rq) \ - (((rq)->hard_cur_sectors - (rq)->current_nr_sectors) << 9) - -static inline void *ide_map_buffer(struct request *rq, unsigned long *flags) -{ - return bio_kmap_irq(rq->bio, flags) + ide_rq_offset(rq); -} - -static inline void ide_unmap_buffer(struct request *rq, char *buffer, unsigned long *flags) -{ - bio_kunmap_irq(buffer, flags); -} -#endif /* !CONFIG_IDE_TASKFILE_IO */ - #define IDE_CHIPSET_PCI_MASK \ ((1<> (c)) & 1) @@ -1375,6 +1354,11 @@ extern void atapi_output_bytes(ide_drive_t *, void *, u32); extern void taskfile_input_data(ide_drive_t *, void *, u32); extern void taskfile_output_data(ide_drive_t *, void *, u32); +void ide_pio_sector(ide_drive_t *, unsigned int); +void ide_pio_multi(ide_drive_t *, unsigned int); + +ide_startstop_t task_error(ide_drive_t *, struct request *, const char *, u8); + extern int drive_is_ready(ide_drive_t *); extern int wait_for_ready(ide_drive_t *, int /* timeout */); @@ -1505,6 +1489,7 @@ typedef struct ide_pci_device_s { extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); extern void ide_setup_pci_devices(struct pci_dev *, struct pci_dev *, ide_pci_device_t *); +void ide_map_sg(ide_drive_t *, struct request *); void ide_init_sg_cmd(ide_drive_t *, struct request *); #define BAD_DMA_DRIVE 0 -- cgit v1.2.3 From 01b81c2d5b185e19e828c53d284fe5c1b1fb8232 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 20 Oct 2004 23:10:23 +0200 Subject: [ide] unify PIO code Use PIO code from ide-taskfile.c in ide-disk.c so: * drive status is checked after PIO read * request is failed if invalid data phase is detected during PIO write Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-disk.c | 86 ++-------------------------------------------- drivers/ide/ide-taskfile.c | 15 +++----- include/linux/ide.h | 5 --- 3 files changed, 7 insertions(+), 99 deletions(-) (limited to 'include/linux') diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index b08175f6ff51..6dc7a643e78c 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -122,72 +122,6 @@ static int lba_capacity_is_ok (struct hd_driveid *id) #ifndef CONFIG_IDE_TASKFILE_IO -/* - * read_intr() is the handler for disk read/multread interrupts - */ -static ide_startstop_t read_intr (ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct request *rq = hwif->hwgroup->rq; - u8 stat; - - /* new way for dealing with premature shared PCI interrupts */ - if (!OK_STAT(stat=hwif->INB(IDE_STATUS_REG),DATA_READY,BAD_R_STAT)) { - if (stat & (ERR_STAT|DRQ_STAT)) { - return task_error(drive, rq, __FUNCTION__, stat); - } - /* no data yet, so wait for another interrupt */ - ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); - return ide_started; - } - - if (drive->mult_count) - ide_pio_multi(drive, 0); - else - ide_pio_sector(drive, 0); - rq->errors = 0; - if (!hwif->nleft) { - ide_end_request(drive, 1, hwif->nsect); - return ide_stopped; - } - ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); - return ide_started; -} - -/* - * write_intr() is the handler for disk write/multwrite interrupts - */ -static ide_startstop_t write_intr (ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - ide_hwif_t *hwif = HWIF(drive); - struct request *rq = hwgroup->rq; - u8 stat; - - if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), - DRIVE_READY, drive->bad_wstat)) { - printk("%s: write_intr error1: nr_sectors=%u, stat=0x%02x\n", - drive->name, hwif->nleft, stat); - } else { - if ((hwif->nleft == 0) ^ ((stat & DRQ_STAT) != 0)) { - rq->errors = 0; - if (!hwif->nleft) { - ide_end_request(drive, 1, hwif->nsect); - return ide_stopped; - } - if (drive->mult_count) - ide_pio_multi(drive, 1); - else - ide_pio_sector(drive, 1); - ide_set_handler(drive, &write_intr, WAIT_CMD, NULL); - return ide_started; - } - /* the original code did this here (?) */ - return ide_stopped; - } - return task_error(drive, rq, __FUNCTION__, stat); -} - /* * __ide_do_rw_disk() issues READ and WRITE commands to a disk, * using LBA if supported, or CHS otherwise, to address sectors. @@ -309,11 +243,9 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector command = lba48 ? WIN_READ_EXT : WIN_READ; } - ide_execute_command(drive, command, &read_intr, WAIT_CMD, NULL); + ide_execute_command(drive, command, &task_in_intr, WAIT_CMD, NULL); return ide_started; } else { - ide_startstop_t startstop; - if (drive->mult_count) { hwif->data_phase = TASKFILE_MULTI_OUT; command = lba48 ? WIN_MULTWRITE_EXT : WIN_MULTWRITE; @@ -324,21 +256,7 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector hwif->OUTB(command, IDE_COMMAND_REG); - if (ide_wait_stat(&startstop, drive, DATA_READY, - drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing %s\n", - drive->name, - drive->mult_count ? "MULTWRITE" : "WRITE"); - return startstop; - } - if (!drive->unmask) - local_irq_disable(); - ide_set_handler(drive, &write_intr, WAIT_CMD, NULL); - if (drive->mult_count) { - ide_pio_multi(drive, 1); - } else { - ide_pio_sector(drive, 1); - } + pre_task_out_intr(drive, rq); return ide_started; } } diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 41dab5656281..0fae337537a4 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -273,7 +273,7 @@ static u8 wait_drive_not_busy(ide_drive_t *drive) return stat; } -void ide_pio_sector(ide_drive_t *drive, unsigned int write) +static void ide_pio_sector(ide_drive_t *drive, unsigned int write) { ide_hwif_t *hwif = drive->hwif; struct scatterlist *sg = hwif->sg_table; @@ -310,9 +310,7 @@ void ide_pio_sector(ide_drive_t *drive, unsigned int write) #endif } -EXPORT_SYMBOL_GPL(ide_pio_sector); - -void ide_pio_multi(ide_drive_t *drive, unsigned int write) +static void ide_pio_multi(ide_drive_t *drive, unsigned int write) { unsigned int nsect; @@ -321,8 +319,6 @@ void ide_pio_multi(ide_drive_t *drive, unsigned int write) ide_pio_sector(drive, write); } -EXPORT_SYMBOL_GPL(ide_pio_multi); - static inline void ide_pio_datablock(ide_drive_t *drive, struct request *rq, unsigned int write) { @@ -340,8 +336,8 @@ static inline void ide_pio_datablock(ide_drive_t *drive, struct request *rq, } } -ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, - const char *s, u8 stat) +static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, + const char *s, u8 stat) { if (rq->bio) { ide_hwif_t *hwif = drive->hwif; @@ -371,8 +367,6 @@ ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, return drive->driver->error(drive, s, stat); } -EXPORT_SYMBOL_GPL(task_error); - static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) { if (rq->flags & REQ_DRIVE_TASKFILE) { @@ -396,6 +390,7 @@ ide_startstop_t task_in_intr (ide_drive_t *drive) struct request *rq = HWGROUP(drive)->rq; u8 stat = hwif->INB(IDE_STATUS_REG); + /* new way for dealing with premature shared PCI interrupts */ if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { if (stat & (ERR_STAT | DRQ_STAT)) return task_error(drive, rq, __FUNCTION__, stat); diff --git a/include/linux/ide.h b/include/linux/ide.h index a5482c0bcd0b..10d947f64cb2 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1354,11 +1354,6 @@ extern void atapi_output_bytes(ide_drive_t *, void *, u32); extern void taskfile_input_data(ide_drive_t *, void *, u32); extern void taskfile_output_data(ide_drive_t *, void *, u32); -void ide_pio_sector(ide_drive_t *, unsigned int); -void ide_pio_multi(ide_drive_t *, unsigned int); - -ide_startstop_t task_error(ide_drive_t *, struct request *, const char *, u8); - extern int drive_is_ready(ide_drive_t *); extern int wait_for_ready(ide_drive_t *, int /* timeout */); -- cgit v1.2.3 From a962bb7a4d2226dc7eee62e23930ca1cfd04af31 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Wed, 20 Oct 2004 03:16:17 -0700 Subject: [PATCH] if_ppp.h __user annotation annotated ioctl structure Signed-off-by: Linus Torvalds --- include/linux/if_ppp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/if_ppp.h b/include/linux/if_ppp.h index 6ee8b0470b1d..572aff7daa21 100644 --- a/include/linux/if_ppp.h +++ b/include/linux/if_ppp.h @@ -92,7 +92,7 @@ struct npioctl { /* Structure describing a CCP configuration option, for PPPIOCSCOMPRESS */ struct ppp_option_data { - __u8 *ptr; + __u8 __user *ptr; __u32 length; int transmit; }; -- cgit v1.2.3 From 15b5423757a750b2c7efabd77bb6ed8aa6ffb20e Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 21 Oct 2004 00:55:08 +0100 Subject: Shared Reed-Solomon ECC library The attached patch contains a shared Reed-Solomon Library analogous to the shared zlib. (N)AND FLASH is gaining popularity and there are a lot of ASIC/SoC/FPGA controllers around which implement hardware support for Reed-Solomon error correction. As usual they use different implementations (polynomials etc.). So it's obvious to use a shared library for the common tasks of error correction. A short scan through the kernel revealed that at least the ftape driver uses Reed-Solomon error correction. It could be easily converted to use the shared library code. The encoder/decoder code is lifted from the GPL'd userspace RS-library written by Phil Karn. I modified/wrapped it to provide the different functions which we need in the MTD/NAND code. The library is tested in extenso under various MTD/NAND configurations. The lib should be usable for other purposes right out of the box. Adjustment for currently not implemented functionality is an easy task. I'm willing to take the maintainership of the library. Signed-Off-By: Thomas Gleixner Signed-Off-By: David Woodhouse "No objections at all. Just keep the authorship notices." -- Phil Karn --- Documentation/DocBook/Makefile | 2 +- Documentation/DocBook/librs.tmpl | 287 +++++++++++++++++++++++++++++++++ include/linux/rslib.h | 105 ++++++++++++ lib/Kconfig | 18 +++ lib/Makefile | 1 + lib/reed_solomon/Makefile | 6 + lib/reed_solomon/decode_rs.c | 272 +++++++++++++++++++++++++++++++ lib/reed_solomon/encode_rs.c | 54 +++++++ lib/reed_solomon/reed_solomon.c | 335 +++++++++++++++++++++++++++++++++++++++ 9 files changed, 1079 insertions(+), 1 deletion(-) create mode 100644 Documentation/DocBook/librs.tmpl create mode 100644 include/linux/rslib.h create mode 100644 lib/reed_solomon/Makefile create mode 100644 lib/reed_solomon/decode_rs.c create mode 100644 lib/reed_solomon/encode_rs.c create mode 100644 lib/reed_solomon/reed_solomon.c (limited to 'include/linux') diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 9a23eab001d4..4cba5e9e4bbf 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -11,7 +11,7 @@ DOCBOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml \ mousedrivers.sgml deviceiobook.sgml procfs-guide.sgml \ tulip-user.sgml writing_usb_driver.sgml scsidrivers.sgml \ sis900.sgml kernel-api.sgml journal-api.sgml lsm.sgml usb.sgml \ - gadget.sgml libata.sgml + gadget.sgml libata.sgml librs.sgml ### # The build process is as follows (targets): diff --git a/Documentation/DocBook/librs.tmpl b/Documentation/DocBook/librs.tmpl new file mode 100644 index 000000000000..ea94ae848b21 --- /dev/null +++ b/Documentation/DocBook/librs.tmpl @@ -0,0 +1,287 @@ + + + + + Reed-Solomon Library Programming Interface + + + + Thomas + Gleixner + +
+ tglx@linutronix.de +
+
+
+
+ + + 2004 + Thomas Gleixner + + + + + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License version 2 as published by the Free Software Foundation. + + + + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + + For more details see the file COPYING in the source + distribution of Linux. + + +
+ + + + + Introduction + + The generic Reed-Solomon Library provides encoding, decoding + and error correction functions. + + + Reed-Solomon codes are used in communication and storage + applications to ensure data integrity. + + + This documentation is provided for developers who want to utilize + the functions provided by the library. + + + + + Known Bugs And Assumptions + + None. + + + + + Usage + + This chapter provides examples how to use the library. + + + Initializing + + The init function init_rs returns a pointer to a + rs decoder structure, which holds the neccecary + information for encoding, decoding and error correction + with the given polynomial. It either uses an existing + matching decoder or creates a new one. On creation all + the lookup tables for fast en/decoding are created. + The function may take a while, so make sure not to + call it in critical code pathes. + + +/* the Reed Solomon control structure */ +static struct rs_control *rs_decoder; + +/* Symbolsize is 10 (bits) + * Primitve polynomial is x^10+x^3+1 + * first consecutive root is 0 + * primitve element to generate roots = 1 + * generator polinomial degree (number of roots) = 6 + */ +rs_decoder = init_rs (10, 0x409, 0, 1, 6); + + + + Encoding + + The encoder calculates the Reed-Solomon code over + the given data length and stores the result in + the parity buffer. Note that the parity buffer must + be initialized before calling the encoder. + + + The expanded data can be inverted on the fly by + providing a non zero inversion mask. The expanded data is + XOR'ed with the mask. This is used e.g. for FLASH + ECC, where the all 0xFF is inverted to an all 0x00. + The Reed-Solomon code for all 0x00 is all 0x00. The + code is inverted before storing to FLASH so it is 0xFF + too. This prevent's that reading from an erased FLASH + results in ECC errors. + + + The databytes are expanded to the given symbolsize + on the fly. There is no support for encoding continuos + bitstreams with a symbolsize != 8 at the moment. If + it is neccecary it should be not a big deal to implement + such functionality. + + +/* Parity buffer. Size = number of roots */ +uint16_t par[6]; +/* Initialize the parity buffer */ +memset(par, 0, sizeof(par)); +/* Encode 512 byte in data8. Store parity in buffer par */ +encode_rs8 (rs_decoder, data8, 512, par, 0); + + + + Decoding + + The decoder calculates the syndrome over + the given data length and the received parity symbols + and corrects errors in the data. + + + If a syndrome is available from a hardware decoder + then the syndrome calculation is skipped. + + + The correction of the data buffer can be suppressed + by providing a correction pattern buffer and an error + location buffer to the decoder. The decoder stores the + calculated error location and the correction bitmask + in the given buffers. This is useful for hardware + decoders which use a weird bitordering scheme. + + + The databytes are expanded to the given symbolsize + on the fly. There is no support for decoding continuos + bitstreams with a symbolsize != 8 at the moment. If + it is neccecary it should be not a big deal to implement + such functionality. + + + + + Decoding with syndrome calculation, direct data correction + + +/* Parity buffer. Size = number of roots */ +uint16_t par[6]; +uint8_t data[512]; +int numerr; +/* Receive data */ +..... +/* Receive parity */ +..... +/* Decode 512 byte in data8.*/ +numerr = decode_rs8 (rs_decoder, data8, par, 512, NULL, 0, NULL, 0, NULL); + + + + + + Decoding with syndrome given by hardware decoder, direct data correction + + +/* Parity buffer. Size = number of roots */ +uint16_t par[6], syn[6]; +uint8_t data[512]; +int numerr; +/* Receive data */ +..... +/* Receive parity */ +..... +/* Get syndrome from hardware decoder */ +..... +/* Decode 512 byte in data8.*/ +numerr = decode_rs8 (rs_decoder, data8, par, 512, syn, 0, NULL, 0, NULL); + + + + + + Decoding with syndrome given by hardware decoder, no direct data correction. + + + Note: It's not neccecary to give data and recieved parity to the decoder. + + +/* Parity buffer. Size = number of roots */ +uint16_t par[6], syn[6], corr[8]; +uint8_t data[512]; +int numerr, errpos[8]; +/* Receive data */ +..... +/* Receive parity */ +..... +/* Get syndrome from hardware decoder */ +..... +/* Decode 512 byte in data8.*/ +numerr = decode_rs8 (rs_decoder, NULL, NULL, 512, syn, 0, errpos, 0, corr); +for (i = 0; i < numerr; i++) { + do_error_correction_in_your_buffer(errpos[i], corr[i]); +} + + + + + Cleanup + + The function free_rs frees the allocated resources, + if the caller is the last user of the decoder. + + +/* Release resources */ +free_rs(rs_decoder); + + + + + + + Structures + + This chapter contains the autogenerated documentation of the structures which are + used in the Reed-Solomon Library and are relevant for a developer. + +!Iinclude/linux/rslib.h + + + + Public Functions Provided + + This chapter contains the autogenerated documentation of the Reed-Solomon functions + which are exported. + +!Elib/reed_solomon/reed_solomon.c + + + + Credits + + The library code for encoding and decoding was written by Phil Karn. + + + Copyright 2002, Phil Karn, KA9Q + May be used under the terms of the GNU General Public License (GPL) + + + The wrapper functions and interfaces are written by Thomas Gleixner + + + Many users have provided bugfixes, improvements and helping hands for testing. + Thanks a lot. + + + The following people have contributed to this document: + + + Thomas Gleixnertglx@linutronix.de + + +
diff --git a/include/linux/rslib.h b/include/linux/rslib.h new file mode 100644 index 000000000000..980c8f74d8dc --- /dev/null +++ b/include/linux/rslib.h @@ -0,0 +1,105 @@ +/* + * include/linux/rslib.h + * + * Overview: + * Generic Reed Solomon encoder / decoder library + * + * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) + * + * RS code lifted from reed solomon library written by Phil Karn + * Copyright 2002 Phil Karn, KA9Q + * + * $Id: rslib.h,v 1.3 2004/10/05 22:08:22 gleixner Exp $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _RSLIB_H_ +#define _RSLIB_H_ + +#include + +/** + * struct rs_control - rs control structure + * + * @mm: Bits per symbol + * @nn: Symbols per block (= (1<mm = number of bits per symbol + * rs->nn = (2^rs->mm) - 1 + * + * Simple arithmetic modulo would return a wrong result for values + * >= 3 * rs->nn +*/ +static inline int rs_modnn(struct rs_control *rs, int x) +{ + while (x >= rs->nn) { + x -= rs->nn; + x = (x >> rs->mm) + (x & rs->nn); + } + return x; +} + +#endif diff --git a/lib/Kconfig b/lib/Kconfig index 2f25b0cfa9ae..eeb45225248f 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -39,5 +39,23 @@ config ZLIB_INFLATE config ZLIB_DEFLATE tristate +# +# reed solomon support is select'ed if needed +# +config REED_SOLOMON + tristate + +config REED_SOLOMON_ENC8 + boolean + +config REED_SOLOMON_DEC8 + boolean + +config REED_SOLOMON_ENC16 + boolean + +config REED_SOLOMON_DEC16 + boolean + endmenu diff --git a/lib/Makefile b/lib/Makefile index 24bbe1cac5bd..373b170e2c01 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_GENERIC_IOMAP) += iomap.o obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/ obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/ +obj-$(CONFIG_REED_SOLOMON) += reed_solomon/ hostprogs-y := gen_crc32table clean-files := crc32table.h diff --git a/lib/reed_solomon/Makefile b/lib/reed_solomon/Makefile new file mode 100644 index 000000000000..747a2de29346 --- /dev/null +++ b/lib/reed_solomon/Makefile @@ -0,0 +1,6 @@ +# +# This is a modified version of reed solomon lib, +# + +obj-$(CONFIG_REED_SOLOMON) += reed_solomon.o + diff --git a/lib/reed_solomon/decode_rs.c b/lib/reed_solomon/decode_rs.c new file mode 100644 index 000000000000..4bce4fdd4d8c --- /dev/null +++ b/lib/reed_solomon/decode_rs.c @@ -0,0 +1,272 @@ +/* + * lib/reed_solomon/decode_rs.c + * + * Overview: + * Generic Reed Solomon encoder / decoder library + * + * Copyright 2002, Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + * + * Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de) + * + * $Id: decode_rs.c,v 1.5 2004/10/05 22:07:53 gleixner Exp $ + * + */ + +/* Generic data witdh independend code which is included by the + * wrappers. + */ +{ + int deg_lambda, el, deg_omega; + int i, j, r, k, pad; + int nn = rs->nn; + int nroots = rs->nroots; + int fcr = rs->fcr; + int prim = rs->prim; + int iprim = rs->iprim; + uint16_t *alpha_to = rs->alpha_to; + uint16_t *index_of = rs->index_of; + uint16_t u, q, tmp, num1, num2, den, discr_r, syn_error; + /* Err+Eras Locator poly and syndrome poly The maximum value + * of nroots is 8. So the neccecary stacksize will be about + * 220 bytes max. + */ + uint16_t lambda[nroots + 1], syn[nroots]; + uint16_t b[nroots + 1], t[nroots + 1], omega[nroots + 1]; + uint16_t root[nroots], reg[nroots + 1], loc[nroots]; + int count = 0; + uint16_t msk = (uint16_t) rs->nn; + + /* Check length parameter for validity */ + pad = nn - nroots - len; + if (pad < 0 || pad >= nn) + return -ERANGE; + + /* Deos the caller provide the syndrome ? */ + if (s != NULL) + goto decode; + + /* form the syndromes; i.e., evaluate data(x) at roots of + * g(x) */ + for (i = 0; i < nroots; i++) + syn[i] = (((uint16_t) data[0]) ^ invmsk) & msk; + + for (j = 1; j < len; j++) { + for (i = 0; i < nroots; i++) { + if (syn[i] == 0) { + syn[i] = (((uint16_t) data[j]) ^ + invmsk) & msk; + } else { + syn[i] = ((((uint16_t) data[j]) ^ + invmsk) & msk) ^ + alpha_to[rs_modnn(rs, index_of[syn[i]] + + (fcr + i) * prim)]; + } + } + } + + for (j = 0; j < nroots; j++) { + for (i = 0; i < nroots; i++) { + if (syn[i] == 0) { + syn[i] = ((uint16_t) par[j]) & msk; + } else { + syn[i] = (((uint16_t) par[j]) & msk) ^ + alpha_to[rs_modnn(rs, index_of[syn[i]] + + (fcr+i)*prim)]; + } + } + } + s = syn; + + /* Convert syndromes to index form, checking for nonzero condition */ + syn_error = 0; + for (i = 0; i < nroots; i++) { + syn_error |= s[i]; + s[i] = index_of[s[i]]; + } + + if (!syn_error) { + /* if syndrome is zero, data[] is a codeword and there are no + * errors to correct. So return data[] unmodified + */ + count = 0; + goto finish; + } + + decode: + memset(&lambda[1], 0, nroots * sizeof(lambda[0])); + lambda[0] = 1; + + if (no_eras > 0) { + /* Init lambda to be the erasure locator polynomial */ + lambda[1] = alpha_to[rs_modnn(rs, + prim * (nn - 1 - eras_pos[0]))]; + for (i = 1; i < no_eras; i++) { + u = rs_modnn(rs, prim * (nn - 1 - eras_pos[i])); + for (j = i + 1; j > 0; j--) { + tmp = index_of[lambda[j - 1]]; + if (tmp != nn) { + lambda[j] ^= + alpha_to[rs_modnn(rs, u + tmp)]; + } + } + } + } + + for (i = 0; i < nroots + 1; i++) + b[i] = index_of[lambda[i]]; + + /* + * Begin Berlekamp-Massey algorithm to determine error+erasure + * locator polynomial + */ + r = no_eras; + el = no_eras; + while (++r <= nroots) { /* r is the step number */ + /* Compute discrepancy at the r-th step in poly-form */ + discr_r = 0; + for (i = 0; i < r; i++) { + if ((lambda[i] != 0) && (s[r - i - 1] != nn)) { + discr_r ^= + alpha_to[rs_modnn(rs, + index_of[lambda[i]] + + s[r - i - 1])]; + } + } + discr_r = index_of[discr_r]; /* Index form */ + if (discr_r == nn) { + /* 2 lines below: B(x) <-- x*B(x) */ + memmove (&b[1], b, nroots * sizeof (b[0])); + b[0] = nn; + } else { + /* 7 lines below: T(x) <-- lambda(x)-discr_r*x*b(x) */ + t[0] = lambda[0]; + for (i = 0; i < nroots; i++) { + if (b[i] != nn) { + t[i + 1] = lambda[i + 1] ^ + alpha_to[rs_modnn(rs, discr_r + + b[i])]; + } else + t[i + 1] = lambda[i + 1]; + } + if (2 * el <= r + no_eras - 1) { + el = r + no_eras - el; + /* + * 2 lines below: B(x) <-- inv(discr_r) * + * lambda(x) + */ + for (i = 0; i <= nroots; i++) { + b[i] = (lambda[i] == 0) ? nn : + rs_modnn(rs, index_of[lambda[i]] + - discr_r + nn); + } + } else { + /* 2 lines below: B(x) <-- x*B(x) */ + memmove(&b[1], b, nroots * sizeof(b[0])); + b[0] = nn; + } + memcpy(lambda, t, (nroots + 1) * sizeof(t[0])); + } + } + + /* Convert lambda to index form and compute deg(lambda(x)) */ + deg_lambda = 0; + for (i = 0; i < nroots + 1; i++) { + lambda[i] = index_of[lambda[i]]; + if (lambda[i] != nn) + deg_lambda = i; + } + /* Find roots of error+erasure locator polynomial by Chien search */ + memcpy(®[1], &lambda[1], nroots * sizeof(reg[0])); + count = 0; /* Number of roots of lambda(x) */ + for (i = 1, k = iprim - 1; i <= nn; i++, k = rs_modnn(rs, k + iprim)) { + q = 1; /* lambda[0] is always 0 */ + for (j = deg_lambda; j > 0; j--) { + if (reg[j] != nn) { + reg[j] = rs_modnn(rs, reg[j] + j); + q ^= alpha_to[reg[j]]; + } + } + if (q != 0) + continue; /* Not a root */ + /* store root (index-form) and error location number */ + root[count] = i; + loc[count] = k; + /* If we've already found max possible roots, + * abort the search to save time + */ + if (++count == deg_lambda) + break; + } + if (deg_lambda != count) { + /* + * deg(lambda) unequal to number of roots => uncorrectable + * error detected + */ + count = -1; + goto finish; + } + /* + * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo + * x**nroots). in index form. Also find deg(omega). + */ + deg_omega = deg_lambda - 1; + for (i = 0; i <= deg_omega; i++) { + tmp = 0; + for (j = i; j >= 0; j--) { + if ((s[i - j] != nn) && (lambda[j] != nn)) + tmp ^= + alpha_to[rs_modnn(rs, s[i - j] + lambda[j])]; + } + omega[i] = index_of[tmp]; + } + + /* + * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = + * inv(X(l))**(fcr-1) and den = lambda_pr(inv(X(l))) all in poly-form + */ + for (j = count - 1; j >= 0; j--) { + num1 = 0; + for (i = deg_omega; i >= 0; i--) { + if (omega[i] != nn) + num1 ^= alpha_to[rs_modnn(rs, omega[i] + + i * root[j])]; + } + num2 = alpha_to[rs_modnn(rs, root[j] * (fcr - 1) + nn)]; + den = 0; + + /* lambda[i+1] for i even is the formal derivative + * lambda_pr of lambda[i] */ + for (i = min(deg_lambda, nroots - 1) & ~1; i >= 0; i -= 2) { + if (lambda[i + 1] != nn) { + den ^= alpha_to[rs_modnn(rs, lambda[i + 1] + + i * root[j])]; + } + } + /* Apply error to data */ + if (num1 != 0 && loc[j] >= pad) { + uint16_t cor = alpha_to[rs_modnn(rs,index_of[num1] + + index_of[num2] + + nn - index_of[den])]; + /* Store the error correction pattern, if a + * correction buffer is available */ + if (corr) { + corr[j] = cor; + } else { + /* If a data buffer is given and the + * error is inside the message, + * correct it */ + if (data && (loc[j] < (nn - nroots))) + data[loc[j] - pad] ^= cor; + } + } + } + +finish: + if (eras_pos != NULL) { + for (i = 0; i < count; i++) + eras_pos[i] = loc[i] - pad; + } + return count; + +} diff --git a/lib/reed_solomon/encode_rs.c b/lib/reed_solomon/encode_rs.c new file mode 100644 index 000000000000..762c3724e5ad --- /dev/null +++ b/lib/reed_solomon/encode_rs.c @@ -0,0 +1,54 @@ +/* + * lib/reed_solomon/encode_rs.c + * + * Overview: + * Generic Reed Solomon encoder / decoder library + * + * Copyright 2002, Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + * + * Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de) + * + * $Id: encode_rs.c,v 1.3 2004/10/05 22:07:53 gleixner Exp $ + * + */ + +/* Generic data witdh independend code which is included by the + * wrappers. + * int encode_rsX (struct rs_control *rs, uintX_t *data, int len, uintY_t *par) + */ +{ + int i, j, pad; + int nn = rs->nn; + int nroots = rs->nroots; + uint16_t *alpha_to = rs->alpha_to; + uint16_t *index_of = rs->index_of; + uint16_t *genpoly = rs->genpoly; + uint16_t fb; + uint16_t msk = (uint16_t) rs->nn; + + /* Check length parameter for validity */ + pad = nn - nroots - len; + if (pad < 0 || pad >= nn) + return -ERANGE; + + for (i = 0; i < len; i++) { + fb = index_of[((((uint16_t) data[i])^invmsk) & msk) ^ par[0]]; + /* feedback term is non-zero */ + if (fb != nn) { + for (j = 1; j < nroots; j++) { + par[j] ^= alpha_to[rs_modnn(rs, fb + + genpoly[nroots - j])]; + } + } + /* Shift */ + memmove(&par[0], &par[1], sizeof(uint16_t) * (nroots - 1)); + if (fb != nn) { + par[nroots - 1] = alpha_to[rs_modnn(rs, + fb + genpoly[0])]; + } else { + par[nroots - 1] = 0; + } + } + return 0; +} diff --git a/lib/reed_solomon/reed_solomon.c b/lib/reed_solomon/reed_solomon.c new file mode 100644 index 000000000000..87d425929b11 --- /dev/null +++ b/lib/reed_solomon/reed_solomon.c @@ -0,0 +1,335 @@ +/* + * lib/reed_solomon/rslib.c + * + * Overview: + * Generic Reed Solomon encoder / decoder library + * + * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) + * + * Reed Solomon code lifted from reed solomon library written by Phil Karn + * Copyright 2002 Phil Karn, KA9Q + * + * $Id: rslib.c,v 1.4 2004/10/05 22:07:53 gleixner Exp $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Description: + * + * The generic Reed Solomon library provides runtime configurable + * encoding / decoding of RS codes. + * Each user must call init_rs to get a pointer to a rs_control + * structure for the given rs parameters. This structure is either + * generated or a already available matching control structure is used. + * If a structure is generated then the polynominal arrays for + * fast encoding / decoding are built. This can take some time so + * make sure not to call this function from a timecritical path. + * Usually a module / driver should initialize the neccecary + * rs_control structure on module / driver init and release it + * on exit. + * The encoding puts the calculated syndrome into a given syndrom + * buffer. + * The decoding is a two step process. The first step calculates + * the syndrome over the received (data + syndrom) and calls the + * second stage, which does the decoding / error correction itself. + * Many hw encoders provide a syndrom calculation over the received + * data + syndrom and can call the second stage directly. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +/* This list holds all currently allocated rs control structures */ +static LIST_HEAD (rslist); +/* Protection for the list */ +static DECLARE_MUTEX(rslistlock); + +/** + * rs_init - Initialize a Reed-Solomon codec + * + * @symsize: symbol size, bits (1-8) + * @gfpoly: Field generator polynomial coefficients + * @fcr: first root of RS code generator polynomial, index form + * @prim: primitive element to generate polynomial roots + * @nroots: RS code generator polynomial degree (number of roots) + * + * Allocate a control structure and the polynom arrays for faster + * en/decoding. Fill the arrays according to the given parameters + */ +static struct rs_control *rs_init(int symsize, int gfpoly, int fcr, + int prim, int nroots) +{ + struct rs_control *rs; + int i, j, sr, root, iprim; + + /* Allocate the control structure */ + rs = kmalloc(sizeof (struct rs_control), GFP_KERNEL); + if (rs == NULL) + return NULL; + + INIT_LIST_HEAD(&rs->list); + + rs->mm = symsize; + rs->nn = (1 << symsize) - 1; + rs->fcr = fcr; + rs->prim = prim; + rs->nroots = nroots; + rs->gfpoly = gfpoly; + + /* Allocate the arrays */ + rs->alpha_to = kmalloc(sizeof(uint16_t) * (rs->nn + 1), GFP_KERNEL); + if (rs->alpha_to == NULL) + goto errrs; + + rs->index_of = kmalloc(sizeof(uint16_t) * (rs->nn + 1), GFP_KERNEL); + if (rs->index_of == NULL) + goto erralp; + + rs->genpoly = kmalloc(sizeof(uint16_t) * (rs->nroots + 1), GFP_KERNEL); + if(rs->genpoly == NULL) + goto erridx; + + /* Generate Galois field lookup tables */ + rs->index_of[0] = rs->nn; /* log(zero) = -inf */ + rs->alpha_to[rs->nn] = 0; /* alpha**-inf = 0 */ + sr = 1; + for (i = 0; i < rs->nn; i++) { + rs->index_of[sr] = i; + rs->alpha_to[i] = sr; + sr <<= 1; + if (sr & (1 << symsize)) + sr ^= gfpoly; + sr &= rs->nn; + } + /* If it's not primitive, exit */ + if(sr != 1) + goto errpol; + + /* Find prim-th root of 1, used in decoding */ + for(iprim = 1; (iprim % prim) != 0; iprim += rs->nn); + /* prim-th root of 1, index form */ + rs->iprim = iprim / prim; + + /* Form RS code generator polynomial from its roots */ + rs->genpoly[0] = 1; + for (i = 0, root = fcr * prim; i < nroots; i++, root += prim) { + rs->genpoly[i + 1] = 1; + /* Multiply rs->genpoly[] by @**(root + x) */ + for (j = i; j > 0; j--) { + if (rs->genpoly[j] != 0) { + rs->genpoly[j] = rs->genpoly[j -1] ^ + rs->alpha_to[rs_modnn(rs, + rs->index_of[rs->genpoly[j]] + root)]; + } else + rs->genpoly[j] = rs->genpoly[j - 1]; + } + /* rs->genpoly[0] can never be zero */ + rs->genpoly[0] = + rs->alpha_to[rs_modnn(rs, + rs->index_of[rs->genpoly[0]] + root)]; + } + /* convert rs->genpoly[] to index form for quicker encoding */ + for (i = 0; i <= nroots; i++) + rs->genpoly[i] = rs->index_of[rs->genpoly[i]]; + return rs; + + /* Error exit */ +errpol: + kfree(rs->genpoly); +erridx: + kfree(rs->index_of); +erralp: + kfree(rs->alpha_to); +errrs: + kfree(rs); + return NULL; +} + + +/** + * free_rs - Free the rs control structure, if its not longer used + * + * @rs: the control structure which is not longer used by the + * caller + */ +void free_rs(struct rs_control *rs) +{ + down(&rslistlock); + rs->users--; + if(!rs->users) { + list_del(&rs->list); + kfree(rs->alpha_to); + kfree(rs->index_of); + kfree(rs->genpoly); + kfree(rs); + } + up(&rslistlock); +} + +/** + * init_rs - Find a matching or allocate a new rs control structure + * + * @symsize: the symbol size (number of bits) + * @gfpoly: the extended Galois field generator polynomial coefficients, + * with the 0th coefficient in the low order bit. The polynomial + * must be primitive; + * @fcr: the first consecutive root of the rs code generator polynomial + * in index form + * @prim: primitive element to generate polynomial roots + * @nroots: RS code generator polynomial degree (number of roots) + */ +struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, + int nroots) +{ + struct list_head *tmp; + struct rs_control *rs; + + /* Sanity checks */ + if (symsize < 1) + return NULL; + if (fcr < 0 || fcr >= (1<= (1<= (1< 8) + return NULL; + + down(&rslistlock); + + /* Walk through the list and look for a matching entry */ + list_for_each(tmp, &rslist) { + rs = list_entry(tmp, struct rs_control, list); + if (symsize != rs->mm) + continue; + if (gfpoly != rs->gfpoly) + continue; + if (fcr != rs->fcr) + continue; + if (prim != rs->prim) + continue; + if (nroots != rs->nroots) + continue; + /* We have a matching one already */ + rs->users++; + goto out; + } + + /* Create a new one */ + rs = rs_init(symsize, gfpoly, fcr, prim, nroots); + if (rs) { + rs->users = 1; + list_add(&rs->list, &rslist); + } +out: + up(&rslistlock); + return rs; +} + +#ifdef CONFIG_REED_SOLOMON_ENC8 +/** + * encode_rs8 - Calculate the parity for data values (8bit data width) + * + * @rs: the rs control structure + * @data: data field of a given type + * @len: data length + * @par: parity data, must be initialized by caller (usually all 0) + * @invmsk: invert data mask (will be xored on data) + * + * The parity uses a uint16_t data type to enable + * symbol size > 8. The calling code must take care of encoding of the + * syndrome result for storage itself. + */ +int encode_rs8(struct rs_control *rs, uint8_t *data, int len, uint16_t *par, + uint16_t invmsk) +{ +#include "encode_rs.c" +} +EXPORT_SYMBOL_GPL(encode_rs8); +#endif + +#ifdef CONFIG_REED_SOLOMON_DEC8 +/** + * decode_rs8 - Decode codeword (8bit data width) + * + * @rs: the rs control structure + * @data: data field of a given type + * @par: received parity data field + * @len: data length + * @s: syndrome data field (if NULL, syndrome is calculated) + * @no_eras: number of erasures + * @eras_pos: position of erasures, can be NULL + * @invmsk: invert data mask (will be xored on data, not on parity!) + * @corr: buffer to store correction bitmask on eras_pos + * + * The syndrome and parity uses a uint16_t data type to enable + * symbol size > 8. The calling code must take care of decoding of the + * syndrome result and the received parity before calling this code. + */ +int decode_rs8(struct rs_control *rs, uint8_t *data, uint16_t *par, int len, + uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, + uint16_t *corr) +{ +#include "decode_rs.c" +} +EXPORT_SYMBOL_GPL(decode_rs8); +#endif + +#ifdef CONFIG_REED_SOLOMON_ENC16 +/** + * encode_rs16 - Calculate the parity for data values (16bit data width) + * + * @rs: the rs control structure + * @data: data field of a given type + * @len: data length + * @par: parity data, must be initialized by caller (usually all 0) + * @invmsk: invert data mask (will be xored on data, not on parity!) + * + * Each field in the data array contains up to symbol size bits of valid data. + */ +int encode_rs16(struct rs_control *rs, uint16_t *data, int len, uint16_t *par, + uint16_t invmsk) +{ +#include "encode_rs.c" +} +EXPORT_SYMBOL_GPL(encode_rs16); +#endif + +#ifdef CONFIG_REED_SOLOMON_DEC16 +/** + * decode_rs16 - Decode codeword (16bit data width) + * + * @rs: the rs control structure + * @data: data field of a given type + * @par: received parity data field + * @len: data length + * @s: syndrome data field (if NULL, syndrome is calculated) + * @no_eras: number of erasures + * @eras_pos: position of erasures, can be NULL + * @invmsk: invert data mask (will be xored on data, not on parity!) + * @corr: buffer to store correction bitmask on eras_pos + * + * Each field in the data array contains up to symbol size bits of valid data. + */ +int decode_rs16(struct rs_control *rs, uint16_t *data, uint16_t *par, int len, + uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, + uint16_t *corr) +{ +#include "decode_rs.c" +} +EXPORT_SYMBOL_GPL(decode_rs16); +#endif + +EXPORT_SYMBOL_GPL(init_rs); +EXPORT_SYMBOL_GPL(free_rs); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Reed Solomon encoder/decoder"); +MODULE_AUTHOR("Phil Karn, Thomas Gleixner"); + -- cgit v1.2.3 From d0669b55e1f8e20ebeaafc7e1a6cb87578672f5e Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 21 Oct 2004 01:23:38 +0100 Subject: MTD updates for __iomem Signed-Off-By: Thomas Gleixner Signed-Off-By: David Woodhouse --- drivers/mtd/maps/arctic-mtd.c | 4 ++-- drivers/mtd/maps/autcpu12-nvram.c | 6 ++--- drivers/mtd/maps/beech-mtd.c | 4 ++-- drivers/mtd/maps/cdb89712.c | 8 +++---- drivers/mtd/maps/ceiva.c | 6 ++--- drivers/mtd/maps/cfi_flagadm.c | 4 ++-- drivers/mtd/maps/cstm_mips_ixx.c | 4 ++-- drivers/mtd/maps/dbox2-flash.c | 4 ++-- drivers/mtd/maps/dc21285.c | 4 ++-- drivers/mtd/maps/dilnetpc.c | 4 ++-- drivers/mtd/maps/dmv182.c | 4 ++-- drivers/mtd/maps/edb7312.c | 14 +++++------ drivers/mtd/maps/elan-104nc.c | 6 ++--- drivers/mtd/maps/epxa10db-flash.c | 4 ++-- drivers/mtd/maps/fortunet.c | 4 ++-- drivers/mtd/maps/h720x-flash.c | 4 ++-- drivers/mtd/maps/impa7.c | 8 +++---- drivers/mtd/maps/integrator-flash.c | 4 ++-- drivers/mtd/maps/iq80310.c | 4 ++-- drivers/mtd/maps/ixp2000.c | 48 ++++++++++++++++++------------------- drivers/mtd/maps/ixp4xx.c | 8 +++---- drivers/mtd/maps/l440gx.c | 4 ++-- drivers/mtd/maps/lasat.c | 4 ++-- drivers/mtd/maps/mbx860.c | 4 ++-- drivers/mtd/maps/mpc1211.c | 4 ++-- drivers/mtd/maps/netsc520.c | 4 ++-- drivers/mtd/maps/nettel.c | 5 ++-- drivers/mtd/maps/ocelot.c | 6 ++--- drivers/mtd/maps/omap-toto-flash.c | 4 ++-- drivers/mtd/maps/pb1550-flash.c | 4 ++-- drivers/mtd/maps/pb1xxx-flash.c | 5 ++-- drivers/mtd/maps/physmap.c | 4 ++-- drivers/mtd/maps/pnc2000.c | 4 ++-- drivers/mtd/maps/redwood.c | 4 ++-- drivers/mtd/maps/rpxlite.c | 4 ++-- drivers/mtd/maps/sbc_gxx.c | 6 ++--- drivers/mtd/maps/sc520cdp.c | 4 ++-- drivers/mtd/maps/scb2_flash.c | 4 ++-- drivers/mtd/maps/scx200_docflash.c | 4 ++-- drivers/mtd/maps/solutionengine.c | 6 ++--- drivers/mtd/maps/sun_uflash.c | 4 ++-- drivers/mtd/maps/uclinux.c | 9 +++---- drivers/mtd/maps/wr_sbc82xx_flash.c | 4 ++-- include/linux/mtd/doc2000.h | 8 +++---- 44 files changed, 132 insertions(+), 133 deletions(-) (limited to 'include/linux') diff --git a/drivers/mtd/maps/arctic-mtd.c b/drivers/mtd/maps/arctic-mtd.c index 2acf5b0b8cc3..36e3ff869ba4 100644 --- a/drivers/mtd/maps/arctic-mtd.c +++ b/drivers/mtd/maps/arctic-mtd.c @@ -1,5 +1,5 @@ /* - * $Id: arctic-mtd.c,v 1.11 2004/07/12 21:59:43 dwmw2 Exp $ + * $Id: arctic-mtd.c,v 1.12 2004/09/16 23:27:12 gleixner Exp $ * * drivers/mtd/maps/arctic-mtd.c MTD mappings and partition tables for * IBM 405LP Arctic boards. @@ -98,7 +98,7 @@ init_arctic_mtd(void) { printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR); - arctic_mtd_map.virt = (unsigned long) ioremap(PADDR, SIZE); + arctic_mtd_map.virt = (void __iomem *) ioremap(PADDR, SIZE); if (!arctic_mtd_map.virt) { printk("%s: failed to ioremap 0x%x\n", NAME, PADDR); diff --git a/drivers/mtd/maps/autcpu12-nvram.c b/drivers/mtd/maps/autcpu12-nvram.c index 31e9df6629c8..cd02989de726 100644 --- a/drivers/mtd/maps/autcpu12-nvram.c +++ b/drivers/mtd/maps/autcpu12-nvram.c @@ -2,7 +2,7 @@ * NV-RAM memory access on autcpu12 * (C) 2002 Thomas Gleixner (gleixner@autronix.de) * - * $Id: autcpu12-nvram.c,v 1.6 2004/07/12 21:59:43 dwmw2 Exp $ + * $Id: autcpu12-nvram.c,v 1.7 2004/09/16 23:27:12 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,7 +47,7 @@ static int __init init_autcpu12_sram (void) { int err, save0, save1; - autcpu12_sram_map.virt = (unsigned long)ioremap(0x12000000, SZ_128K); + autcpu12_sram_map.virt = (void __iomem *)ioremap(0x12000000, SZ_128K); if (!autcpu12_sram_map.virt) { printk("Failed to ioremap autcpu12 NV-RAM space\n"); err = -EIO; @@ -76,7 +76,7 @@ static int __init init_autcpu12_sram (void) /* We have a 128K found, restore 0x10000 and set size * to 128K */ - ma[_write32(&autcpu12_sram_map,save1,0x10000); + map_write32(&autcpu12_sram_map,save1,0x10000); autcpu12_sram_map.size = SZ_128K; map: diff --git a/drivers/mtd/maps/beech-mtd.c b/drivers/mtd/maps/beech-mtd.c index d8f737aa745d..56c7370fc544 100644 --- a/drivers/mtd/maps/beech-mtd.c +++ b/drivers/mtd/maps/beech-mtd.c @@ -1,5 +1,5 @@ /* - * $Id: beech-mtd.c,v 1.8 2004/07/12 21:59:43 dwmw2 Exp $ + * $Id: beech-mtd.c,v 1.9 2004/09/16 23:27:12 gleixner Exp $ * * drivers/mtd/maps/beech-mtd.c MTD mappings and partition tables for * IBM 405LP Beech boards. @@ -74,7 +74,7 @@ init_beech_mtd(void) { printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR); - beech_mtd_map.virt = (unsigned long) ioremap(PADDR, SIZE); + beech_mtd_map.virt = (void __iomem *) ioremap(PADDR, SIZE); if (!beech_mtd_map.virt) { printk("%s: failed to ioremap 0x%x\n", NAME, PADDR); diff --git a/drivers/mtd/maps/cdb89712.c b/drivers/mtd/maps/cdb89712.c index e8c984ee13e2..23b1289905d2 100644 --- a/drivers/mtd/maps/cdb89712.c +++ b/drivers/mtd/maps/cdb89712.c @@ -1,7 +1,7 @@ /* * Flash on Cirrus CDB89712 * - * $Id: cdb89712.c,v 1.8 2004/07/12 21:59:43 dwmw2 Exp $ + * $Id: cdb89712.c,v 1.9 2004/09/16 23:27:12 gleixner Exp $ */ #include @@ -44,7 +44,7 @@ static int __init init_cdb89712_flash (void) goto out; } - cdb89712_flash_map.virt = (unsigned long)ioremap(FLASH_START, FLASH_SIZE); + cdb89712_flash_map.virt = (void __iomem *)ioremap(FLASH_START, FLASH_SIZE); if (!cdb89712_flash_map.virt) { printk(KERN_NOTICE "Failed to ioremap Cdb89712 FLASH space\n"); err = -EIO; @@ -114,7 +114,7 @@ static int __init init_cdb89712_sram (void) goto out; } - cdb89712_sram_map.virt = (unsigned long)ioremap(SRAM_START, SRAM_SIZE); + cdb89712_sram_map.virt = (void __iomem *)ioremap(SRAM_START, SRAM_SIZE); if (!cdb89712_sram_map.virt) { printk(KERN_NOTICE "Failed to ioremap Cdb89712 SRAM space\n"); err = -EIO; @@ -182,7 +182,7 @@ static int __init init_cdb89712_bootrom (void) goto out; } - cdb89712_bootrom_map.virt = (unsigned long)ioremap(BOOTROM_START, BOOTROM_SIZE); + cdb89712_bootrom_map.virt = (void __iomem *)ioremap(BOOTROM_START, BOOTROM_SIZE); if (!cdb89712_bootrom_map.virt) { printk(KERN_NOTICE "Failed to ioremap Cdb89712 BootROM space\n"); err = -EIO; diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c index e34420bb101d..da8584a662f4 100644 --- a/drivers/mtd/maps/ceiva.c +++ b/drivers/mtd/maps/ceiva.c @@ -11,7 +11,7 @@ * * (C) 2000 Nicolas Pitre * - * $Id: ceiva.c,v 1.10 2004/07/12 21:59:43 dwmw2 Exp $ + * $Id: ceiva.c,v 1.11 2004/09/16 23:27:12 gleixner Exp $ */ #include @@ -103,7 +103,7 @@ struct clps_info { unsigned long base; unsigned long size; int width; - void __iomem *vbase; + void *vbase; struct map_info *map; struct mtd_info *mtd; struct resource *res; @@ -150,7 +150,7 @@ static int __init clps_setup_mtd(struct clps_info *clps, int nr, struct mtd_info break; } - clps[i].map->virt = clps[i].vbase; + clps[i].map->virt = (void __iomem *)clps[i].vbase; clps[i].map->bankwidth = clps[i].width; clps[i].map->size = clps[i].size; diff --git a/drivers/mtd/maps/cfi_flagadm.c b/drivers/mtd/maps/cfi_flagadm.c index 28d59ff7782d..f923e8b8cebc 100644 --- a/drivers/mtd/maps/cfi_flagadm.c +++ b/drivers/mtd/maps/cfi_flagadm.c @@ -1,7 +1,7 @@ /* * Copyright © 2001 Flaga hf. Medical Devices, Kári Davíðsson * - * $Id: cfi_flagadm.c,v 1.12 2004/07/12 21:59:43 dwmw2 Exp $ + * $Id: cfi_flagadm.c,v 1.13 2004/09/16 23:27:12 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -96,7 +96,7 @@ int __init init_flagadm(void) FLASH_SIZE, FLASH_PHYS_ADDR); flagadm_map.phys = FLASH_PHYS_ADDR; - flagadm_map.virt = (unsigned long)ioremap(FLASH_PHYS_ADDR, + flagadm_map.virt = (void __iomem *s)ioremap(FLASH_PHYS_ADDR, FLASH_SIZE); if (!flagadm_map.virt) { diff --git a/drivers/mtd/maps/cstm_mips_ixx.c b/drivers/mtd/maps/cstm_mips_ixx.c index 773b1ba9ac9d..c5b742df4e39 100644 --- a/drivers/mtd/maps/cstm_mips_ixx.c +++ b/drivers/mtd/maps/cstm_mips_ixx.c @@ -1,5 +1,5 @@ /* - * $Id: cstm_mips_ixx.c,v 1.10 2004/07/12 21:59:43 dwmw2 Exp $ + * $Id: cstm_mips_ixx.c,v 1.11 2004/09/16 23:27:12 gleixner Exp $ * * Mapping of a custom board with both AMD CFI and JEDEC flash in partitions. * Config with both CFI and JEDEC device support. @@ -170,7 +170,7 @@ int __init init_cstm_mips_ixx(void) cstm_mips_ixx_map[i].phys = cstm_mips_ixx_board_desc[i].window_addr; - cstm_mips_ixx_map[i].virt = (unsigned long)ioremap(cstm_mips_ixx_board_desc[i].window_addr, cstm_mips_ixx_board_desc[i].window_size); + cstm_mips_ixx_map[i].virt = (void __iomem *)ioremap(cstm_mips_ixx_board_desc[i].window_addr, cstm_mips_ixx_board_desc[i].window_size); if (!cstm_mips_ixx_map[i].virt) { printk(KERN_WARNING "Failed to ioremap\n"); return -EIO; diff --git a/drivers/mtd/maps/dbox2-flash.c b/drivers/mtd/maps/dbox2-flash.c index 7c4de43c0ef1..e40465bfa482 100644 --- a/drivers/mtd/maps/dbox2-flash.c +++ b/drivers/mtd/maps/dbox2-flash.c @@ -1,5 +1,5 @@ /* - * $Id: dbox2-flash.c,v 1.11 2004/07/12 21:59:43 dwmw2 Exp $ + * $Id: dbox2-flash.c,v 1.12 2004/09/16 23:27:12 gleixner Exp $ * * D-Box 2 flash driver */ @@ -75,7 +75,7 @@ struct map_info dbox2_flash_map = { int __init init_dbox2_flash(void) { printk(KERN_NOTICE "D-Box 2 flash driver (size->0x%X mem->0x%X)\n", WINDOW_SIZE, WINDOW_ADDR); - dbox2_flash_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); + dbox2_flash_map.virt = (void __iomem *)ioremap(WINDOW_ADDR, WINDOW_SIZE); if (!dbox2_flash_map.virt) { printk("Failed to ioremap\n"); diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c index fc72bb5c5d22..5f61a6ef4036 100644 --- a/drivers/mtd/maps/dc21285.c +++ b/drivers/mtd/maps/dc21285.c @@ -5,7 +5,7 @@ * * This code is GPL * - * $Id: dc21285.c,v 1.20 2004/07/12 22:38:29 dwmw2 Exp $ + * $Id: dc21285.c,v 1.21 2004/09/16 23:27:13 gleixner Exp $ */ #include #include @@ -175,7 +175,7 @@ static int __init init_dc21285(void) dc21285_map.bankwidth*8); /* Let's map the flash area */ - dc21285_map.map_priv_1 = (unsigned long)ioremap(DC21285_FLASH, 16*1024*1024); + dc21285_map.map_priv_1 = (void __iomem *)ioremap(DC21285_FLASH, 16*1024*1024); if (!dc21285_map.map_priv_1) { printk("Failed to ioremap\n"); return -EIO; diff --git a/drivers/mtd/maps/dilnetpc.c b/drivers/mtd/maps/dilnetpc.c index feb38ba14f26..f69992c1ba1a 100644 --- a/drivers/mtd/maps/dilnetpc.c +++ b/drivers/mtd/maps/dilnetpc.c @@ -14,7 +14,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: dilnetpc.c,v 1.13 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: dilnetpc.c,v 1.14 2004/09/16 23:27:13 gleixner Exp $ * * The DIL/Net PC is a tiny embedded PC board made by SSV Embedded Systems * featuring the AMD Elan SC410 processor. There are two variants of this @@ -403,7 +403,7 @@ static int __init init_dnpc(void) printk(KERN_NOTICE "DIL/Net %s flash: 0x%lx at 0x%lx\n", is_dnp ? "DNPC" : "ADNP", dnpc_map.size, dnpc_map.phys); - dnpc_map.virt = (unsigned long)ioremap_nocache(dnpc_map.phys, dnpc_map.size); + dnpc_map.virt = (void __iomem *)ioremap_nocache(dnpc_map.phys, dnpc_map.size); dnpc_map_flash(dnpc_map.phys, dnpc_map.size); diff --git a/drivers/mtd/maps/dmv182.c b/drivers/mtd/maps/dmv182.c index cdb9c1bc9c4e..124d02165cbc 100644 --- a/drivers/mtd/maps/dmv182.c +++ b/drivers/mtd/maps/dmv182.c @@ -4,7 +4,7 @@ * * Flash map driver for the Dy4 SVME182 board * - * $Id: dmv182.c,v 1.3 2004/07/14 17:45:40 dwmw2 Exp $ + * $Id: dmv182.c,v 1.4 2004/09/16 23:27:13 gleixner Exp $ * * Copyright 2003-2004, TimeSys Corporation * @@ -104,7 +104,7 @@ static int __init init_svme182(void) partitions = svme182_partitions; svme182_map.virt = - (unsigned long)ioremap(FLASH_BASE_ADDR, svme182_map.size); + (void __iomem *)ioremap(FLASH_BASE_ADDR, svme182_map.size); if (svme182_map.virt == 0) { printk("Failed to ioremap FLASH memory area.\n"); diff --git a/drivers/mtd/maps/edb7312.c b/drivers/mtd/maps/edb7312.c index b7fd849dc1fc..4a98dff01db3 100644 --- a/drivers/mtd/maps/edb7312.c +++ b/drivers/mtd/maps/edb7312.c @@ -1,5 +1,5 @@ /* - * $Id: edb7312.c,v 1.11 2004/07/14 09:52:55 dwmw2 Exp $ + * $Id: edb7312.c,v 1.12 2004/09/16 23:27:13 gleixner Exp $ * * Handle mapping of the NOR flash on Cogent EDB7312 boards * @@ -71,19 +71,19 @@ static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; #endif -static int mtd_parts_nb; -static struct mtd_partition *mtd_parts; +static int mtd_parts_nb = 0; +static struct mtd_partition *mtd_parts = 0; int __init init_edb7312nor(void) { static const char *rom_probe_types[] = PROBETYPES; const char **type; - const char *part_type = NULL; + const char *part_type = 0; printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n", WINDOW_SIZE, WINDOW_ADDR); - edb7312nor_map.virt = (unsigned long) - ioremap(WINDOW_ADDR, WINDOW_SIZE); + edb7312nor_map.virt = (void __iomem *) + ioremap(WINDOW_ADDR, WINDOW_SIZE); if (!edb7312nor_map.virt) { printk(MSG_PREFIX "failed to ioremap\n"); @@ -92,7 +92,7 @@ int __init init_edb7312nor(void) simple_map_init(&edb7312nor_map); - mymtd = NULL; + mymtd = 0; type = rom_probe_types; for(; !mymtd && *type; type++) { mymtd = do_map_probe(*type, &edb7312nor_map); diff --git a/drivers/mtd/maps/elan-104nc.c b/drivers/mtd/maps/elan-104nc.c index 9410e1fb28d5..d39bfa633491 100644 --- a/drivers/mtd/maps/elan-104nc.c +++ b/drivers/mtd/maps/elan-104nc.c @@ -16,7 +16,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - $Id: elan-104nc.c,v 1.21 2004/07/12 22:38:29 dwmw2 Exp $ + $Id: elan-104nc.c,v 1.22 2004/09/16 23:27:13 gleixner Exp $ The ELAN-104NC has up to 8 Mibyte of Intel StrataFlash (28F320/28F640) in x16 mode. This drivers uses the CFI probe and Intel Extended Command Set drivers. @@ -53,7 +53,7 @@ always fail. So we don't do it. I just hope it doesn't break anything. #define PAGE_IO_SIZE 2 static volatile int page_in_window = -1; // Current page in window. -static unsigned long iomapadr; +static void __iomem *iomapadr; static spinlock_t elan_104nc_spin = SPIN_LOCK_UNLOCKED; /* partition_info gives details on the logical partitions that the split the @@ -190,7 +190,7 @@ int __init init_elan_104nc(void) /* Urg! We use I/O port 0x22 without request_region()ing it, because it's already allocated to the PIC. */ - iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH); + iomapadr = (void __iomem *)ioremap(WINDOW_START, WINDOW_LENGTH); if (!iomapadr) { printk( KERN_ERR"%s: failed to ioremap memory region\n", elan_104nc_map.name ); diff --git a/drivers/mtd/maps/epxa10db-flash.c b/drivers/mtd/maps/epxa10db-flash.c index 545a398c47b9..4a4bf79e8a0c 100644 --- a/drivers/mtd/maps/epxa10db-flash.c +++ b/drivers/mtd/maps/epxa10db-flash.c @@ -5,7 +5,7 @@ * Copyright (C) 2001 Altera Corporation * Copyright (C) 2001 Red Hat, Inc. * - * $Id: epxa10db-flash.c,v 1.11 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: epxa10db-flash.c,v 1.12 2004/09/16 23:27:13 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -62,7 +62,7 @@ static int __init epxa_mtd_init(void) printk(KERN_NOTICE "%s flash device: 0x%x at 0x%x\n", BOARD_NAME, FLASH_SIZE, FLASH_START); - epxa_map.virt = (unsigned long)ioremap(FLASH_START, FLASH_SIZE); + epxa_map.virt = (void __iomem *)ioremap(FLASH_START, FLASH_SIZE); if (!epxa_map.virt) { printk("Failed to ioremap %s flash\n",BOARD_NAME); return -EIO; diff --git a/drivers/mtd/maps/fortunet.c b/drivers/mtd/maps/fortunet.c index 50409efda9c9..a7dc9c3905d4 100644 --- a/drivers/mtd/maps/fortunet.c +++ b/drivers/mtd/maps/fortunet.c @@ -1,6 +1,6 @@ /* fortunet.c memory map * - * $Id: fortunet.c,v 1.7 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: fortunet.c,v 1.8 2004/09/16 23:27:13 gleixner Exp $ */ #include @@ -210,7 +210,7 @@ int __init init_fortunet(void) map_regions[ix].map_info.phys = map_regions[ix].window_addr_physical, map_regions[ix].map_info.virt = - (int)ioremap_nocache( + (void __iomem *)ioremap_nocache( map_regions[ix].window_addr_physical, map_regions[ix].map_info.size); if(!map_regions[ix].map_info.virt) diff --git a/drivers/mtd/maps/h720x-flash.c b/drivers/mtd/maps/h720x-flash.c index e7cd7b022eb7..46e654786249 100644 --- a/drivers/mtd/maps/h720x-flash.c +++ b/drivers/mtd/maps/h720x-flash.c @@ -2,7 +2,7 @@ * Flash memory access on Hynix GMS30C7201/HMS30C7202 based * evaluation boards * - * $Id: h720x-flash.c,v 1.9 2004/07/14 17:45:40 dwmw2 Exp $ + * $Id: h720x-flash.c,v 1.10 2004/09/16 23:27:13 gleixner Exp $ * * (C) 2002 Jungjun Kim * 2003 Thomas Gleixner @@ -73,7 +73,7 @@ int __init h720x_mtd_init(void) char *part_type = NULL; - h720x_map.virt = (unsigned long)ioremap(FLASH_PHYS, FLASH_SIZE); + h720x_map.virt = (void __iomem *)ioremap(FLASH_PHYS, FLASH_SIZE); if (!h720x_map.virt) { printk(KERN_ERR "H720x-MTD: ioremap failed\n"); diff --git a/drivers/mtd/maps/impa7.c b/drivers/mtd/maps/impa7.c index 7d2b42436958..34ed09fca8e2 100644 --- a/drivers/mtd/maps/impa7.c +++ b/drivers/mtd/maps/impa7.c @@ -1,5 +1,5 @@ /* - * $Id: impa7.c,v 1.11 2004/07/14 09:52:55 dwmw2 Exp $ + * $Id: impa7.c,v 1.12 2004/09/16 23:27:13 gleixner Exp $ * * Handle mapping of the NOR flash on implementa A7 boards * @@ -77,7 +77,7 @@ int __init init_impa7(void) { static const char *rom_probe_types[] = PROBETYPES; const char **type; - const char *part_type = NULL; + const char *part_type = 0; int i; static struct { u_long addr; u_long size; } pt[NUM_FLASHBANKS] = { { WINDOW_ADDR0, WINDOW_SIZE0 }, @@ -91,7 +91,7 @@ int __init init_impa7(void) pt[i].size, pt[i].addr); impa7_map[i].phys = pt[i].addr; - impa7_map[i].virt = (unsigned long) + impa7_map[i].virt = (void __iomem *) ioremap(pt[i].addr, pt[i].size); if (!impa7_map[i].virt) { printk(MSG_PREFIX "failed to ioremap\n"); @@ -99,7 +99,7 @@ int __init init_impa7(void) } simple_map_init(&impa7_map[i]); - impa7_mtd[i] = NULL; + impa7_mtd[i] = 0; type = rom_probe_types; for(; !impa7_mtd[i] && *type; type++) { impa7_mtd[i] = do_map_probe(*type, &impa7_map[i]); diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c index 1f23ab1cd882..710bec4c89ef 100644 --- a/drivers/mtd/maps/integrator-flash.c +++ b/drivers/mtd/maps/integrator-flash.c @@ -22,7 +22,7 @@ This is access code for flashes using ARM's flash partitioning standards. - $Id: integrator-flash.c,v 1.16 2004/07/12 21:59:44 dwmw2 Exp $ + $Id: integrator-flash.c,v 1.17 2004/09/16 23:27:13 gleixner Exp $ ======================================================================*/ @@ -110,7 +110,7 @@ static int armflash_probe(struct device *_dev) info->map.size = size; info->map.bankwidth = plat->width; info->map.phys = res->start; - info->map.virt = (unsigned long) base; + info->map.virt = (void __iomem *) base; info->map.name = dev->dev.bus_id; info->map.set_vpp = armflash_set_vpp; diff --git a/drivers/mtd/maps/iq80310.c b/drivers/mtd/maps/iq80310.c index 17d7c77594e4..977a084b60f8 100644 --- a/drivers/mtd/maps/iq80310.c +++ b/drivers/mtd/maps/iq80310.c @@ -1,5 +1,5 @@ /* - * $Id: iq80310.c,v 1.18 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: iq80310.c,v 1.19 2004/09/16 23:27:13 gleixner Exp $ * * Mapping for the Intel XScale IQ80310 evaluation board * @@ -68,7 +68,7 @@ static int __init init_iq80310(void) int parsed_nr_parts = 0; int ret; - iq80310_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); + iq80310_map.virt = (void __iomem *)ioremap(WINDOW_ADDR, WINDOW_SIZE); if (!iq80310_map.virt) { printk("Failed to ioremap\n"); return -EIO; diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c index 104488c0b188..6d3715c4219a 100644 --- a/drivers/mtd/maps/ixp2000.c +++ b/drivers/mtd/maps/ixp2000.c @@ -1,5 +1,5 @@ /* - * $Id: ixp2000.c,v 1.1 2004/09/02 00:13:41 dsaxena Exp $ + * $Id: ixp2000.c,v 1.3 2004/09/16 23:27:13 gleixner Exp $ * * drivers/mtd/maps/ixp2000.c * @@ -14,7 +14,7 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * + * */ #include @@ -44,8 +44,8 @@ struct ixp2000_flash_info { }; static inline unsigned long flash_bank_setup(struct map_info *map, unsigned long ofs) -{ - unsigned long (*set_bank)(unsigned long) = +{ + unsigned long (*set_bank)(unsigned long) = (unsigned long(*)(unsigned long))map->map_priv_2; return (set_bank ? set_bank(ofs) : ofs); @@ -53,15 +53,15 @@ static inline unsigned long flash_bank_setup(struct map_info *map, unsigned long #ifdef __ARMEB__ /* - * Rev A0 and A1 of IXP2400 silicon have a broken addressing unit which - * causes the lower address bits to be XORed with 0x11 on 8 bit accesses - * and XORed with 0x10 on 16 bit accesses. See the spec update, erratta 44. + * Rev A0 and A1 of IXP2400 silicon have a broken addressing unit which + * causes the lower address bits to be XORed with 0x11 on 8 bit accesses + * and XORed with 0x10 on 16 bit accesses. See the spec update, erratum 44. */ -static int errata44_workaround = 0; +static int erratum44_workaround = 0; static inline unsigned long address_fix8_write(unsigned long addr) { - if (errata44_workaround) { + if (erratum44_workaround) { return (addr ^ 3); } return addr; @@ -88,7 +88,7 @@ static void ixp2000_flash_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) { from = flash_bank_setup(map, from); - while(len--) + while(len--) *(__u8 *) to++ = *(__u8 *)(map->map_priv_1 + from++); } @@ -127,8 +127,8 @@ static int ixp2000_flash_remove(struct device *_dev) if (info->map.map_priv_1) iounmap((void *) info->map.map_priv_1); - if (info->partitions) - kfree(info->partitions); + if (info->partitions) { + kfree(info->partitions); } if (info->res) { release_resource(info->res); @@ -147,11 +147,11 @@ static int ixp2000_flash_probe(struct device *_dev) static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; struct platform_device *dev = to_platform_device(_dev); struct ixp2000_flash_data *ixp_data = dev->dev.platform_data; - struct flash_platform_data *plat; + struct flash_platform_data *plat; struct ixp2000_flash_info *info; unsigned long window_size; int err = -1; - + if (!ixp_data) return -ENODEV; @@ -160,7 +160,7 @@ static int ixp2000_flash_probe(struct device *_dev) return -ENODEV; window_size = dev->resource->end - dev->resource->start + 1; - dev_info(_dev, "Probe of IXP2000 flash(%d banks x %dM)\n", + dev_info(_dev, "Probe of IXP2000 flash(%d banks x %dMiB)\n", ixp_data->nr_banks, ((u32)window_size >> 20)); if (plat->width != 1) { @@ -173,7 +173,7 @@ static int ixp2000_flash_probe(struct device *_dev) if(!info) { err = -ENOMEM; goto Error; - } + } memzero(info, sizeof(struct ixp2000_flash_info)); dev_set_drvdata(&dev->dev, info); @@ -183,7 +183,7 @@ static int ixp2000_flash_probe(struct device *_dev) * not attempt to do a direct access on us. */ info->map.phys = NO_XIP; - + info->nr_banks = ixp_data->nr_banks; info->map.size = ixp_data->nr_banks * window_size; info->map.bankwidth = 1; @@ -191,7 +191,7 @@ static int ixp2000_flash_probe(struct device *_dev) /* * map_priv_2 is used to store a ptr to to the bank_setup routine */ - info->map.map_priv_2 = (u32) ixp_data->bank_setup; + info->map.map_priv_2 = (void __iomem *) ixp_data->bank_setup; info->map.name = dev->dev.bus_id; info->map.read = ixp2000_flash_read8; @@ -199,8 +199,8 @@ static int ixp2000_flash_probe(struct device *_dev) info->map.copy_from = ixp2000_flash_copy_from; info->map.copy_to = ixp2000_flash_copy_to; - info->res = request_mem_region(dev->resource->start, - dev->resource->end - dev->resource->start + 1, + info->res = request_mem_region(dev->resource->start, + dev->resource->end - dev->resource->start + 1, dev->dev.bus_id); if (!info->res) { dev_err(_dev, "Could not reserve memory region\n"); @@ -209,7 +209,7 @@ static int ixp2000_flash_probe(struct device *_dev) } info->map.map_priv_1 = - (unsigned long) ioremap(dev->resource->start, + (void __iomem *) ioremap(dev->resource->start, dev->resource->end - dev->resource->start + 1); if (!info->map.map_priv_1) { dev_err(_dev, "Failed to ioremap flash region\n"); @@ -224,12 +224,12 @@ static int ixp2000_flash_probe(struct device *_dev) #if defined(__ARMEB__) /* - * Enable errata 44 workaround for NPUs with broken slowport + * Enable erratum 44 workaround for NPUs with broken slowport */ errata44_workaround = ixp2000_has_broken_slowport(); - dev_info(_dev, "Errata 44 workaround %s\n", - errata44_workaround ? "enabled" : "disabled"); + dev_info(_dev, "Erratum 44 workaround %s\n", + erratum44_workaround ? "enabled" : "disabled"); #endif info->mtd = do_map_probe(plat->map_name, &info->map); diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index 1770b1acc2b9..ba874b8d07a4 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c @@ -69,7 +69,7 @@ static void ixp4xx_copy_from(struct map_info *map, void *to, dest[len - 1] = BYTE0(src[i]); } -/* +/* * Unaligned writes are ignored, causing the 8-bit * probe to fail and proceed to the 16-bit probe (which succeeds). */ @@ -79,7 +79,7 @@ static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long *(__u16 *) (map->map_priv_1 + adr) = d.x[0]; } -/* +/* * Fast write16 function without the probing check above */ static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr) @@ -197,7 +197,7 @@ static int ixp4xx_flash_probe(struct device *_dev) } info->map.map_priv_1 = - (void __iomem *) ioremap(dev->resource->start, + (void __iomem *) ioremap(dev->resource->start, dev->resource->end - dev->resource->start + 1); if (!info->map.map_priv_1) { printk(KERN_ERR "IXP4XXFlash: Failed to ioremap region\n"); @@ -212,7 +212,7 @@ static int ixp4xx_flash_probe(struct device *_dev) goto Error; } info->mtd->owner = THIS_MODULE; - + /* Use the fast version */ info->map.write = ixp4xx_write16, diff --git a/drivers/mtd/maps/l440gx.c b/drivers/mtd/maps/l440gx.c index 046f7efbd8e6..f8c5b0b2f8a0 100644 --- a/drivers/mtd/maps/l440gx.c +++ b/drivers/mtd/maps/l440gx.c @@ -1,5 +1,5 @@ /* - * $Id: l440gx.c,v 1.13 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: l440gx.c,v 1.14 2004/09/16 23:27:13 gleixner Exp $ * * BIOS Flash chip on Intel 440GX board. * @@ -73,7 +73,7 @@ static int __init init_l440gx(void) return -ENODEV; } - l440gx_map.virt = (unsigned long)ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE); + l440gx_map.virt = (void __iomem *)ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE); if (!l440gx_map.virt) { printk(KERN_WARNING "Failed to ioremap L440GX flash region\n"); diff --git a/drivers/mtd/maps/lasat.c b/drivers/mtd/maps/lasat.c index 2a2efaa42456..6451c7ead44a 100644 --- a/drivers/mtd/maps/lasat.c +++ b/drivers/mtd/maps/lasat.c @@ -7,7 +7,7 @@ * modify it under the terms of the GNU General Public License version * 2 as published by the Free Software Foundation. * - * $Id: lasat.c,v 1.7 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: lasat.c,v 1.8 2004/09/16 23:27:13 gleixner Exp $ * */ @@ -50,7 +50,7 @@ static int __init init_lasat(void) ENABLE_VPP((&lasat_map)); lasat_map.phys = lasat_flash_partition_start(LASAT_MTD_BOOTLOADER); - lasat_map.virt = (unsigned long)ioremap_nocache( + lasat_map.virt = (void __iomem *)ioremap_nocache( lasat_map.phys, lasat_board_info.li_flash_size); lasat_map.size = lasat_board_info.li_flash_size; diff --git a/drivers/mtd/maps/mbx860.c b/drivers/mtd/maps/mbx860.c index 4c0f9e967cc8..0945f44375be 100644 --- a/drivers/mtd/maps/mbx860.c +++ b/drivers/mtd/maps/mbx860.c @@ -1,5 +1,5 @@ /* - * $Id: mbx860.c,v 1.6 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: mbx860.c,v 1.7 2004/09/16 23:27:13 gleixner Exp $ * * Handle mapping of the flash on MBX860 boards * @@ -60,7 +60,7 @@ struct map_info mbx_map = { int __init init_mbx(void) { printk(KERN_NOTICE "Motorola MBX flash device: 0x%x at 0x%x\n", WINDOW_SIZE*4, WINDOW_ADDR); - mbx_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); + mbx_map.virt = (void __iomem *)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); if (!mbx_map.virt) { printk("Failed to ioremap\n"); diff --git a/drivers/mtd/maps/mpc1211.c b/drivers/mtd/maps/mpc1211.c index cc55200a21e3..4685e8e13460 100644 --- a/drivers/mtd/maps/mpc1211.c +++ b/drivers/mtd/maps/mpc1211.c @@ -1,7 +1,7 @@ /* * Flash on MPC-1211 * - * $Id: mpc1211.c,v 1.3 2004/07/14 17:45:40 dwmw2 Exp $ + * $Id: mpc1211.c,v 1.4 2004/09/16 23:27:13 gleixner Exp $ * * (C) 2002 Interface, Saito.K & Jeanne * @@ -44,7 +44,7 @@ static int __init init_mpc1211_maps(void) int nr_parts; mpc1211_flash_map.phys = 0; - mpc1211_flash_map.virt = P2SEGADDR(0); + mpc1211_flash_map.virt = (void __iomem *)P2SEGADDR(0); simple_map_init(&mpc1211_flash_map); diff --git a/drivers/mtd/maps/netsc520.c b/drivers/mtd/maps/netsc520.c index afdf6589bfbe..c91115868a15 100644 --- a/drivers/mtd/maps/netsc520.c +++ b/drivers/mtd/maps/netsc520.c @@ -3,7 +3,7 @@ * Copyright (C) 2001 Mark Langsdorf (mark.langsdorf@amd.com) * based on sc520cdp.c by Sysgo Real-Time Solutions GmbH * - * $Id: netsc520.c,v 1.10 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: netsc520.c,v 1.11 2004/09/16 23:27:13 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -95,7 +95,7 @@ static struct mtd_info *mymtd; static int __init init_netsc520(void) { printk(KERN_NOTICE "NetSc520 flash device: 0x%lx at 0x%lx\n", netsc520_map.size, netsc520_map.phys); - netsc520_map.virt = (unsigned long)ioremap_nocache(netsc520_map.phys, netsc520_map.size); + netsc520_map.virt = (void __iomem *)ioremap_nocache(netsc520_map.phys, netsc520_map.size); if (!netsc520_map.virt) { printk("Failed to ioremap_nocache\n"); diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c index 38a81462ff4c..8541d9b75de6 100644 --- a/drivers/mtd/maps/nettel.c +++ b/drivers/mtd/maps/nettel.c @@ -6,7 +6,7 @@ * (C) Copyright 2000-2001, Greg Ungerer (gerg@snapgear.com) * (C) Copyright 2001-2002, SnapGear (www.snapgear.com) * - * $Id: nettel.c,v 1.5 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: nettel.c,v 1.7 2004/10/20 22:17:30 dwmw2 Exp $ */ /****************************************************************************/ @@ -273,8 +273,7 @@ int __init nettel_init(void) __asm__ ("wbinvd"); nettel_amd_map.phys = amdaddr; - nettel_amd_map.virt = (unsigned long) - ioremap_nocache(amdaddr, maxsize); + nettel_amd_map.virt = (void __iomem *) ioremap_nocache(amdaddr, maxsize); if (!nettel_amd_map.virt) { printk("SNAPGEAR: failed to ioremap() BOOTCS\n"); return(-EIO); diff --git a/drivers/mtd/maps/ocelot.c b/drivers/mtd/maps/ocelot.c index 40c524d62047..eb5a00316b23 100644 --- a/drivers/mtd/maps/ocelot.c +++ b/drivers/mtd/maps/ocelot.c @@ -1,5 +1,5 @@ /* - * $Id: ocelot.c,v 1.13 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: ocelot.c,v 1.14 2004/09/16 23:27:13 gleixner Exp $ * * Flash on Momenco Ocelot */ @@ -81,7 +81,7 @@ static int __init init_ocelot_maps(void) iounmap(pld); /* Now ioremap the NVRAM space */ - ocelot_nvram_map.virt = (unsigned long)ioremap_nocache(NVRAM_WINDOW_ADDR, NVRAM_WINDOW_SIZE); + ocelot_nvram_map.virt = (void __iomem *)ioremap_nocache(NVRAM_WINDOW_ADDR, NVRAM_WINDOW_SIZE); if (!ocelot_nvram_map.virt) { printk(KERN_NOTICE "Failed to ioremap Ocelot NVRAM space\n"); return -EIO; @@ -101,7 +101,7 @@ static int __init init_ocelot_maps(void) nvram_mtd->write = ocelot_ram_write; /* Now map the flash space */ - ocelot_flash_map.virt = (unsigned long)ioremap_nocache(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE); + ocelot_flash_map.virt = (void __iomem *)ioremap_nocache(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE); if (!ocelot_flash_map.virt) { printk(KERN_NOTICE "Failed to ioremap Ocelot flash space\n"); goto fail_2; diff --git a/drivers/mtd/maps/omap-toto-flash.c b/drivers/mtd/maps/omap-toto-flash.c index 4262f1c03c09..496109071cb1 100644 --- a/drivers/mtd/maps/omap-toto-flash.c +++ b/drivers/mtd/maps/omap-toto-flash.c @@ -5,7 +5,7 @@ * * (C) 2002 MontVista Software, Inc. * - * $Id: omap-toto-flash.c,v 1.2 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: omap-toto-flash.c,v 1.3 2004/09/16 23:27:13 gleixner Exp $ */ #include @@ -35,7 +35,7 @@ static struct map_info omap_toto_map_flash = { .name = "OMAP Toto flash", .bankwidth = 2, - .virt = OMAP_TOTO_FLASH_BASE, + .virt = (void __iomem *)OMAP_TOTO_FLASH_BASE, }; diff --git a/drivers/mtd/maps/pb1550-flash.c b/drivers/mtd/maps/pb1550-flash.c index 4747fbc1fa79..ebc54a65f7ee 100644 --- a/drivers/mtd/maps/pb1550-flash.c +++ b/drivers/mtd/maps/pb1550-flash.c @@ -1,7 +1,7 @@ /* * Flash memory access on Alchemy Pb1550 board * - * $Id: pb1550-flash.c,v 1.4 2004/07/14 17:45:40 dwmw2 Exp $ + * $Id: pb1550-flash.c,v 1.5 2004/09/16 23:27:13 gleixner Exp $ * * (C) 2004 Embedded Edge, LLC, based on pb1550-flash.c: * (C) 2003 Pete Popov @@ -179,7 +179,7 @@ int __init pb1550_mtd_init(void) printk(KERN_NOTICE "Pb1550 flash: probing %d-bit flash bus\n", pb1550_map.bankwidth*8); pb1550_map.virt = - (unsigned long)ioremap(window_addr, window_size); + (void __iomem *)ioremap(window_addr, window_size); mymtd = do_map_probe("cfi_probe", &pb1550_map); if (!mymtd) return -ENXIO; mymtd->owner = THIS_MODULE; diff --git a/drivers/mtd/maps/pb1xxx-flash.c b/drivers/mtd/maps/pb1xxx-flash.c index b6b8ccf48d9f..1971208dc330 100644 --- a/drivers/mtd/maps/pb1xxx-flash.c +++ b/drivers/mtd/maps/pb1xxx-flash.c @@ -3,7 +3,7 @@ * * (C) 2001 Pete Popov * - * $Id: pb1xxx-flash.c,v 1.11 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: pb1xxx-flash.c,v 1.13 2004/09/26 07:33:01 ppopov Exp $ */ #include @@ -17,7 +17,6 @@ #include #include -#include #ifdef DEBUG_RW #define DBG(x...) printk(x) @@ -150,7 +149,7 @@ int __init pb1xxx_mtd_init(void) */ printk(KERN_NOTICE "Pb1xxx flash: probing %d-bit flash bus\n", BUSWIDTH*8); - pb1xxx_mtd_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); + pb1xxx_mtd_map.virt = (void __iomem *)ioremap(WINDOW_ADDR, WINDOW_SIZE); simple_map_init(&pb1xxx_mtd_map); diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 5822ba99c195..a57a672884e9 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -1,5 +1,5 @@ /* - * $Id: physmap.c,v 1.34 2004/07/21 00:16:14 jwboyer Exp $ + * $Id: physmap.c,v 1.35 2004/09/16 23:27:13 gleixner Exp $ * * Normal mappings of chips in physical memory * @@ -51,7 +51,7 @@ static int __init init_physmap(void) const char **type; printk(KERN_NOTICE "physmap flash device: %lx at %lx\n", physmap_map.size, physmap_map.phys); - physmap_map.virt = (unsigned long)ioremap(physmap_map.phys, physmap_map.size); + physmap_map.virt = (void __iomem *)ioremap(physmap_map.phys, physmap_map.size); if (!physmap_map.virt) { printk("Failed to ioremap\n"); diff --git a/drivers/mtd/maps/pnc2000.c b/drivers/mtd/maps/pnc2000.c index b204786d52f8..3636d5a23c9a 100644 --- a/drivers/mtd/maps/pnc2000.c +++ b/drivers/mtd/maps/pnc2000.c @@ -5,7 +5,7 @@ * * This code is GPL * - * $Id: pnc2000.c,v 1.15 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: pnc2000.c,v 1.16 2004/09/16 23:27:13 gleixner Exp $ */ #include @@ -31,7 +31,7 @@ struct map_info pnc_map = { .size = WINDOW_SIZE, .bankwidth = 4, .phys = 0xFFFFFFFF, - .virt = WINDOW_ADDR, + .virt = (void __iomem *)WINDOW_ADDR, }; diff --git a/drivers/mtd/maps/redwood.c b/drivers/mtd/maps/redwood.c index acc3af90ad5c..00a518d43a88 100644 --- a/drivers/mtd/maps/redwood.c +++ b/drivers/mtd/maps/redwood.c @@ -1,5 +1,5 @@ /* - * $Id: redwood.c,v 1.8 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: redwood.c,v 1.9 2004/09/16 23:27:13 gleixner Exp $ * * drivers/mtd/maps/redwood.c * @@ -132,7 +132,7 @@ int __init init_redwood_flash(void) WINDOW_SIZE, WINDOW_ADDR); redwood_flash_map.virt = - (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); + (void __iomem *)ioremap(WINDOW_ADDR, WINDOW_SIZE); if (!redwood_flash_map.virt) { printk("init_redwood_flash: failed to ioremap\n"); diff --git a/drivers/mtd/maps/rpxlite.c b/drivers/mtd/maps/rpxlite.c index 837089a8f13d..24ca248dd460 100644 --- a/drivers/mtd/maps/rpxlite.c +++ b/drivers/mtd/maps/rpxlite.c @@ -1,5 +1,5 @@ /* - * $Id: rpxlite.c,v 1.20 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: rpxlite.c,v 1.21 2004/09/16 23:27:13 gleixner Exp $ * * Handle mapping of the flash on the RPX Lite and CLLF boards */ @@ -28,7 +28,7 @@ static struct map_info rpxlite_map = { int __init init_rpxlite(void) { printk(KERN_NOTICE "RPX Lite or CLLF flash device: %x at %x\n", WINDOW_SIZE*4, WINDOW_ADDR); - rpxlite_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); + rpxlite_map.virt = (void __iomem *)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); if (!rpxlite_map.virt) { printk("Failed to ioremap\n"); diff --git a/drivers/mtd/maps/sbc_gxx.c b/drivers/mtd/maps/sbc_gxx.c index 7a9cb1d45348..bb1823121cf0 100644 --- a/drivers/mtd/maps/sbc_gxx.c +++ b/drivers/mtd/maps/sbc_gxx.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - $Id: sbc_gxx.c,v 1.29 2004/07/12 22:38:29 dwmw2 Exp $ + $Id: sbc_gxx.c,v 1.30 2004/09/16 23:27:14 gleixner Exp $ The SBC-MediaGX / SBC-GXx has up to 16 MiB of Intel StrataFlash (28F320/28F640) in x8 mode. @@ -84,7 +84,7 @@ separate MTD devices. // Globals static volatile int page_in_window = -1; // Current page in window. -static unsigned long iomapadr; +static void __iomem *iomapadr; static spinlock_t sbc_gxx_spin = SPIN_LOCK_UNLOCKED; /* partition_info gives details on the logical partitions that the split the @@ -195,7 +195,7 @@ static void cleanup_sbc_gxx(void) int __init init_sbc_gxx(void) { - iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH); + iomapadr = (void __iomem *)ioremap(WINDOW_START, WINDOW_LENGTH); if (!iomapadr) { printk( KERN_ERR"%s: failed to ioremap memory region\n", sbc_gxx_map.name ); diff --git a/drivers/mtd/maps/sc520cdp.c b/drivers/mtd/maps/sc520cdp.c index 8269b6029c17..adb8f120b8dd 100644 --- a/drivers/mtd/maps/sc520cdp.c +++ b/drivers/mtd/maps/sc520cdp.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: sc520cdp.c,v 1.16 2004/07/12 21:59:45 dwmw2 Exp $ + * $Id: sc520cdp.c,v 1.17 2004/09/16 23:27:14 gleixner Exp $ * * * The SC520CDP is an evaluation board for the Elan SC520 processor available @@ -241,7 +241,7 @@ static int __init init_sc520cdp(void) printk(KERN_NOTICE "SC520 CDP flash device: 0x%lx at 0x%lx\n", sc520cdp_map[i].size, sc520cdp_map[i].phys); - sc520cdp_map[i].virt = (unsigned long)ioremap_nocache(sc520cdp_map[i].phys, sc520cdp_map[i].size); + sc520cdp_map[i].virt = (void __iomem *)ioremap_nocache(sc520cdp_map[i].phys, sc520cdp_map[i].size); if (!sc520cdp_map[i].virt) { printk("Failed to ioremap_nocache\n"); diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c index ff2328dbbc8c..288e4e19eb72 100644 --- a/drivers/mtd/maps/scb2_flash.c +++ b/drivers/mtd/maps/scb2_flash.c @@ -1,6 +1,6 @@ /* * MTD map driver for BIOS Flash on Intel SCB2 boards - * $Id: scb2_flash.c,v 1.8 2004/07/12 21:59:45 dwmw2 Exp $ + * $Id: scb2_flash.c,v 1.9 2004/09/16 23:27:14 gleixner Exp $ * Copyright (C) 2002 Sun Microsystems, Inc. * Tim Hockin * @@ -163,7 +163,7 @@ scb2_flash_probe(struct pci_dev *dev, const struct pci_device_id *ent) } scb2_map.phys = SCB2_ADDR; - scb2_map.virt = (unsigned long)scb2_ioaddr; + scb2_map.virt = (void __iomem *)scb2_ioaddr; scb2_map.size = SCB2_WINDOW; simple_map_init(&scb2_map); diff --git a/drivers/mtd/maps/scx200_docflash.c b/drivers/mtd/maps/scx200_docflash.c index 58855a15e3eb..031ad2e83029 100644 --- a/drivers/mtd/maps/scx200_docflash.c +++ b/drivers/mtd/maps/scx200_docflash.c @@ -2,7 +2,7 @@ Copyright (c) 2001,2002 Christer Weinigel - $Id: scx200_docflash.c,v 1.6 2004/07/12 21:59:45 dwmw2 Exp $ + $Id: scx200_docflash.c,v 1.7 2004/09/16 23:27:14 gleixner Exp $ National Semiconductor SCx200 flash mapped with DOCCS */ @@ -180,7 +180,7 @@ int __init init_scx200_docflash(void) simple_map_init(&scx200_docflash_map); scx200_docflash_map.phys = docmem.start; - scx200_docflash_map.virt = (unsigned long)ioremap(docmem.start, scx200_docflash_map.size); + scx200_docflash_map.virt = (void __iomem *)ioremap(docmem.start, scx200_docflash_map.size); if (!scx200_docflash_map.virt) { printk(KERN_ERR NAME ": failed to ioremap the flash\n"); release_resource(&docmem); diff --git a/drivers/mtd/maps/solutionengine.c b/drivers/mtd/maps/solutionengine.c index 9b2eebe1b97b..8ce5d897645c 100644 --- a/drivers/mtd/maps/solutionengine.c +++ b/drivers/mtd/maps/solutionengine.c @@ -1,5 +1,5 @@ /* - * $Id: solutionengine.c,v 1.13 2004/07/12 21:59:45 dwmw2 Exp $ + * $Id: solutionengine.c,v 1.14 2004/09/16 23:27:14 gleixner Exp $ * * Flash and EPROM on Hitachi Solution Engine and similar boards. * @@ -62,9 +62,9 @@ static int __init init_soleng_maps(void) /* First probe at offset 0 */ soleng_flash_map.phys = 0; - soleng_flash_map.virt = P2SEGADDR(0); + soleng_flash_map.virt = (void __iomem *)P2SEGADDR(0); soleng_eprom_map.phys = 0x01000000; - soleng_eprom_map.virt = P1SEGADDR(0x01000000); + soleng_eprom_map.virt = (void __iomem *)P1SEGADDR(0x01000000); simple_map_init(&soleng_eprom_map); simple_map_init(&soleng_flash_map); diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c index 2a9932c50959..4398538ed07d 100644 --- a/drivers/mtd/maps/sun_uflash.c +++ b/drivers/mtd/maps/sun_uflash.c @@ -1,4 +1,4 @@ -/* $Id: sun_uflash.c,v 1.9 2004/07/12 21:59:45 dwmw2 Exp $ +/* $Id: sun_uflash.c,v 1.10 2004/09/16 23:27:14 gleixner Exp $ * * sun_uflash - Driver implementation for user-programmable flash * present on many Sun Microsystems SME boardsets. @@ -97,7 +97,7 @@ int uflash_devinit(struct linux_ebus_device* edev) } pdev->map.phys = edev->resource[0].start; pdev->map.virt = - (unsigned long)ioremap_nocache(edev->resource[0].start, pdev->map.size); + (void __iomem *)ioremap_nocache(edev->resource[0].start, pdev->map.size); if(0 == pdev->map.virt) { printk("%s: failed to map device\n", __FUNCTION__); kfree(pdev->name); diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c index baff49bf7df3..27af674e0b03 100644 --- a/drivers/mtd/maps/uclinux.c +++ b/drivers/mtd/maps/uclinux.c @@ -5,7 +5,7 @@ * * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) * - * $Id: uclinux.c,v 1.7 2004/07/12 21:59:45 dwmw2 Exp $ + * $Id: uclinux.c,v 1.8 2004/09/16 23:27:14 gleixner Exp $ */ /****************************************************************************/ @@ -69,9 +69,10 @@ int __init uclinux_mtd_init(void) printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n", (int) mapp->map_priv_2, (int) mapp->size); - mapp->virt = ioremap_nocache(mapp->phys, mapp->size); + mapp->virt = (void __iomem *) + ioremap_nocache(mapp->phys, mapp->size); - if (!mapp->virt) { + if (mapp->virt == 0) { printk("uclinux[mtd]: ioremap_nocache() failed\n"); return(-EIO); } @@ -81,7 +82,7 @@ int __init uclinux_mtd_init(void) mtd = do_map_probe("map_ram", mapp); if (!mtd) { printk("uclinux[mtd]: failed to find a mapping?\n"); - iounmap(mapp->virt); + iounmap((void *) mapp->virt); return(-ENXIO); } diff --git a/drivers/mtd/maps/wr_sbc82xx_flash.c b/drivers/mtd/maps/wr_sbc82xx_flash.c index b7fdece51650..02b1b56f4858 100644 --- a/drivers/mtd/maps/wr_sbc82xx_flash.c +++ b/drivers/mtd/maps/wr_sbc82xx_flash.c @@ -1,5 +1,5 @@ /* - * $Id: wr_sbc82xx_flash.c,v 1.5 2004/07/15 14:52:02 dwmw2 Exp $ + * $Id: wr_sbc82xx_flash.c,v 1.6 2004/09/16 23:27:14 gleixner Exp $ * * Map for flash chips on Wind River PowerQUICC II SBC82xx board. * @@ -116,7 +116,7 @@ int __init init_sbc82xx_flash(void) } printk(" at %08lx)\n", sbc82xx_flash_map[i].phys); - sbc82xx_flash_map[i].virt = (unsigned long)ioremap(sbc82xx_flash_map[i].phys, sbc82xx_flash_map[i].size); + sbc82xx_flash_map[i].virt = (void __iomem *)ioremap(sbc82xx_flash_map[i].phys, sbc82xx_flash_map[i].size); if (!sbc82xx_flash_map[i].virt) { printk("Failed to ioremap\n"); diff --git a/include/linux/mtd/doc2000.h b/include/linux/mtd/doc2000.h index 0fd8f49c649b..bc58c4f55ab0 100644 --- a/include/linux/mtd/doc2000.h +++ b/include/linux/mtd/doc2000.h @@ -6,7 +6,7 @@ * Copyright (C) 2002-2003 Greg Ungerer * Copyright (C) 2002-2003 SnapGear Inc * - * $Id: doc2000.h,v 1.22 2003/11/05 10:51:36 dwmw2 Exp $ + * $Id: doc2000.h,v 1.23 2004/09/16 23:26:08 gleixner Exp $ * * Released under GPL */ @@ -89,8 +89,8 @@ #define WriteDOC_(d, adr, reg) do{ *(volatile __u16 *)(((unsigned long)adr)+((reg)<<1)) = (__u16)d; wmb();} while(0) #define DOC_IOREMAP_LEN 0x4000 #else -#define ReadDOC_(adr, reg) readb(((unsigned long)adr) + (reg)) -#define WriteDOC_(d, adr, reg) writeb(d, ((unsigned long)adr) + (reg)) +#define ReadDOC_(adr, reg) readb((void __iomem *)(((unsigned long)adr) + (reg))) +#define WriteDOC_(d, adr, reg) writeb(d, (void __iomem *)(((unsigned long)adr) + (reg))) #define DOC_IOREMAP_LEN 0x2000 #endif @@ -168,7 +168,7 @@ struct Nand { struct DiskOnChip { unsigned long physadr; - unsigned long virtadr; + void __iomem *virtadr; unsigned long totlen; unsigned char ChipID; /* Type of DiskOnChip */ int ioreg; -- cgit v1.2.3 From 8eb2a259ae800d553296d0a1b6b2cd6ebff6c569 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 21 Oct 2004 01:50:36 +0100 Subject: MTD map access: Fix calculation of the number of longs in a bus access Patch from Ben Dooks Signed-Off-By: David Woodhouse --- include/linux/mtd/map.h | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index 278d0f30de20..a960be2cc33c 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h @@ -1,6 +1,6 @@ /* Overhauled routines for dealing with different mmap regions of flash */ -/* $Id: map.h,v 1.43 2004/07/14 13:30:27 dwmw2 Exp $ */ +/* $Id: map.h,v 1.45 2004/09/21 14:31:17 bjd Exp $ */ #ifndef __LINUX_MTD_MAP_H__ #define __LINUX_MTD_MAP_H__ @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,11 @@ #define map_bankwidth_is_4(map) (0) #endif +/* ensure we never evaluate anything shorted than an unsigned long + * to zero, and ensure we'll never miss the end of an comparison (bjd) */ + +#define map_calc_words(map) ((map_bankwidth(map) + (sizeof(unsigned long)-1))/ sizeof(unsigned long)) + #ifdef CONFIG_MTD_MAP_BANK_WIDTH_8 # ifdef map_bankwidth # undef map_bankwidth @@ -63,12 +69,12 @@ # undef map_bankwidth_is_large # define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8) # undef map_words -# define map_words(map) (map_bankwidth(map) / sizeof(unsigned long)) +# define map_words(map) map_calc_words(map) # endif # else # define map_bankwidth(map) 8 # define map_bankwidth_is_large(map) (BITS_PER_LONG < 64) -# define map_words(map) (map_bankwidth(map) / sizeof(unsigned long)) +# define map_words(map) map_calc_words(map) # endif #define map_bankwidth_is_8(map) (map_bankwidth(map) == 8) #undef MAX_MAP_BANKWIDTH @@ -84,11 +90,11 @@ # undef map_bankwidth_is_large # define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8) # undef map_words -# define map_words(map) (map_bankwidth(map) / sizeof(unsigned long)) +# define map_words(map) map_calc_words(map) # else # define map_bankwidth(map) 16 # define map_bankwidth_is_large(map) (1) -# define map_words(map) (map_bankwidth(map) / sizeof(unsigned long)) +# define map_words(map) map_calc_words(map) # endif #define map_bankwidth_is_16(map) (map_bankwidth(map) == 16) #undef MAX_MAP_BANKWIDTH @@ -104,11 +110,11 @@ # undef map_bankwidth_is_large # define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8) # undef map_words -# define map_words(map) (map_bankwidth(map) / sizeof(unsigned long)) +# define map_words(map) map_calc_words(map) # else # define map_bankwidth(map) 32 # define map_bankwidth_is_large(map) (1) -# define map_words(map) (map_bankwidth(map) / sizeof(unsigned long)) +# define map_words(map) map_calc_words(map) # endif #define map_bankwidth_is_32(map) (map_bankwidth(map) == 32) #undef MAX_MAP_BANKWIDTH -- cgit v1.2.3 From 637465e067650cadceadd427af6b869a9a8fce70 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 21 Oct 2004 02:13:45 +0100 Subject: MTD: NOR flash chip driver updates Mostly from Eric Biederman for supporting BIOS flash. - Move support firmware hub style lock and unlock into fhw_lock.h (from cfi_cmdset_0002) - Move cfi_varsize_frob into cfi_util from cfi_cmdset_0001.c and cfi_cmdset_0002.c - reduce gen_probe probe failuers to a debug level message - Modify cfi_fixup to take a struct mtd_info instead of a struct map_info So that the fixup routines can modify the mtd functions. - Modify cfi_cmdset_0001() to allocate and initialize the mtd structure before calling cfi_fixup. - Modify cfi_cmdset_0002() to allocate and initialize the mtd structure before calling cfi_fixup. - Refactor the hard coded fixups in cfi_cmdset_0001 and cfi_cmdset_0002 so the improved cfi_fixup infrastructure. - Rewrote amd76xrom and ichxrom. They now report their starting physical address in their name. They now both handle multiple bankwidth configurations They both can create multipe mtd devices. They both now assume the rom windows are properly opened by the BIOS or whatever runs previous to them. Their code is now synchromized so it is almost identical, and could be a starting point for a x86_rom_probe. Signed-Off-By: David Woodhouse --- drivers/mtd/chips/cfi_cmdset_0001.c | 283 ++++++++------------ drivers/mtd/chips/cfi_cmdset_0002.c | 504 ++++++++++-------------------------- drivers/mtd/chips/cfi_probe.c | 21 +- drivers/mtd/chips/cfi_util.c | 102 +++++++- drivers/mtd/chips/fwh_lock.h | 107 ++++++++ drivers/mtd/chips/gen_probe.c | 12 +- drivers/mtd/chips/jedec_probe.c | 178 ++++++++----- drivers/mtd/maps/amd76xrom.c | 382 +++++++++++++++------------ drivers/mtd/maps/ichxrom.c | 494 +++++++++++++++++------------------ include/linux/mtd/cfi.h | 40 ++- 10 files changed, 1067 insertions(+), 1056 deletions(-) create mode 100644 drivers/mtd/chips/fwh_lock.h (limited to 'include/linux') diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index c1e3536c2147..cca36dd074a5 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -4,7 +4,7 @@ * * (C) 2000 Red Hat. GPL'd * - * $Id: cfi_cmdset_0001.c,v 1.154 2004/08/09 13:19:43 dwmw2 Exp $ + * $Id: cfi_cmdset_0001.c,v 1.157 2004/10/15 20:00:26 nico Exp $ * * * 10/10/2000 Nicolas Pitre @@ -39,6 +39,12 @@ // debugging, turns off buffer write mode if set to 1 #define FORCE_WORD_WRITE 0 +#define MANUFACTURER_INTEL 0x0089 +#define I82802AB 0x00ad +#define I82802AC 0x00ac +#define MANUFACTURER_ST 0x0020 +#define M50LPW080 0x002F + static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); //static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); //static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); @@ -55,7 +61,7 @@ static void cfi_intelext_destroy(struct mtd_info *); struct mtd_info *cfi_cmdset_0001(struct map_info *, int); -static struct mtd_info *cfi_intelext_setup (struct map_info *); +static struct mtd_info *cfi_intelext_setup (struct mtd_info *); static int cfi_intelext_partition_fixup(struct map_info *, struct cfi_private **); static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, @@ -63,6 +69,11 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len); +static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode); +static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr); +#include "fwh_lock.h" + + /* * *********** SETUP AND PROBE BITS *********** @@ -123,8 +134,9 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp) #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE /* Some Intel Strata Flash prior to FPO revision C has bugs in this area */ -static void fixup_intel_strataflash(struct map_info *map, void* param) +static void fixup_intel_strataflash(struct mtd_info *mtd, void* param) { + struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; struct cfi_pri_amdstd *extp = cfi->cmdset_priv; @@ -134,16 +146,18 @@ static void fixup_intel_strataflash(struct map_info *map, void* param) } #endif -static void fixup_st_m28w320ct(struct map_info *map, void* param) +static void fixup_st_m28w320ct(struct mtd_info *mtd, void* param) { + struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; cfi->cfiq->BufWriteTimeoutTyp = 0; /* Not supported */ cfi->cfiq->BufWriteTimeoutMax = 0; /* Not supported */ } -static void fixup_st_m28w320cb(struct map_info *map, void* param) +static void fixup_st_m28w320cb(struct mtd_info *mtd, void* param) { + struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; /* Note this is done after the region info is endian swapped */ @@ -151,24 +165,51 @@ static void fixup_st_m28w320cb(struct map_info *map, void* param) (cfi->cfiq->EraseRegionInfo[1] & 0xffff0000) | 0x3e; }; -static struct cfi_fixup fixup_table[] = { +static void fixup_use_point(struct mtd_info *mtd, void *param) +{ + struct map_info *map = mtd->priv; + if (!mtd->point && map_is_linear(map)) { + mtd->point = cfi_intelext_point; + mtd->unpoint = cfi_intelext_unpoint; + } +} + +static void fixup_use_write_buffers(struct mtd_info *mtd, void *param) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + if (cfi->cfiq->BufWriteTimeoutTyp) { + printk(KERN_INFO "Using buffer write method\n" ); + mtd->write = cfi_intelext_write_buffers; + } +} + +static struct cfi_fixup cfi_fixup_table[] = { #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE - { - CFI_MFR_ANY, CFI_ID_ANY, - fixup_intel_strataflash, NULL - }, + { CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL }, #endif - { - 0x0020, /* STMicroelectronics */ - 0x00ba, /* M28W320CT */ - fixup_st_m28w320ct, NULL - }, { - 0x0020, /* STMicroelectronics */ - 0x00bb, /* M28W320CB */ - fixup_st_m28w320cb, NULL - }, { - 0, 0, NULL, NULL - } +#if !FORCE_WORD_WRITE + { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL }, +#endif + { CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct, NULL }, + { CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb, NULL }, + { 0, 0, NULL, NULL } +}; + +static struct cfi_fixup jedec_fixup_table[] = { + { MANUFACTURER_INTEL, I82802AB, fixup_use_fwh_lock, NULL, }, + { MANUFACTURER_INTEL, I82802AC, fixup_use_fwh_lock, NULL, }, + { MANUFACTURER_ST, M50LPW080, fixup_use_fwh_lock, NULL, }, + { 0, 0, NULL, NULL } +}; +static struct cfi_fixup fixup_table[] = { + /* The CFI vendor ids and the JEDEC vendor IDs appear + * to be common. It is like the devices id's are as + * well. This table is to pick all cases where + * we know that is the case. + */ + { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_point, NULL }, + { 0, 0, NULL, NULL } }; /* This routine is made available to other mtd code via @@ -181,8 +222,30 @@ static struct cfi_fixup fixup_table[] = { struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) { struct cfi_private *cfi = map->fldrv_priv; + struct mtd_info *mtd; int i; + mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); + if (!mtd) { + printk(KERN_ERR "Failed to allocate memory for MTD device\n"); + return NULL; + } + memset(mtd, 0, sizeof(*mtd)); + mtd->priv = map; + mtd->type = MTD_NORFLASH; + + /* Fill in the default mtd operations */ + mtd->erase = cfi_intelext_erase_varsize; + mtd->read = cfi_intelext_read; + mtd->write = cfi_intelext_write_words; + mtd->sync = cfi_intelext_sync; + mtd->lock = cfi_intelext_lock; + mtd->unlock = cfi_intelext_unlock; + mtd->suspend = cfi_intelext_suspend; + mtd->resume = cfi_intelext_resume; + mtd->flags = MTD_CAP_NORFLASH; + mtd->name = map->name; + if (cfi->cfi_mode == CFI_MODE_CFI) { /* * It's a real CFI chip, not one for which the probe @@ -193,8 +256,10 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) struct cfi_pri_intelext *extp; extp = (struct cfi_pri_intelext*)cfi_read_pri(map, adr, sizeof(*extp), "Intel/Sharp"); - if (!extp) + if (!extp) { + kfree(mtd); return NULL; + } /* Do some byteswapping if necessary */ extp->FeatureSupport = le32_to_cpu(extp->FeatureSupport); @@ -204,7 +269,7 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) /* Install our own private info structure */ cfi->cmdset_priv = extp; - cfi_fixup(map, fixup_table); + cfi_fixup(mtd, cfi_fixup_table); #ifdef DEBUG_CFI_FEATURES /* Tell the user about it in lots of lovely detail */ @@ -215,6 +280,12 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) printk(KERN_NOTICE "cfi_cmdset_0001: Erase suspend on write enabled\n"); } } + else if (cfi->cfi_mode == CFI_MODE_JEDEC) { + /* Apply jedec specific fixups */ + cfi_fixup(mtd, jedec_fixup_table); + } + /* Apply generic fixups */ + cfi_fixup(mtd, fixup_table); for (i=0; i< cfi->numchips; i++) { cfi->chips[i].word_write_time = 1<cfiq->WordWriteTimeoutTyp; @@ -225,28 +296,19 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) map->fldrv = &cfi_intelext_chipdrv; - return cfi_intelext_setup(map); + return cfi_intelext_setup(mtd); } -static struct mtd_info *cfi_intelext_setup(struct map_info *map) +static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd) { + struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; - struct mtd_info *mtd; unsigned long offset = 0; int i,j; unsigned long devsize = (1<cfiq->DevSize) * cfi->interleave; - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); //printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips); - if (!mtd) { - printk(KERN_ERR "Failed to allocate memory for MTD device\n"); - goto setup_err; - } - - memset(mtd, 0, sizeof(*mtd)); - mtd->priv = map; - mtd->type = MTD_NORFLASH; mtd->size = devsize * cfi->numchips; mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; @@ -286,34 +348,10 @@ static struct mtd_info *cfi_intelext_setup(struct map_info *map) mtd->eraseregions[i].numblocks); } - /* Also select the correct geometry setup too */ - mtd->erase = cfi_intelext_erase_varsize; - mtd->read = cfi_intelext_read; - - if (map_is_linear(map)) { - mtd->point = cfi_intelext_point; - mtd->unpoint = cfi_intelext_unpoint; - } - - if ( cfi->cfiq->BufWriteTimeoutTyp && !FORCE_WORD_WRITE) { - printk(KERN_INFO "Using buffer write method\n" ); - mtd->write = cfi_intelext_write_buffers; - } else { - printk(KERN_INFO "Using word write method\n" ); - mtd->write = cfi_intelext_write_words; - } #if 0 mtd->read_user_prot_reg = cfi_intelext_read_user_prot_reg; mtd->read_fact_prot_reg = cfi_intelext_read_fact_prot_reg; #endif - mtd->sync = cfi_intelext_sync; - mtd->lock = cfi_intelext_lock; - mtd->unlock = cfi_intelext_unlock; - mtd->suspend = cfi_intelext_suspend; - mtd->resume = cfi_intelext_resume; - mtd->flags = MTD_CAP_NORFLASH; - map->fldrv = &cfi_intelext_chipdrv; - mtd->name = map->name; /* This function has the potential to distort the reality a bit and therefore should be called last. */ @@ -515,7 +553,8 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr return 0; case FL_ERASING: - if (!(cfip->FeatureSupport & 2) || + if (!cfip || + !(cfip->FeatureSupport & 2) || !(mode == FL_READY || mode == FL_POINT || (mode == FL_WRITING && (cfip->SuspendCmdSupport & 1)))) goto sleep; @@ -884,7 +923,7 @@ static int cfi_intelext_read_user_prot_reg (struct mtd_info *mtd, loff_t from, s int base_offst,reg_sz; /* Check that we actually have some protection registers */ - if(!(extp->FeatureSupport&64)){ + if(!extp || !(extp->FeatureSupport&64)){ printk(KERN_WARNING "%s: This flash device has no protection data to read!\n",map->name); return 0; } @@ -903,7 +942,7 @@ static int cfi_intelext_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, s int base_offst,reg_sz; /* Check that we actually have some protection registers */ - if(!(extp->FeatureSupport&64)){ + if(!extp || !(extp->FeatureSupport&64)){ printk(KERN_WARNING "%s: This flash device has no protection data to read!\n",map->name); return 0; } @@ -1308,102 +1347,6 @@ static int cfi_intelext_write_buffers (struct mtd_info *mtd, loff_t to, return 0; } -typedef int (*varsize_frob_t)(struct map_info *map, struct flchip *chip, - unsigned long adr, int len, void *thunk); - -static int cfi_intelext_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob, - loff_t ofs, size_t len, void *thunk) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - unsigned long adr; - int chipnum, ret = 0; - int i, first; - struct mtd_erase_region_info *regions = mtd->eraseregions; - - if (ofs > mtd->size) - return -EINVAL; - - if ((len + ofs) > mtd->size) - return -EINVAL; - - /* Check that both start and end of the requested erase are - * aligned with the erasesize at the appropriate addresses. - */ - - i = 0; - - /* Skip all erase regions which are ended before the start of - the requested erase. Actually, to save on the calculations, - we skip to the first erase region which starts after the - start of the requested erase, and then go back one. - */ - - while (i < mtd->numeraseregions && ofs >= regions[i].offset) - i++; - i--; - - /* OK, now i is pointing at the erase region in which this - erase request starts. Check the start of the requested - erase range is aligned with the erase size which is in - effect here. - */ - - if (ofs & (regions[i].erasesize-1)) - return -EINVAL; - - /* Remember the erase region we start on */ - first = i; - - /* Next, check that the end of the requested erase is aligned - * with the erase region at that address. - */ - - while (inumeraseregions && (ofs + len) >= regions[i].offset) - i++; - - /* As before, drop back one to point at the region in which - the address actually falls - */ - i--; - - if ((ofs + len) & (regions[i].erasesize-1)) - return -EINVAL; - - chipnum = ofs >> cfi->chipshift; - adr = ofs - (chipnum << cfi->chipshift); - - i=first; - - while(len) { - unsigned long chipmask; - int size = regions[i].erasesize; - - ret = (*frob)(map, &cfi->chips[chipnum], adr, size, thunk); - - if (ret) - return ret; - - adr += size; - len -= size; - - chipmask = (1 << cfi->chipshift) - 1; - if ((adr & chipmask) == ((regions[i].offset + size * regions[i].numblocks) & chipmask)) - i++; - - if (adr >> cfi->chipshift) { - adr = 0; - chipnum++; - - if (chipnum >= cfi->numchips) - break; - } - } - - return 0; -} - - static int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk) { @@ -1550,7 +1493,7 @@ int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) ofs = instr->addr; len = instr->len; - ret = cfi_intelext_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL); + ret = cfi_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL); if (ret) return ret; @@ -1695,18 +1638,18 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len) #ifdef DEBUG_LOCK_BITS printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n", __FUNCTION__, ofs, len); - cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock, - ofs, len, 0); + cfi_varsize_frob(mtd, do_printlockstatus_oneblock, + ofs, len, 0); #endif - ret = cfi_intelext_varsize_frob(mtd, do_xxlock_oneblock, - ofs, len, DO_XXLOCK_ONEBLOCK_LOCK); + ret = cfi_varsize_frob(mtd, do_xxlock_oneblock, + ofs, len, DO_XXLOCK_ONEBLOCK_LOCK); #ifdef DEBUG_LOCK_BITS printk(KERN_DEBUG "%s: lock status after, ret=%d\n", __FUNCTION__, ret); - cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock, - ofs, len, 0); + cfi_varsize_frob(mtd, do_printlockstatus_oneblock, + ofs, len, 0); #endif return ret; @@ -1719,18 +1662,18 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) #ifdef DEBUG_LOCK_BITS printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n", __FUNCTION__, ofs, len); - cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock, - ofs, len, 0); + cfi_varsize_frob(mtd, do_printlockstatus_oneblock, + ofs, len, 0); #endif - ret = cfi_intelext_varsize_frob(mtd, do_xxlock_oneblock, + ret = cfi_varsize_frob(mtd, do_xxlock_oneblock, ofs, len, DO_XXLOCK_ONEBLOCK_UNLOCK); #ifdef DEBUG_LOCK_BITS printk(KERN_DEBUG "%s: lock status after, ret=%d\n", __FUNCTION__, ret); - cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock, - ofs, len, 0); + cfi_varsize_frob(mtd, do_printlockstatus_oneblock, + ofs, len, 0); #endif return ret; diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 5bd15f548f22..1f9fe2ae780b 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -13,7 +13,7 @@ * * This code is GPL * - * $Id: cfi_cmdset_0002.c,v 1.106 2004/08/09 14:02:32 dwmw2 Exp $ + * $Id: cfi_cmdset_0002.c,v 1.110 2004/09/24 04:26:04 eric Exp $ * */ @@ -40,13 +40,15 @@ #define MAX_WORD_RETRIES 3 +#define MANUFACTURER_AMD 0x0001 +#define MANUFACTURER_SST 0x00BF +#define SST49LF004B 0x0060 + static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *); static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *); -static int cfi_amdstd_lock_varsize(struct mtd_info *, loff_t, size_t); -static int cfi_amdstd_unlock_varsize(struct mtd_info *, loff_t, size_t); static void cfi_amdstd_sync (struct mtd_info *); static int cfi_amdstd_suspend (struct mtd_info *); static void cfi_amdstd_resume (struct mtd_info *); @@ -55,8 +57,11 @@ static int cfi_amdstd_secsi_read (struct mtd_info *, loff_t, size_t, size_t *, u static void cfi_amdstd_destroy(struct mtd_info *); struct mtd_info *cfi_cmdset_0002(struct map_info *, int); -static struct mtd_info *cfi_amdstd_setup (struct map_info *); +static struct mtd_info *cfi_amdstd_setup (struct mtd_info *); +static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode); +static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr); +#include "fwh_lock.h" static struct mtd_chip_driver cfi_amdstd_chipdrv = { .probe = NULL, /* Not usable directly */ @@ -66,7 +71,6 @@ static struct mtd_chip_driver cfi_amdstd_chipdrv = { }; -/* #define DEBUG_LOCK_BITS */ /* #define DEBUG_CFI_FEATURES */ @@ -122,8 +126,9 @@ static void cfi_tell_features(struct cfi_pri_amdstd *extp) #ifdef AMD_BOOTLOC_BUG /* Wheee. Bring me the head of someone at AMD. */ -static void fixup_amd_bootblock(struct map_info *map, void* param) +static void fixup_amd_bootblock(struct mtd_info *mtd, void* param) { + struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; struct cfi_pri_amdstd *extp = cfi->cmdset_priv; __u8 major = extp->MajorVersion; @@ -141,25 +146,92 @@ static void fixup_amd_bootblock(struct map_info *map, void* param) } #endif -static struct cfi_fixup fixup_table[] = { +static void fixup_use_write_buffers(struct mtd_info *mtd, void *param) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + if (cfi->cfiq->BufWriteTimeoutTyp) { + DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" ); + mtd->write = cfi_amdstd_write_buffers; + } +} + +static void fixup_use_secsi(struct mtd_info *mtd, void *param) +{ + /* Setup for chips with a secsi area */ + mtd->read_user_prot_reg = cfi_amdstd_secsi_read; + mtd->read_fact_prot_reg = cfi_amdstd_secsi_read; +} + +static void fixup_use_erase_chip(struct mtd_info *mtd, void *param) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + if ((cfi->cfiq->NumEraseRegions == 1) && + ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0)) { + mtd->erase = cfi_amdstd_erase_chip; + } + +} + +static struct cfi_fixup cfi_fixup_table[] = { #ifdef AMD_BOOTLOC_BUG - { - 0x0001, /* AMD */ - CFI_ID_ANY, - fixup_amd_bootblock, NULL - }, + { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL }, +#endif + { CFI_MFR_AMD, 0x0050, fixup_use_secsi, NULL, }, + { CFI_MFR_AMD, 0x0053, fixup_use_secsi, NULL, }, + { CFI_MFR_AMD, 0x0055, fixup_use_secsi, NULL, }, + { CFI_MFR_AMD, 0x0056, fixup_use_secsi, NULL, }, + { CFI_MFR_AMD, 0x005C, fixup_use_secsi, NULL, }, + { CFI_MFR_AMD, 0x005F, fixup_use_secsi, NULL, }, +#if !FORCE_WORD_WRITE + { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, #endif { 0, 0, NULL, NULL } }; +static struct cfi_fixup jedec_fixup_table[] = { + { MANUFACTURER_SST, SST49LF004B, fixup_use_fwh_lock, NULL, }, + { 0, 0, NULL, NULL } +}; + +static struct cfi_fixup fixup_table[] = { + /* The CFI vendor ids and the JEDEC vendor IDs appear + * to be common. It is like the devices id's are as + * well. This table is to pick all cases where + * we know that is the case. + */ + { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL }, + { 0, 0, NULL, NULL } +}; struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) { struct cfi_private *cfi = map->fldrv_priv; - unsigned char bootloc; + struct mtd_info *mtd; int i; + mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); + if (!mtd) { + printk(KERN_WARNING "Failed to allocate memory for MTD device\n"); + return NULL; + } + memset(mtd, 0, sizeof(*mtd)); + mtd->priv = map; + mtd->type = MTD_NORFLASH; + + /* Fill in the default mtd operations */ + mtd->erase = cfi_amdstd_erase_varsize; + mtd->write = cfi_amdstd_write_words; + mtd->read = cfi_amdstd_read; + mtd->sync = cfi_amdstd_sync; + mtd->suspend = cfi_amdstd_suspend; + mtd->resume = cfi_amdstd_resume; + mtd->flags = MTD_CAP_NORFLASH; + mtd->name = map->name; + if (cfi->cfi_mode==CFI_MODE_CFI){ + unsigned char bootloc; /* * It's a real CFI chip, not one for which the probe * routine faked a CFI structure. So we read the feature @@ -169,13 +241,16 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) struct cfi_pri_amdstd *extp; extp = (struct cfi_pri_amdstd*)cfi_read_pri(map, adr, sizeof(*extp), "Amd/Fujitsu"); - if (!extp) + if (!extp) { + kfree(mtd); return NULL; + } /* Install our own private info structure */ cfi->cmdset_priv = extp; - cfi_fixup(map, fixup_table); + /* Apply cfi device specific fixups */ + cfi_fixup(mtd, cfi_fixup_table); #ifdef DEBUG_CFI_FEATURES /* Tell the user about it in lots of lovely detail */ @@ -201,43 +276,28 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) cfi->cfiq->EraseRegionInfo[j] = swap; } } - /* - * These might already be setup (more correctly) by - * jedec_probe.c - still need it for cfi_probe.c path. - */ - if ( ! (cfi->addr_unlock1 && cfi->addr_unlock2) ) { - switch (cfi->device_type) { - case CFI_DEVICETYPE_X8: - cfi->addr_unlock1 = 0x555; - cfi->addr_unlock2 = 0x2aa; - break; - case CFI_DEVICETYPE_X16: - cfi->addr_unlock1 = 0xaaa; - if (map_bankwidth(map) == cfi_interleave(cfi)) { - /* X16 chip(s) in X8 mode */ - cfi->addr_unlock2 = 0x555; - } else { - cfi->addr_unlock2 = 0x554; - } - break; - case CFI_DEVICETYPE_X32: - cfi->addr_unlock1 = 0x1554; - if (map_bankwidth(map) == cfi_interleave(cfi)*2) { - /* X32 chip(s) in X16 mode */ - cfi->addr_unlock1 = 0xaaa; - } else { - cfi->addr_unlock2 = 0xaa8; - } - break; - default: - printk(KERN_WARNING - "MTD %s(): Unsupported device type %d\n", - __func__, cfi->device_type); - return NULL; - } + /* Set the default CFI lock/unlock addresses */ + cfi->addr_unlock1 = 0x555; + cfi->addr_unlock2 = 0x2aa; + /* Modify the unlock address if we are in compatibility mode */ + if ( /* x16 in x8 mode */ + ((cfi->device_type == CFI_DEVICETYPE_X8) && + (cfi->cfiq->InterfaceDesc == 2)) || + /* x32 in x16 mode */ + ((cfi->device_type == CFI_DEVICETYPE_X16) && + (cfi->cfiq->InterfaceDesc == 4))) + { + cfi->addr_unlock1 = 0xaaa; + cfi->addr_unlock2 = 0x555; } } /* CFI mode */ + else if (cfi->cfi_mode == CFI_MODE_JEDEC) { + /* Apply jedec specific fixups */ + cfi_fixup(mtd, jedec_fixup_table); + } + /* Apply generic fixups */ + cfi_fixup(mtd, fixup_table); for (i=0; i< cfi->numchips; i++) { cfi->chips[i].word_write_time = 1<cfiq->WordWriteTimeoutTyp; @@ -246,32 +306,22 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) } map->fldrv = &cfi_amdstd_chipdrv; - - return cfi_amdstd_setup(map); + + return cfi_amdstd_setup(mtd); } -static struct mtd_info *cfi_amdstd_setup(struct map_info *map) +static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) { + struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; - struct mtd_info *mtd; unsigned long devsize = (1<cfiq->DevSize) * cfi->interleave; unsigned long offset = 0; int i,j; - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); printk(KERN_NOTICE "number of %s chips: %d\n", (cfi->cfi_mode == CFI_MODE_CFI)?"CFI":"JEDEC",cfi->numchips); - - if (!mtd) { - printk(KERN_WARNING "Failed to allocate memory for MTD device\n"); - goto setup_err; - } - - memset(mtd, 0, sizeof(*mtd)); - mtd->priv = map; - mtd->type = MTD_NORFLASH; - /* Also select the correct geometry setup too */ + /* Select the correct geometry setup */ mtd->size = devsize * cfi->numchips; mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; @@ -312,54 +362,10 @@ static struct mtd_info *cfi_amdstd_setup(struct map_info *map) } #endif - if (mtd->numeraseregions == 1 - && ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) + 1) == 1) { - mtd->erase = cfi_amdstd_erase_chip; - } else { - mtd->erase = cfi_amdstd_erase_varsize; - mtd->lock = cfi_amdstd_lock_varsize; - mtd->unlock = cfi_amdstd_unlock_varsize; - } - - if ( cfi->cfiq->BufWriteTimeoutTyp && !FORCE_WORD_WRITE) { - DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" ); - mtd->write = cfi_amdstd_write_buffers; - } else { - DEBUG(MTD_DEBUG_LEVEL1, "Using word write method\n" ); - mtd->write = cfi_amdstd_write_words; - } - - mtd->read = cfi_amdstd_read; - /* FIXME: erase-suspend-program is broken. See http://lists.infradead.org/pipermail/linux-mtd/2003-December/009001.html */ printk(KERN_NOTICE "cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.\n"); - /* does this chip have a secsi area? */ - if(cfi->mfr==1){ - - switch(cfi->id){ - case 0x50: - case 0x53: - case 0x55: - case 0x56: - case 0x5C: - case 0x5F: - /* Yes */ - mtd->read_user_prot_reg = cfi_amdstd_secsi_read; - mtd->read_fact_prot_reg = cfi_amdstd_secsi_read; - default: - ; - } - } - - - mtd->sync = cfi_amdstd_sync; - mtd->suspend = cfi_amdstd_suspend; - mtd->resume = cfi_amdstd_resume; - mtd->flags = MTD_CAP_NORFLASH; - map->fldrv = &cfi_amdstd_chipdrv; - mtd->name = map->name; __module_get(THIS_MODULE); return mtd; @@ -434,6 +440,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr goto sleep; if (!(mode == FL_READY || mode == FL_POINT + || !cfip || (mode == FL_WRITING && (cfip->EraseSuspend & 0x2)) || (mode == FL_WRITING && (cfip->EraseSuspend & 0x1)))) goto sleep; @@ -624,14 +631,12 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi chip->state = FL_READY; - /* should these be CFI_DEVICETYPE_X8 instead of cfi->device_type? */ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x88, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); map_copy_from(map, buf, adr, len); - /* should these be CFI_DEVICETYPE_X8 instead of cfi->device_type? */ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); @@ -732,17 +737,9 @@ static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned ENABLE_VPP(map); retry: - /* - * The CFI_DEVICETYPE_X8 argument is needed even when - * cfi->device_type != CFI_DEVICETYPE_X8. The addresses for - * command sequences don't scale even when the device is - * wider. This is the case for many of the cfi_send_gen_cmd() - * below. I'm not sure, however, why some use - * cfi->device_type. - */ - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); map_write(map, datum, adr); chip->state = FL_WRITING; @@ -958,7 +955,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, struct cfi_private *cfi = map->fldrv_priv; unsigned long timeo = jiffies + HZ; /* see comments in do_write_oneword() regarding uWriteTimeo. */ - static unsigned long uWriteTimeout = ( HZ / 1000 ) + 1; + unsigned long uWriteTimeout = ( HZ / 1000 ) + 1; int ret = -EIO; unsigned long cmd_adr; int z, words; @@ -980,9 +977,9 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, __func__, adr, datum.x[0] ); ENABLE_VPP(map); - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); + //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); /* Write Buffer Load */ map_write(map, CMD(0x25), cmd_adr); @@ -1081,8 +1078,8 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, size_t local_len = (-ofs)&(map_bankwidth(map)-1); if (local_len > len) local_len = len; - ret = cfi_amdstd_write_words(mtd, to, local_len, - retlen, buf); + ret = cfi_amdstd_write_words(mtd, ofs + (chipnum<chipshift), + local_len, retlen, buf); if (ret) return ret; ofs += local_len; @@ -1128,7 +1125,8 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, if (len) { size_t retlen_dregs = 0; - ret = cfi_amdstd_write_words(mtd, to, len, &retlen_dregs, buf); + ret = cfi_amdstd_write_words(mtd, ofs + (chipnum<chipshift), + len, &retlen_dregs, buf); *retlen += retlen_dregs; return ret; @@ -1163,12 +1161,12 @@ static inline int do_erase_chip(struct map_info *map, struct flchip *chip) __func__, chip->start ); ENABLE_VPP(map); - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x10, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x10, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); chip->state = FL_ERASING; chip->erase_suspended = 0; @@ -1229,100 +1227,7 @@ static inline int do_erase_chip(struct map_info *map, struct flchip *chip) } -typedef int (*frob_t)(struct map_info *map, struct flchip *chip, - unsigned long adr, void *thunk); - - -static int cfi_amdstd_varsize_frob(struct mtd_info *mtd, frob_t frob, - loff_t ofs, size_t len, void *thunk) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - unsigned long adr; - int chipnum, ret = 0; - int i, first; - struct mtd_erase_region_info *regions = mtd->eraseregions; - - if (ofs > mtd->size) - return -EINVAL; - - if ((len + ofs) > mtd->size) - return -EINVAL; - - /* Check that both start and end of the requested erase are - * aligned with the erasesize at the appropriate addresses. - */ - - i = 0; - - /* Skip all erase regions which are ended before the start of - the requested erase. Actually, to save on the calculations, - we skip to the first erase region which starts after the - start of the requested erase, and then go back one. - */ - - while (i < mtd->numeraseregions && ofs >= regions[i].offset) - i++; - i--; - - /* OK, now i is pointing at the erase region in which this - erase request starts. Check the start of the requested - erase range is aligned with the erase size which is in - effect here. - */ - - if (ofs & (regions[i].erasesize-1)) - return -EINVAL; - - /* Remember the erase region we start on */ - first = i; - - /* Next, check that the end of the requested erase is aligned - * with the erase region at that address. - */ - - while (inumeraseregions && (ofs + len) >= regions[i].offset) - i++; - - /* As before, drop back one to point at the region in which - the address actually falls - */ - i--; - - if ((ofs + len) & (regions[i].erasesize-1)) - return -EINVAL; - - chipnum = ofs >> cfi->chipshift; - adr = ofs - (chipnum << cfi->chipshift); - - i=first; - - while (len) { - ret = (*frob)(map, &cfi->chips[chipnum], adr, thunk); - - if (ret) - return ret; - - adr += regions[i].erasesize; - len -= regions[i].erasesize; - - if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift))) - i++; - - if (adr >> cfi->chipshift) { - adr = 0; - chipnum++; - - if (chipnum >= cfi->numchips) - break; - } - } - - return 0; -} - - -static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, void *thunk) +static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk) { struct cfi_private *cfi = map->fldrv_priv; unsigned long timeo = jiffies + HZ; @@ -1342,11 +1247,11 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u __func__, adr ); ENABLE_VPP(map); - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); map_write(map, CMD(0x30), adr); chip->state = FL_ERASING; @@ -1415,7 +1320,7 @@ int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) ofs = instr->addr; len = instr->len; - ret = cfi_amdstd_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL); + ret = cfi_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL); if (ret) return ret; @@ -1588,137 +1493,6 @@ static void cfi_amdstd_resume(struct mtd_info *mtd) } } - -#ifdef DEBUG_LOCK_BITS - -static int do_printlockstatus_oneblock(struct map_info *map, - struct flchip *chip, - unsigned long adr, - void *thunk) -{ - struct cfi_private *cfi = map->fldrv_priv; - int ofs_factor = cfi->interleave * cfi->device_type; - - cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL); - printk(KERN_DEBUG "block status register for 0x%08lx is %x\n", - adr, cfi_read_query(map, adr+(2*ofs_factor))); - cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL); - - return 0; -} - - -#define debug_dump_locks(mtd, frob, ofs, len, thunk) \ - cfi_amdstd_varsize_frob((mtd), (frob), (ofs), (len), (thunk)) - -#else - -#define debug_dump_locks(...) - -#endif /* DEBUG_LOCK_BITS */ - - -struct xxlock_thunk { - uint8_t val; - flstate_t state; -}; - - -#define DO_XXLOCK_ONEBLOCK_LOCK ((struct xxlock_thunk){0x01, FL_LOCKING}) -#define DO_XXLOCK_ONEBLOCK_UNLOCK ((struct xxlock_thunk){0x00, FL_UNLOCKING}) - - -/* - * FIXME - this is *very* specific to a particular chip. It likely won't - * work for all chips that require unlock. It also hasn't been tested - * with interleaved chips. - */ -static int do_xxlock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, void *thunk) -{ - struct cfi_private *cfi = map->fldrv_priv; - struct xxlock_thunk *xxlt = (struct xxlock_thunk *)thunk; - int ret; - - /* - * This is easy because these are writes to registers and not writes - * to flash memory - that means that we don't have to check status - * and timeout. - */ - - adr += chip->start; - /* - * lock block registers: - * - on 64k boundariesand - * - bit 1 set high - * - block lock registers are 4MiB lower - overflow subtract (danger) - */ - adr = ((adr & ~0xffff) | 0x2) + ~0x3fffff; - - cfi_spin_lock(chip->mutex); - ret = get_chip(map, chip, adr, FL_LOCKING); - if (ret) { - cfi_spin_unlock(chip->mutex); - return ret; - } - - chip->state = xxlt->state; - map_write(map, CMD(xxlt->val), adr); - - /* Done and happy. */ - chip->state = FL_READY; - put_chip(map, chip, adr); - cfi_spin_unlock(chip->mutex); - return 0; -} - - -static int cfi_amdstd_lock_varsize(struct mtd_info *mtd, - loff_t ofs, - size_t len) -{ - int ret; - - DEBUG(MTD_DEBUG_LEVEL3, - "%s: lock status before, ofs=0x%08llx, len=0x%08zX\n", - __func__, ofs, len); - debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0); - - ret = cfi_amdstd_varsize_frob(mtd, do_xxlock_oneblock, ofs, len, - (void *)&DO_XXLOCK_ONEBLOCK_LOCK); - - DEBUG(MTD_DEBUG_LEVEL3, - "%s: lock status after, ret=%d\n", - __func__, ret); - - debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0); - - return ret; -} - - -static int cfi_amdstd_unlock_varsize(struct mtd_info *mtd, - loff_t ofs, - size_t len) -{ - int ret; - - DEBUG(MTD_DEBUG_LEVEL3, - "%s: lock status before, ofs=0x%08llx, len=0x%08zX\n", - __func__, ofs, len); - debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0); - - ret = cfi_amdstd_varsize_frob(mtd, do_xxlock_oneblock, ofs, len, - (void *)&DO_XXLOCK_ONEBLOCK_UNLOCK); - - DEBUG(MTD_DEBUG_LEVEL3, - "%s: lock status after, ret=%d\n", - __func__, ret); - debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0); - - return ret; -} - - static void cfi_amdstd_destroy(struct mtd_info *mtd) { struct map_info *map = mtd->priv; diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c index 071be4220417..be55c6f2f670 100644 --- a/drivers/mtd/chips/cfi_probe.c +++ b/drivers/mtd/chips/cfi_probe.c @@ -1,7 +1,7 @@ /* Common Flash Interface probe code. (C) 2000 Red Hat. GPL'd. - $Id: cfi_probe.c,v 1.77 2004/07/14 08:38:44 dwmw2 Exp $ + $Id: cfi_probe.c,v 1.79 2004/10/20 23:04:01 dwmw2 Exp $ */ #include @@ -243,12 +243,27 @@ static char *vendorname(__u16 vendor) case P_ID_AMD_EXT: return "AMD/Fujitsu Extended"; + + case P_ID_WINBOND: + return "Winbond Standard"; + case P_ID_ST_ADV: + return "ST Advanced"; + case P_ID_MITSUBISHI_STD: return "Mitsubishi Standard"; case P_ID_MITSUBISHI_EXT: return "Mitsubishi Extended"; + + case P_ID_SST_PAGE: + return "SST Page Write"; + + case P_ID_INTEL_PERFORMANCE: + return "Intel Performance Code"; + + case P_ID_INTEL_DATA: + return "Intel Data"; case P_ID_RESERVED: return "Not Allowed / Reserved for Future Use"; @@ -327,6 +342,10 @@ static void print_cfi_ident(struct cfi_ident *cfip) printk(" - x32-only asynchronous interface\n"); break; + case 4: + printk(" - supports x16 and x32 via Word# with asynchronous interface\n"); + break; + case 65535: printk(" - Not Allowed / Reserved\n"); break; diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index d1a785628c49..49c97bc96bba 100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c @@ -7,7 +7,7 @@ * * This code is covered by the GPL. * - * $Id: cfi_util.c,v 1.4 2004/07/14 08:38:44 dwmw2 Exp $ + * $Id: cfi_util.c,v 1.5 2004/08/12 06:40:23 eric Exp $ * */ @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -74,19 +75,114 @@ out: EXPORT_SYMBOL(cfi_read_pri); -void cfi_fixup(struct map_info *map, struct cfi_fixup* fixups) +void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup *fixups) { + struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; struct cfi_fixup *f; for (f=fixups; f->fixup; f++) { if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi->mfr)) && ((f->id == CFI_ID_ANY) || (f->id == cfi->id))) { - f->fixup(map, f->param); + f->fixup(mtd, f->param); } } } EXPORT_SYMBOL(cfi_fixup); +int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob, + loff_t ofs, size_t len, void *thunk) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + unsigned long adr; + int chipnum, ret = 0; + int i, first; + struct mtd_erase_region_info *regions = mtd->eraseregions; + + if (ofs > mtd->size) + return -EINVAL; + + if ((len + ofs) > mtd->size) + return -EINVAL; + + /* Check that both start and end of the requested erase are + * aligned with the erasesize at the appropriate addresses. + */ + + i = 0; + + /* Skip all erase regions which are ended before the start of + the requested erase. Actually, to save on the calculations, + we skip to the first erase region which starts after the + start of the requested erase, and then go back one. + */ + + while (i < mtd->numeraseregions && ofs >= regions[i].offset) + i++; + i--; + + /* OK, now i is pointing at the erase region in which this + erase request starts. Check the start of the requested + erase range is aligned with the erase size which is in + effect here. + */ + + if (ofs & (regions[i].erasesize-1)) + return -EINVAL; + + /* Remember the erase region we start on */ + first = i; + + /* Next, check that the end of the requested erase is aligned + * with the erase region at that address. + */ + + while (inumeraseregions && (ofs + len) >= regions[i].offset) + i++; + + /* As before, drop back one to point at the region in which + the address actually falls + */ + i--; + + if ((ofs + len) & (regions[i].erasesize-1)) + return -EINVAL; + + chipnum = ofs >> cfi->chipshift; + adr = ofs - (chipnum << cfi->chipshift); + + i=first; + + while(len) { + unsigned long chipmask; + int size = regions[i].erasesize; + + ret = (*frob)(map, &cfi->chips[chipnum], adr, size, thunk); + + if (ret) + return ret; + + adr += size; + len -= size; + + chipmask = (1 << cfi->chipshift) - 1; + if ((adr & chipmask) == ((regions[i].offset + size * regions[i].numblocks) & chipmask)) + i++; + + if (adr >> cfi->chipshift) { + adr = 0; + chipnum++; + + if (chipnum >= cfi->numchips) + break; + } + } + + return 0; +} + +EXPORT_SYMBOL(cfi_varsize_frob); + MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/chips/fwh_lock.h b/drivers/mtd/chips/fwh_lock.h new file mode 100644 index 000000000000..fbf44708a861 --- /dev/null +++ b/drivers/mtd/chips/fwh_lock.h @@ -0,0 +1,107 @@ +#ifndef FWH_LOCK_H +#define FWH_LOCK_H + + +enum fwh_lock_state { + FWH_UNLOCKED = 0, + FWH_DENY_WRITE = 1, + FWH_IMMUTABLE = 2, + FWH_DENY_READ = 4, +}; + +struct fwh_xxlock_thunk { + enum fwh_lock_state val; + flstate_t state; +}; + + +#define FWH_XXLOCK_ONEBLOCK_LOCK ((struct fwh_xxlock_thunk){ FWH_DENY_WRITE, FL_LOCKING}) +#define FWH_XXLOCK_ONEBLOCK_UNLOCK ((struct fwh_xxlock_thunk){ FWH_UNLOCKED, FL_UNLOCKING}) + +/* + * This locking/unlock is specific to firmware hub parts. Only one + * is known that supports the Intel command set. Firmware + * hub parts cannot be interleaved as they are on the LPC bus + * so this code has not been tested with interleaved chips, + * and will likely fail in that context. + */ +static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip, + unsigned long adr, int len, void *thunk) +{ + struct cfi_private *cfi = map->fldrv_priv; + struct fwh_xxlock_thunk *xxlt = (struct fwh_xxlock_thunk *)thunk; + int ret; + + /* Refuse the operation if the we cannot look behind the chip */ + if (chip->start < 0x400000) { + DEBUG( MTD_DEBUG_LEVEL3, + "MTD %s(): chip->start: %lx wanted >= 0x400000\n", + __func__, chip->start ); + return -EIO; + } + /* + * lock block registers: + * - on 64k boundariesand + * - bit 1 set high + * - block lock registers are 4MiB lower - overflow subtract (danger) + * + * The address manipulation is first done on the logical address + * which is 0 at the start of the chip, and then the offset of + * the individual chip is addted to it. Any other order a weird + * map offset could cause problems. + */ + adr = (adr & ~0xffffUL) | 0x2; + adr += chip->start - 0x400000; + + /* + * This is easy because these are writes to registers and not writes + * to flash memory - that means that we don't have to check status + * and timeout. + */ + cfi_spin_lock(chip->mutex); + ret = get_chip(map, chip, adr, FL_LOCKING); + if (ret) { + cfi_spin_unlock(chip->mutex); + return ret; + } + + chip->state = xxlt->state; + map_write(map, CMD(xxlt->val), adr); + + /* Done and happy. */ + chip->state = FL_READY; + put_chip(map, chip, adr); + cfi_spin_unlock(chip->mutex); + return 0; +} + + +static int fwh_lock_varsize(struct mtd_info *mtd, loff_t ofs, size_t len) +{ + int ret; + + ret = cfi_varsize_frob(mtd, fwh_xxlock_oneblock, ofs, len, + (void *)&FWH_XXLOCK_ONEBLOCK_LOCK); + + return ret; +} + + +static int fwh_unlock_varsize(struct mtd_info *mtd, loff_t ofs, size_t len) +{ + int ret; + + ret = cfi_varsize_frob(mtd, fwh_xxlock_oneblock, ofs, len, + (void *)&FWH_XXLOCK_ONEBLOCK_UNLOCK); + + return ret; +} + +static void fixup_use_fwh_lock(struct mtd_info *mtd, void *param) +{ + printk(KERN_NOTICE "using fwh lock/unlock method\n"); + /* Setup for the chips with the fwh lock method */ + mtd->lock = fwh_lock_varsize; + mtd->unlock = fwh_unlock_varsize; +} +#endif /* FWH_LOCK_H */ diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c index 3615fd815aef..fc982c4671f0 100644 --- a/drivers/mtd/chips/gen_probe.c +++ b/drivers/mtd/chips/gen_probe.c @@ -2,7 +2,7 @@ * Routines common to all CFI-type probes. * (C) 2001-2003 Red Hat, Inc. * GPL'd - * $Id: gen_probe.c,v 1.19 2004/07/13 22:33:32 dwmw2 Exp $ + * $Id: gen_probe.c,v 1.21 2004/08/14 15:14:05 dwmw2 Exp $ */ #include @@ -64,7 +64,7 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi interleave and device type, etc. */ if (!genprobe_new_chip(map, cp, &cfi)) { /* The probe didn't like it */ - printk(KERN_WARNING "%s: Found no %s device at location zero\n", + printk(KERN_DEBUG "%s: Found no %s device at location zero\n", cp->name, map->name); return NULL; } @@ -169,8 +169,12 @@ static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp, cfi->interleave = nr_chips; - for (type = 0; type < 3; type++) { - cfi->device_type = 1<device_type = type; if (cp->probe_chip(map, 0, NULL, cfi)) return 1; diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index 8fb85f079111..250d038d2775 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c @@ -1,7 +1,7 @@ /* Common Flash Interface probe code. (C) 2000 Red Hat. GPL'd. - $Id: jedec_probe.c,v 1.51 2004/07/14 14:44:30 thayne Exp $ + $Id: jedec_probe.c,v 1.57 2004/09/17 11:45:05 eric Exp $ See JEDEC (http://www.jedec.org/) standard JESD21C (section 3.5) for the standard this probe goes back to. @@ -107,6 +107,7 @@ #define I82802AC 0x00ac /* Macronix */ +#define MX29LV040C 0x004F #define MX29LV160T 0x22C4 #define MX29LV160B 0x2249 #define MX29F016 0x00AD @@ -128,6 +129,7 @@ #define M50FW040 0x002C #define M50FW080 0x002D #define M50FW016 0x002E +#define M50LPW080 0x002F /* SST */ #define SST29EE020 0x0010 @@ -181,8 +183,8 @@ enum uaddr { struct unlock_addr { - int addr1; - int addr2; + u32 addr1; + u32 addr2; }; @@ -512,12 +514,12 @@ static const struct amd_flash_info jedec_table[] = { ERASEINFO(0x10000,8), } }, { - .mfr_id = MANUFACTURER_AMD, - .dev_id = AM29F002T, - .name = "AMD AM29F002T", - .DevSize = SIZE_256KiB, - .NumEraseRegions = 4, - .regions = {ERASEINFO(0x10000,3), + mfr_id: MANUFACTURER_AMD, + dev_id: AM29F002T, + name: "AMD AM29F002T", + DevSize: SIZE_256KiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,3), ERASEINFO(0x08000,1), ERASEINFO(0x02000,2), ERASEINFO(0x04000,1) @@ -768,12 +770,12 @@ static const struct amd_flash_info jedec_table[] = { ERASEINFO(0x04000,1) } }, { - .mfr_id = MANUFACTURER_HYUNDAI, - .dev_id = HY29F002T, - .name = "Hyundai HY29F002T", - .DevSize = SIZE_256KiB, - .NumEraseRegions = 4, - .regions = {ERASEINFO(0x10000,3), + mfr_id: MANUFACTURER_HYUNDAI, + dev_id: HY29F002T, + name: "Hyundai HY29F002T", + DevSize: SIZE_256KiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,3), ERASEINFO(0x08000,1), ERASEINFO(0x02000,2), ERASEINFO(0x04000,1) @@ -1082,6 +1084,19 @@ static const struct amd_flash_info jedec_table[] = { .regions = { ERASEINFO(0x10000,16), } + }, { + .mfr_id = MANUFACTURER_MACRONIX, + .dev_id = MX29LV040C, + .name = "Macronix MX29LV040C", + .uaddr = { + [0] = MTD_UADDR_0x0555_0x02AA, /* x8 */ + }, + .DevSize = SIZE_512KiB, + .CmdSet = P_ID_AMD_STD, + .NumEraseRegions= 1, + .regions = { + ERASEINFO(0x10000,8), + } }, { .mfr_id = MANUFACTURER_MACRONIX, .dev_id = MX29LV160T, @@ -1162,12 +1177,12 @@ static const struct amd_flash_info jedec_table[] = { ERASEINFO(0x10000,7), } }, { - .mfr_id = MANUFACTURER_MACRONIX, - .dev_id = MX29F002T, - .name = "Macronix MX29F002T", - .DevSize = SIZE_256KiB, - .NumEraseRegions = 4, - .regions = {ERASEINFO(0x10000,3), + mfr_id: MANUFACTURER_MACRONIX, + dev_id: MX29F002T, + name: "Macronix MX29F002T", + DevSize: SIZE_256KiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,3), ERASEINFO(0x08000,1), ERASEINFO(0x02000,2), ERASEINFO(0x04000,1) @@ -1247,7 +1262,7 @@ static const struct amd_flash_info jedec_table[] = { .DevSize = SIZE_256KiB, .CmdSet = P_ID_SST_PAGE, .NumEraseRegions= 1, - .regions = {ERASEINFO(0x01000,64), + regions: {ERASEINFO(0x01000,64), } }, { .mfr_id = MANUFACTURER_SST, @@ -1259,7 +1274,7 @@ static const struct amd_flash_info jedec_table[] = { .DevSize = SIZE_256KiB, .CmdSet = P_ID_SST_PAGE, .NumEraseRegions= 1, - .regions = {ERASEINFO(0x01000,64), + regions: {ERASEINFO(0x01000,64), } }, { .mfr_id = MANUFACTURER_SST, @@ -1379,6 +1394,22 @@ static const struct amd_flash_info jedec_table[] = { ERASEINFO(0x01000,256), } }, { + .mfr_id = MANUFACTURER_SST, /* should be CFI */ + .dev_id = SST39LF160, + .name = "SST 39LF160", + .uaddr = { + [0] = MTD_UADDR_0x5555_0x2AAA, /* x8 */ + [1] = MTD_UADDR_0x5555_0x2AAA /* x16 */ + }, + .DevSize = SIZE_2MiB, + .CmdSet = P_ID_AMD_STD, + .NumEraseRegions= 2, + .regions = { + ERASEINFO(0x1000,256), + ERASEINFO(0x1000,256) + } + + }, { .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */ .dev_id = M29W800DT, .name = "ST M29W800DT", @@ -1498,6 +1529,19 @@ static const struct amd_flash_info jedec_table[] = { .regions = { ERASEINFO(0x10000,32), } + }, { + .mfr_id = MANUFACTURER_ST, + .dev_id = M50LPW080, + .name = "ST M50LPW080", + .uaddr = { + [0] = MTD_UADDR_UNNECESSARY, /* x8 */ + }, + .DevSize = SIZE_1MiB, + .CmdSet = P_ID_INTEL_EXT, + .NumEraseRegions= 1, + .regions = { + ERASEINFO(0x10000,16), + } }, { .mfr_id = MANUFACTURER_TOSHIBA, .dev_id = TC58FVT160, @@ -1624,20 +1668,20 @@ static inline u32 jedec_read_mfr(struct map_info *map, __u32 base, { map_word result; unsigned long mask; + u32 ofs = cfi_build_cmd_addr(0, cfi_interleave(cfi), cfi->device_type); mask = (1 << (cfi->device_type * 8)) -1; - result = map_read(map, base); + result = map_read(map, base + ofs); return result.x[0] & mask; } static inline u32 jedec_read_id(struct map_info *map, __u32 base, struct cfi_private *cfi) { - int osf; map_word result; unsigned long mask; - osf = cfi->interleave *cfi->device_type; + u32 ofs = cfi_build_cmd_addr(1, cfi_interleave(cfi), cfi->device_type); mask = (1 << (cfi->device_type * 8)) -1; - result = map_read(map, base + osf); + result = map_read(map, base + ofs); return result.x[0] & mask; } @@ -1653,9 +1697,11 @@ static inline void jedec_reset(u32 base, struct map_info *map, * as they will ignore the writes and dont care what address * the F0 is written to */ if(cfi->addr_unlock1) { - /*printk("reset unlock called %x %x \n",cfi->addr_unlock1,cfi->addr_unlock2);*/ - cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL); + DEBUG( MTD_DEBUG_LEVEL3, + "reset unlock called %x %x \n", + cfi->addr_unlock1,cfi->addr_unlock2); + cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL); } cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); @@ -1700,7 +1746,6 @@ static inline __u8 finfo_uaddr(const struct amd_flash_info *finfo, int device_ty static int cfi_jedec_setup(struct cfi_private *p_cfi, int index) { int i,num_erase_regions; - unsigned long mask; __u8 uaddr; printk("Found: %s\n",jedec_table[index].name); @@ -1736,9 +1781,8 @@ static int cfi_jedec_setup(struct cfi_private *p_cfi, int index) } /* Mask out address bits which are smaller than the device type */ - mask = ~(p_cfi->device_type-1); - p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1 & mask; - p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2 & mask; + p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1; + p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2; return 1; /* ok */ } @@ -1759,7 +1803,6 @@ static inline int jedec_match( __u32 base, int rc = 0; /* failure until all tests pass */ u32 mfr, id; __u8 uaddr; - unsigned long mask; /* * The IDs must match. For X16 and X32 devices operating in @@ -1797,7 +1840,7 @@ static inline int jedec_match( __u32 base, DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n", __func__, base, 1 << finfo->DevSize, base + (1 << finfo->DevSize) ); - if ( base + cfi->interleave * ( 1 << finfo->DevSize ) > map->size ) { + if ( base + cfi_interleave(cfi) * ( 1 << finfo->DevSize ) > map->size ) { DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n", __func__, finfo->mfr_id, finfo->dev_id, @@ -1810,18 +1853,16 @@ static inline int jedec_match( __u32 base, goto match_done; } - mask = ~(cfi->device_type-1); - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n", __func__, cfi->addr_unlock1, cfi->addr_unlock2 ); if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr - && ( (unlock_addrs[uaddr].addr1 & mask) != cfi->addr_unlock1 || - (unlock_addrs[uaddr].addr2 & mask) != cfi->addr_unlock2 ) ) { + && ( unlock_addrs[uaddr].addr1 != cfi->addr_unlock1 || + unlock_addrs[uaddr].addr2 != cfi->addr_unlock2 ) ) { DEBUG( MTD_DEBUG_LEVEL3, - "MTD %s(): 0x%.4lx 0x%.4lx did not match\n", - __func__, - unlock_addrs[uaddr].addr1 & mask, - unlock_addrs[uaddr].addr2 & mask); + "MTD %s(): 0x%.4x 0x%.4x did not match\n", + __func__, + unlock_addrs[uaddr].addr1, + unlock_addrs[uaddr].addr2); goto match_done; } @@ -1857,10 +1898,10 @@ static inline int jedec_match( __u32 base, */ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): return to ID mode\n", __func__ ); if(cfi->addr_unlock1) { - cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL); } - cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); /* FIXME - should have a delay before continuing */ match_done: @@ -1873,19 +1914,18 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, { int i; enum uaddr uaddr_idx = MTD_UADDR_NOT_SUPPORTED; + u32 probe_offset1, probe_offset2; retry: if (!cfi->numchips) { - unsigned long mask = ~(cfi->device_type-1); - uaddr_idx++; if (MTD_UADDR_UNNECESSARY == uaddr_idx) return 0; /* Mask out address bits which are smaller than the device type */ - cfi->addr_unlock1 = unlock_addrs[uaddr_idx].addr1 & mask; - cfi->addr_unlock2 = unlock_addrs[uaddr_idx].addr2 & mask; + cfi->addr_unlock1 = unlock_addrs[uaddr_idx].addr1; + cfi->addr_unlock2 = unlock_addrs[uaddr_idx].addr2; } /* Make certain we aren't probing past the end of map */ @@ -1896,30 +1936,30 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, return 0; } - if ((base + cfi->addr_unlock1) >= map->size) { - printk(KERN_NOTICE - "Probe at addr_unlock1(0x%08x + 0x%08x) past the end of the map(0x%08lx)\n", - base, cfi->addr_unlock1, map->size -1); - - return 0; + /* Ensure the unlock addresses we try stay inside the map */ + probe_offset1 = cfi_build_cmd_addr( + cfi->addr_unlock1, + cfi_interleave(cfi), + cfi->device_type); + probe_offset2 = cfi_build_cmd_addr( + cfi->addr_unlock1, + cfi_interleave(cfi), + cfi->device_type); + if ( ((base + probe_offset1 + map_bankwidth(map)) >= map->size) || + ((base + probe_offset2 + map_bankwidth(map)) >= map->size)) + { + goto retry; } - if ((base + cfi->addr_unlock2) >= map->size) { - printk(KERN_NOTICE - "Probe at addr_unlock2(0x%08x + 0x%08x) past the end of the map(0x%08lx)\n", - base, cfi->addr_unlock2, map->size -1); - return 0; - } - /* Reset */ jedec_reset(base, map, cfi); /* Autoselect Mode */ if(cfi->addr_unlock1) { - cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL); } - cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); /* FIXME - should have a delay before continuing */ if (!cfi->numchips) { @@ -1930,7 +1970,7 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, cfi->id = jedec_read_id(map, base, cfi); DEBUG(MTD_DEBUG_LEVEL3, "Search for id:(%02x %02x) interleave(%d) type(%d)\n", - cfi->mfr, cfi->id, cfi->interleave, cfi->device_type); + cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type); for (i=0; iname, cfi->interleave, cfi->device_type*8, base, + map->name, cfi_interleave(cfi), cfi->device_type*8, base, map->bankwidth*8); return 1; diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c index b43312731270..cde413dbd846 100644 --- a/drivers/mtd/maps/amd76xrom.c +++ b/drivers/mtd/maps/amd76xrom.c @@ -2,7 +2,7 @@ * amd76xrom.c * * Normal mappings of chips in physical memory - * $Id: amd76xrom.c,v 1.12 2004/07/14 14:44:31 thayne Exp $ + * $Id: amd76xrom.c,v 1.17 2004/09/18 01:59:56 eric Exp $ */ #include @@ -12,61 +12,73 @@ #include #include #include +#include +#include #include #include #include +#include #define xstr(s) str(s) #define str(s) #s #define MOD_NAME xstr(KBUILD_BASENAME) -#define MTD_DEV_NAME_LENGTH 16 +#define ADDRESS_NAME_LEN 18 + +#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */ + +struct amd76xrom_window { + void __iomem *virt; + unsigned long phys; + unsigned long size; + struct list_head maps; + struct resource rsrc; + struct pci_dev *pdev; +}; struct amd76xrom_map_info { + struct list_head list; struct map_info map; struct mtd_info *mtd; - void __iomem * window_addr; - u32 window_start, window_size; - struct pci_dev *pdev; - struct resource window_rsrc; - struct resource rom_rsrc; - char mtd_name[MTD_DEV_NAME_LENGTH]; + struct resource rsrc; + char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN]; }; - -static struct amd76xrom_map_info amd76xrom_map = { - .map = { - .name = MOD_NAME, - .size = 0, - .bankwidth = 1, - } - /* remaining fields of structure are initialized to 0 */ +static struct amd76xrom_window amd76xrom_window = { + .maps = LIST_HEAD_INIT(amd76xrom_window.maps), }; - -static void amd76xrom_cleanup(struct amd76xrom_map_info *info) +static void amd76xrom_cleanup(struct amd76xrom_window *window) { + struct amd76xrom_map_info *map, *scratch; u8 byte; - /* Disable writes through the rom window */ - pci_read_config_byte(info->pdev, 0x40, &byte); - pci_write_config_byte(info->pdev, 0x40, byte & ~1); + if (window->pdev) { + /* Disable writes through the rom window */ + pci_read_config_byte(window->pdev, 0x40, &byte); + pci_write_config_byte(window->pdev, 0x40, byte & ~1); + } - if (info->mtd) { - del_mtd_device(info->mtd); - map_destroy(info->mtd); - info->mtd = NULL; - info->map.virt = NULL; + /* Free all of the mtd devices */ + list_for_each_entry_safe(map, scratch, &window->maps, list) { + if (map->rsrc.parent) { + release_resource(&map->rsrc); + } + del_mtd_device(map->mtd); + map_destroy(map->mtd); + list_del(&map->list); + kfree(map); } - if (info->rom_rsrc.parent) - release_resource(&info->rom_rsrc); - if (info->window_rsrc.parent) - release_resource(&info->window_rsrc); - - if (info->window_addr) { - iounmap(info->window_addr); - info->window_addr = NULL; + if (window->rsrc.parent) + release_resource(&window->rsrc); + + if (window->virt) { + iounmap(window->virt); + window->virt = NULL; + window->phys = 0; + window->size = 0; + window->pdev = NULL; } } @@ -74,167 +86,196 @@ static void amd76xrom_cleanup(struct amd76xrom_map_info *info) static int __devinit amd76xrom_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { - struct rom_window { - u32 start; - u32 size; - u8 segen_bits; - }; - static struct rom_window rom_window[] = { - /* - * Need the 5MiB window for chips that have block lock/unlock - * registers located below 4MiB window. - */ - { 0xffb00000, 5*1024*1024, (1<<7) | (1<<6), }, - { 0xffc00000, 4*1024*1024, (1<<7), }, - { 0xffff0000, 64*1024, 0 }, - { 0 , 0, 0 }, - }; - static const u32 rom_probe_sizes[] = { - 5*1024*1024, 4*1024*1024, 2*1024*1024, 1024*1024, 512*1024, - 256*1024, 128*1024, 64*1024, 0}; static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; u8 byte; - struct amd76xrom_map_info *info = &amd76xrom_map; - struct rom_window *window; - int i; - u32 rom_size; - - info->pdev = pdev; - window = &rom_window[0]; - - while (window->size) { - /* - * Try to reserve the window mem region. If this fails then - * it is likely due to a fragment of the window being - * "reseved" by the BIOS. In the case that the - * request_mem_region() fails then once the rom size is - * discovered we will try to reserve the unreserved fragment. - */ - info->window_rsrc.name = MOD_NAME; - info->window_rsrc.start = window->start; - info->window_rsrc.end = window->start + window->size - 1; - info->window_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; - if (request_resource(&iomem_resource, &info->window_rsrc)) { - info->window_rsrc.parent = NULL; - printk(KERN_ERR MOD_NAME - " %s(): Unable to register resource" - " 0x%.08lx-0x%.08lx - kernel bug?\n", - __func__, - info->window_rsrc.start, info->window_rsrc.end); - } + struct amd76xrom_window *window = &amd76xrom_window; + struct amd76xrom_map_info *map = 0; + unsigned long map_top; + + /* Remember the pci dev I find the window in */ + window->pdev = pdev; - /* Enable the selected rom window */ - pci_read_config_byte(pdev, 0x43, &byte); - pci_write_config_byte(pdev, 0x43, byte | window->segen_bits); + /* Assume the rom window is properly setup, and find it's size */ + pci_read_config_byte(pdev, 0x43, &byte); + if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) { + window->phys = 0xffb00000; /* 5MiB */ + } + else if ((byte & (1<<7)) == (1<<7)) { + window->phys = 0xffc00000; /* 4MiB */ + } + else { + window->phys = 0xffff0000; /* 64KiB */ + } + window->size = 0xffffffffUL - window->phys + 1UL; + + /* + * Try to reserve the window mem region. If this fails then + * it is likely due to a fragment of the window being + * "reseved" by the BIOS. In the case that the + * request_mem_region() fails then once the rom size is + * discovered we will try to reserve the unreserved fragment. + */ + window->rsrc.name = MOD_NAME; + window->rsrc.start = window->phys; + window->rsrc.end = window->phys + window->size - 1; + window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; + if (request_resource(&iomem_resource, &window->rsrc)) { + window->rsrc.parent = NULL; + printk(KERN_ERR MOD_NAME + " %s(): Unable to register resource" + " 0x%.08lx-0x%.08lx - kernel bug?\n", + __func__, + window->rsrc.start, window->rsrc.end); + } - /* Enable writes through the rom window */ - pci_read_config_byte(pdev, 0x40, &byte); - pci_write_config_byte(pdev, 0x40, byte | 1); +#if 0 - /* FIXME handle registers 0x80 - 0x8C the bios region locks */ + /* Enable the selected rom window */ + pci_read_config_byte(pdev, 0x43, &byte); + pci_write_config_byte(pdev, 0x43, byte | rwindow->segen_bits); +#endif - printk(KERN_NOTICE MOD_NAME " window : %x at %x\n", - window->size, window->start); - /* For write accesses caches are useless */ - info->window_addr = ioremap_nocache(window->start, - window->size); + /* Enable writes through the rom window */ + pci_read_config_byte(pdev, 0x40, &byte); + pci_write_config_byte(pdev, 0x40, byte | 1); + + /* FIXME handle registers 0x80 - 0x8C the bios region locks */ + + /* For write accesses caches are useless */ + window->virt = ioremap_nocache(window->phys, window->size); + if (!window->virt) { + printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n", + window->phys, window->size); + goto out; + } - if (!info->window_addr) { - printk(KERN_ERR "Failed to ioremap\n"); - continue; + /* Get the first address to look for an rom chip at */ + map_top = window->phys; +#if 1 + /* The probe sequence run over the firmware hub lock + * registers sets them to 0x7 (no access). + * Probe at most the last 4M of the address space. + */ + if (map_top < 0xffc00000) { + map_top = 0xffc00000; + } +#endif + /* Loop through and look for rom chips */ + while((map_top - 1) < 0xffffffffUL) { + struct cfi_private *cfi; + unsigned long offset; + int i; + + if (!map) { + map = kmalloc(sizeof(*map), GFP_KERNEL); + } + if (!map) { + printk(KERN_ERR MOD_NAME ": kmalloc failed"); + goto out; } + memset(map, 0, sizeof(*map)); + INIT_LIST_HEAD(&map->list); + map->map.name = map->map_name; + map->map.phys = map_top; + offset = map_top - window->phys; + map->map.virt = (void __iomem *) + (((unsigned long)(window->virt)) + offset); + map->map.size = 0xffffffffUL - map_top + 1UL; + /* Set the name of the map to the address I am trying */ + sprintf(map->map_name, "%s @%08lx", + MOD_NAME, map->map.phys); + + /* There is no generic VPP support */ + for(map->map.bankwidth = 32; map->map.bankwidth; + map->map.bankwidth >>= 1) + { + char **probe_type; + /* Skip bankwidths that are not supported */ + if (!map_bankwidth_supported(map->map.bankwidth)) + continue; - info->mtd = NULL; + /* Setup the map methods */ + simple_map_init(&map->map); - for(i = 0; (rom_size = rom_probe_sizes[i]); i++) { - char **chip_type; - if (rom_size > window->size) { - continue; - } - info->map.phys = window->start + window->size - rom_size; - info->map.virt = - info->window_addr + window->size - rom_size; - info->map.size = rom_size; - simple_map_init(&info->map); - chip_type = rom_probe_types; - for(; !info->mtd && *chip_type; chip_type++) { - info->mtd = do_map_probe(*chip_type, &amd76xrom_map.map); + /* Try all of the probe methods */ + probe_type = rom_probe_types; + for(; *probe_type; probe_type++) { + map->mtd = do_map_probe(*probe_type, &map->map); + if (map->mtd) + goto found; } - if (info->mtd) goto found_mtd; } - iounmap(info->window_addr); - info->window_addr = NULL; - - /* Disable writes through the rom window */ - pci_read_config_byte(pdev, 0x40, &byte); - pci_write_config_byte(pdev, 0x40, byte & ~1); - - window++; - } - goto failed; - - found_mtd: - printk(KERN_NOTICE MOD_NAME " chip at offset: 0x%x\n", - window->size - rom_size); - - info->mtd->owner = THIS_MODULE; - - if (!info->window_rsrc.parent) { - /* failed to reserve entire window - try fragments */ - info->window_rsrc.name = MOD_NAME; - info->window_rsrc.start = window->start; - info->window_rsrc.end = window->start + window->size - rom_size - 1; - info->window_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; - if (request_resource(&iomem_resource, &info->window_rsrc)) { - printk(KERN_ERR MOD_NAME - ": cannot reserve window resource fragment\n"); -#if 0 + map_top += ROM_PROBE_STEP_SIZE; + continue; + found: + /* Trim the size if we are larger than the map */ + if (map->mtd->size > map->map.size) { + printk(KERN_WARNING MOD_NAME + " rom(%u) larger than window(%lu). fixing...\n", + map->mtd->size, map->map.size); + map->mtd->size = map->map.size; + } + if (window->rsrc.parent) { /* - * The BIOS e820 usually reserves this so it isn't - * usually an error. + * Registering the MTD device in iomem may not be possible + * if there is a BIOS "reserved" and BUSY range. If this + * fails then continue anyway. */ - goto failed; -#endif + map->rsrc.name = map->map_name; + map->rsrc.start = map->map.phys; + map->rsrc.end = map->map.phys + map->mtd->size - 1; + map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; + if (request_resource(&window->rsrc, &map->rsrc)) { + printk(KERN_ERR MOD_NAME + ": cannot reserve MTD resource\n"); + map->rsrc.parent = NULL; + } } - } - add_mtd_device(info->mtd); - info->window_start = window->start; - info->window_size = window->size; - - if (info->window_rsrc.parent) { - /* - * Registering the MTD device in iomem may not be possible - * if there is a BIOS "reserved" and BUSY range. If this - * fails then continue anyway. - */ - snprintf(info->mtd_name, MTD_DEV_NAME_LENGTH, - "mtd%d", info->mtd->index); - - info->rom_rsrc.name = info->mtd_name; - info->rom_rsrc.start = window->start + window->size - rom_size; - info->rom_rsrc.end = window->start + window->size - 1; - info->rom_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; - if (request_resource(&info->window_rsrc, &info->rom_rsrc)) { - printk(KERN_ERR MOD_NAME - ": cannot reserve MTD resource\n"); - info->rom_rsrc.parent = NULL; + /* Make the whole region visible in the map */ + map->map.virt = window->virt; + map->map.phys = window->phys; + cfi = map->map.fldrv_priv; + for(i = 0; i < cfi->numchips; i++) { + cfi->chips[i].start += offset; } + + /* Now that the mtd devices is complete claim and export it */ + map->mtd->owner = THIS_MODULE; + if (add_mtd_device(map->mtd)) { + map_destroy(map->mtd); + map->mtd = 0; + goto out; + } + + + /* Calculate the new value of map_top */ + map_top += map->mtd->size; + + /* File away the map structure */ + list_add(&map->list, &window->maps); + map = 0; } + out: + /* Free any left over map structures */ + if (map) { + kfree(map); + } + /* See if I have any map structures */ + if (list_empty(&window->maps)) { + amd76xrom_cleanup(window); + return -ENODEV; + } return 0; - - failed: - amd76xrom_cleanup(info); - return -ENODEV; } static void __devexit amd76xrom_remove_one (struct pci_dev *pdev) { - struct amd76xrom_map_info *info = &amd76xrom_map; + struct amd76xrom_window *window = &amd76xrom_window; - amd76xrom_cleanup(info); + amd76xrom_cleanup(window); } static struct pci_device_id amd76xrom_pci_tbl[] = { @@ -269,7 +310,6 @@ int __init init_amd76xrom(void) } } if (pdev) { - amd76xrom_map.pdev = pdev; return amd76xrom_init_one(pdev, &amd76xrom_pci_tbl[0]); } return -ENXIO; @@ -280,7 +320,7 @@ int __init init_amd76xrom(void) static void __exit cleanup_amd76xrom(void) { - amd76xrom_remove_one(amd76xrom_map.pdev); + amd76xrom_remove_one(amd76xrom_window.pdev); } module_init(init_amd76xrom); diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c index a26cc3af5e1f..03a5d772f56a 100644 --- a/drivers/mtd/maps/ichxrom.c +++ b/drivers/mtd/maps/ichxrom.c @@ -2,7 +2,7 @@ * ichxrom.c * * Normal mappings of chips in physical memory - * $Id: ichxrom.c,v 1.8 2004/07/16 17:43:11 dwmw2 Exp $ + * $Id: ichxrom.c,v 1.14 2004/09/18 01:59:56 eric Exp $ */ #include @@ -12,187 +12,87 @@ #include #include #include +#include +#include #include #include #include -#include +#include #define xstr(s) str(s) #define str(s) #s #define MOD_NAME xstr(KBUILD_BASENAME) -#define MTD_DEV_NAME_LENGTH 16 - -#define RESERVE_MEM_REGION 0 - +#define ADDRESS_NAME_LEN 18 -#define MANUFACTURER_INTEL 0x0089 -#define I82802AB 0x00ad -#define I82802AC 0x00ac +#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */ -#define ICHX_FWH_REGION_START 0xFF000000UL -#define ICHX_FWH_REGION_SIZE 0x01000000UL #define BIOS_CNTL 0x4e #define FWH_DEC_EN1 0xE3 #define FWH_DEC_EN2 0xF0 #define FWH_SEL1 0xE8 #define FWH_SEL2 0xEE -struct ichxrom_map_info { - struct map_info map; - struct mtd_info *mtd; - unsigned long window_addr; +struct ichxrom_window { + void __iomem* virt; + unsigned long phys; + unsigned long size; + struct list_head maps; + struct resource rsrc; struct pci_dev *pdev; - struct resource window_rsrc; - struct resource rom_rsrc; - char mtd_name[MTD_DEV_NAME_LENGTH]; }; -static inline unsigned long addr(struct map_info *map, unsigned long ofs) -{ - unsigned long offset; - offset = ((8*1024*1024) - map->size) + ofs; - if (offset >= (4*1024*1024)) { - offset += 0x400000; - } - return map->map_priv_1 + 0x400000 + offset; -} - -static inline unsigned long dbg_addr(struct map_info *map, unsigned long addr) -{ - return addr - map->map_priv_1 + ICHX_FWH_REGION_START; -} - -static map_word ichxrom_read(struct map_info *map, unsigned long ofs) -{ - map_word val; - int i; - switch(map->bankwidth) { - case 1: val.x[0] = __raw_readb(addr(map, ofs)); break; - case 2: val.x[0] = __raw_readw(addr(map, ofs)); break; - case 4: val.x[0] = __raw_readl(addr(map, ofs)); break; -#if BITS_PER_LONG >= 64 - case 8: val.x[0] = __raw_readq(addr(map, ofs)); break; -#endif - default: val.x[0] = 0; break; - } - for(i = 1; i < map_words(map); i++) { - val.x[i] = 0; - } - return val; -} - -static void ichxrom_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -{ - memcpy_fromio(to, addr(map, from), len); -} - -static void ichxrom_write(struct map_info *map, map_word d, unsigned long ofs) -{ - switch(map->bankwidth) { - case 1: __raw_writeb(d.x[0], addr(map,ofs)); break; - case 2: __raw_writew(d.x[0], addr(map,ofs)); break; - case 4: __raw_writel(d.x[0], addr(map,ofs)); break; -#if BITS_PER_LONG >= 64 - case 8: __raw_writeq(d.x[0], addr(map,ofs)); break; -#endif - } - mb(); -} - -static void ichxrom_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -{ - memcpy_toio(addr(map, to), from, len); -} - -static struct ichxrom_map_info ichxrom_map = { - .map = { - .name = MOD_NAME, - .phys = NO_XIP, - .size = 0, - .bankwidth = 1, - .read = ichxrom_read, - .copy_from = ichxrom_copy_from, - .write = ichxrom_write, - .copy_to = ichxrom_copy_to, - /* Firmware hubs only use vpp when being programmed - * in a factory setting. So in-place programming - * needs to use a different method. - */ - }, - /* remaining fields of structure are initialized to 0 */ +struct ichxrom_map_info { + struct list_head list; + struct map_info map; + struct mtd_info *mtd; + struct resource rsrc; + char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN]; }; -enum fwh_lock_state { - FWH_DENY_WRITE = 1, - FWH_IMMUTABLE = 2, - FWH_DENY_READ = 4, +static struct ichxrom_window ichxrom_window = { + .maps = LIST_HEAD_INIT(ichxrom_window.maps), }; -static void ichxrom_cleanup(struct ichxrom_map_info *info) +static void ichxrom_cleanup(struct ichxrom_window *window) { + struct ichxrom_map_info *map, *scratch; u16 word; /* Disable writes through the rom window */ - pci_read_config_word(info->pdev, BIOS_CNTL, &word); - pci_write_config_word(info->pdev, BIOS_CNTL, word & ~1); - - if (info->mtd) { - del_mtd_device(info->mtd); - map_destroy(info->mtd); - info->mtd = NULL; - info->map.virt = 0; + pci_read_config_word(window->pdev, BIOS_CNTL, &word); + pci_write_config_word(window->pdev, BIOS_CNTL, word & ~1); + + /* Free all of the mtd devices */ + list_for_each_entry_safe(map, scratch, &window->maps, list) { + if (map->rsrc.parent) + release_resource(&map->rsrc); + del_mtd_device(map->mtd); + map_destroy(map->mtd); + list_del(&map->list); + kfree(map); } - if (info->rom_rsrc.parent) - release_resource(&info->rom_rsrc); - if (info->window_rsrc.parent) - release_resource(&info->window_rsrc); - - if (info->window_addr) { - iounmap((void *)(info->window_addr)); - info->window_addr = 0; - } -} - - -static int ichxrom_set_lock_state(struct mtd_info *mtd, loff_t ofs, size_t len, - enum fwh_lock_state state) -{ - struct map_info *map = mtd->priv; - unsigned long start = ofs; - unsigned long end = start + len -1; - - /* FIXME do I need to guard against concurrency here? */ - /* round down to 64K boundaries */ - start = start & ~0xFFFF; - end = end & ~0xFFFF; - while (start <= end) { - unsigned long ctrl_addr; - ctrl_addr = addr(map, start) - 0x400000 + 2; - writeb(state, ctrl_addr); - start = start + 0x10000; + if (window->rsrc.parent) + release_resource(&window->rsrc); + if (window->virt) { + iounmap(window->virt); + window->virt = NULL; + window->phys = 0; + window->size = 0; + window->pdev = NULL; } - return 0; } -static int ichxrom_lock(struct mtd_info *mtd, loff_t ofs, size_t len) -{ - return ichxrom_set_lock_state(mtd, ofs, len, FWH_DENY_WRITE); -} - -static int ichxrom_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) -{ - return ichxrom_set_lock_state(mtd, ofs, len, 0); -} static int __devinit ichxrom_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { + static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; + struct ichxrom_window *window = &ichxrom_window; + struct ichxrom_map_info *map = 0; + unsigned long map_top; + u8 byte; u16 word; - struct ichxrom_map_info *info = &ichxrom_map; - unsigned long map_size; - static char *probes[] = { "cfi_probe", "jedec_probe" }; - struct cfi_private *cfi; /* For now I just handle the ichx and I assume there * are not a lot of resources up at the top of the address @@ -204,26 +104,56 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev, * Also you can page firmware hubs if an 8MB window isn't enough * but don't currently handle that case either. */ + window->pdev = pdev; + + /* Find a region continuous to the end of the ROM window */ + window->phys = 0; + pci_read_config_byte(pdev, FWH_DEC_EN1, &byte); + if (byte == 0xff) { + window->phys = 0xffc00000; + pci_read_config_byte(pdev, FWH_DEC_EN2, &byte); + if ((byte & 0x0f) == 0x0f) { + window->phys = 0xff400000; + } + else if ((byte & 0x0e) == 0x0e) { + window->phys = 0xff500000; + } + else if ((byte & 0x0c) == 0x0c) { + window->phys = 0xff600000; + } + else if ((byte & 0x08) == 0x08) { + window->phys = 0xff700000; + } + } + else if ((byte & 0xfe) == 0xfe) { + window->phys = 0xffc80000; + } + else if ((byte & 0xfc) == 0xfc) { + window->phys = 0xffd00000; + } + else if ((byte & 0xf8) == 0xf8) { + window->phys = 0xffd80000; + } + else if ((byte & 0xf0) == 0xf0) { + window->phys = 0xffe00000; + } + else if ((byte & 0xe0) == 0xe0) { + window->phys = 0xffe80000; + } + else if ((byte & 0xc0) == 0xc0) { + window->phys = 0xfff00000; + } + else if ((byte & 0x80) == 0x80) { + window->phys = 0xfff80000; + } - info->pdev = pdev; - - /* - * Try to reserve the window mem region. If this fails then - * it is likely due to the window being "reseved" by the BIOS. - */ - info->window_rsrc.name = MOD_NAME; - info->window_rsrc.start = ICHX_FWH_REGION_START; - info->window_rsrc.end = ICHX_FWH_REGION_START + ICHX_FWH_REGION_SIZE - 1; - info->window_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; - if (request_resource(&iomem_resource, &info->window_rsrc)) { - info->window_rsrc.parent = NULL; - printk(KERN_ERR MOD_NAME - " %s(): Unable to register resource" - " 0x%.08lx-0x%.08lx - kernel bug?\n", - __func__, - info->window_rsrc.start, info->window_rsrc.end); + if (window->phys == 0) { + printk(KERN_ERR MOD_NAME ": Rom window is closed\n"); + goto out; } - + window->phys -= 0x400000UL; + window->size = (0xffffffffUL - window->phys) + 1UL; + /* Enable writes through the rom window */ pci_read_config_word(pdev, BIOS_CNTL, &word); if (!(word & 1) && (word & (1<<1))) { @@ -231,119 +161,167 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev, * this device, so don't even try. */ printk(KERN_ERR MOD_NAME ": firmware access control, I can't enable writes\n"); - goto failed; + goto out; } pci_write_config_word(pdev, BIOS_CNTL, word | 1); + /* + * Try to reserve the window mem region. If this fails then + * it is likely due to the window being "reseved" by the BIOS. + */ + window->rsrc.name = MOD_NAME; + window->rsrc.start = window->phys; + window->rsrc.end = window->phys + window->size - 1; + window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; + if (request_resource(&iomem_resource, &window->rsrc)) { + window->rsrc.parent = NULL; + printk(KERN_DEBUG MOD_NAME + ": %s(): Unable to register resource" + " 0x%.08lx-0x%.08lx - kernel bug?\n", + __func__, + window->rsrc.start, window->rsrc.end); + } /* Map the firmware hub into my address space. */ - /* Does this use too much virtual address space? */ - info->window_addr = (unsigned long)ioremap( - ICHX_FWH_REGION_START, ICHX_FWH_REGION_SIZE); - if (!info->window_addr) { - printk(KERN_ERR "Failed to ioremap\n"); - goto failed; + window->virt = ioremap_nocache(window->phys, window->size); + if (!window->virt) { + printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n", + window->phys, window->size); + goto out; } - /* For now assume the firmware has setup all relevant firmware - * windows. We don't have enough information to handle this case - * intelligently. + /* Get the first address to look for an rom chip at */ + map_top = window->phys; + if ((window->phys & 0x3fffff) != 0) { + map_top = window->phys + 0x400000; + } +#if 1 + /* The probe sequence run over the firmware hub lock + * registers sets them to 0x7 (no access). + * Probe at most the last 4M of the address space. */ + if (map_top < 0xffc00000) { + map_top = 0xffc00000; + } +#endif + /* Loop through and look for rom chips */ + while((map_top - 1) < 0xffffffffUL) { + struct cfi_private *cfi; + unsigned long offset; + int i; + + if (!map) { + map = kmalloc(sizeof(*map), GFP_KERNEL); + } + if (!map) { + printk(KERN_ERR MOD_NAME ": kmalloc failed"); + goto out; + } + memset(map, 0, sizeof(*map)); + INIT_LIST_HEAD(&map->list); + map->map.name = map->map_name; + map->map.phys = map_top; + offset = map_top - window->phys; + map->map.virt = (void __iomem *) + (((unsigned long)(window->virt)) + offset); + map->map.size = 0xffffffffUL - map_top + 1UL; + /* Set the name of the map to the address I am trying */ + sprintf(map->map_name, "%s @%08lx", + MOD_NAME, map->map.phys); - /* FIXME select the firmware hub and enable a window to it. */ - - info->mtd = NULL; - info->map.map_priv_1 = info->window_addr; - - /* Loop through the possible bankwidths */ - for(ichxrom_map.map.bankwidth = 4; ichxrom_map.map.bankwidth; ichxrom_map.map.bankwidth >>= 1) { - map_size = ICHX_FWH_REGION_SIZE; - while(!info->mtd && (map_size > 0)) { - int i; - info->map.size = map_size; - for(i = 0; i < sizeof(probes)/sizeof(char *); i++) { - info->mtd = do_map_probe(probes[i], &ichxrom_map.map); - if (info->mtd) - break; + /* Firmware hubs only use vpp when being programmed + * in a factory setting. So in-place programming + * needs to use a different method. + */ + for(map->map.bankwidth = 32; map->map.bankwidth; + map->map.bankwidth >>= 1) + { + char **probe_type; + /* Skip bankwidths that are not supported */ + if (!map_bankwidth_supported(map->map.bankwidth)) + continue; + + /* Setup the map methods */ + simple_map_init(&map->map); + + /* Try all of the probe methods */ + probe_type = rom_probe_types; + for(; *probe_type; probe_type++) { + map->mtd = do_map_probe(*probe_type, &map->map); + if (map->mtd) + goto found; } - map_size -= 512*1024; } - if (info->mtd) - break; - } - if (!info->mtd) { - goto failed; - } - cfi = ichxrom_map.map.fldrv_priv; - if ((cfi->mfr == MANUFACTURER_INTEL) && ( - (cfi->id == I82802AB) || - (cfi->id == I82802AC))) - { - /* If it is a firmware hub put in the special lock - * and unlock routines. - */ - info->mtd->lock = ichxrom_lock; - info->mtd->unlock = ichxrom_unlock; - } - if (info->mtd->size > info->map.size) { - printk(KERN_WARNING MOD_NAME " rom(%u) larger than window(%lu). fixing...\n", - info->mtd->size, info->map.size); - info->mtd->size = info->map.size; - } + map_top += ROM_PROBE_STEP_SIZE; + continue; + found: + /* Trim the size if we are larger than the map */ + if (map->mtd->size > map->map.size) { + printk(KERN_WARNING MOD_NAME + " rom(%u) larger than window(%lu). fixing...\n", + map->mtd->size, map->map.size); + map->mtd->size = map->map.size; + } + if (window->rsrc.parent) { + /* + * Registering the MTD device in iomem may not be possible + * if there is a BIOS "reserved" and BUSY range. If this + * fails then continue anyway. + */ + map->rsrc.name = map->map_name; + map->rsrc.start = map->map.phys; + map->rsrc.end = map->map.phys + map->mtd->size - 1; + map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; + if (request_resource(&window->rsrc, &map->rsrc)) { + printk(KERN_ERR MOD_NAME + ": cannot reserve MTD resource\n"); + map->rsrc.parent = NULL; + } + } + + /* Make the whole region visible in the map */ + map->map.virt = window->virt; + map->map.phys = window->phys; + cfi = map->map.fldrv_priv; + for(i = 0; i < cfi->numchips; i++) { + cfi->chips[i].start += offset; + } - info->mtd->owner = THIS_MODULE; - add_mtd_device(info->mtd); - - if (info->window_rsrc.parent) { - /* - * Registering the MTD device in iomem may not be possible - * if there is a BIOS "reserved" and BUSY range. If this - * fails then continue anyway. - */ - snprintf(info->mtd_name, MTD_DEV_NAME_LENGTH, - "mtd%d", info->mtd->index); - - info->rom_rsrc.name = info->mtd_name; - info->rom_rsrc.start = ICHX_FWH_REGION_START - + ICHX_FWH_REGION_SIZE - map_size; - info->rom_rsrc.end = ICHX_FWH_REGION_START - + ICHX_FWH_REGION_SIZE; - info->rom_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; - if (request_resource(&info->window_rsrc, &info->rom_rsrc)) { - printk(KERN_ERR MOD_NAME - ": cannot reserve MTD resource\n"); - info->rom_rsrc.parent = NULL; + /* Now that the mtd devices is complete claim and export it */ + map->mtd->owner = THIS_MODULE; + if (add_mtd_device(map->mtd)) { + map_destroy(map->mtd); + map->mtd = 0; + goto out; } + + + /* Calculate the new value of map_top */ + map_top += map->mtd->size; + + /* File away the map structure */ + list_add(&map->list, &window->maps); + map = 0; } + out: + /* Free any left over map structures */ + if (map) { + kfree(map); + } + /* See if I have any map structures */ + if (list_empty(&window->maps)) { + ichxrom_cleanup(window); + return -ENODEV; + } return 0; - - failed: - ichxrom_cleanup(info); - return -ENODEV; } static void __devexit ichxrom_remove_one (struct pci_dev *pdev) { - struct ichxrom_map_info *info = &ichxrom_map; - u16 word; - - del_mtd_device(info->mtd); - map_destroy(info->mtd); - info->mtd = NULL; - info->map.map_priv_1 = 0; - - iounmap((void *)(info->window_addr)); - info->window_addr = 0; - - /* Disable writes through the rom window */ - pci_read_config_word(pdev, BIOS_CNTL, &word); - pci_write_config_word(pdev, BIOS_CNTL, word & ~1); - -#if RESERVE_MEM_REGION - release_mem_region(ICHX_FWH_REGION_START, ICHX_FWH_REGION_SIZE); -#endif + struct ichxrom_window *window = &ichxrom_window; + ichxrom_cleanup(window); } static struct pci_device_id ichxrom_pci_tbl[] __devinitdata = { @@ -371,7 +349,6 @@ static struct pci_driver ichxrom_driver = { }; #endif -static struct pci_dev *mydev; int __init init_ichxrom(void) { struct pci_dev *pdev; @@ -385,7 +362,6 @@ int __init init_ichxrom(void) } } if (pdev) { - mydev = pdev; return ichxrom_init_one(pdev, &ichxrom_pci_tbl[0]); } return -ENXIO; @@ -396,7 +372,7 @@ int __init init_ichxrom(void) static void __exit cleanup_ichxrom(void) { - ichxrom_remove_one(mydev); + ichxrom_remove_one(ichxrom_window.pdev); } module_init(init_ichxrom); diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index a3efae0cd9a2..284f24851f1d 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -1,7 +1,7 @@ /* Common Flash Interface structures * See http://support.intel.com/design/flash/technote/index.htm - * $Id: cfi.h,v 1.45 2004/07/20 02:44:27 dwmw2 Exp $ + * $Id: cfi.h,v 1.48 2004/10/20 23:08:05 dwmw2 Exp $ */ #ifndef __MTD_CFI_H__ @@ -177,16 +177,19 @@ struct cfi_bri_query { uint32_t ConfField[1]; /* Not host ordered */ } __attribute__((packed)); -#define P_ID_NONE 0 -#define P_ID_INTEL_EXT 1 -#define P_ID_AMD_STD 2 -#define P_ID_INTEL_STD 3 -#define P_ID_AMD_EXT 4 -#define P_ID_ST_ADV 32 -#define P_ID_MITSUBISHI_STD 256 -#define P_ID_MITSUBISHI_EXT 257 -#define P_ID_SST_PAGE 258 -#define P_ID_RESERVED 65535 +#define P_ID_NONE 0x0000 +#define P_ID_INTEL_EXT 0x0001 +#define P_ID_AMD_STD 0x0002 +#define P_ID_INTEL_STD 0x0003 +#define P_ID_AMD_EXT 0x0004 +#define P_ID_WINBOND 0x0006 +#define P_ID_ST_ADV 0x0020 +#define P_ID_MITSUBISHI_STD 0x0100 +#define P_ID_MITSUBISHI_EXT 0x0101 +#define P_ID_SST_PAGE 0x0102 +#define P_ID_INTEL_PERFORMANCE 0x0200 +#define P_ID_INTEL_DATA 0x0210 +#define P_ID_RESERVED 0xffff #define CFI_MODE_CFI 1 @@ -350,17 +353,26 @@ static inline void cfi_spin_unlock(spinlock_t *mutex) struct cfi_extquery *cfi_read_pri(struct map_info *map, uint16_t adr, uint16_t size, const char* name); - struct cfi_fixup { uint16_t mfr; uint16_t id; - void (*fixup)(struct map_info *map, void* param); + void (*fixup)(struct mtd_info *mtd, void* param); void* param; }; #define CFI_MFR_ANY 0xffff #define CFI_ID_ANY 0xffff -void cfi_fixup(struct map_info *map, struct cfi_fixup* fixups); +#define CFI_MFR_AMD 0x0001 +#define CFI_MFR_ST 0x0020 /* STMicroelectronics */ + +void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup* fixups); + +typedef int (*varsize_frob_t)(struct map_info *map, struct flchip *chip, + unsigned long adr, int len, void *thunk); + +int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob, + loff_t ofs, size_t len, void *thunk); + #endif /* __MTD_CFI_H__ */ -- cgit v1.2.3 From ce9ef9d9bdd861fbcd221d1722deb5ce13ded23e Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 21 Oct 2004 02:35:05 +0100 Subject: MTD: NAND flash driver updates. - Use new RS library for ECC - Add support for new NAND flash chips - New board support: - iPAQ H1910 - Renesas AG-AND devel board - Simtec S3C210 - Support for shared controllers on multiple chips. Signed-Off-By: Thomas Gleixner Signed-Off-By: David Woodhouse --- drivers/mtd/nand/Kconfig | 49 ++- drivers/mtd/nand/Makefile | 5 +- drivers/mtd/nand/au1550nd.c | 420 ++++++++++++++--------- drivers/mtd/nand/autcpu12.c | 6 +- drivers/mtd/nand/diskonchip.c | 234 ++++++++++--- drivers/mtd/nand/edb7312.c | 27 +- drivers/mtd/nand/h1910.c | 208 +++++++++++ drivers/mtd/nand/nand_base.c | 147 ++++---- drivers/mtd/nand/nand_bbt.c | 5 +- drivers/mtd/nand/ppchameleonevb.c | 51 ++- drivers/mtd/nand/rtc_from4.c | 561 ++++++++++++++++++++++++++++++ drivers/mtd/nand/s3c2410.c | 704 ++++++++++++++++++++++++++++++++++++++ drivers/mtd/nand/spia.c | 23 +- drivers/mtd/nand/toto.c | 24 +- drivers/mtd/nand/tx4925ndfmc.c | 30 +- drivers/mtd/nand/tx4938ndfmc.c | 22 +- include/linux/mtd/nand.h | 20 +- 17 files changed, 2101 insertions(+), 435 deletions(-) create mode 100644 drivers/mtd/nand/h1910.c create mode 100644 drivers/mtd/nand/rtc_from4.c create mode 100644 drivers/mtd/nand/s3c2410.c (limited to 'include/linux') diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index ed085292c57d..89ab7da160f1 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -1,5 +1,5 @@ # drivers/mtd/nand/Kconfig -# $Id: Kconfig,v 1.17 2004/08/10 14:24:07 dwmw2 Exp $ +# $Id: Kconfig,v 1.22 2004/10/05 22:11:46 gleixner Exp $ menu "NAND Flash Device Drivers" depends on MTD!=n @@ -36,6 +36,12 @@ config MTD_NAND_EDB7312 This enables the driver for the Cirrus Logic EBD7312 evaluation board to access the onboard NAND Flash. +config MTD_NAND_H1900 + tristate "iPAQ H1900 flash" + depends on ARM && MTD_NAND && ARCH_PXA && MTD_PARTITIONS + help + This enables the driver for the iPAQ h1900 flash. + config MTD_NAND_SPIA tristate "NAND Flash device on SPIA board" depends on ARM && ARCH_P720T && MTD_NAND @@ -74,15 +80,54 @@ config MTD_NAND_AU1550 This enables the driver for the NAND flash controller on the AMD/Alchemy 1550 SOC. +config MTD_NAND_RTC_FROM4 + tristate "Renesas Flash ROM 4-slot interface board (FROM_BOARD4)" + depends on MTD_NAND && SH_SOLUTION_ENGINE + select REED_SOLOMON + select REED_SOLOMON_DEC8 + help + This enables the driver for the Renesas Technology AG-AND + flash interface board (FROM_BOARD4) + config MTD_NAND_PPCHAMELEONEVB tristate "NAND Flash device on PPChameleonEVB board" depends on PPCHAMELEONEVB && MTD_NAND help - This enables the NAND flash driver on the PPChameleon EVB Board. + This enables the NAND flash driver on the PPChameleon EVB Board. + +config MTD_NAND_S3C2410 + tristate "NAND Flash support for S3C2410 SoC" + depends on ARCH_S3C2410 && MTD_NAND + help + This enables the NAND flash controller on the S3C2410. + + No board specfic support is done by this driver, each board + must advertise a platform_device for the driver to attach. + +config MTD_NAND_S3C2410_DEBUG + bool "S3C2410 NAND driver debug" + depends on MTD_NAND_S3C2410 + help + Enable debugging of the S3C2410 NAND driver + +config MTD_NAND_S3C2410_HWECC + bool "S3C2410 NAND Hardware ECC" + depends on MTD_NAND_S3C2410 + help + Enable the use of the S3C2410's internal ECC generator when + using NAND. Early versions of the chip have had problems with + incorrect ECC generation, and if using these, the default of + software ECC is preferable. + + If you lay down a device with the hardware ECC, then you will + currently not be able to switch to software, as there is no + implementation for ECC method used by the S3C2410 config MTD_NAND_DISKONCHIP tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)" depends on MTD_NAND && EXPERIMENTAL + select REED_SOLOMON + select REED_SOLOMON_DEC16 help This is a reimplementation of M-Systems DiskOnChip 2000, Millennium and Millennium Plus as a standard NAND device driver, diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index db19399398ad..a0b6c60528da 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -1,7 +1,7 @@ # # linux/drivers/nand/Makefile # -# $Id: Makefile.common,v 1.9 2004/07/12 16:07:31 dwmw2 Exp $ +# $Id: Makefile.common,v 1.13 2004/09/28 22:04:23 bjd Exp $ obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o @@ -14,6 +14,9 @@ obj-$(CONFIG_MTD_NAND_TX4925NDFMC) += tx4925ndfmc.o obj-$(CONFIG_MTD_NAND_TX4938NDFMC) += tx4938ndfmc.o obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o +obj-$(CONFIG_MTD_NAND_S3C2410) += s3c2410.o obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o +obj-$(CONFIG_MTD_NAND_H1900) += h1910.o +obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o nand-objs = nand_base.o nand_bbt.o diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 8e4da650603f..196d1f20a47b 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -3,7 +3,7 @@ * * Copyright (C) 2004 Embedded Edge, LLC * - * $Id: au1550nd.c,v 1.5 2004/05/17 07:19:35 ppopov Exp $ + * $Id: au1550nd.c,v 1.9 2004/10/20 05:58:30 ppopov Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,6 +18,17 @@ #include #include #include + +/* fixme: this is ugly */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 0) +#include +#ifdef CONFIG_MIPS_PB1550 +#include +#endif +#ifdef CONFIG_MIPS_DB1550 +#include +#endif +#else #include #ifdef CONFIG_MIPS_PB1550 #include @@ -25,18 +36,16 @@ #ifdef CONFIG_MIPS_DB1550 #include #endif - +#endif /* * MTD structure for NAND controller */ static struct mtd_info *au1550_mtd = NULL; -static volatile u32 p_nand; -static int nand_width = 1; /* default, only x8 supported for now */ +static void __iomem *p_nand; +static int nand_width = 1; /* default x8*/ -/* Internal buffers. Page buffer and oob buffer for one block*/ -static u_char data_buf[512 + 16]; -static u_char oob_buf[16 * 32]; +#define NAND_CS 1 /* * Define partitions for flash device @@ -70,183 +79,262 @@ const static struct mtd_partition partition_info[] = { #endif }; -static inline void write_cmd_reg(u8 cmd) + +/** + * au_read_byte - read one byte from the chip + * @mtd: MTD device structure + * + * read function for 8bit buswith + */ +static u_char au_read_byte(struct mtd_info *mtd) { - if (nand_width) - *((volatile u8 *)(p_nand + MEM_STNAND_CMD)) = cmd; - else - *((volatile u16 *)(p_nand + MEM_STNAND_CMD)) = cmd; + struct nand_chip *this = mtd->priv; + u_char ret = readb(this->IO_ADDR_R); au_sync(); + return ret; } -static inline void write_addr_reg(u8 addr) +/** + * au_write_byte - write one byte to the chip + * @mtd: MTD device structure + * @byte: pointer to data byte to write + * + * write function for 8it buswith + */ +static void au_write_byte(struct mtd_info *mtd, u_char byte) { - if (nand_width) - *((volatile u8 *)(p_nand + MEM_STNAND_ADDR)) = addr; - else - *((volatile u16 *)(p_nand + MEM_STNAND_ADDR)) = addr; + struct nand_chip *this = mtd->priv; + writeb(byte, this->IO_ADDR_W); au_sync(); } -static inline void write_data_reg(u8 data) +/** + * au_read_byte16 - read one byte endianess aware from the chip + * @mtd: MTD device structure + * + * read function for 16bit buswith with + * endianess conversion + */ +static u_char au_read_byte16(struct mtd_info *mtd) { - if (nand_width) - *((volatile u8 *)(p_nand + MEM_STNAND_DATA)) = data; - else - *((volatile u16 *)(p_nand + MEM_STNAND_DATA)) = data; + struct nand_chip *this = mtd->priv; + u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R)); au_sync(); + return ret; } -static inline u32 read_data_reg(void) +/** + * au_write_byte16 - write one byte endianess aware to the chip + * @mtd: MTD device structure + * @byte: pointer to data byte to write + * + * write function for 16bit buswith with + * endianess conversion + */ +static void au_write_byte16(struct mtd_info *mtd, u_char byte) { - u32 data; - if (nand_width) { - data = *((volatile u8 *)(p_nand + MEM_STNAND_DATA)); - au_sync(); - } - else { - data = *((volatile u16 *)(p_nand + MEM_STNAND_DATA)); - au_sync(); - } - return data; + struct nand_chip *this = mtd->priv; + writew(le16_to_cpu((u16) byte), this->IO_ADDR_W); + au_sync(); } -void au1550_hwcontrol(struct mtd_info *mtd, int cmd) +/** + * au_read_word - read one word from the chip + * @mtd: MTD device structure + * + * read function for 16bit buswith without + * endianess conversion + */ +static u16 au_read_word(struct mtd_info *mtd) { + struct nand_chip *this = mtd->priv; + u16 ret = readw(this->IO_ADDR_R); + au_sync(); + return ret; } -int au1550_device_ready(struct mtd_info *mtd) +/** + * au_write_word - write one word to the chip + * @mtd: MTD device structure + * @word: data word to write + * + * write function for 16bit buswith without + * endianess conversion + */ +static void au_write_word(struct mtd_info *mtd, u16 word) { - int ready; - ready = (au_readl(MEM_STSTAT) & 0x1) ? 1 : 0; - return ready; + struct nand_chip *this = mtd->priv; + writew(word, this->IO_ADDR_W); + au_sync(); } -static u_char au1550_nand_read_byte(struct mtd_info *mtd) +/** + * au_write_buf - write buffer to chip + * @mtd: MTD device structure + * @buf: data buffer + * @len: number of bytes to write + * + * write function for 8bit buswith + */ +static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len) { - u_char ret; - ret = read_data_reg(); - return ret; -} + int i; + struct nand_chip *this = mtd->priv; -static void au1550_nand_write_byte(struct mtd_info *mtd, u_char byte) -{ - write_data_reg((u8)byte); + for (i=0; iIO_ADDR_W); + au_sync(); + } } -static void -au1550_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +/** + * au_read_buf - read chip data into buffer + * @mtd: MTD device structure + * @buf: buffer to store date + * @len: number of bytes to read + * + * read function for 8bit buswith + */ +static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len) { int i; + struct nand_chip *this = mtd->priv; - for (i=0; iIO_ADDR_R); + au_sync(); + } } -static void -au1550_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) +/** + * au_verify_buf - Verify chip data against buffer + * @mtd: MTD device structure + * @buf: buffer containing the data to compare + * @len: number of bytes to compare + * + * verify function for 8bit buswith + */ +static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) { int i; + struct nand_chip *this = mtd->priv; - for (i=0; iIO_ADDR_R)) + return -EFAULT; + au_sync(); + } + + return 0; } -static int -au1550_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) +/** + * au_write_buf16 - write buffer to chip + * @mtd: MTD device structure + * @buf: data buffer + * @len: number of bytes to write + * + * write function for 16bit buswith + */ +static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len) { int i; + struct nand_chip *this = mtd->priv; + u16 *p = (u16 *) buf; + len >>= 1; + + for (i=0; iIO_ADDR_W); + au_sync(); + } + +} - for (i=0; ipriv; + u16 *p = (u16 *) buf; + len >>= 1; - return 0; + for (i=0; iIO_ADDR_R); + au_sync(); + } } -static void au1550_nand_select_chip(struct mtd_info *mtd, int chip) +/** + * au_verify_buf16 - Verify chip data against buffer + * @mtd: MTD device structure + * @buf: buffer containing the data to compare + * @len: number of bytes to compare + * + * verify function for 16bit buswith + */ +static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len) { - switch(chip) { - case -1: - /* deassert chip enable */ - au_writel(au_readl(MEM_STNDCTL) & ~0x20 , MEM_STNDCTL); - break; - case 0: - /* assert (force assert) chip enable */ - au_writel(au_readl(MEM_STNDCTL) | 0x20 , MEM_STNDCTL); - break; + int i; + struct nand_chip *this = mtd->priv; + u16 *p = (u16 *) buf; + len >>= 1; - default: - BUG(); + for (i=0; iIO_ADDR_R)) + return -EFAULT; + au_sync(); } + return 0; } -static void au1550_nand_command (struct mtd_info *mtd, unsigned command, - int column, int page_addr) + +static void au1550_hwcontrol(struct mtd_info *mtd, int cmd) { register struct nand_chip *this = mtd->priv; - /* - * Write out the command to the device. - */ - if (command == NAND_CMD_SEQIN) { - int readcmd; - - if (column >= mtd->oobblock) { - /* OOB area */ - column -= mtd->oobblock; - readcmd = NAND_CMD_READOOB; - } else if (column < 256) { - /* First 256 bytes --> READ0 */ - readcmd = NAND_CMD_READ0; - } else { - column -= 256; - readcmd = NAND_CMD_READ1; - } - write_cmd_reg(readcmd); - } - write_cmd_reg(command); - - if (column != -1 || page_addr != -1) { - - /* Serially input address */ - if (column != -1) - write_addr_reg(column); - if (page_addr != -1) { - write_addr_reg((unsigned char) (page_addr & 0xff)); - write_addr_reg(((page_addr >> 8) & 0xff)); - /* One more address cycle for higher density devices */ - if (mtd->size & 0x0c000000) - write_addr_reg((unsigned char) ((page_addr >> 16) & 0x0f)); - } - } - - switch (command) { - - case NAND_CMD_PAGEPROG: - case NAND_CMD_ERASE1: - case NAND_CMD_ERASE2: - case NAND_CMD_SEQIN: - case NAND_CMD_STATUS: + switch(cmd){ + + case NAND_CTL_SETCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_CMD; break; + case NAND_CTL_CLRCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; break; + + case NAND_CTL_SETALE: this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR; break; + case NAND_CTL_CLRALE: + this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; + /* FIXME: Nobody knows why this is neccecary, + * but it works only that way */ + udelay(1); break; - case NAND_CMD_RESET: - if (this->dev_ready) - break; - udelay(this->chip_delay); - write_cmd_reg(NAND_CMD_STATUS); - while ( !(read_data_reg() & 0x40)); - return; - - /* This applies to read commands */ - default: - udelay (this->chip_delay); + case NAND_CTL_SETNCE: + /* assert (force assert) chip enable */ + au_writel(au_readl(MEM_STNDCTL) | (1<<(4+NAND_CS)) , MEM_STNDCTL); + break; + + case NAND_CTL_CLRNCE: + /* deassert chip enable */ + au_writel(au_readl(MEM_STNDCTL) & ~(1<<(4+NAND_CS)), MEM_STNDCTL); + break; } + + this->IO_ADDR_R = this->IO_ADDR_W; - /* wait until command is processed */ - while (!this->dev_ready(mtd)); + /* Drain the writebuffer */ + au_sync(); } +int au1550_device_ready(struct mtd_info *mtd) +{ + int ret = (au_readl(MEM_STSTAT) & 0x1) ? 1 : 0; + au_sync(); + return ret; +} /* * Main initialization routine @@ -255,7 +343,7 @@ int __init au1550_init (void) { struct nand_chip *this; u16 boot_swapboot = 0; /* default value */ - u32 mem_time; + int retval; /* Allocate memory for MTD device structure and private data */ au1550_mtd = kmalloc (sizeof(struct mtd_info) + @@ -275,9 +363,10 @@ int __init au1550_init (void) /* Link the private data with the MTD structure */ au1550_mtd->priv = this; + + /* MEM_STNDCTL: disable ints, disable nand boot */ /* disable interrupts */ au_writel(au_readl(MEM_STNDCTL) & ~(1<<8), MEM_STNDCTL); - /* disable NAND boot */ au_writel(au_readl(MEM_STNDCTL) & ~(1<<0), MEM_STNDCTL); @@ -295,7 +384,6 @@ int __init au1550_init (void) case 0xD: /* x16 NAND Flash */ nand_width = 0; - printk("Pb1550 NAND: 16-bit NAND not supported by MTD\n"); break; case 1: case 9: @@ -307,62 +395,62 @@ int __init au1550_init (void) break; default: printk("Pb1550 NAND: bad boot:swap\n"); - kfree(au1550_mtd); - return 1; + retval = -EINVAL; + goto outmem; } +#endif /* Configure RCE1 - should be done by YAMON */ - au_writel(0x5 | (nand_width << 22), MEM_STCFG1); - au_writel(NAND_TIMING, MEM_STTIME1); - mem_time = au_readl(MEM_STTIME1); + au_writel(0x5 | (nand_width << 22), 0xB4001010); /* MEM_STCFG1 */ + au_writel(NAND_TIMING, 0xB4001014); /* MEM_STTIME1 */ au_sync(); - /* setup and enable chip select */ + /* setup and enable chip select, MEM_STADDR1 */ /* we really need to decode offsets only up till 0x20 */ au_writel((1<<28) | (NAND_PHYS_ADDR>>4) | (((NAND_PHYS_ADDR + 0x1000)-1) & (0x3fff<<18)>>18), MEM_STADDR1); au_sync(); -#endif -#ifdef CONFIG_MIPS_DB1550 - /* Configure RCE1 - should be done by YAMON */ - au_writel(0x00400005, MEM_STCFG1); - au_writel(0x00007774, MEM_STTIME1); - au_writel(0x12000FFF, MEM_STADDR1); -#endif - - p_nand = (volatile struct nand_regs *)ioremap(NAND_PHYS_ADDR, 0x1000); + p_nand = (void __iomem *)ioremap(NAND_PHYS_ADDR, 0x1000); /* Set address of hardware control function */ this->hwcontrol = au1550_hwcontrol; this->dev_ready = au1550_device_ready; /* 30 us command delay time */ this->chip_delay = 30; - - this->cmdfunc = au1550_nand_command; - this->select_chip = au1550_nand_select_chip; - this->write_byte = au1550_nand_write_byte; - this->read_byte = au1550_nand_read_byte; - this->write_buf = au1550_nand_write_buf; - this->read_buf = au1550_nand_read_buf; - this->verify_buf = au1550_nand_verify_buf; this->eccmode = NAND_ECC_SOFT; - /* Set internal data buffer */ - this->data_buf = data_buf; - this->oob_buf = oob_buf; + this->options = NAND_NO_AUTOINCR; + + if (!nand_width) + this->options |= NAND_BUSWIDTH_16; + + this->read_byte = (!nand_width) ? au_read_byte16 : au_read_byte; + this->write_byte = (!nand_width) ? au_write_byte16 : au_write_byte; + this->write_word = au_write_word; + this->read_word = au_read_word; + this->write_buf = (!nand_width) ? au_write_buf16 : au_write_buf; + this->read_buf = (!nand_width) ? au_read_buf16 : au_read_buf; + this->verify_buf = (!nand_width) ? au_verify_buf16 : au_verify_buf; /* Scan to find existence of the device */ if (nand_scan (au1550_mtd, 1)) { - kfree (au1550_mtd); - return -ENXIO; + retval = -ENXIO; + goto outio; } /* Register the partitions */ add_mtd_partitions(au1550_mtd, partition_info, NUM_PARTITIONS); return 0; + + outio: + iounmap ((void *)p_nand); + + outmem: + kfree (au1550_mtd); + return retval; } module_init(au1550_init); @@ -375,16 +463,14 @@ static void __exit au1550_cleanup (void) { struct nand_chip *this = (struct nand_chip *) &au1550_mtd[1]; - iounmap ((void *)p_nand); - - /* Unregister partitions */ - del_mtd_partitions(au1550_mtd); - - /* Unregister the device */ - del_mtd_device (au1550_mtd); + /* Release resources, unregister device */ + nand_release (au1550_mtd); /* Free the MTD device structure */ kfree (au1550_mtd); + + /* Unmap */ + iounmap ((void *)p_nand); } module_exit(au1550_cleanup); #endif diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c index 33779a8dadf4..eb101b47c9ce 100644 --- a/drivers/mtd/nand/autcpu12.c +++ b/drivers/mtd/nand/autcpu12.c @@ -6,7 +6,7 @@ * Derived from drivers/mtd/spia.c * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) * - * $Id: autcpu12.c,v 1.20 2004/07/20 02:44:26 dwmw2 Exp $ + * $Id: autcpu12.c,v 1.21 2004/09/16 23:27:14 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -48,7 +48,7 @@ static int autcpu12_io_base = CS89712_VIRT_BASE; static int autcpu12_fio_pbase = AUTCPU12_PHYS_SMC; static int autcpu12_fio_ctrl = AUTCPU12_SMC_SELECT_OFFSET; static int autcpu12_pedr = AUTCPU12_SMC_PORT_OFFSET; -static int autcpu12_fio_base; +static void __iomem * autcpu12_fio_base; #ifdef MODULE MODULE_PARM(autcpu12_fio_pbase, "i"); @@ -150,7 +150,7 @@ int __init autcpu12_init (void) } /* map physical adress */ - autcpu12_fio_base=(unsigned long)ioremap(autcpu12_fio_pbase,SZ_1K); + autcpu12_fio_base=(void __iomem *)ioremap(autcpu12_fio_pbase,SZ_1K); if(!autcpu12_fio_base){ printk("Ioremap autcpu12 SmartMedia Card failed\n"); err = -EIO; diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 0f7dedd6b88e..a94cca472f81 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -8,16 +8,22 @@ * Author: David Woodhouse * Additional Diskonchip 2000 and Millennium support by Dan Brown * Diskonchip Millennium Plus support by Kalev Lember - * + * + * Error correction code lifted from the old docecc code + * Author: Fabrice Bellard (fabrice.bellard@netgem.com) + * Copyright (C) 2000 Netgem S.A. + * converted to the generic Reed-Solomon library by Thomas Gleixner + * * Interface to generic NAND code for M-Systems DiskOnChip devices * - * $Id: diskonchip.c,v 1.34 2004/08/09 19:41:12 dbrown Exp $ + * $Id: diskonchip.c,v 1.38 2004/10/05 22:11:46 gleixner Exp $ */ #include #include #include #include +#include #include #include @@ -62,7 +68,7 @@ static unsigned long __initdata doc_locations[] = { static struct mtd_info *doclist = NULL; struct doc_priv { - unsigned long virtadr; + void __iomem *virtadr; unsigned long physadr; u_char ChipID; u_char CDSNControl; @@ -104,8 +110,10 @@ MODULE_PARM(try_dword, "i"); static int no_ecc_failures=0; MODULE_PARM(no_ecc_failures, "i"); +#ifdef CONFIG_MTD_PARTITIONS static int no_autopart=0; MODULE_PARM(no_autopart, "i"); +#endif #ifdef MTD_NAND_DISKONCHIP_BBTWRITE static int inftl_bbt_write=1; @@ -118,6 +126,112 @@ static unsigned long doc_config_location = CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS; MODULE_PARM(doc_config_location, "l"); MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip"); + +/* Sector size for HW ECC */ +#define SECTOR_SIZE 512 +/* The sector bytes are packed into NB_DATA 10 bit words */ +#define NB_DATA (((SECTOR_SIZE + 1) * 8 + 6) / 10) +/* Number of roots */ +#define NROOTS 4 +/* First consective root */ +#define FCR 510 +/* Number of symbols */ +#define NN 1023 + +/* the Reed Solomon control structure */ +static struct rs_control *rs_decoder; + +/* + * The HW decoder in the DoC ASIC's provides us a error syndrome, + * which we must convert to a standard syndrom usable by the generic + * Reed-Solomon library code. + * + * Fabrice Bellard figured this out in the old docecc code. I added + * some comments, improved a minor bit and converted it to make use + * of the generic Reed-Solomon libary. tglx + */ +static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) +{ + int i, j, nerr, errpos[8]; + uint8_t parity; + uint16_t ds[4], s[5], tmp, errval[8], syn[4]; + + /* Convert the ecc bytes into words */ + ds[0] = ((ecc[4] & 0xff) >> 0) | ((ecc[5] & 0x03) << 8); + ds[1] = ((ecc[5] & 0xfc) >> 2) | ((ecc[2] & 0x0f) << 6); + ds[2] = ((ecc[2] & 0xf0) >> 4) | ((ecc[3] & 0x3f) << 4); + ds[3] = ((ecc[3] & 0xc0) >> 6) | ((ecc[0] & 0xff) << 2); + parity = ecc[1]; + + /* Initialize the syndrom buffer */ + for (i = 0; i < NROOTS; i++) + s[i] = ds[0]; + /* + * Evaluate + * s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0] + * where x = alpha^(FCR + i) + */ + for(j = 1; j < NROOTS; j++) { + if(ds[j] == 0) + continue; + tmp = rs->index_of[ds[j]]; + for(i = 0; i < NROOTS; i++) + s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)]; + } + + /* Calc s[i] = s[i] / alpha^(v + i) */ + for (i = 0; i < NROOTS; i++) { + if (syn[i]) + syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i)); + } + /* Call the decoder library */ + nerr = decode_rs16(rs, NULL, NULL, 1019, syn, 0, errpos, 0, errval); + + /* Incorrectable errors ? */ + if (nerr < 0) + return nerr; + + /* + * Correct the errors. The bitpositions are a bit of magic, + * but they are given by the design of the de/encoder circuit + * in the DoC ASIC's. + */ + for(i = 0;i < nerr; i++) { + int index, bitpos, pos = 1015 - errpos[i]; + uint8_t val; + if (pos >= NB_DATA && pos < 1019) + continue; + if (pos < NB_DATA) { + /* extract bit position (MSB first) */ + pos = 10 * (NB_DATA - 1 - pos) - 6; + /* now correct the following 10 bits. At most two bytes + can be modified since pos is even */ + index = (pos >> 3) ^ 1; + bitpos = pos & 7; + if ((index >= 0 && index < SECTOR_SIZE) || + index == (SECTOR_SIZE + 1)) { + val = (uint8_t) (errval[i] >> (2 + bitpos)); + parity ^= val; + if (index < SECTOR_SIZE) + data[index] ^= val; + } + index = ((pos >> 3) + 1) ^ 1; + bitpos = (bitpos + 10) & 7; + if (bitpos == 0) + bitpos = 8; + if ((index >= 0 && index < SECTOR_SIZE) || + index == (SECTOR_SIZE + 1)) { + val = (uint8_t)(errval[i] << (8 - bitpos)); + parity ^= val; + if (index < SECTOR_SIZE) + data[index] ^= val; + } + } + } + /* If the parity is wrong, no rescue possible */ + return parity ? -1 : nerr; +} + static void DoC_Delay(struct doc_priv *doc, unsigned short cycles) { volatile char dummy; @@ -139,7 +253,7 @@ static void DoC_Delay(struct doc_priv *doc, unsigned short cycles) /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ static int _DoC_WaitReady(struct doc_priv *doc) { - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; unsigned long timeo = jiffies + (HZ * 10); if(debug) printk("_DoC_WaitReady...\n"); @@ -169,7 +283,7 @@ static int _DoC_WaitReady(struct doc_priv *doc) static inline int DoC_WaitReady(struct doc_priv *doc) { - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int ret = 0; if (DoC_is_MillenniumPlus(doc)) { @@ -195,7 +309,7 @@ static void doc2000_write_byte(struct mtd_info *mtd, u_char datum) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; if(debug)printk("write_byte %02x\n", datum); WriteDOC(datum, docptr, CDSNSlowIO); @@ -206,7 +320,7 @@ static u_char doc2000_read_byte(struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; u_char ret; ReadDOC(docptr, CDSNSlowIO); @@ -221,7 +335,7 @@ static void doc2000_writebuf(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; if (debug)printk("writebuf of %d bytes: ", len); for (i=0; i < len; i++) { @@ -237,7 +351,7 @@ static void doc2000_readbuf(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; if (debug)printk("readbuf of %d bytes: ", len); @@ -252,7 +366,7 @@ static void doc2000_readbuf_dword(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; if (debug) printk("readbuf_dword of %d bytes: ", len); @@ -273,7 +387,7 @@ static int doc2000_verifybuf(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; for (i=0; i < len; i++) @@ -305,7 +419,7 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) uint32_t dword; uint8_t byte[4]; } ident; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; doc200x_hwcontrol(mtd, NAND_CTL_SETCLE); doc2000_write_byte(mtd, NAND_CMD_READID); @@ -364,7 +478,7 @@ static void doc2001_write_byte(struct mtd_info *mtd, u_char datum) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; WriteDOC(datum, docptr, CDSNSlowIO); WriteDOC(datum, docptr, Mil_CDSN_IO); @@ -375,7 +489,7 @@ static u_char doc2001_read_byte(struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; //ReadDOC(docptr, CDSNSlowIO); /* 11.4.5 -- delay twice to allow extended length cycle */ @@ -390,7 +504,7 @@ static void doc2001_writebuf(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; for (i=0; i < len; i++) @@ -404,7 +518,7 @@ static void doc2001_readbuf(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; /* Start read pipeline */ @@ -422,7 +536,7 @@ static int doc2001_verifybuf(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; /* Start read pipeline */ @@ -442,7 +556,7 @@ static u_char doc2001plus_read_byte(struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; u_char ret; ReadDOC(docptr, Mplus_ReadPipeInit); @@ -457,7 +571,7 @@ static void doc2001plus_writebuf(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; if (debug)printk("writebuf of %d bytes: ", len); @@ -474,7 +588,7 @@ static void doc2001plus_readbuf(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; if (debug)printk("readbuf of %d bytes: ", len); @@ -504,7 +618,7 @@ static int doc2001plus_verifybuf(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; if (debug)printk("verifybuf of %d bytes: ", len); @@ -530,7 +644,7 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int floor = 0; if(debug)printk("select chip (%d)\n", chip); @@ -556,7 +670,7 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int floor = 0; if(debug)printk("select chip (%d)\n", chip); @@ -583,7 +697,7 @@ static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; switch(cmd) { case NAND_CTL_SETNCE: @@ -621,7 +735,7 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; /* * Must terminate write pipeline before sending any commands @@ -725,7 +839,7 @@ static int doc200x_dev_ready(struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; if (DoC_is_MillenniumPlus(doc)) { /* 11.4.2 -- must NOP four times before checking FR/B# */ @@ -763,7 +877,7 @@ static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; /* Prime the ECC engine */ switch(mode) { @@ -782,7 +896,7 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; /* Prime the ECC engine */ switch(mode) { @@ -803,7 +917,7 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; int emptymatch = 1; @@ -861,7 +975,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ int i, ret = 0; struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; volatile u_char dummy; int emptymatch = 1; @@ -914,7 +1028,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ erased block, in which case the ECC will not come out right. We'll suppress the error and tell the caller everything's OK. Because it is. */ - if (!emptymatch) ret = doc_decode_ecc (dat, calc_ecc); + if (!emptymatch) ret = doc_ecc_decode (rs_decoder, dat, calc_ecc); if (ret > 0) printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret); } @@ -1385,13 +1499,13 @@ static inline int __init doc_probe(unsigned long physadr) struct mtd_info *mtd; struct nand_chip *nand; struct doc_priv *doc; - unsigned long virtadr; + void __iomem *virtadr; unsigned char save_control; unsigned char tmp, tmpb, tmpc; int reg, len, numchips; int ret = 0; - virtadr = (unsigned long)ioremap(physadr, DOC_IOREMAP_LEN); + virtadr = (void __iomem *)ioremap(physadr, DOC_IOREMAP_LEN); if (!virtadr) { printk(KERN_ERR "Diskonchip ioremap failed: 0x%x bytes at 0x%lx\n", DOC_IOREMAP_LEN, physadr); return -EIO; @@ -1518,7 +1632,7 @@ static inline int __init doc_probe(unsigned long physadr) sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr)); - mtd = kmalloc(len, GFP_KERNEL); + mtd = kmalloc(len, GFP_KERNEL); if (!mtd) { printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len); ret = -ENOMEM; @@ -1543,7 +1657,7 @@ static inline int __init doc_probe(unsigned long physadr) nand->enable_hwecc = doc200x_enable_hwecc; nand->calculate_ecc = doc200x_calculate_ecc; nand->correct_data = doc200x_correct_data; - //nand->data_buf + nand->autooob = &doc200x_oobinfo; nand->eccmode = NAND_ECC_HW6_512; nand->options = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME; @@ -1589,6 +1703,23 @@ fail: return ret; } +static void release_nanddoc(void) +{ + struct mtd_info *mtd, *nextmtd; + struct nand_chip *nand; + struct doc_priv *doc; + + for (mtd = doclist; mtd; mtd = nextmtd) { + nand = mtd->priv; + doc = (void *)nand->priv; + + nextmtd = doc->nextdoc; + nand_release(mtd); + iounmap((void *)doc->virtadr); + kfree(mtd); + } +} + int __init init_nanddoc(void) { int i; @@ -1607,23 +1738,34 @@ int __init init_nanddoc(void) printk(KERN_INFO "No valid DiskOnChip devices found\n"); return -ENODEV; } + + /* We could create the decoder on demand, if memory is a concern. + * This way we have it handy, if an error happens + * + * Symbolsize is 10 (bits) + * Primitve polynomial is x^10+x^3+1 + * first consecutive root is 510 + * primitve element to generate roots = 1 + * generator polinomial degree = 4 + */ + rs_decoder = init_rs(10, 0x409, FCR, 1, NROOTS); + if (!rs_decoder) { + printk (KERN_ERR "DiskOnChip: Could not create a RS decoder\n"); + release_nanddoc(); + return -ENOMEM; + } + return 0; } void __exit cleanup_nanddoc(void) { - struct mtd_info *mtd, *nextmtd; - struct nand_chip *nand; - struct doc_priv *doc; - - for (mtd = doclist; mtd; mtd = nextmtd) { - nand = mtd->priv; - doc = (void *)nand->priv; + /* Cleanup the nand/DoC resources */ + release_nanddoc(); - nextmtd = doc->nextdoc; - nand_release(mtd); - iounmap((void *)doc->virtadr); - kfree(mtd); + /* Free the reed solomon resources */ + if (rs_decoder) { + free_rs(rs_decoder); } } diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c index 797794069103..805102e000bd 100644 --- a/drivers/mtd/nand/edb7312.c +++ b/drivers/mtd/nand/edb7312.c @@ -6,7 +6,7 @@ * Derived from drivers/mtd/nand/autcpu12.c * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) * - * $Id: edb7312.c,v 1.8 2004/07/12 15:03:26 dwmw2 Exp $ + * $Id: edb7312.c,v 1.10 2004/10/05 13:50:20 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -53,9 +53,9 @@ static struct mtd_info *ep7312_mtd = NULL; * Module stuff */ -static int ep7312_fio_pbase = EP7312_FIO_PBASE; -static int ep7312_pxdr = EP7312_PXDR; -static int ep7312_pxddr = EP7312_PXDDR; +static unsigned long ep7312_fio_pbase = EP7312_FIO_PBASE; +static void __iomem * ep7312_pxdr = (void __iomem *) EP7312_PXDR; +static void __iomem * ep7312_pxddr = (void __iomem *) EP7312_PXDDR; #ifdef MODULE MODULE_PARM(ep7312_fio_pbase, "i"); @@ -131,7 +131,7 @@ static int __init ep7312_init (void) const char *part_type = 0; int mtd_parts_nb = 0; struct mtd_partition *mtd_parts = 0; - int ep7312_fio_base; + void __iomem * ep7312_fio_base; /* Allocate memory for MTD device structure and private data */ ep7312_mtd = kmalloc(sizeof(struct mtd_info) + @@ -143,7 +143,7 @@ static int __init ep7312_init (void) } /* map physical adress */ - ep7312_fio_base = (unsigned long)ioremap(ep7312_fio_pbase, SZ_1K); + ep7312_fio_base = (void __iomem *)ioremap(ep7312_fio_pbase, SZ_1K); if(!ep7312_fio_base) { printk("ioremap EDB7312 NAND flash failed\n"); kfree(ep7312_mtd); @@ -181,16 +181,7 @@ static int __init ep7312_init (void) return -ENXIO; } - /* Allocate memory for internal data buffer */ - this->data_buf = kmalloc (sizeof(u_char) * (ep7312_mtd->oobblock + ep7312_mtd->oobsize), GFP_KERNEL); - if (!this->data_buf) { - printk("Unable to allocate NAND data buffer for EDB7312.\n"); - iounmap((void *)ep7312_fio_base); - kfree (ep7312_mtd); - return -ENOMEM; - } - -#ifdef CONFIG_PARTITIONS +#ifdef CONFIG_MTD_PARTITIONS ep7312_mtd->name = "edb7312-nand"; mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, &mtd_parts, 0); @@ -221,8 +212,8 @@ static void __exit ep7312_cleanup (void) { struct nand_chip *this = (struct nand_chip *) &ep7312_mtd[1]; - /* Unregister the device */ - del_mtd_device (ep7312_mtd); + /* Release resources, unregister device */ + nand_release (ap7312_mtd); /* Free internal data buffer */ kfree (this->data_buf); diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c new file mode 100644 index 000000000000..5d284f68d706 --- /dev/null +++ b/drivers/mtd/nand/h1910.c @@ -0,0 +1,208 @@ +/* + * drivers/mtd/nand/h1910.c + * + * Copyright (C) 2003 Joshua Wise (joshua@joshuawise.com) + * + * Derived from drivers/mtd/nand/edb7312.c + * Copyright (C) 2002 Marius Gröger (mag@sysgo.de) + * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) + * + * $Id: h1910.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Overview: + * This is a device driver for the NAND flash device found on the + * iPAQ h1910 board which utilizes the Samsung K9F2808 part. This is + * a 128Mibit (16MiB x 8 bits) NAND flash device. + */ + +#include +#include +#include +#include +#include +#include +#include +#include /* for CLPS7111_VIRT_BASE */ +#include +#include +#include + +/* + * MTD structure for EDB7312 board + */ +static struct mtd_info *h1910_nand_mtd = NULL; + +/* + * Module stuff + */ + +#ifdef CONFIG_MTD_PARTITIONS +/* + * Define static partitions for flash device + */ +static struct mtd_partition partition_info[] = { + { name: "h1910 NAND Flash", + offset: 0, + size: 16*1024*1024 } +}; +#define NUM_PARTITIONS 1 + +#endif + + +/* + * hardware specific access to control-lines + */ +static void h1910_hwcontrol(struct mtd_info *mtd, int cmd) +{ + struct nand_chip* this = (struct nand_chip *) (mtd->priv); + + switch(cmd) { + + case NAND_CTL_SETCLE: + this->IO_ADDR_R |= (1 << 2); + this->IO_ADDR_W |= (1 << 2); + break; + case NAND_CTL_CLRCLE: + this->IO_ADDR_R &= ~(1 << 2); + this->IO_ADDR_W &= ~(1 << 2); + break; + + case NAND_CTL_SETALE: + this->IO_ADDR_R |= (1 << 3); + this->IO_ADDR_W |= (1 << 3); + break; + case NAND_CTL_CLRALE: + this->IO_ADDR_R &= ~(1 << 3); + this->IO_ADDR_W &= ~(1 << 3); + break; + + case NAND_CTL_SETNCE: + break; + case NAND_CTL_CLRNCE: + break; + } +} + +/* + * read device ready pin + */ +#if 0 +static int h1910_device_ready(struct mtd_info *mtd) +{ + return (GPLR(55) & GPIO_bit(55)); +} +#endif + +/* + * Main initialization routine + */ +static int __init h1910_init (void) +{ + struct nand_chip *this; + const char *part_type = 0; + int mtd_parts_nb = 0; + struct mtd_partition *mtd_parts = 0; + void __iomem *nandaddr; + + if (!machine_is_h1900()) + return -ENODEV; + + nandaddr = (void __iomem *)__ioremap(0x08000000, 0x1000, 0, 1); + if (!nandaddr) { + printk("Failed to ioremap nand flash.\n"); + return -ENOMEM; + } + + /* Allocate memory for MTD device structure and private data */ + h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) + + sizeof(struct nand_chip), + GFP_KERNEL); + if (!h1910_nand_mtd) { + printk("Unable to allocate h1910 NAND MTD device structure.\n"); + iounmap ((void *) nandaddr); + return -ENOMEM; + } + + /* Get pointer to private data */ + this = (struct nand_chip *) (&h1910_nand_mtd[1]); + + /* Initialize structures */ + memset((char *) h1910_nand_mtd, 0, sizeof(struct mtd_info)); + memset((char *) this, 0, sizeof(struct nand_chip)); + + /* Link the private data with the MTD structure */ + h1910_nand_mtd->priv = this; + + /* + * Enable VPEN + */ + GPSR(37) = GPIO_bit(37); + + /* insert callbacks */ + this->IO_ADDR_R = nandaddr; + this->IO_ADDR_W = nandaddr; + this->hwcontrol = h1910_hwcontrol; + this->dev_ready = NULL; /* unknown whether that was correct or not so we will just do it like this */ + /* 15 us command delay time */ + this->chip_delay = 50; + this->eccmode = NAND_ECC_SOFT; + this->options = NAND_NO_AUTOINCR; + + /* Scan to find existence of the device */ + if (nand_scan (h1910_nand_mtd, 1)) { + printk(KERN_NOTICE "No NAND device - returning -ENXIO\n"); + kfree (h1910_nand_mtd); + iounmap ((void *) nandaddr); + return -ENXIO; + } + +#ifdef CONFIG_MTD_CMDLINE_PARTS + mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, + "h1910-nand"); + if (mtd_parts_nb > 0) + part_type = "command line"; + else + mtd_parts_nb = 0; +#endif + if (mtd_parts_nb == 0) + { + mtd_parts = partition_info; + mtd_parts_nb = NUM_PARTITIONS; + part_type = "static"; + } + + /* Register the partitions */ + printk(KERN_NOTICE "Using %s partition definition\n", part_type); + add_mtd_partitions(h1910_nand_mtd, mtd_parts, mtd_parts_nb); + + /* Return happy */ + return 0; +} +module_init(h1910_init); + +/* + * Clean up routine + */ +static void __exit h1910_cleanup (void) +{ + struct nand_chip *this = (struct nand_chip *) &h1910_nand_mtd[1]; + + /* Release resources, unregister device */ + nand_release (h1910_nand_mtd); + + /* Release io resource */ + iounmap ((void *) this->IO_ADDR_W); + + /* Free the MTD device structure */ + kfree (h1910_nand_mtd); +} +module_exit(h1910_cleanup); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Joshua Wise "); +MODULE_DESCRIPTION("NAND flash driver for iPAQ h1910"); diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index ff6adf43f73a..181b95275352 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -24,6 +24,10 @@ * * 05-19-2004 tglx: Basic support for Renesas AG-AND chips * + * 09-24-2004 tglx: add support for hardware controllers (e.g. ECC) shared + * among multiple independend devices. Suggestions and initial patch + * from Ben Dooks + * * Credits: * David Woodhouse for adding multichip support * @@ -37,7 +41,7 @@ * The AG-AND chips have nice features for speed improvement, * which are not supported yet. Read / program 4 pages in one go. * - * $Id: nand_base.c,v 1.115 2004/08/09 13:19:45 dwmw2 Exp $ + * $Id: nand_base.c,v 1.121 2004/10/06 19:53:11 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -131,25 +135,31 @@ static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int #define nand_verify_pages(...) (0) #endif -static void nand_get_chip (struct nand_chip *this, struct mtd_info *mtd, int new_state); +static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state); /** - * nand_release_chip - [GENERIC] release chip + * nand_release_device - [GENERIC] release chip * @mtd: MTD device structure * * Deselect, release chip lock and wake up anyone waiting on the device */ -static void nand_release_chip (struct mtd_info *mtd) +static void nand_release_device (struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; /* De-select the NAND device */ this->select_chip(mtd, -1); + /* Do we have a hardware controller ? */ + if (this->controller) { + spin_lock(&this->controller->lock); + this->controller->active = NULL; + spin_unlock(&this->controller->lock); + } /* Release the chip */ - spin_lock_bh (&this->chip_lock); + spin_lock (&this->chip_lock); this->state = FL_READY; wake_up (&this->wq); - spin_unlock_bh (&this->chip_lock); + spin_unlock (&this->chip_lock); } /** @@ -388,7 +398,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) chipnr = (int)(ofs >> this->chip_shift); /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd, FL_READING); + nand_get_device (this, mtd, FL_READING); /* Select the NAND device */ this->select_chip(mtd, chipnr); @@ -410,7 +420,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) if (getchip) { /* Deselect and wake up anyone waiting on the device */ - nand_release_chip(mtd); + nand_release_device(mtd); } return res; @@ -533,8 +543,8 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in if (page_addr != -1) { this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); - /* One more address cycle for higher density devices */ - if (this->chipsize & 0x0c000000) + /* One more address cycle for devices > 32MiB */ + if (this->chipsize > (32 << 20)) this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f)); } /* Latch in address */ @@ -689,15 +699,16 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, } /** - * nand_get_chip - [GENERIC] Get chip for selected access + * nand_get_device - [GENERIC] Get chip for selected access * @this: the nand chip descriptor * @mtd: MTD device structure * @new_state: the state which is requested * * Get the device and lock it for exclusive access */ -static void nand_get_chip (struct nand_chip *this, struct mtd_info *mtd, int new_state) +static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state) { + struct nand_chip *active = this; DECLARE_WAITQUEUE (wait, current); @@ -705,19 +716,29 @@ static void nand_get_chip (struct nand_chip *this, struct mtd_info *mtd, int new * Grab the lock and see if the device is available */ retry: - spin_lock_bh (&this->chip_lock); - - if (this->state == FL_READY) { - this->state = new_state; - spin_unlock_bh (&this->chip_lock); - return; + /* Hardware controller shared among independend devices */ + if (this->controller) { + spin_lock (&this->controller->lock); + if (this->controller->active) + active = this->controller->active; + else + this->controller->active = this; + spin_unlock (&this->controller->lock); } - + + if (active == this) { + spin_lock (&this->chip_lock); + if (this->state == FL_READY) { + this->state = new_state; + spin_unlock (&this->chip_lock); + return; + } + } set_current_state (TASK_UNINTERRUPTIBLE); - add_wait_queue (&this->wq, &wait); - spin_unlock_bh (&this->chip_lock); + add_wait_queue (&active->wq, &wait); + spin_unlock (&active->chip_lock); schedule (); - remove_wait_queue (&this->wq, &wait); + remove_wait_queue (&active->wq, &wait); goto retry; } @@ -747,7 +768,6 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) * any case on any machine. */ ndelay (100); - spin_lock_bh (&this->chip_lock); if ((state == FL_ERASING) && (this->options & NAND_IS_AND)) this->cmdfunc (mtd, NAND_CMD_STATUS_MULTI, -1, -1); else @@ -755,24 +775,19 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) while (time_before(jiffies, timeo)) { /* Check, if we were interrupted */ - if (this->state != state) { - spin_unlock_bh (&this->chip_lock); + if (this->state != state) return 0; - } + if (this->dev_ready) { if (this->dev_ready(mtd)) + break; + } else { + if (this->read_byte(mtd) & NAND_STATUS_READY) break; } - if (this->read_byte(mtd) & NAND_STATUS_READY) - break; - - spin_unlock_bh (&this->chip_lock); yield (); - spin_lock_bh (&this->chip_lock); } status = (int) this->read_byte(mtd); - spin_unlock_bh (&this->chip_lock); - return status; } @@ -1051,7 +1066,7 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, } /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd ,FL_READING); + nand_get_device (this, mtd ,FL_READING); /* use userspace supplied oobinfo, if zero */ if (oobsel == NULL) @@ -1281,7 +1296,7 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, } /* Deselect and wake up anyone waiting on the device */ - nand_release_chip(mtd); + nand_release_device(mtd); /* * Return success, if no ECC failures, else -EBADMSG @@ -1328,7 +1343,7 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t } /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd , FL_READING); + nand_get_device (this, mtd , FL_READING); /* Select the NAND device */ this->select_chip(mtd, chipnr); @@ -1379,7 +1394,7 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t } /* Deselect and wake up anyone waiting on the device */ - nand_release_chip(mtd); + nand_release_device(mtd); /* Return happy */ *retlen = len; @@ -1413,7 +1428,7 @@ int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, } /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd , FL_READING); + nand_get_device (this, mtd , FL_READING); this->select_chip (mtd, chip); @@ -1442,7 +1457,7 @@ int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, } /* Deselect and wake up anyone waiting on the device */ - nand_release_chip(mtd); + nand_release_device(mtd); return 0; } @@ -1564,7 +1579,7 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, } /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd, FL_WRITING); + nand_get_device (this, mtd, FL_WRITING); /* Calculate chipnr */ chipnr = (int)(to >> this->chip_shift); @@ -1669,7 +1684,7 @@ cmp: out: /* Deselect and wake up anyone waiting on the device */ - nand_release_chip(mtd); + nand_release_device(mtd); return ret; } @@ -1709,7 +1724,7 @@ static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * } /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd, FL_WRITING); + nand_get_device (this, mtd, FL_WRITING); /* Select the NAND device */ this->select_chip(mtd, chipnr); @@ -1771,7 +1786,7 @@ static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * ret = 0; out: /* Deselect and wake up anyone waiting on the device */ - nand_release_chip(mtd); + nand_release_device(mtd); return ret; } @@ -1838,7 +1853,7 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig } /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd, FL_WRITING); + nand_get_device (this, mtd, FL_WRITING); /* Get the current chip-nr */ chipnr = (int) (to >> this->chip_shift); @@ -1952,7 +1967,7 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig ret = 0; out: /* Deselect and wake up anyone waiting on the device */ - nand_release_chip(mtd); + nand_release_device(mtd); *retlen = written; return ret; @@ -2041,7 +2056,7 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb instr->fail_addr = 0xffffffff; /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd, FL_ERASING); + nand_get_device (this, mtd, FL_ERASING); /* Shift to get first page */ page = (int) (instr->addr >> this->page_shift); @@ -2112,7 +2127,7 @@ erase_exit: mtd_erase_callback(instr); /* Deselect and wake up anyone waiting on the device */ - nand_release_chip(mtd); + nand_release_device(mtd); /* Return more or less happy */ return ret; @@ -2127,43 +2142,13 @@ erase_exit: static void nand_sync (struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; - DECLARE_WAITQUEUE (wait, current); DEBUG (MTD_DEBUG_LEVEL3, "nand_sync: called\n"); -retry: - /* Grab the spinlock */ - spin_lock_bh (&this->chip_lock); - - /* See what's going on */ - switch (this->state) { - case FL_READY: - case FL_SYNCING: - this->state = FL_SYNCING; - spin_unlock_bh (&this->chip_lock); - break; - - default: - /* Not an idle state */ - add_wait_queue (&this->wq, &wait); - spin_unlock_bh (&this->chip_lock); - schedule (); - - remove_wait_queue (&this->wq, &wait); - goto retry; - } - - /* Lock the device */ - spin_lock_bh (&this->chip_lock); - - /* Set the device to be ready again */ - if (this->state == FL_SYNCING) { - this->state = FL_READY; - wake_up (&this->wq); - } - - /* Unlock the device */ - spin_unlock_bh (&this->chip_lock); + /* Grab the lock and see if the device is available */ + nand_get_device (this, mtd, FL_SYNCING); + /* Release it and go back */ + nand_release_device (mtd); } diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 2642e11516e7..77f08d1ee14f 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -6,7 +6,7 @@ * * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) * - * $Id: nand_bbt.c,v 1.24 2004/06/28 08:25:35 gleixner Exp $ + * $Id: nand_bbt.c,v 1.26 2004/10/05 13:50:20 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -114,6 +114,7 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des * @num: the number of bbt descriptors to read * @bits: number of bits per block * @offs: offset in the memory table + * @reserved_block_code: Pattern to identify reserved blocks * * Read the bad block table starting from page. * @@ -796,7 +797,7 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) len = mtd->size >> (this->bbt_erase_shift + 2); /* Allocate memory (2bit per block) */ - this->bbt = (uint8_t *) kmalloc (len, GFP_KERNEL); + this->bbt = kmalloc (len, GFP_KERNEL); if (!this->bbt) { printk (KERN_ERR "nand_scan_bbt: Out of memory\n"); return -ENOMEM; diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c index 9c356a0a78ec..d024a5b9a1a8 100644 --- a/drivers/mtd/nand/ppchameleonevb.c +++ b/drivers/mtd/nand/ppchameleonevb.c @@ -6,7 +6,7 @@ * Derived from drivers/mtd/nand/edb7312.c * * - * $Id: ppchameleonevb.c,v 1.2 2004/05/05 22:09:54 gleixner Exp $ + * $Id: ppchameleonevb.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -74,12 +74,6 @@ MODULE_PARM(ppchameleonevb_fio_pbase, "i"); __setup("ppchameleonevb_fio_pbase=",ppchameleonevb_fio_pbase); #endif -/* Internal buffers. Page buffer and oob buffer for one block */ -static u_char data_buf[2048 + 64]; -static u_char oob_buf[64 * 64]; -static u_char data_buf_evb[512 + 16]; -static u_char oob_buf_evb[16 * 32]; - #ifdef CONFIG_MTD_PARTITIONS /* * Define static partitions for flash devices @@ -196,8 +190,8 @@ static int __init ppchameleonevb_init (void) const char *part_type = 0; int mtd_parts_nb = 0; struct mtd_partition *mtd_parts = 0; - int ppchameleon_fio_base; - int ppchameleonevb_fio_base; + void __iomem *ppchameleon_fio_base; + void __iomem *ppchameleonevb_fio_base; /********************************* @@ -205,15 +199,14 @@ static int __init ppchameleonevb_init (void) *********************************/ /* Allocate memory for MTD device structure and private data */ ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) + - sizeof(struct nand_chip), - GFP_KERNEL); + sizeof(struct nand_chip), GFP_KERNEL); if (!ppchameleon_mtd) { printk("Unable to allocate PPChameleon NAND MTD device structure.\n"); return -ENOMEM; } /* map physical address */ - ppchameleon_fio_base = (unsigned long)ioremap(ppchameleon_fio_pbase, SZ_4M); + ppchameleon_fio_base = (void __iomem *) ioremap(ppchameleon_fio_pbase, SZ_4M); if(!ppchameleon_fio_base) { printk("ioremap PPChameleon NAND flash failed\n"); kfree(ppchameleon_mtd); @@ -264,10 +257,6 @@ static int __init ppchameleonevb_init (void) /* ECC mode */ this->eccmode = NAND_ECC_SOFT; - /* Set internal data buffer */ - this->data_buf = data_buf; - this->oob_buf = oob_buf; - /* Scan to find existence of the device (it could not be mounted) */ if (nand_scan (ppchameleon_mtd, 1)) { iounmap((void *)ppchameleon_fio_base); @@ -309,15 +298,14 @@ nand_evb_init: ****************************/ /* Allocate memory for MTD device structure and private data */ ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) + - sizeof(struct nand_chip), - GFP_KERNEL); + sizeof(struct nand_chip), GFP_KERNEL); if (!ppchameleonevb_mtd) { printk("Unable to allocate PPChameleonEVB NAND MTD device structure.\n"); return -ENOMEM; } /* map physical address */ - ppchameleonevb_fio_base = (unsigned long)ioremap(ppchameleonevb_fio_pbase, SZ_4M); + ppchameleonevb_fio_base = (void __iomem *)ioremap(ppchameleonevb_fio_pbase, SZ_4M); if(!ppchameleonevb_fio_base) { printk("ioremap PPChameleonEVB NAND flash failed\n"); kfree(ppchameleonevb_mtd); @@ -349,7 +337,8 @@ nand_evb_init: out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFFFFFFF0); out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0x3FFFFFFF); /* enable output driver */ - out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN | NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN); + out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN | + NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN); #ifdef USE_READY_BUSY_PIN /* three-state select */ out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0xFFFFFFFC); @@ -359,7 +348,6 @@ nand_evb_init: out_be32((volatile unsigned*)GPIO0_ISR1L, (in_be32((volatile unsigned*)GPIO0_ISR1L) & 0xFFFFFFFC) | 0x00000001); #endif - /* insert callbacks */ this->IO_ADDR_R = ppchameleonevb_fio_base; this->IO_ADDR_W = ppchameleonevb_fio_base; @@ -372,10 +360,6 @@ nand_evb_init: /* ECC mode */ this->eccmode = NAND_ECC_SOFT; - /* Set internal data buffer */ - this->data_buf = data_buf_evb; - this->oob_buf = oob_buf_evb; - /* Scan to find existence of the device */ if (nand_scan (ppchameleonevb_mtd, 1)) { iounmap((void *)ppchameleonevb_fio_base); @@ -412,15 +396,20 @@ module_init(ppchameleonevb_init); */ static void __exit ppchameleonevb_cleanup (void) { - struct nand_chip *this = (struct nand_chip *) &ppchameleonevb_mtd[1]; - - /* Unregister the device */ - del_mtd_device (ppchameleonevb_mtd); + struct nand_chip *this; - /* Free internal data buffer */ - kfree (this->data_buf); + /* Release resources, unregister device(s) */ + nand_release (ppchameleon_mtd); + nand_release (ppchameleonevb_mtd); + + /* Release iomaps */ + this = (struct nand_chip *) &ppchameleon_mtd[1]; + iounmap((void *) this->IO_ADDR_R; + this = (struct nand_chip *) &ppchameleonevb_mtd[1]; + iounmap((void *) this->IO_ADDR_R; /* Free the MTD device structure */ + kfree (ppchameleon_mtd); kfree (ppchameleonevb_mtd); } module_exit(ppchameleonevb_cleanup); diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c new file mode 100644 index 000000000000..2d65fa7ce0d1 --- /dev/null +++ b/drivers/mtd/nand/rtc_from4.c @@ -0,0 +1,561 @@ +/* + * drivers/mtd/nand/rtc_from4.c + * + * Copyright (C) 2004 Red Hat, Inc. + * + * Derived from drivers/mtd/nand/spia.c + * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) + * + * $Id: rtc_from4.c,v 1.6 2004/10/05 22:11:46 gleixner Exp $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Overview: + * This is a device driver for the AG-AND flash device found on the + * Renesas Technology Corp. Flash ROM 4-slot interface board (FROM_BOARD4), + * which utilizes the Renesas HN29V1G91T-30 part. + * This chip is a 1 GBibit (128MiB x 8 bits) AG-AND flash device. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * MTD structure for Renesas board + */ +static struct mtd_info *rtc_from4_mtd = NULL; + +#define RTC_FROM4_MAX_CHIPS 2 + +/* HS77x9 processor register defines */ +#define SH77X9_BCR1 ((volatile unsigned short *)(0xFFFFFF60)) +#define SH77X9_BCR2 ((volatile unsigned short *)(0xFFFFFF62)) +#define SH77X9_WCR1 ((volatile unsigned short *)(0xFFFFFF64)) +#define SH77X9_WCR2 ((volatile unsigned short *)(0xFFFFFF66)) +#define SH77X9_MCR ((volatile unsigned short *)(0xFFFFFF68)) +#define SH77X9_PCR ((volatile unsigned short *)(0xFFFFFF6C)) +#define SH77X9_FRQCR ((volatile unsigned short *)(0xFFFFFF80)) + +/* + * Values specific to the Renesas Technology Corp. FROM_BOARD4 (used with HS77x9 processor) + */ +/* Address where flash is mapped */ +#define RTC_FROM4_FIO_BASE 0x14000000 + +/* CLE and ALE are tied to address lines 5 & 4, respectively */ +#define RTC_FROM4_CLE (1 << 5) +#define RTC_FROM4_ALE (1 << 4) + +/* address lines A24-A22 used for chip selection */ +#define RTC_FROM4_NAND_ADDR_SLOT3 (0x00800000) +#define RTC_FROM4_NAND_ADDR_SLOT4 (0x00C00000) +#define RTC_FROM4_NAND_ADDR_FPGA (0x01000000) +/* mask address lines A24-A22 used for chip selection */ +#define RTC_FROM4_NAND_ADDR_MASK (RTC_FROM4_NAND_ADDR_SLOT3 | RTC_FROM4_NAND_ADDR_SLOT4 | RTC_FROM4_NAND_ADDR_FPGA) + +/* FPGA status register for checking device ready (bit zero) */ +#define RTC_FROM4_FPGA_SR (RTC_FROM4_NAND_ADDR_FPGA | 0x00000002) +#define RTC_FROM4_DEVICE_READY 0x0001 + +/* FPGA Reed-Solomon ECC Control register */ + +#define RTC_FROM4_RS_ECC_CTL (RTC_FROM4_NAND_ADDR_FPGA | 0x00000050) +#define RTC_FROM4_RS_ECC_CTL_CLR (1 << 7) +#define RTC_FROM4_RS_ECC_CTL_GEN (1 << 6) +#define RTC_FROM4_RS_ECC_CTL_FD_E (1 << 5) + +/* FPGA Reed-Solomon ECC code base */ +#define RTC_FROM4_RS_ECC (RTC_FROM4_NAND_ADDR_FPGA | 0x00000060) +#define RTC_FROM4_RS_ECCN (RTC_FROM4_NAND_ADDR_FPGA | 0x00000080) + +/* FPGA Reed-Solomon ECC check register */ +#define RTC_FROM4_RS_ECC_CHK (RTC_FROM4_NAND_ADDR_FPGA | 0x00000070) +#define RTC_FROM4_RS_ECC_CHK_ERROR (1 << 7) + +/* Undefine for software ECC */ +#define RTC_FROM4_HWECC 1 + +/* + * Module stuff + */ +static void __iomem *rtc_from4_fio_base = P2SEGADDR(RTC_FROM4_FIO_BASE); + +MODULE_PARM(rtc_from4_fio_base, "i"); + +const static struct mtd_partition partition_info[] = { + { + .name = "Renesas flash partition 1", + .offset = 0, + .size = MTDPART_SIZ_FULL + }, +}; +#define NUM_PARTITIONS 1 + +/* + * hardware specific flash bbt decriptors + * Note: this is to allow debugging by disabling + * NAND_BBT_CREATE and/or NAND_BBT_WRITE + * + */ +static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; +static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' }; + +static struct nand_bbt_descr rtc_from4_bbt_main_descr = { + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, + .offs = 40, + .len = 4, + .veroffs = 44, + .maxblocks = 4, + .pattern = bbt_pattern +}; + +static struct nand_bbt_descr rtc_from4_bbt_mirror_descr = { + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, + .offs = 40, + .len = 4, + .veroffs = 44, + .maxblocks = 4, + .pattern = mirror_pattern +}; + + + +#ifdef RTC_FROM4_HWECC + +/* the Reed Solomon control structure */ +static struct rs_control *rs_decoder; + +/* + * hardware specific Out Of Band information + */ +static struct nand_oobinfo rtc_from4_nand_oobinfo = { + .useecc = MTD_NANDECC_AUTOPLACE, + .eccbytes = 32, + .eccpos = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31}, + .oobfree = { {32, 32} } +}; + +/* Aargh. I missed the reversed bit order, when I + * was talking to Renesas about the FPGA. + * + * The table is used for bit reordering and inversion + * of the ecc byte which we get from the FPGA + */ +static uint8_t revbits[256] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, +}; + +#endif + + + +/* + * rtc_from4_hwcontrol - hardware specific access to control-lines + * @mtd: MTD device structure + * @cmd: hardware control command + * + * Address lines (A5 and A4) are used to control Command and Address Latch + * Enable on this board, so set the read/write address appropriately. + * + * Chip Enable is also controlled by the Chip Select (CS5) and + * Address lines (A24-A22), so no action is required here. + * + */ +static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd) +{ + struct nand_chip* this = (struct nand_chip *) (mtd->priv); + + switch(cmd) { + + case NAND_CTL_SETCLE: + this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_CLE); + break; + case NAND_CTL_CLRCLE: + this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_CLE); + break; + + case NAND_CTL_SETALE: + this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_ALE); + break; + case NAND_CTL_CLRALE: + this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_ALE); + break; + + case NAND_CTL_SETNCE: + break; + case NAND_CTL_CLRNCE: + break; + + } +} + + +/* + * rtc_from4_nand_select_chip - hardware specific chip select + * @mtd: MTD device structure + * @chip: Chip to select (0 == slot 3, 1 == slot 4) + * + * The chip select is based on address lines A24-A22. + * This driver uses flash slots 3 and 4 (A23-A22). + * + */ +static void rtc_from4_nand_select_chip(struct mtd_info *mtd, int chip) +{ + struct nand_chip *this = mtd->priv; + + this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R & ~RTC_FROM4_NAND_ADDR_MASK); + this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_NAND_ADDR_MASK); + + switch(chip) { + + case 0: /* select slot 3 chip */ + this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R | RTC_FROM4_NAND_ADDR_SLOT3); + this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_NAND_ADDR_SLOT3); + break; + case 1: /* select slot 4 chip */ + this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R | RTC_FROM4_NAND_ADDR_SLOT4); + this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_NAND_ADDR_SLOT4); + break; + + } +} + + + +/* + * rtc_from4_nand_device_ready - hardware specific ready/busy check + * @mtd: MTD device structure + * + * This board provides the Ready/Busy state in the status register + * of the FPGA. Bit zero indicates the RDY(1)/BSY(0) signal. + * + */ +static int rtc_from4_nand_device_ready(struct mtd_info *mtd) +{ + unsigned short status; + + status = *((volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_FPGA_SR)); + + return (status & RTC_FROM4_DEVICE_READY); + +} + +#ifdef RTC_FROM4_HWECC +/* + * rtc_from4_enable_hwecc - hardware specific hardware ECC enable function + * @mtd: MTD device structure + * @mode: I/O mode; read or write + * + * enable hardware ECC for data read or write + * + */ +static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode) +{ + volatile unsigned short * rs_ecc_ctl = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CTL); + unsigned short status; + + switch (mode) { + case NAND_ECC_READ : + status = RTC_FROM4_RS_ECC_CTL_CLR + | RTC_FROM4_RS_ECC_CTL_FD_E; + + *rs_ecc_ctl = status; + break; + + case NAND_ECC_READSYN : + status = 0x00; + + *rs_ecc_ctl = status; + break; + + case NAND_ECC_WRITE : + status = RTC_FROM4_RS_ECC_CTL_CLR + | RTC_FROM4_RS_ECC_CTL_GEN + | RTC_FROM4_RS_ECC_CTL_FD_E; + + *rs_ecc_ctl = status; + break; + + default: + BUG(); + break; + } + +} + +/* + * rtc_from4_calculate_ecc - hardware specific code to read ECC code + * @mtd: MTD device structure + * @dat: buffer containing the data to generate ECC codes + * @ecc_code ECC codes calculated + * + * The ECC code is calculated by the FPGA. All we have to do is read the values + * from the FPGA registers. + * + * Note: We read from the inverted registers, since data is inverted before + * the code is calculated. So all 0xff data (blank page) results in all 0xff rs code + * + */ +static void rtc_from4_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) +{ + volatile unsigned short * rs_eccn = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECCN); + unsigned short value; + int i; + + for (i = 0; i < 8; i++) { + value = *rs_eccn; + ecc_code[i] = (unsigned char)value; + rs_eccn++; + } + ecc_code[7] |= 0x0f; /* set the last four bits (not used) */ +} + +/* + * rtc_from4_correct_data - hardware specific code to correct data using ECC code + * @mtd: MTD device structure + * @buf: buffer containing the data to generate ECC codes + * @ecc1 ECC codes read + * @ecc2 ECC codes calculated + * + * The FPGA tells us fast, if there's an error or not. If no, we go back happy + * else we read the ecc results from the fpga and call the rs library to decode + * and hopefully correct the error + * + * For now I use the code, which we read from the FLASH to use the RS lib, + * as the syndrom conversion has a unresolved issue. + */ +static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_char *ecc1, u_char *ecc2) +{ + int i, j, res; + unsigned short status; + uint16_t par[6], syn[6], tmp; + uint8_t ecc[8]; + volatile unsigned short *rs_ecc; + + status = *((volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CHK)); + + if (!(status & RTC_FROM4_RS_ECC_CHK_ERROR)) { + return 0; + } + + /* Read the syndrom pattern from the FPGA and correct the bitorder */ + rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC); + for (i = 0; i < 8; i++) { + ecc[i] = revbits[(*rs_ecc) & 0xFF]; + rs_ecc++; + } + + /* convert into 6 10bit syndrome fields */ + par[5] = rs_decoder->index_of[(((uint16_t)ecc[0] >> 0) & 0x0ff) | + (((uint16_t)ecc[1] << 8) & 0x300)]; + par[4] = rs_decoder->index_of[(((uint16_t)ecc[1] >> 2) & 0x03f) | + (((uint16_t)ecc[2] << 6) & 0x3c0)]; + par[3] = rs_decoder->index_of[(((uint16_t)ecc[2] >> 4) & 0x00f) | + (((uint16_t)ecc[3] << 4) & 0x3f0)]; + par[2] = rs_decoder->index_of[(((uint16_t)ecc[3] >> 6) & 0x003) | + (((uint16_t)ecc[4] << 2) & 0x3fc)]; + par[1] = rs_decoder->index_of[(((uint16_t)ecc[5] >> 0) & 0x0ff) | + (((uint16_t)ecc[6] << 8) & 0x300)]; + par[0] = (((uint16_t)ecc[6] >> 2) & 0x03f) | (((uint16_t)ecc[7] << 6) & 0x3c0); + + /* Convert to computable syndrome */ + for (i = 0; i < 6; i++) { + syn[i] = par[0]; + for (j = 1; j < 6; j++) + if (par[j] != rs_decoder->nn) + syn[i] ^= rs_decoder->alpha_to[rs_modnn(rs_decoder, par[j] + i * j)]; + + /* Convert to index form */ + syn[i] = rs_decoder->index_of[syn[i]]; + } + + /* Let the library code do its magic.*/ + res = decode_rs8(rs_decoder, buf, par, 512, syn, 0, NULL, 0xff, NULL); + if (res > 0) { + DEBUG (MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " + "ECC corrected %d errors on read\n", res); + } + return res; +} +#endif + +/* + * Main initialization routine + */ +int __init rtc_from4_init (void) +{ + struct nand_chip *this; + unsigned short bcr1, bcr2, wcr2; + + /* Allocate memory for MTD device structure and private data */ + rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof (struct nand_chip), + GFP_KERNEL); + if (!rtc_from4_mtd) { + printk ("Unable to allocate Renesas NAND MTD device structure.\n"); + return -ENOMEM; + } + + /* Get pointer to private data */ + this = (struct nand_chip *) (&rtc_from4_mtd[1]); + + /* Initialize structures */ + memset((char *) rtc_from4_mtd, 0, sizeof(struct mtd_info)); + memset((char *) this, 0, sizeof(struct nand_chip)); + + /* Link the private data with the MTD structure */ + rtc_from4_mtd->priv = this; + + /* set area 5 as PCMCIA mode to clear the spec of tDH(Data hold time;9ns min) */ + bcr1 = *SH77X9_BCR1 & ~0x0002; + bcr1 |= 0x0002; + *SH77X9_BCR1 = bcr1; + + /* set */ + bcr2 = *SH77X9_BCR2 & ~0x0c00; + bcr2 |= 0x0800; + *SH77X9_BCR2 = bcr2; + + /* set area 5 wait states */ + wcr2 = *SH77X9_WCR2 & ~0x1c00; + wcr2 |= 0x1c00; + *SH77X9_WCR2 = wcr2; + + /* Set address of NAND IO lines */ + this->IO_ADDR_R = rtc_from4_fio_base; + this->IO_ADDR_W = rtc_from4_fio_base; + /* Set address of hardware control function */ + this->hwcontrol = rtc_from4_hwcontrol; + /* Set address of chip select function */ + this->select_chip = rtc_from4_nand_select_chip; + /* command delay time (in us) */ + this->chip_delay = 100; + /* return the status of the Ready/Busy line */ + this->dev_ready = rtc_from4_nand_device_ready; + +#ifdef RTC_FROM4_HWECC + printk(KERN_INFO "rtc_from4_init: using hardware ECC detection.\n"); + + this->eccmode = NAND_ECC_HW8_512; + this->options |= NAND_HWECC_SYNDROME; + /* set the nand_oobinfo to support FPGA H/W error detection */ + this->autooob = &rtc_from4_nand_oobinfo; + this->enable_hwecc = rtc_from4_enable_hwecc; + this->calculate_ecc = rtc_from4_calculate_ecc; + this->correct_data = rtc_from4_correct_data; +#else + printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n"); + + this->eccmode = NAND_ECC_SOFT; +#endif + + /* set the bad block tables to support debugging */ + this->bbt_td = &rtc_from4_bbt_main_descr; + this->bbt_md = &rtc_from4_bbt_mirror_descr; + + /* Scan to find existence of the device */ + if (nand_scan(rtc_from4_mtd, RTC_FROM4_MAX_CHIPS)) { + kfree(rtc_from4_mtd); + return -ENXIO; + } + + /* Register the partitions */ + add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS); + +#ifdef RTC_FROM4_HWECC + /* We could create the decoder on demand, if memory is a concern. + * This way we have it handy, if an error happens + * + * Symbolsize is 10 (bits) + * Primitve polynomial is x^10+x^3+1 + * first consecutive root is 0 + * primitve element to generate roots = 1 + * generator polinomial degree = 6 + */ + rs_decoder = init_rs(10, 0x409, 0, 1, 6); + if (!rs_decoder) { + printk (KERN_ERR "Could not create a RS decoder\n"); + nand_release(rtc_from4_mtd); + kfree(rtc_from4_mtd); + return -ENOMEM; + } +#endif + /* Return happy */ + return 0; +} +module_init(rtc_from4_init); + + +/* + * Clean up routine + */ +#ifdef MODULE +static void __exit rtc_from4_cleanup (void) +{ + /* Release resource, unregister partitions */ + nand_release(rtc_from4_mtd); + + /* Free the MTD device structure */ + kfree (rtc_from4_mtd); + +#ifdef RTC_FROM4_HWECC + /* Free the reed solomon resources */ + if (rs_decoder) { + free_rs(rs_decoder); + } +#endif +} +module_exit(rtc_from4_cleanup); +#endif + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("d.marlin + * + * Samsung S3C2410 NAND driver + * + * Changelog: + * 21-Sep-2004 BJD Initial version + * 23-Sep-2004 BJD Mulitple device support + * 28-Sep-2004 BJD Fixed ECC placement for Hardware mode + * 12-Oct-2004 BJD Fixed errors in use of platform data + * + * $Id: s3c2410.c,v 1.5 2004/10/12 10:10:15 bjd Exp $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include + +#ifdef CONFIG_MTD_NAND_S3C2410_DEBUG +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#define PFX "s3c2410-nand: " + +#ifdef CONFIG_MTD_NAND_S3C2410_HWECC +static int hardware_ecc = 1; +#else +static int hardware_ecc = 0; +#endif + +/* new oob placement block for use with hardware ecc generation + */ + +static struct nand_oobinfo nand_hw_eccoob = { + .useecc = MTD_NANDECC_AUTOPLACE, + .eccbytes = 3, + .eccpos = {0, 1, 2 }, + .oobfree = { {8, 8} } +}; + +/* controller and mtd information */ + +struct s3c2410_nand_info; + +struct s3c2410_nand_mtd { + struct mtd_info mtd; + struct nand_chip chip; + struct s3c2410_nand_set *set; + struct s3c2410_nand_info *info; + int scan_res; +}; + +/* overview of the s3c2410 nand state */ + +struct s3c2410_nand_info { + /* mtd info */ + struct nand_hw_control controller; + struct s3c2410_nand_mtd *mtds; + struct s3c2410_platform_nand *platform; + + /* device info */ + struct device *device; + struct resource *area; + struct clk *clk; + void *regs; + int mtd_count; +}; + +/* conversion functions */ + +static struct s3c2410_nand_mtd *s3c2410_nand_mtd_toours(struct mtd_info *mtd) +{ + return container_of(mtd, struct s3c2410_nand_mtd, mtd); +} + +static struct s3c2410_nand_info *s3c2410_nand_mtd_toinfo(struct mtd_info *mtd) +{ + return s3c2410_nand_mtd_toours(mtd)->info; +} + +static struct s3c2410_nand_info *to_nand_info(struct device *dev) +{ + return (struct s3c2410_nand_info *)dev_get_drvdata(dev); +} + +static struct s3c2410_platform_nand *to_nand_plat(struct device *dev) +{ + return (struct s3c2410_platform_nand *)dev->platform_data; +} + +/* timing calculations */ + +#define NS_IN_KHZ 10000000 + +static int s3c2410_nand_calc_rate(int wanted, unsigned long clk, int max) +{ + int result; + + result = (wanted * NS_IN_KHZ) / clk; + result++; + + pr_debug("result %d from %ld, %d\n", result, clk, wanted); + + if (result > max) { + printk("%d ns is too big for current clock rate %ld\n", + wanted, clk); + return -1; + } + + if (result < 1) + result = 1; + + return result; +} + +#define to_ns(ticks,clk) (((clk) * (ticks)) / NS_IN_KHZ) + +/* controller setup */ + +static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, + struct device *dev) +{ + struct s3c2410_platform_nand *plat = to_nand_plat(dev); + unsigned int tacls, twrph0, twrph1; + unsigned long clkrate = clk_get_rate(info->clk); + unsigned long cfg; + + /* calculate the timing information for the controller */ + + if (plat != NULL) { + tacls = s3c2410_nand_calc_rate(plat->tacls, clkrate, 8); + twrph0 = s3c2410_nand_calc_rate(plat->twrph0, clkrate, 8); + twrph1 = s3c2410_nand_calc_rate(plat->twrph0, clkrate, 8); + } else { + /* default timings */ + tacls = 8; + twrph0 = 8; + twrph1 = 8; + } + + if (tacls < 0 || twrph0 < 0 || twrph1 < 0) { + printk(KERN_ERR PFX "cannot get timings suitable for board\n"); + return -EINVAL; + } + + printk(KERN_INFO PFX "timing: Tacls %ldns, Twrph0 %ldns, Twrph1 %ldns\n", + to_ns(tacls, clkrate), + to_ns(twrph0, clkrate), + to_ns(twrph1, clkrate)); + + cfg = S3C2410_NFCONF_EN; + cfg |= S3C2410_NFCONF_TACLS(tacls-1); + cfg |= S3C2410_NFCONF_TWRPH0(twrph0-1); + cfg |= S3C2410_NFCONF_TWRPH1(twrph1-1); + + pr_debug(PFX "NF_CONF is 0x%lx\n", cfg); + + writel(cfg, info->regs + S3C2410_NFCONF); + return 0; +} + +/* select chip */ + +static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip) +{ + struct s3c2410_nand_info *info; + struct s3c2410_nand_mtd *nmtd; + struct nand_chip *this = mtd->priv; + unsigned long cur; + + nmtd = (struct s3c2410_nand_mtd *)this->priv; + info = nmtd->info; + + cur = readl(info->regs + S3C2410_NFCONF); + + if (chip == -1) { + cur |= S3C2410_NFCONF_nFCE; + } else { + if (chip > nmtd->set->nr_chips) { + printk(KERN_ERR PFX "chip %d out of range\n", chip); + return; + } + + if (info->platform != NULL) { + if (info->platform->select_chip != NULL) + (info->platform->select_chip)(nmtd->set, chip); + } + + cur &= ~S3C2410_NFCONF_nFCE; + } + + writel(cur, info->regs + S3C2410_NFCONF); +} + +/* command and control functions */ + +static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd) +{ + struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); + unsigned long cur; + + switch (cmd) { + case NAND_CTL_SETNCE: + cur = readl(info->regs + S3C2410_NFCONF); + cur &= ~S3C2410_NFCONF_nFCE; + writel(cur, info->regs + S3C2410_NFCONF); + break; + + case NAND_CTL_CLRNCE: + cur = readl(info->regs + S3C2410_NFCONF); + cur |= S3C2410_NFCONF_nFCE; + writel(cur, info->regs + S3C2410_NFCONF); + break; + + /* we don't need to implement these */ + case NAND_CTL_SETCLE: + case NAND_CTL_CLRCLE: + case NAND_CTL_SETALE: + case NAND_CTL_CLRALE: + pr_debug(PFX "s3c2410_nand_hwcontrol(%d) unusedn", cmd); + break; + } +} + +/* s3c2410_nand_command + * + * This function implements sending commands and the relevant address + * information to the chip, via the hardware controller. Since the + * S3C2410 generates the correct ALE/CLE signaling automatically, we + * do not need to use hwcontrol. +*/ + +static void s3c2410_nand_command (struct mtd_info *mtd, unsigned command, + int column, int page_addr) +{ + register struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); + register struct nand_chip *this = mtd->priv; + + /* + * Write out the command to the device. + */ + if (command == NAND_CMD_SEQIN) { + int readcmd; + + if (column >= mtd->oobblock) { + /* OOB area */ + column -= mtd->oobblock; + readcmd = NAND_CMD_READOOB; + } else if (column < 256) { + /* First 256 bytes --> READ0 */ + readcmd = NAND_CMD_READ0; + } else { + column -= 256; + readcmd = NAND_CMD_READ1; + } + + writeb(readcmd, info->regs + S3C2410_NFCMD); + } + writeb(command, info->regs + S3C2410_NFCMD); + + /* Set ALE and clear CLE to start address cycle */ + + if (column != -1 || page_addr != -1) { + + /* Serially input address */ + if (column != -1) { + /* Adjust columns for 16 bit buswidth */ + if (this->options & NAND_BUSWIDTH_16) + column >>= 1; + writeb(column, info->regs + S3C2410_NFADDR); + } + if (page_addr != -1) { + writeb((unsigned char) (page_addr), info->regs + S3C2410_NFADDR); + writeb((unsigned char) (page_addr >> 8), info->regs + S3C2410_NFADDR); + /* One more address cycle for higher density devices */ + if (this->chipsize & 0x0c000000) + writeb((unsigned char) ((page_addr >> 16) & 0x0f), + info->regs + S3C2410_NFADDR); + } + /* Latch in address */ + } + + /* + * program and erase have their own busy handlers + * status and sequential in needs no delay + */ + switch (command) { + + case NAND_CMD_PAGEPROG: + case NAND_CMD_ERASE1: + case NAND_CMD_ERASE2: + case NAND_CMD_SEQIN: + case NAND_CMD_STATUS: + return; + + case NAND_CMD_RESET: + if (this->dev_ready) + break; + + udelay(this->chip_delay); + writeb(NAND_CMD_STATUS, info->regs + S3C2410_NFCMD); + + while ( !(this->read_byte(mtd) & 0x40)); + return; + + /* This applies to read commands */ + default: + /* + * If we don't have access to the busy pin, we apply the given + * command delay + */ + if (!this->dev_ready) { + udelay (this->chip_delay); + return; + } + } + + /* Apply this short delay always to ensure that we do wait tWB in + * any case on any machine. */ + ndelay (100); + /* wait until command is processed */ + while (!this->dev_ready(mtd)); +} + + +/* s3c2410_nand_devready() + * + * returns 0 if the nand is busy, 1 if it is ready +*/ + +static int s3c2410_nand_devready(struct mtd_info *mtd) +{ + struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); + + return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY; +} + +/* ECC handling functions */ + +static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, + u_char *read_ecc, u_char *calc_ecc) +{ + pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n", + mtd, dat, read_ecc, calc_ecc); + + pr_debug("eccs: read %02x,%02x,%02x vs calc %02x,%02x,%02x\n", + read_ecc[0], read_ecc[1], read_ecc[2], + calc_ecc[0], calc_ecc[1], calc_ecc[2]); + + if (read_ecc[0] == calc_ecc[0] && + read_ecc[1] == calc_ecc[1] && + read_ecc[2] == calc_ecc[2]) + return 0; + + /* we curently have no method for correcting the error */ + + return -1; +} + +static void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode) +{ + struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); + unsigned long ctrl; + + ctrl = readl(info->regs + S3C2410_NFCONF); + ctrl |= S3C2410_NFCONF_INITECC; + writel(ctrl, info->regs + S3C2410_NFCONF); +} + +static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, + const u_char *dat, u_char *ecc_code) +{ + struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); + + ecc_code[0] = readb(info->regs + S3C2410_NFECC + 0); + ecc_code[1] = readb(info->regs + S3C2410_NFECC + 1); + ecc_code[2] = readb(info->regs + S3C2410_NFECC + 2); + + pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", + ecc_code[0], ecc_code[1], ecc_code[2]); + + return 0; +} + + +/* over-ride the standard functions for a little more speed? */ + +static void s3c2410_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) +{ + struct nand_chip *this = (struct nand_chip *)mtd->priv; + readsb(this->IO_ADDR_R, buf, len); +} + +static void s3c2410_nand_write_buf(struct mtd_info *mtd, + const u_char *buf, int len) +{ + struct nand_chip *this = (struct nand_chip *)mtd->priv; + writesb(this->IO_ADDR_W, buf, len); +} + +/* device management functions */ + +static int s3c2410_nand_remove(struct device *dev) +{ + struct s3c2410_nand_info *info = to_nand_info(dev); + + dev_set_drvdata(dev, NULL); + + if (info == NULL) + return 0; + + /* first thing we need to do is release all our mtds + * and their partitions, then go through freeing the + * resources used + */ + + if (info->mtds != NULL) { + struct s3c2410_nand_mtd *ptr = info->mtds; + int mtdno; + + for (mtdno = 0; mtdno < info->mtd_count; mtdno++, ptr++) { + pr_debug("releasing mtd %d (%p)\n", mtdno, ptr); + nand_release(&ptr->mtd); + } + + kfree(info->mtds); + } + + /* free the common resources */ + + if (info->clk != NULL && !IS_ERR(info->clk)) { + clk_disable(info->clk); + clk_unuse(info->clk); + clk_put(info->clk); + } + + if (info->regs != NULL) { + iounmap(info->regs); + info->regs = NULL; + } + + if (info->area != NULL) { + release_resource(info->area); + kfree(info->area); + info->area = NULL; + } + + kfree(info); + + return 0; +} + +#ifdef CONFIG_MTD_PARTITIONS +static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, + struct s3c2410_nand_mtd *mtd, + struct s3c2410_nand_set *set) +{ + if (set == NULL) + return add_mtd_device(&mtd->mtd); + + if (set->nr_partitions > 0 && set->partitions != NULL) { + return add_mtd_partitions(&mtd->mtd, + set->partitions, + set->nr_partitions); + } + + return add_mtd_device(&mtd->mtd); +} +#else +static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, + struct s3c2410_nand_mtd *mtd, + struct s3c2410_nand_set *set) +{ + return add_mtd_device(&mtd->mtd); +} +#endif + +/* s3c2410_nand_init_chip + * + * init a single instance of an chip +*/ + +static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, + struct s3c2410_nand_mtd *nmtd, + struct s3c2410_nand_set *set) +{ + struct nand_chip *chip = &nmtd->chip; + + chip->IO_ADDR_R = (char *)info->regs + S3C2410_NFDATA; + chip->IO_ADDR_W = (char *)info->regs + S3C2410_NFDATA; + chip->hwcontrol = s3c2410_nand_hwcontrol; + chip->dev_ready = s3c2410_nand_devready; + chip->cmdfunc = s3c2410_nand_command; + chip->write_buf = s3c2410_nand_write_buf; + chip->read_buf = s3c2410_nand_read_buf; + chip->select_chip = s3c2410_nand_select_chip; + chip->chip_delay = 50; + chip->priv = nmtd; + chip->options = 0; + chip->controller = &info->controller; + + nmtd->info = info; + nmtd->mtd.priv = chip; + nmtd->set = set; + + if (hardware_ecc) { + chip->correct_data = s3c2410_nand_correct_data; + chip->enable_hwecc = s3c2410_nand_enable_hwecc; + chip->calculate_ecc = s3c2410_nand_calculate_ecc; + chip->eccmode = NAND_ECC_HW3_512; + chip->autooob = &nand_hw_eccoob; + } else { + chip->eccmode = NAND_ECC_SOFT; + } +} + +/* s3c2410_nand_probe + * + * called by device layer when it finds a device matching + * one our driver can handled. This code checks to see if + * it can allocate all necessary resources then calls the + * nand layer to look for devices +*/ + +static int s3c2410_nand_probe(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct s3c2410_platform_nand *plat = to_nand_plat(dev); + struct s3c2410_nand_info *info; + struct s3c2410_nand_mtd *nmtd; + struct s3c2410_nand_set *sets; + struct resource *res; + int err = 0; + int size; + int nr_sets; + int setno; + + pr_debug("s3c2410_nand_probe(%p)\n", dev); + + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (info == NULL) { + printk(KERN_ERR PFX "no memory for flash info\n"); + err = -ENOMEM; + goto exit_error; + } + + memzero(info, sizeof(*info)); + dev_set_drvdata(dev, info); + + spin_lock_init(&info->controller.lock); + + /* get the clock source and enable it */ + + info->clk = clk_get(dev, "nand"); + if (IS_ERR(info->clk)) { + printk(KERN_ERR PFX "failed to get clock"); + err = -ENOENT; + goto exit_error; + } + + clk_use(info->clk); + clk_enable(info->clk); + + /* allocate and map the resource */ + + res = pdev->resource; /* assume that the flash has one resource */ + size = res->end - res->start + 1; + + info->area = request_mem_region(res->start, size, pdev->name); + + if (info->area == NULL) { + printk(KERN_ERR PFX "cannot reserve register region\n"); + err = -ENOENT; + goto exit_error; + } + + info->device = dev; + info->platform = plat; + info->regs = ioremap(res->start, size); + + if (info->regs == NULL) { + printk(KERN_ERR PFX "cannot reserve register region\n"); + err = -EIO; + goto exit_error; + } + + printk(KERN_INFO PFX "mapped registers at %p\n", info->regs); + + /* initialise the hardware */ + + err = s3c2410_nand_inithw(info, dev); + if (err != 0) + goto exit_error; + + sets = (plat != NULL) ? plat->sets : NULL; + nr_sets = (plat != NULL) ? plat->nr_sets : 1; + + info->mtd_count = nr_sets; + + /* allocate our information */ + + size = nr_sets * sizeof(*info->mtds); + info->mtds = kmalloc(size, GFP_KERNEL); + if (info->mtds == NULL) { + printk(KERN_ERR PFX "failed to allocate mtd storage\n"); + err = -ENOMEM; + goto exit_error; + } + + memzero(info->mtds, size); + + /* initialise all possible chips */ + + nmtd = info->mtds; + + for (setno = 0; setno < nr_sets; setno++, nmtd++) { + pr_debug("initialising set %d (%p, info %p)\n", + setno, nmtd, info); + + s3c2410_nand_init_chip(info, nmtd, sets); + + nmtd->scan_res = nand_scan(&nmtd->mtd, + (sets) ? sets->nr_chips : 1); + + if (nmtd->scan_res == 0) { + s3c2410_nand_add_partition(info, nmtd, sets); + } + + if (sets != NULL) + sets++; + } + + pr_debug("initialised ok\n"); + return 0; + + exit_error: + s3c2410_nand_remove(dev); + + if (err == 0) + err = -EINVAL; + return err; +} + +static struct device_driver s3c2410_nand_driver = { + .name = "s3c2410-nand", + .bus = &platform_bus_type, + .probe = s3c2410_nand_probe, + .remove = s3c2410_nand_remove, +}; + +static int __init s3c2410_nand_init(void) +{ + printk("S3C2410 NAND Driver, (c) 2004 Simtec Electronics\n"); + return driver_register(&s3c2410_nand_driver); +} + +static void __exit s3c2410_nand_exit(void) +{ + driver_unregister(&s3c2410_nand_driver); +} + +module_init(s3c2410_nand_init); +module_exit(s3c2410_nand_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ben Dooks "); +MODULE_DESCRIPTION("S3C2410 MTD NAND driver"); diff --git a/drivers/mtd/nand/spia.c b/drivers/mtd/nand/spia.c index acf6fc808b76..b0de249628f2 100644 --- a/drivers/mtd/nand/spia.c +++ b/drivers/mtd/nand/spia.c @@ -8,7 +8,7 @@ * to controllines (due to change in nand.c) * page_cache added * - * $Id: spia.c,v 1.21 2003/07/11 15:12:29 dwmw2 Exp $ + * $Id: spia.c,v 1.23 2004/10/05 13:50:20 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -132,8 +132,8 @@ int __init spia_init (void) (*(volatile unsigned char *) (spia_io_base + spia_peddr)) = 0x07; /* Set address of NAND IO lines */ - this->IO_ADDR_R = spia_fio_base; - this->IO_ADDR_W = spia_fio_base; + this->IO_ADDR_R = (void __iomem *) spia_fio_base; + this->IO_ADDR_W = (void __iomem *) spia_fio_base; /* Set address of hardware control function */ this->hwcontrol = spia_hwcontrol; /* 15 us command delay time */ @@ -145,14 +145,6 @@ int __init spia_init (void) return -ENXIO; } - /* Allocate memory for internal data buffer */ - this->data_buf = kmalloc (sizeof(u_char) * (spia_mtd->oobblock + spia_mtd->oobsize), GFP_KERNEL); - if (!this->data_buf) { - printk ("Unable to allocate NAND data buffer for SPIA.\n"); - kfree (spia_mtd); - return -ENOMEM; - } - /* Register the partitions */ add_mtd_partitions(spia_mtd, partition_info, NUM_PARTITIONS); @@ -167,13 +159,8 @@ module_init(spia_init); #ifdef MODULE static void __exit spia_cleanup (void) { - struct nand_chip *this = (struct nand_chip *) &spia_mtd[1]; - - /* Unregister the device */ - del_mtd_device (spia_mtd); - - /* Free internal data buffer */ - kfree (this->data_buf); + /* Release resources, unregister device */ + nand_release (spia_mtd); /* Free the MTD device structure */ kfree (spia_mtd); diff --git a/drivers/mtd/nand/toto.c b/drivers/mtd/nand/toto.c index ecb9f3dc8805..52c808fb5fa9 100644 --- a/drivers/mtd/nand/toto.c +++ b/drivers/mtd/nand/toto.c @@ -15,7 +15,7 @@ * This is a device driver for the NAND flash device found on the * TI fido board. It supports 32MiB and 64MiB cards * - * $Id: toto.c,v 1.2 2003/10/21 10:04:58 dwmw2 Exp $ + * $Id: toto.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $ */ #include @@ -37,7 +37,7 @@ */ static struct mtd_info *toto_mtd = NULL; -static int toto_io_base = OMAP_FLASH_1_BASE; +static unsigned long toto_io_base = OMAP_FLASH_1_BASE; #define CONFIG_NAND_WORKAROUND 1 @@ -155,14 +155,6 @@ int __init toto_init (void) goto out_mtd; } - /* Allocate memory for internal data buffer */ - this->data_buf = kmalloc (sizeof(u_char) * (toto_mtd->oobblock + toto_mtd->oobsize), GFP_KERNEL); - if (!this->data_buf) { - printk (KERN_WARNING "Unable to allocate NAND data buffer for toto.\n"); - err = -ENOMEM; - goto out_mtd; - } - /* Register the partitions */ switch(toto_mtd->size){ case SZ_64M: add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M); break; @@ -194,16 +186,8 @@ module_init(toto_init); */ static void __exit toto_cleanup (void) { - struct nand_chip *this = (struct nand_chip *) &toto_mtd[1]; - - /* Unregister partitions */ - del_mtd_partitions(toto_mtd); - - /* Unregister the device */ - del_mtd_device (toto_mtd); - - /* Free internal data buffers */ - kfree (this->data_buf); + /* Release resources, unregister device */ + nand_release (toto_mtd); /* Free the MTD device structure */ kfree (toto_mtd); diff --git a/drivers/mtd/nand/tx4925ndfmc.c b/drivers/mtd/nand/tx4925ndfmc.c index 5f6a2f5ed138..bba688830c9b 100644 --- a/drivers/mtd/nand/tx4925ndfmc.c +++ b/drivers/mtd/nand/tx4925ndfmc.c @@ -11,7 +11,7 @@ * Derived from drivers/mtd/autcpu12.c * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) * - * $Id: tx4925ndfmc.c,v 1.3 2004/07/20 02:44:26 dwmw2 Exp $ + * $Id: tx4925ndfmc.c,v 1.5 2004/10/05 13:50:20 gleixner Exp $ * * Copyright (C) 2001 Toshiba Corporation * @@ -340,8 +340,8 @@ int __init tx4925ndfmc_init (void) tx4925ndfmc_mtd->priv = this; /* Set address of NAND IO lines */ - this->IO_ADDR_R = (unsigned long)&(tx4925_ndfmcptr->dtr); - this->IO_ADDR_W = (unsigned long)&(tx4925_ndfmcptr->dtr); + this->IO_ADDR_R = (void __iomem *)&(tx4925_ndfmcptr->dtr); + this->IO_ADDR_W = (void __iomem *)&(tx4925_ndfmcptr->dtr); this->hwcontrol = tx4925ndfmc_hwcontrol; this->enable_hwecc = tx4925ndfmc_enable_hwecc; this->calculate_ecc = tx4925ndfmc_readecc; @@ -363,14 +363,6 @@ int __init tx4925ndfmc_init (void) goto out_ior; } - /* Allocate memory for internal data buffer */ - this->data_buf = kmalloc (sizeof(u_char) * (tx4925ndfmc_mtd->oobblock + tx4925ndfmc_mtd->oobsize), GFP_KERNEL); - if (!this->data_buf) { - printk ("Unable to allocate NAND data buffer for RBTX4925.\n"); - err = -ENOMEM; - goto out_ior; - } - /* Register the partitions */ #ifdef CONFIG_MTD_CMDLINE_PARTS { @@ -391,14 +383,12 @@ int __init tx4925ndfmc_init (void) default: { printk ("Unsupported SmartMedia device\n"); err = -ENXIO; - goto out_buf; + goto out_ior; } } #endif /* ifdef CONFIG_MTD_CMDLINE_PARTS */ goto out; -out_buf: - kfree (this->data_buf); out_ior: out: return err; @@ -412,16 +402,8 @@ module_init(tx4925ndfmc_init); #ifdef MODULE static void __exit tx4925ndfmc_cleanup (void) { - struct nand_chip *this = (struct nand_chip *) &tx4925ndfmc_mtd[1]; - - /* Unregister partitions */ - del_mtd_partitions(tx4925ndfmc_mtd); - - /* Unregister the device */ - del_mtd_device (tx4925ndfmc_mtd); - - /* Free internal data buffers */ - kfree (this->data_buf); + /* Release resources, unregister device */ + nand_release (tx4925ndfmc_mtd); /* Free the MTD device structure */ kfree (tx4925ndfmc_mtd); diff --git a/drivers/mtd/nand/tx4938ndfmc.c b/drivers/mtd/nand/tx4938ndfmc.c index f2375b24187c..df26e58820b3 100644 --- a/drivers/mtd/nand/tx4938ndfmc.c +++ b/drivers/mtd/nand/tx4938ndfmc.c @@ -10,7 +10,7 @@ * * Based on spia.c by Steven J. Hill * - * $Id: tx4938ndfmc.c,v 1.2 2004/03/27 19:55:53 gleixner Exp $ + * $Id: tx4938ndfmc.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $ * * Copyright (C) 2000-2001 Toshiba Corporation * @@ -365,14 +365,6 @@ int __init tx4938ndfmc_init (void) return -ENXIO; } - /* Allocate memory for internal data buffer */ - this->data_buf = kmalloc (sizeof(u_char) * (tx4938ndfmc_mtd->oobblock + tx4938ndfmc_mtd->oobsize), GFP_KERNEL); - if (!this->data_buf) { - printk ("Unable to allocate NAND data buffer for TX4938.\n"); - kfree (tx4938ndfmc_mtd); - return -ENOMEM; - } - if (protected) { printk(KERN_INFO "TX4938 NDFMC: write protected.\n"); tx4938ndfmc_mtd->flags &= ~(MTD_WRITEABLE | MTD_ERASEABLE); @@ -401,19 +393,11 @@ module_init(tx4938ndfmc_init); */ static void __exit tx4938ndfmc_cleanup (void) { - struct nand_chip *this = (struct nand_chip *) tx4938ndfmc_mtd->priv; - - /* Unregister the device */ -#ifdef CONFIG_MTD_CMDLINE_PARTS - del_mtd_partitions(tx4938ndfmc_mtd); -#endif - del_mtd_device (tx4938ndfmc_mtd); + /* Release resources, unregister device */ + nand_release (tx4938ndfmc_mtd); /* Free the MTD device structure */ kfree (tx4938ndfmc_mtd); - - /* Free internal data buffer */ - kfree (this->data_buf); } module_exit(tx4938ndfmc_cleanup); diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 7de9f8dfa8ab..9453cb58c683 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -5,7 +5,7 @@ * Steven J. Hill * Thomas Gleixner * - * $Id: nand.h,v 1.63 2004/07/07 16:29:43 gleixner Exp $ + * $Id: nand.h,v 1.66 2004/10/02 10:07:08 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -212,6 +212,18 @@ typedef enum { FL_CACHEDPRG, } nand_state_t; +/* Keep gcc happy */ +struct nand_chip; + +/** + * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independend devices + * @lock: protection lock + * @active: the mtd device which holds the controller currently + */ +struct nand_hw_control { + spinlock_t lock; + struct nand_chip *active; +}; /** * struct nand_chip - NAND Private Flash Chip Data @@ -265,12 +277,13 @@ typedef enum { * @bbt: [INTERN] bad block table pointer * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup * @bbt_md: [REPLACEABLE] bad block table mirror descriptor + * @controller: [OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices * @priv: [OPTIONAL] pointer to private chip date */ struct nand_chip { - unsigned long IO_ADDR_R; - unsigned long IO_ADDR_W; + void __iomem *IO_ADDR_R; + void __iomem *IO_ADDR_W; u_char (*read_byte)(struct mtd_info *mtd); void (*write_byte)(struct mtd_info *mtd, u_char byte); @@ -317,6 +330,7 @@ struct nand_chip { uint8_t *bbt; struct nand_bbt_descr *bbt_td; struct nand_bbt_descr *bbt_md; + struct nand_hw_control *controller; void *priv; }; -- cgit v1.2.3 From 652faad54e678d6b529150627b2058e99a3731c3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 20 Oct 2004 20:03:33 -0700 Subject: Update tty layer to not mix kernel and user pointers. Instead, tty_io.c will always copy user space data to kernel space, leaving the drivers to worry only about normal kernel buffers. No more "from_user" flag, and having the user copy in each driver. This cleans up the code and also fixes a number of locking bugs. --- Documentation/tty.txt | 7 +- arch/alpha/kernel/srmcons.c | 31 +------ arch/cris/arch-v10/drivers/serial.c | 85 ++++++------------ arch/ia64/hp/sim/simserial.c | 66 ++++---------- arch/ppc/4xx_io/serial_sicc.c | 69 ++++----------- arch/ppc/8xx_io/uart.c | 12 +-- arch/um/drivers/line.c | 19 +--- arch/um/drivers/ssl.c | 4 +- arch/um/drivers/stdio_console.c | 4 +- arch/um/include/line.h | 3 +- arch/v850/kernel/memcons.c | 3 +- arch/v850/kernel/simcons.c | 2 +- drivers/bluetooth/hci_ldisc.c | 4 +- drivers/char/amiserial.c | 69 ++++----------- drivers/char/cyclades.c | 61 +++---------- drivers/char/epca.c | 162 +---------------------------------- drivers/char/esp.c | 21 +---- drivers/char/generic_serial.c | 111 +++++++----------------- drivers/char/hvc_console.c | 66 +------------- drivers/char/hvcs.c | 28 ++---- drivers/char/hvsi.c | 17 +--- drivers/char/isicom.c | 25 +----- drivers/char/istallion.c | 42 +-------- drivers/char/moxa.c | 26 ++---- drivers/char/mxser.c | 60 ++++--------- drivers/char/n_hdlc.c | 22 ++--- drivers/char/n_r3964.c | 15 +--- drivers/char/n_tty.c | 30 +++---- drivers/char/pcmcia/synclink_cs.c | 15 +--- drivers/char/pcxx.c | 32 +------ drivers/char/pty.c | 45 ++-------- drivers/char/riscom8.c | 59 +++---------- drivers/char/rocket.c | 22 +---- drivers/char/serial167.c | 58 +++---------- drivers/char/specialix.c | 58 +++---------- drivers/char/stallion.c | 23 +---- drivers/char/synclink.c | 96 ++++----------------- drivers/char/synclinkmp.c | 25 ++---- drivers/char/tty_io.c | 85 ++++++++++++------ drivers/char/tty_ioctl.c | 2 +- drivers/char/viocons.c | 41 +-------- drivers/char/vt.c | 42 +-------- drivers/input/serio/serport.c | 2 +- drivers/isdn/capi/capi.c | 19 +--- drivers/isdn/i4l/isdn_tty.c | 45 +++------- drivers/macintosh/macserial.c | 59 ++++--------- drivers/net/hamradio/6pack.c | 30 +++---- drivers/net/hamradio/mkiss.c | 4 +- drivers/net/irda/irtty-sir.c | 2 +- drivers/net/ppp_async.c | 4 +- drivers/net/ppp_synctty.c | 4 +- drivers/net/slip.c | 6 +- drivers/net/wan/pc300_tty.c | 34 ++------ drivers/net/wan/sdla_chdlc.c | 63 +++----------- drivers/net/wan/x25_asy.c | 4 +- drivers/net/wireless/strip.c | 4 +- drivers/s390/char/con3215.c | 24 +----- drivers/s390/char/sclp_tty.c | 26 +----- drivers/s390/char/sclp_vt220.c | 28 +----- drivers/s390/char/tty3270.c | 24 +----- drivers/s390/net/ctctty.c | 12 +-- drivers/sbus/char/aurora.c | 57 +++--------- drivers/serial/68328serial.c | 12 +-- drivers/serial/68360serial.c | 14 +-- drivers/serial/mcfserial.c | 20 +---- drivers/serial/serial_core.c | 11 +-- drivers/tc/zs.c | 12 +-- drivers/usb/class/bluetty.c | 20 +---- drivers/usb/class/cdc-acm.c | 14 ++- drivers/usb/gadget/serial.c | 32 +------ drivers/usb/serial/cyberjack.c | 15 +--- drivers/usb/serial/digi_acceleport.c | 19 ++-- drivers/usb/serial/empeg.c | 12 +-- drivers/usb/serial/ftdi_sio.c | 27 ++---- drivers/usb/serial/generic.c | 10 +-- drivers/usb/serial/io_edgeport.c | 22 ++--- drivers/usb/serial/io_ti.c | 13 +-- drivers/usb/serial/ipaq.c | 17 ++-- drivers/usb/serial/ipw.c | 13 +-- drivers/usb/serial/ir-usb.c | 11 +-- drivers/usb/serial/keyspan.c | 9 +- drivers/usb/serial/keyspan.h | 1 - drivers/usb/serial/keyspan_pda.c | 13 +-- drivers/usb/serial/kl5kusb105.c | 13 +-- drivers/usb/serial/kobil_sct.c | 12 +-- drivers/usb/serial/mct_u232.c | 12 +-- drivers/usb/serial/omninet.c | 15 +--- drivers/usb/serial/pl2303.c | 19 +--- drivers/usb/serial/safe_serial.c | 9 +- drivers/usb/serial/usb-serial.c | 4 +- drivers/usb/serial/usb-serial.h | 4 +- drivers/usb/serial/visor.c | 14 +-- drivers/usb/serial/whiteheat.c | 11 +-- include/linux/generic_serial.h | 2 +- include/linux/tty.h | 2 + include/linux/tty_driver.h | 6 +- include/linux/tty_ldisc.h | 2 +- kernel/printk.c | 2 +- net/bluetooth/rfcomm/tty.c | 14 +-- net/irda/ircomm/ircomm_tty.c | 28 ++---- 100 files changed, 561 insertions(+), 2043 deletions(-) (limited to 'include/linux') diff --git a/Documentation/tty.txt b/Documentation/tty.txt index a496056426c6..5f6dc126775e 100644 --- a/Documentation/tty.txt +++ b/Documentation/tty.txt @@ -49,10 +49,9 @@ open() - Called when the line discipline is attached to discipline for this tty will occur until it completes successfully. Can sleep. -write() - A process is writing data from user space - through the line discipline. Multiple write calls - are serialized by the tty layer for the ldisc. May - sleep. +write() - A process is writing data through the line + discipline. Multiple write calls are serialized + by the tty layer for the ldisc. May sleep. flush_buffer() - May be called at any point between open and close. diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c index 49c8c97ed82d..631240245e9e 100644 --- a/arch/alpha/kernel/srmcons.c +++ b/arch/alpha/kernel/srmcons.c @@ -132,40 +132,11 @@ srmcons_do_write(struct tty_struct *tty, const char *buf, int count) } static int -srmcons_write(struct tty_struct *tty, int from_user, +srmcons_write(struct tty_struct *tty, const unsigned char *buf, int count) { unsigned long flags; - if (from_user) { - char tmp[512]; - int ret = 0; - size_t c; - - while ((c = count) > 0) { - if (c > sizeof(tmp)) - c = sizeof(tmp); - - c -= copy_from_user(tmp, (const char __user *) buf, c); - - if (!c) { - printk("%s: EFAULT (count %d)\n", - __FUNCTION__, count); - return -EFAULT; - } - - spin_lock_irqsave(&srmcons_callback_lock, flags); - srmcons_do_write(tty, tmp, c); - spin_unlock_irqrestore(&srmcons_callback_lock, flags); - - buf += c; - count -= c; - ret += c; - } - - return ret; - } - spin_lock_irqsave(&srmcons_callback_lock, flags); srmcons_do_write(tty, (const char *) buf, count); spin_unlock_irqrestore(&srmcons_callback_lock, flags); diff --git a/arch/cris/arch-v10/drivers/serial.c b/arch/cris/arch-v10/drivers/serial.c index 5881533878d1..d5e780da7bfe 100644 --- a/arch/cris/arch-v10/drivers/serial.c +++ b/arch/cris/arch-v10/drivers/serial.c @@ -577,12 +577,12 @@ unsigned long timer_data_to_ns(unsigned long timer_data); static void change_speed(struct e100_serial *info); static void rs_throttle(struct tty_struct * tty); static void rs_wait_until_sent(struct tty_struct *tty, int timeout); -static int rs_write(struct tty_struct * tty, int from_user, +static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count); -extern _INLINE_ int rs_raw_write(struct tty_struct * tty, int from_user, +extern _INLINE_ int rs_raw_write(struct tty_struct * tty, const unsigned char *buf, int count); #ifdef CONFIG_ETRAX_RS485 -static int e100_write_rs485(struct tty_struct * tty, int from_user, +static int e100_write_rs485(struct tty_struct * tty, const unsigned char *buf, int count); #endif static int get_lsr_info(struct e100_serial * info, unsigned int *value); @@ -1786,7 +1786,7 @@ e100_enable_rs485(struct tty_struct *tty,struct rs485_control *r) } static int -e100_write_rs485(struct tty_struct *tty, int from_user, +e100_write_rs485(struct tty_struct *tty, const unsigned char *buf, int count) { struct e100_serial * info = (struct e100_serial *)tty->driver_data; @@ -1799,7 +1799,7 @@ e100_write_rs485(struct tty_struct *tty, int from_user, */ info->rs485.enabled = 1; /* rs_write now deals with RS485 if enabled */ - count = rs_write(tty, from_user, buf, count); + count = rs_write(tty, buf, count); info->rs485.enabled = old_enabled; return count; } @@ -3614,7 +3614,7 @@ rs_flush_chars(struct tty_struct *tty) } extern _INLINE_ int -rs_raw_write(struct tty_struct * tty, int from_user, +rs_raw_write(struct tty_struct * tty, const unsigned char *buf, int count) { int c, ret = 0; @@ -3649,60 +3649,25 @@ rs_raw_write(struct tty_struct * tty, int from_user, * atomic operation... this could perhaps be avoided by more clever * design. */ - if (from_user) { - down(&tmp_buf_sem); - while (1) { - int c1; - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - cli(); - c1 = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (c1 < c) - c = c1; - memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); - restore_flags(flags); - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - cli(); - while (1) { - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - - if (count < c) - c = count; - if (c <= 0) - break; + cli(); + while (1) { + c = CIRC_SPACE_TO_END(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE); + + if (count < c) + c = count; + if (c <= 0) + break; - memcpy(info->xmit.buf + info->xmit.head, buf, c); - info->xmit.head = (info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1); - buf += c; - count -= c; - ret += c; - } - restore_flags(flags); + memcpy(info->xmit.buf + info->xmit.head, buf, c); + info->xmit.head = (info->xmit.head + c) & + (SERIAL_XMIT_SIZE-1); + buf += c; + count -= c; + ret += c; } + restore_flags(flags); /* enable transmitter if not running, unless the tty is stopped * this does not need IRQ protection since if tr_running == 0 @@ -3721,7 +3686,7 @@ rs_raw_write(struct tty_struct * tty, int from_user, } /* raw_raw_write() */ static int -rs_write(struct tty_struct * tty, int from_user, +rs_write(struct tty_struct * tty, const unsigned char *buf, int count) { #if defined(CONFIG_ETRAX_RS485) @@ -3750,7 +3715,7 @@ rs_write(struct tty_struct * tty, int from_user, } #endif /* CONFIG_ETRAX_RS485 */ - count = rs_raw_write(tty, from_user, buf, count); + count = rs_raw_write(tty, buf, count); #if defined(CONFIG_ETRAX_RS485) if (info->rs485.enabled) diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index af4b7143d0c9..786e70718ce4 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -301,7 +301,7 @@ static void rs_flush_chars(struct tty_struct *tty) } -static int rs_write(struct tty_struct * tty, int from_user, +static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) { int c, ret = 0; @@ -310,58 +310,22 @@ static int rs_write(struct tty_struct * tty, int from_user, if (!tty || !info->xmit.buf || !tmp_buf) return 0; - if (from_user) { - down(&tmp_buf_sem); - while (1) { - int c1; - c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - - local_irq_save(flags); - { - c1 = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, - SERIAL_XMIT_SIZE); - if (c1 < c) - c = c1; - memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); - } - local_irq_restore(flags); - - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - local_irq_save(flags); - while (1) { - c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) { - break; - } - memcpy(info->xmit.buf + info->xmit.head, buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); - buf += c; - count -= c; - ret += c; + local_irq_save(flags); + while (1) { + c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) { + break; } - local_irq_restore(flags); + memcpy(info->xmit.buf + info->xmit.head, buf, c); + info->xmit.head = ((info->xmit.head + c) & + (SERIAL_XMIT_SIZE-1)); + buf += c; + count -= c; + ret += c; } + local_irq_restore(flags); /* * Hey, we transmit directly from here in our case */ diff --git a/arch/ppc/4xx_io/serial_sicc.c b/arch/ppc/4xx_io/serial_sicc.c index 0e7ba9ecba26..4a0f3119a749 100644 --- a/arch/ppc/4xx_io/serial_sicc.c +++ b/arch/ppc/4xx_io/serial_sicc.c @@ -933,7 +933,7 @@ static void siccuart_flush_chars(struct tty_struct *tty) restore_flags(flags); } -static int siccuart_write(struct tty_struct *tty, int from_user, +static int siccuart_write(struct tty_struct *tty, const u_char * buf, int count) { struct SICC_info *info = tty->driver_data; @@ -944,58 +944,23 @@ static int siccuart_write(struct tty_struct *tty, int from_user, return 0; save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - int c1; - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SICC_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - cli(); - c1 = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SICC_XMIT_SIZE); - if (c1 < c) - c = c1; - memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); - info->xmit.head = (info->xmit.head + c) & - (SICC_XMIT_SIZE - 1); - restore_flags(flags); - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - cli(); - while (1) { - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SICC_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - memcpy(info->xmit.buf + info->xmit.head, buf, c); - info->xmit.head = (info->xmit.head + c) & - (SICC_XMIT_SIZE - 1); - buf += c; - count -= c; - ret += c; - } - restore_flags(flags); + cli(); + while (1) { + c = CIRC_SPACE_TO_END(info->xmit.head, + info->xmit.tail, + SICC_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) + break; + memcpy(info->xmit.buf + info->xmit.head, buf, c); + info->xmit.head = (info->xmit.head + c) & + (SICC_XMIT_SIZE - 1); + buf += c; + count -= c; + ret += c; } + restore_flags(flags); if (info->xmit.head != info->xmit.tail && !tty->stopped && !tty->hw_stopped) diff --git a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c index 34a463a94c65..39d191bf40b3 100644 --- a/arch/ppc/8xx_io/uart.c +++ b/arch/ppc/8xx_io/uart.c @@ -1053,7 +1053,7 @@ static void rs_8xx_put_char(struct tty_struct *tty, unsigned char ch) } -static int rs_8xx_write(struct tty_struct * tty, int from_user, +static int rs_8xx_write(struct tty_struct * tty, const unsigned char *buf, int count) { int c, ret = 0; @@ -1087,15 +1087,7 @@ static int rs_8xx_write(struct tty_struct * tty, int from_user, } cp = info->tx_va_base + ((bdp - info->tx_bd_base) * TX_BUF_SIZE); - if (from_user) { - if (copy_from_user((void *)cp, buf, c)) { - if (!ret) - ret = -EFAULT; - break; - } - } else { - memcpy((void *)cp, buf, c); - } + memcpy((void *)cp, buf, c); bdp->cbd_datlen = c; bdp->cbd_sc |= BD_SC_READY; diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index c6b77fccd2c4..879edc863e13 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -107,8 +107,7 @@ static int flush_buffer(struct line *line) return(line->head == line->tail); } -int line_write(struct line *lines, struct tty_struct *tty, int from_user, - const char *buf, int len) +int line_write(struct line *lines, struct tty_struct *tty, const char *buf, int len) { struct line *line; char *new; @@ -117,20 +116,6 @@ int line_write(struct line *lines, struct tty_struct *tty, int from_user, if(tty->stopped) return 0; - if(from_user){ - new = kmalloc(len, GFP_KERNEL); - if(new == NULL) - return(0); - n = copy_from_user(new, buf, len); - buf = new; - if(n == len){ - len = -EFAULT; - goto out_free; - } - - len -= n; - } - i = tty->index; line = &lines[i]; @@ -159,8 +144,6 @@ int line_write(struct line *lines, struct tty_struct *tty, int from_user, out_up: up(&line->sem); out_free: - if(from_user) - kfree(buf); return(ret); } diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index 4a3586f0dd2c..479ffc84ef83 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -111,10 +111,10 @@ static void ssl_close(struct tty_struct *tty, struct file * filp) line_close(serial_lines, tty); } -static int ssl_write(struct tty_struct * tty, int from_user, +static int ssl_write(struct tty_struct * tty, const unsigned char *buf, int count) { - return(line_write(serial_lines, tty, from_user, buf, count)); + return(line_write(serial_lines, tty, buf, count)); } static void ssl_put_char(struct tty_struct *tty, unsigned char ch) diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 54e6a57c8973..e721e15d892e 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -143,10 +143,10 @@ static void con_close(struct tty_struct *tty, struct file *filp) line_close(vts, tty); } -static int con_write(struct tty_struct *tty, int from_user, +static int con_write(struct tty_struct *tty, const unsigned char *buf, int count) { - return(line_write(vts, tty, from_user, buf, count)); + return(line_write(vts, tty, buf, count)); } static void set_termios(struct tty_struct *tty, struct termios * old) diff --git a/arch/um/include/line.h b/arch/um/include/line.h index 31911329f265..4f2853fbd31f 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -74,8 +74,7 @@ extern int line_open(struct line *lines, struct tty_struct *tty, struct chan_opts *opts); extern int line_setup(struct line *lines, int num, char *init, int all_allowed); -extern int line_write(struct line *line, struct tty_struct *tty, int from_user, - const char *buf, int len); +extern int line_write(struct line *line, struct tty_struct *tty, const char *buf, int len); extern int line_write_room(struct tty_struct *tty); extern char *add_xterm_umid(char *base); extern int line_setup_irq(int fd, int input, int output, void *data); diff --git a/arch/v850/kernel/memcons.c b/arch/v850/kernel/memcons.c index 9bd818b0f075..673b509942bf 100644 --- a/arch/v850/kernel/memcons.c +++ b/arch/v850/kernel/memcons.c @@ -88,8 +88,7 @@ int memcons_tty_open (struct tty_struct *tty, struct file *filp) return 0; } -int memcons_tty_write (struct tty_struct *tty, int from_user, - const unsigned char *buf, int len) +int memcons_tty_write (struct tty_struct *tty, const unsigned char *buf, int len) { return write (buf, len); } diff --git a/arch/v850/kernel/simcons.c b/arch/v850/kernel/simcons.c index 9aed8871b8c5..7f0efaa025c9 100644 --- a/arch/v850/kernel/simcons.c +++ b/arch/v850/kernel/simcons.c @@ -59,7 +59,7 @@ int simcons_tty_open (struct tty_struct *tty, struct file *filp) return 0; } -int simcons_tty_write (struct tty_struct *tty, int from_user, +int simcons_tty_write (struct tty_struct *tty, const unsigned char *buf, int count) { return V850_SIM_SYSCALL (write, 1, buf, count); diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index fb990ec38968..dfb4142a551a 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -143,7 +143,7 @@ restart: int len; set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - len = tty->driver->write(tty, 0, skb->data, skb->len); + len = tty->driver->write(tty, skb->data, skb->len); hdev->stat.byte_tx += len; skb_pull(skb, len); @@ -502,7 +502,7 @@ static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file, unsi { return 0; } -static ssize_t hci_uart_tty_write(struct tty_struct *tty, struct file *file, const unsigned char __user *data, size_t count) +static ssize_t hci_uart_tty_write(struct tty_struct *tty, struct file *file, const unsigned char *data, size_t count) { return 0; } diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index b657ac4ff7cc..335f38f9d434 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -908,8 +908,7 @@ static void rs_flush_chars(struct tty_struct *tty) local_irq_restore(flags); } -static int rs_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count) +static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) { int c, ret = 0; struct async_struct *info = (struct async_struct *)tty->driver_data; @@ -922,57 +921,25 @@ static int rs_write(struct tty_struct * tty, int from_user, return 0; local_save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - int c1; - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (count < c) - c = count; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - local_irq_disable(); - c1 = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (c1 < c) - c = c1; - memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); - local_irq_restore(flags); - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - local_irq_disable(); - while (1) { - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) { - break; - } - memcpy(info->xmit.buf + info->xmit.head, buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); - buf += c; - count -= c; - ret += c; + local_irq_disable(); + while (1) { + c = CIRC_SPACE_TO_END(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) { + break; } - local_irq_restore(flags); + memcpy(info->xmit.buf + info->xmit.head, buf, c); + info->xmit.head = ((info->xmit.head + c) & + (SERIAL_XMIT_SIZE-1)); + buf += c; + count -= c; + ret += c; } + local_irq_restore(flags); + if (info->xmit.head != info->xmit.tail && !tty->stopped && !tty->hw_stopped diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index d3fd1c9c9301..4a1ac716faab 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -2855,8 +2855,7 @@ cy_close(struct tty_struct *tty, struct file *filp) * */ static int -cy_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count) +cy_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; unsigned long flags; @@ -2874,56 +2873,22 @@ cy_write(struct tty_struct * tty, int from_user, return 0; } - if (from_user) { - down(&tmp_buf_sem); - while (1) { - int c1; - - c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1), - (int)(SERIAL_XMIT_SIZE - info->xmit_head))); - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) { - ret = -EFAULT; - } - break; - } - CY_LOCK(info, flags); - c1 = min(c, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1), - (int)(SERIAL_XMIT_SIZE - info->xmit_head))); - - if (c1 < c) - c = c1; - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - info->xmit_head = ((info->xmit_head + c) & (SERIAL_XMIT_SIZE-1)); - info->xmit_cnt += c; - CY_UNLOCK(info, flags); - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - CY_LOCK(info, flags); - while (1) { - c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1), + CY_LOCK(info, flags); + while (1) { + c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1), (int)(SERIAL_XMIT_SIZE - info->xmit_head))); - if (c <= 0) - break; + if (c <= 0) + break; - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt += c; - buf += c; - count -= c; - ret += c; - } - CY_UNLOCK(info, flags); + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt += c; + buf += c; + count -= c; + ret += c; } + CY_UNLOCK(info, flags); info->idle_stats.xmit_bytes += ret; info->idle_stats.xmit_idle = jiffies; diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 031b178af342..6025e1866c7e 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -218,7 +218,7 @@ void epca_setup(char *, int *); void console_print(const char *); static int get_termio(struct tty_struct *, struct termio __user *); -static int pc_write(struct tty_struct *, int, const unsigned char *, int); +static int pc_write(struct tty_struct *, const unsigned char *, int); int pc_init(void); #ifdef ENABLE_PCI @@ -669,7 +669,7 @@ static void pc_hangup(struct tty_struct *tty) /* ------------------ Begin pc_write ------------------------- */ -static int pc_write(struct tty_struct * tty, int from_user, +static int pc_write(struct tty_struct * tty, const unsigned char *buf, int bytesAvailable) { /* Begin pc_write */ @@ -707,162 +707,6 @@ static int pc_write(struct tty_struct * tty, int from_user, bc = ch->brdchan; size = ch->txbufsize; - if (from_user) - { /* Begin from_user */ - - save_flags(flags); - cli(); - - globalwinon(ch); - - /* ----------------------------------------------------------------- - Anding against size will wrap the pointer back to its beginning - position if it is necessary. This will only work if size is - a power of 2 which should always be the case. Size is determined - by the cards on board FEP/OS. - -------------------------------------------------------------------- */ - - /* head refers to the next empty location in which data may be stored */ - - head = bc->tin & (size - 1); - - /* tail refers to the next data byte to be transmitted */ - - tail = bc->tout; - - /* Consider changing this to a do statement to make sure */ - - if (tail != bc->tout) - tail = bc->tout; - - /* ------------------------------------------------------------------ - Anding against size will wrap the pointer back to its beginning - position if it is necessary. This will only work if size is - a power of 2 which should always be the case. Size is determined - by the cards on board FEP/OS. - --------------------------------------------------------------------- */ - - tail &= (size - 1); - - /* ----------------------------------------------------------------- - Two situations can affect how space in the transmit buffer - is calculated. You can have a situation where the transmit - in pointer (tin) head has wrapped around and actually has a - lower address than the transmit out pointer (tout) tail; or - the transmit in pointer (tin) head will not be wrapped around - yet, and have a higher address than the transmit out pointer - (tout) tail. Obviously space available in the transmit buffer - is calculated differently for each case. - - Example 1: - - Consider a 10 byte buffer where head is a pointer to the next - empty location in the buffer and tail is a pointer to the next - byte to transmit. In this example head will not have wrapped - around and therefore head > tail. - - 0 1 2 3 4 5 6 7 8 9 - tail head - - The above diagram shows that buffer locations 2,3,4,5 and 6 have - data to be transmitted, while head points at the next empty - location. To calculate how much space is available first we have - to determine if the head pointer (tin) has wrapped. To do this - compare the head pointer to the tail pointer, If head is equal - or greater than tail; then it has not wrapped; and the space may - be calculated by subtracting tail from head and then subtracting - that value from the buffers size. A one is subtracted from the - new value to indicate how much space is available between the - head pointer and end of buffer; as well as the space between the - beginning of the buffer and the tail. If the head is not greater - or equal to the tail this indicates that the head has wrapped - around to the beginning of the buffer. To calculate the space - available in this case simply subtract head from tail. This new - value minus one represents the space available betwwen the head - and tail pointers. In this example head (7) is greater than tail (2) - and therefore has not wrapped around. We find the space by first - subtracting tail from head (7-2=5). We then subtract this value - from the buffer size of ten and subtract one (10-5-1=4). The space - remaining is 4 bytes. - - Example 2: - - Consider a 10 byte buffer where head is a pointer to the next - empty location in the buffer and tail is a pointer to the next - byte to transmit. In this example head will wrapped around and - therefore head < tail. - - 0 1 2 3 4 5 6 7 8 9 - head tail - - The above diagram shows that buffer locations 7,8,9,0 and 1 have - data to be transmitted, while head points at the next empty - location. To find the space available we compare head to tail. If - head is not equal to, or greater than tail this indicates that head - has wrapped around. In this case head (2) is not equal to, or - greater than tail (7) and therefore has already wrapped around. To - calculate the available space between the two pointers we subtract - head from tail (7-2=5). We then subtract one from this new value - (5-1=4). We have 5 bytes empty remaining in the buffer. Unlike the - previous example these five bytes are located between the head and - tail pointers. - - ----------------------------------------------------------------------- */ - - dataLen = (head >= tail) ? (size - (head - tail) - 1) : (tail - head - 1); - - /* ---------------------------------------------------------------------- - In this case bytesAvailable has been passed into pc_write and - represents the amount of data that needs to be written. dataLen - represents the amount of space available on the card. Whichever - value is smaller will be the amount actually written. - bytesAvailable will then take on this newly calculated value. - ---------------------------------------------------------------------- */ - - bytesAvailable = min(dataLen, bytesAvailable); - - /* First we read the data in from the file system into a temp buffer */ - - memoff(ch); - restore_flags(flags); - - if (bytesAvailable) - { /* Begin bytesAvailable */ - /* --------------------------------------------------------------- - The below function reads data from user memory. This routine - can not be used in an interrupt routine. (Because it may - generate a page fault) It can only be called while we can the - user context is accessible. - - The prototype is : - inline void copy_from_user(void * to, const void * from, - unsigned long count); - - I also think (Check hackers guide) that optimization must - be turned ON. (Which sounds strange to me...) - - Remember copy_from_user WILL generate a page fault if the - user memory being accessed has been swapped out. This can - cause this routine to temporarily sleep while this page - fault is occurring. - - ----------------------------------------------------------------- */ - - if (copy_from_user(ch->tmp_buf, buf, - bytesAvailable)) - return -EFAULT; - } /* End bytesAvailable */ - - /* ------------------------------------------------------------------ - Set buf to this address for the moment. tmp_buf was allocated in - post_fep_init. - --------------------------------------------------------------------- */ - buf = ch->tmp_buf; - - } /* End from_user */ - - /* All data is now local */ - amountCopied = 0; save_flags(flags); cli(); @@ -953,7 +797,7 @@ static void pc_put_char(struct tty_struct *tty, unsigned char c) { /* Begin pc_put_char */ - pc_write(tty, 0, &c, 1); + pc_write(tty, &c, 1); return; } /* End pc_put_char */ diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 7353c2678916..b0eaa1ec5168 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c @@ -1265,7 +1265,7 @@ static void rs_flush_chars(struct tty_struct *tty) restore_flags(flags); } -static int rs_write(struct tty_struct * tty, int from_user, +static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) { int c, t, ret = 0; @@ -1278,9 +1278,6 @@ static int rs_write(struct tty_struct * tty, int from_user, if (!tty || !info->xmit_buf || !tmp_buf) return 0; - if (from_user) - down(&tmp_buf_sem); - while (1) { /* Thanks to R. Wolff for suggesting how to do this with */ /* interrupts enabled */ @@ -1299,18 +1296,7 @@ static int rs_write(struct tty_struct * tty, int from_user, if (c <= 0) break; - if (from_user) { - c -= copy_from_user(tmp_buf, buf, c); - - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - } else - memcpy(info->xmit_buf + info->xmit_head, buf, c); + memcpy(info->xmit_buf + info->xmit_head, buf, c); info->xmit_head = (info->xmit_head + c) & (ESP_XMIT_SIZE-1); info->xmit_cnt += c; @@ -1319,9 +1305,6 @@ static int rs_write(struct tty_struct * tty, int from_user, ret += c; } - if (from_user) - up(&tmp_buf_sem); - save_flags(flags); cli(); if (info->xmit_cnt && !tty->stopped && !(info->IER & UART_IER_THRI)) { diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index fd9ed4c3434a..830bde170d3f 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c @@ -103,7 +103,7 @@ void gs_put_char(struct tty_struct * tty, unsigned char ch) > -3- Other processes that are also trying to do a "write". */ -int gs_write(struct tty_struct * tty, int from_user, +int gs_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct gs_port *port; @@ -144,15 +144,8 @@ int gs_write(struct tty_struct * tty, int from_user, /* Can't copy more? break out! */ if (c <= 0) break; - if (from_user) { - if (copy_from_user (port->xmit_buf + port->xmit_head, - buf, c)) { - up (& port->port_write_sem); - return -EFAULT; - } - } else - memcpy (port->xmit_buf + port->xmit_head, buf, c); + memcpy (port->xmit_buf + port->xmit_head, buf, c); port -> xmit_cnt += c; port -> xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE -1); @@ -183,7 +176,7 @@ int gs_write(struct tty_struct * tty, int from_user, > -3- Other processes that are also trying to do a "write". */ -int gs_write(struct tty_struct * tty, int from_user, +int gs_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct gs_port *port; @@ -216,79 +209,35 @@ int gs_write(struct tty_struct * tty, int from_user, return -EIO; save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - c = count; - - /* This is safe because we "OWN" the "head". Noone else can - change the "head": we own the port_write_sem. */ - /* Don't overrun the end of the buffer */ - t = SERIAL_XMIT_SIZE - port->xmit_head; - if (t < c) c = t; - - /* This is safe because the xmit_cnt can only decrease. This - would increase "t", so we might copy too little chars. */ - /* Don't copy past the "head" of the buffer */ - t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; - if (t < c) c = t; - - /* Can't copy more? break out! */ - if (c <= 0) break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!total) - total = -EFAULT; - break; - } - cli(); - t = SERIAL_XMIT_SIZE - port->xmit_head; - if (t < c) c = t; - t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; - if (t < c) c = t; - - memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c); - port->xmit_head = ((port->xmit_head + c) & - (SERIAL_XMIT_SIZE-1)); - port->xmit_cnt += c; - restore_flags(flags); - buf += c; - count -= c; - total += c; - } - up(&tmp_buf_sem); - } else { - while (1) { - cli(); - c = count; - - /* This is safe because we "OWN" the "head". Noone else can - change the "head": we own the port_write_sem. */ - /* Don't overrun the end of the buffer */ - t = SERIAL_XMIT_SIZE - port->xmit_head; - if (t < c) c = t; - - /* This is safe because the xmit_cnt can only decrease. This - would increase "t", so we might copy too little chars. */ - /* Don't copy past the "head" of the buffer */ - t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; - if (t < c) c = t; - - /* Can't copy more? break out! */ - 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; + while (1) { + cli(); + c = count; + + /* This is safe because we "OWN" the "head". Noone else can + change the "head": we own the port_write_sem. */ + /* Don't overrun the end of the buffer */ + t = SERIAL_XMIT_SIZE - port->xmit_head; + if (t < c) c = t; + + /* This is safe because the xmit_cnt can only decrease. This + would increase "t", so we might copy too little chars. */ + /* Don't copy past the "head" of the buffer */ + t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; + if (t < c) c = t; + + /* Can't copy more? break out! */ + if (c <= 0) { restore_flags(flags); - buf += c; - count -= c; - total += c; + 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; + restore_flags(flags); + buf += c; + count -= c; + total += c; } if (port->xmit_cnt && diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 44dbc3d80e06..9d7682c82509 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -344,62 +344,6 @@ static void hvc_push(struct hvc_struct *hp) hp->do_wakeup = 1; } -static inline int __hvc_write_user(struct hvc_struct *hp, - const unsigned char *buf, int count) -{ - char *tbuf, *p; - int tbsize, rsize, written = 0; - unsigned long flags; - - tbsize = min(count, (int)PAGE_SIZE); - if (!(tbuf = kmalloc(tbsize, GFP_KERNEL))) - return -ENOMEM; - - while ((rsize = count - written) > 0) { - int wsize; - if (rsize > tbsize) - rsize = tbsize; - - p = tbuf; - rsize -= copy_from_user(p, buf, rsize); - if (!rsize) { - if (written == 0) - written = -EFAULT; - break; - } - buf += rsize; - - spin_lock_irqsave(&hp->lock, flags); - - /* Push pending writes: make some room in buffer */ - if (hp->n_outbuf > 0) - hvc_push(hp); - - for (wsize = N_OUTBUF - hp->n_outbuf; rsize && wsize; - wsize = N_OUTBUF - hp->n_outbuf) { - if (wsize > rsize) - wsize = rsize; - memcpy(hp->outbuf + hp->n_outbuf, p, wsize); - hp->n_outbuf += wsize; - hvc_push(hp); - rsize -= wsize; - p += wsize; - written += wsize; - } - spin_unlock_irqrestore(&hp->lock, flags); - - if (rsize) - break; - - if (count < tbsize) - tbsize = count; - } - - kfree(tbuf); - - return written; -} - static inline int __hvc_write_kernel(struct hvc_struct *hp, const unsigned char *buf, int count) { @@ -426,8 +370,7 @@ static inline int __hvc_write_kernel(struct hvc_struct *hp, return written; } -static int hvc_write(struct tty_struct *tty, int from_user, - const unsigned char *buf, int count) +static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct hvc_struct *hp = tty->driver_data; int written; @@ -439,10 +382,7 @@ static int hvc_write(struct tty_struct *tty, int from_user, if (hp->count <= 0) return -EIO; - if (from_user) - written = __hvc_write_user(hp, buf, count); - else - written = __hvc_write_kernel(hp, buf, count); + written = __hvc_write_kernel(hp, buf, count); /* * Racy, but harmless, kick thread if there is still pending data. @@ -641,7 +581,7 @@ char hvc_driver_name[] = "hvc_console"; static struct vio_device_id hvc_driver_table[] __devinitdata= { {"serial", "hvterm1"}, - { 0, } + { NULL, } }; MODULE_DEVICE_TABLE(vio, hvc_driver_table); diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 15b1d8cbc77d..c60528082bc4 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c @@ -315,7 +315,7 @@ static void hvcs_throttle(struct tty_struct *tty); static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -static int hvcs_write(struct tty_struct *tty, int from_user, +static int hvcs_write(struct tty_struct *tty, const unsigned char *buf, int count); static int hvcs_write_room(struct tty_struct *tty); static int hvcs_chars_in_buffer(struct tty_struct *tty); @@ -527,7 +527,7 @@ static int khvcsd(void *unused) static struct vio_device_id hvcs_driver_table[] __devinitdata= { {"serial-server", "hvterm2"}, - { 0, } + { NULL, } }; MODULE_DEVICE_TABLE(vio, hvcs_driver_table); @@ -1183,12 +1183,12 @@ static void hvcs_hangup(struct tty_struct * tty) * tty_hangup will allow hvcs_write time to complete execution before it * terminates our device. */ -static int hvcs_write(struct tty_struct *tty, int from_user, +static int hvcs_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct hvcs_struct *hvcsd = tty->driver_data; unsigned int unit_address; - unsigned char *charbuf; + const unsigned char *charbuf; unsigned long flags; int total_sent = 0; int tosend = 0; @@ -1208,21 +1208,7 @@ static int hvcs_write(struct tty_struct *tty, int from_user, count = HVCS_MAX_FROM_USER; } - if (!from_user) - charbuf = (unsigned char *)buf; - else { - charbuf = kmalloc(count, GFP_KERNEL); - if (!charbuf) { - printk(KERN_WARNING "HVCS: write -ENOMEM.\n"); - return -ENOMEM; - } - - if (copy_from_user(charbuf, buf, count)) { - kfree(charbuf); - printk(KERN_WARNING "HVCS: write -EFAULT.\n"); - return -EFAULT; - } - } + charbuf = buf; spin_lock_irqsave(&hvcsd->lock, flags); @@ -1234,8 +1220,6 @@ static int hvcs_write(struct tty_struct *tty, int from_user, */ if (hvcsd->open_count <= 0) { spin_unlock_irqrestore(&hvcsd->lock, flags); - if (from_user) - kfree(charbuf); return -ENODEV; } @@ -1292,8 +1276,6 @@ static int hvcs_write(struct tty_struct *tty, int from_user, } spin_unlock_irqrestore(&hvcsd->lock, flags); - if (from_user) - kfree(charbuf); if (result == -1) return -EIO; diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index 595079c07be5..250cc620668a 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c @@ -999,27 +999,15 @@ static int hvsi_chars_in_buffer(struct tty_struct *tty) return hp->n_outbuf; } -static int hvsi_write(struct tty_struct *tty, int from_user, +static int hvsi_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct hvsi_struct *hp = tty->driver_data; const char *source = buf; - char *kbuf = NULL; unsigned long flags; int total = 0; int origcount = count; - if (from_user) { - kbuf = kmalloc(count, GFP_KERNEL); - if (kbuf == NULL) - return -ENOMEM; - if (copy_from_user(kbuf, buf, count)) { - kfree(kbuf); - return -EFAULT; - } - source = kbuf; - } - spin_lock_irqsave(&hp->lock, flags); if (!is_open(hp)) { @@ -1057,9 +1045,6 @@ static int hvsi_write(struct tty_struct *tty, int from_user, out: spin_unlock_irqrestore(&hp->lock, flags); - if (from_user) - kfree(kbuf); - if (total != origcount) pr_debug("%s: wanted %i, only wrote %i\n", __FUNCTION__, origcount, total); diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index eb8c18883a9d..7823c7f50ec6 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -1140,7 +1140,7 @@ static void isicom_close(struct tty_struct * tty, struct file * filp) } /* write et all */ -static int isicom_write(struct tty_struct * tty, int from_user, +static int isicom_write(struct tty_struct * tty, const unsigned char * buf, int count) { struct isi_port * port = (struct isi_port *) tty->driver_data; @@ -1155,8 +1155,6 @@ static int isicom_write(struct tty_struct * tty, int from_user, if (!tty || !port->xmit_buf || !tmp_buf) return 0; - if (from_user) - down(&tmp_buf_sem); /* acquire xclusive access to tmp_buf */ save_flags(flags); while(1) { @@ -1166,24 +1164,7 @@ static int isicom_write(struct tty_struct * tty, int from_user, if (cnt <= 0) break; - if (from_user) { - /* the following may block for paging... hence - enabling interrupts but tx routine may have - created more space in xmit_buf when the ctrl - gets back here */ - sti(); - if (copy_from_user(tmp_buf, buf, cnt)) { - up(&tmp_buf_sem); - restore_flags(flags); - return -EFAULT; - } - cli(); - cnt = min_t(int, cnt, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - memcpy(port->xmit_buf + port->xmit_head, tmp_buf, cnt); - } - else - memcpy(port->xmit_buf + port->xmit_head, buf, cnt); + memcpy(port->xmit_buf + port->xmit_head, buf, cnt); port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE - 1); port->xmit_cnt += cnt; restore_flags(flags); @@ -1191,8 +1172,6 @@ static int isicom_write(struct tty_struct * tty, int from_user, count -= cnt; total += cnt; } - if (from_user) - up(&tmp_buf_sem); if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped) port->status |= ISI_TXOK; restore_flags(flags); diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 832806725c1e..06b4572fa74a 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -660,7 +660,7 @@ static unsigned long stli_atol(char *str); int stli_init(void); static int stli_open(struct tty_struct *tty, struct file *filp); static void stli_close(struct tty_struct *tty, struct file *filp); -static int stli_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count); +static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count); static void stli_putchar(struct tty_struct *tty, unsigned char ch); static void stli_flushchars(struct tty_struct *tty); static int stli_writeroom(struct tty_struct *tty); @@ -1543,7 +1543,7 @@ static int stli_waitcarrier(stlibrd_t *brdp, stliport_t *portp, struct file *fil * service bits for this port. */ -static int stli_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count) +static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count) { volatile cdkasy_t *ap; volatile cdkhdr_t *hdrp; @@ -1555,8 +1555,8 @@ static int stli_write(struct tty_struct *tty, int from_user, const unsigned char unsigned long flags; #ifdef DEBUG - printk("stli_write(tty=%x,from_user=%d,buf=%x,count=%d)\n", - (int) tty, from_user, (int) buf, count); + printk("stli_write(tty=%x,buf=%x,count=%d)\n", + (int) tty, (int) buf, count); #endif if ((tty == (struct tty_struct *) NULL) || @@ -1574,38 +1574,6 @@ static int stli_write(struct tty_struct *tty, int from_user, const unsigned char return(0); chbuf = (unsigned char *) buf; -/* - * If copying direct from user space we need to be able to handle page - * faults while we are copying. To do this copy as much as we can now - * into a kernel buffer. From there we copy it into shared memory. The - * big problem is that we do not want shared memory enabled when we are - * sleeping (other boards may be serviced while asleep). Something else - * to note here is the reading of the tail twice. Since the boards - * shared memory can be on an 8-bit bus then we need to be very careful - * reading 16 bit quantities - since both the board (slave) and host - * could be writing and reading at the same time. - */ - if (from_user) { - save_flags(flags); - cli(); - EBRDENABLE(brdp); - ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr); - head = (unsigned int) ap->txq.head; - tail = (unsigned int) ap->txq.tail; - if (tail != ((unsigned int) ap->txq.tail)) - tail = (unsigned int) ap->txq.tail; - len = (head >= tail) ? (portp->txsize - (head - tail) - 1) : - (tail - head - 1); - count = MIN(len, count); - EBRDDISABLE(brdp); - restore_flags(flags); - - down(&stli_tmpwritesem); - if (copy_from_user(stli_tmpwritebuf, chbuf, count)) - return -EFAULT; - chbuf = &stli_tmpwritebuf[0]; - } - /* * All data is now local, shove as much as possible into shared memory. */ @@ -1656,8 +1624,6 @@ static int stli_write(struct tty_struct *tty, int from_user, const unsigned char set_bit(ST_TXBUSY, &portp->state); EBRDDISABLE(brdp); - if (from_user) - up(&stli_tmpwritesem); restore_flags(flags); return(count); diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index b0bedbbdaf9b..63ae225c6296 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c @@ -222,7 +222,7 @@ static struct semaphore moxaBuffSem; static void do_moxa_softint(void *); static int moxa_open(struct tty_struct *, struct file *); static void moxa_close(struct tty_struct *, struct file *); -static int moxa_write(struct tty_struct *, int, const unsigned char *, int); +static int moxa_write(struct tty_struct *, const unsigned char *, int); static int moxa_write_room(struct tty_struct *); static void moxa_flush_buffer(struct tty_struct *); static int moxa_chars_in_buffer(struct tty_struct *); @@ -632,7 +632,7 @@ static void moxa_close(struct tty_struct *tty, struct file *filp) wake_up_interruptible(&ch->close_wait); } -static int moxa_write(struct tty_struct *tty, int from_user, +static int moxa_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct moxa_str *ch; @@ -644,25 +644,9 @@ static int moxa_write(struct tty_struct *tty, int from_user, return (0); port = ch->port; save_flags(flags); - if (from_user) { - if (count > PAGE_SIZE) - count = PAGE_SIZE; - down(&moxaBuffSem); - if (copy_from_user(moxaXmitBuff, buf, count)) { - len = -EFAULT; - } else { - cli(); - len = MoxaPortWriteData(port, moxaXmitBuff, count); - restore_flags(flags); - } - up(&moxaBuffSem); - if (len < 0) - return len; - } else { - cli(); - len = MoxaPortWriteData(port, (unsigned char *) buf, count); - restore_flags(flags); - } + cli(); + len = MoxaPortWriteData(port, (unsigned char *) buf, count); + restore_flags(flags); /********************************************* if ( !(ch->statusflags & LOWWAIT) && diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 9ed493ed2220..7879e964741f 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -332,7 +332,7 @@ static int mxser_get_ISA_conf(int, struct mxser_hwconf *); static void mxser_do_softint(void *); static int mxser_open(struct tty_struct *, struct file *); static void mxser_close(struct tty_struct *, struct file *); -static int mxser_write(struct tty_struct *, int, const unsigned char *, int); +static int mxser_write(struct tty_struct *, const unsigned char *, int); static int mxser_write_room(struct tty_struct *); static void mxser_flush_buffer(struct tty_struct *); static int mxser_chars_in_buffer(struct tty_struct *); @@ -829,7 +829,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) } -static int mxser_write(struct tty_struct *tty, int from_user, +static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) { int c, total = 0; @@ -840,53 +840,23 @@ static int mxser_write(struct tty_struct *tty, int from_user, return (0); save_flags(flags); - if (from_user) { - down(&mxvar_tmp_buf_sem); - while (1) { - c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) - break; - - c -= copy_from_user(mxvar_tmp_buf, buf, c); - if (!c) { - if (!total) - total = -EFAULT; - break; - } - - cli(); - c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, mxvar_tmp_buf, c); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1); - info->xmit_cnt += c; + while (1) { + cli(); + c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { restore_flags(flags); - - buf += c; - count -= c; - total += c; + break; } - up(&mxvar_tmp_buf_sem); - } else { - while (1) { - cli(); - c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) { - restore_flags(flags); - break; - } - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1); - info->xmit_cnt += c; - restore_flags(flags); + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1); + info->xmit_cnt += c; + restore_flags(flags); - buf += c; - count -= c; - total += c; - } + buf += c; + count -= c; + total += c; } cli(); diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index 0a684d8cc112..d60627b34323 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c @@ -184,7 +184,7 @@ static ssize_t maxframe = 4096; static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, __u8 __user *buf, size_t nr); static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, - const __u8 __user *buf, size_t nr); + const unsigned char *buf, size_t nr); static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, @@ -402,7 +402,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) /* Send the next block of data to device */ tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); - actual = tty->driver->write(tty, 0, tbuf->buf, tbuf->count); + actual = tty->driver->write(tty, tbuf->buf, tbuf->count); /* if transmit error, throw frame away by */ /* pretending it was accepted by driver */ @@ -649,7 +649,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, * Returns the number of bytes written (or error code). */ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, - const __u8 __user *data, size_t count) + const unsigned char *data, size_t count) { struct n_hdlc *n_hdlc = tty2n_hdlc (tty); int error = 0; @@ -704,16 +704,12 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, if (!error) { /* Retrieve the user's buffer */ - if (copy_from_user(tbuf->buf, data, count)) { - /* return tx buffer to free list */ - n_hdlc_buf_put(&n_hdlc->tx_free_buf_list,tbuf); - error = -EFAULT; - } else { - /* Send the data */ - tbuf->count = error = count; - n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf); - n_hdlc_send_frames(n_hdlc,tty); - } + memcpy(tbuf->buf, data, count); + + /* Send the data */ + tbuf->count = error = count; + n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf); + n_hdlc_send_frames(n_hdlc,tty); } return error; diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index e24b7efafadc..3883073ab48f 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c @@ -139,7 +139,7 @@ static void r3964_close(struct tty_struct *tty); static ssize_t r3964_read(struct tty_struct *tty, struct file *file, unsigned char __user *buf, size_t nr); static ssize_t r3964_write(struct tty_struct * tty, struct file * file, - const unsigned char __user * buf, size_t nr); + const unsigned char * buf, size_t nr); static int r3964_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg); static void r3964_set_termios(struct tty_struct *tty, struct termios * old); @@ -1246,13 +1246,12 @@ repeat: } static ssize_t r3964_write(struct tty_struct * tty, struct file * file, - const unsigned char __user *data, size_t count) + const unsigned char *data, size_t count) { struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; struct r3964_block_header *pHeader; struct r3964_client_info *pClient; unsigned char *new_data; - int status; int pid; TRACE_L("write request, %d characters", count); @@ -1263,12 +1262,6 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file, if(!pInfo) return -EIO; - status = verify_area (VERIFY_READ, data, count); - if (status != 0) - { - return status; - } - /* * Ensure that the caller does not wish to send too much. */ @@ -1283,7 +1276,7 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file, count = R3964_MTU; } /* - * Allocate a buffer for the data and fetch it from the user space. + * Allocate a buffer for the data and copy it from the buffer with header prepended */ new_data = kmalloc (count+sizeof(struct r3964_block_header), GFP_KERNEL); TRACE_M("r3964_write - kmalloc %x",(int)new_data); @@ -1310,7 +1303,7 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file, pHeader->owner = pClient; } - __copy_from_user(pHeader->data, data, count); /* We already verified this */ + memcpy(pHeader->data, data, count); /* We already verified this */ if(pInfo->flags & R3964_DEBUG) { diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 3bca97c2ae45..a29dffd9408e 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -270,7 +270,7 @@ static int opost(unsigned char c, struct tty_struct *tty) if (space < spaces) return -1; tty->column += spaces; - tty->driver->write(tty, 0, " ", spaces); + tty->driver->write(tty, " ", spaces); return 0; } tty->column += spaces; @@ -306,12 +306,11 @@ static int opost(unsigned char c, struct tty_struct *tty) */ static ssize_t opost_block(struct tty_struct * tty, - const unsigned char __user * inbuf, unsigned int nr) + const unsigned char * buf, unsigned int nr) { - char buf[80]; int space; int i; - char *cp; + const unsigned char *cp; space = tty->driver->write_room(tty); if (!space) @@ -321,9 +320,6 @@ static ssize_t opost_block(struct tty_struct * tty, if (nr > sizeof(buf)) nr = sizeof(buf); - if (copy_from_user(buf, inbuf, nr)) - return -EFAULT; - for (i = 0, cp = buf; i < nr; i++, cp++) { switch (*cp) { case '\n': @@ -336,12 +332,8 @@ static ssize_t opost_block(struct tty_struct * tty, case '\r': if (O_ONOCR(tty) && tty->column == 0) goto break_out; - if (O_OCRNL(tty)) { - *cp = '\n'; - if (O_ONLRET(tty)) - tty->canon_column = tty->column = 0; - break; - } + if (O_OCRNL(tty)) + goto break_out; tty->canon_column = tty->column = 0; break; case '\t': @@ -352,7 +344,7 @@ static ssize_t opost_block(struct tty_struct * tty, break; default: if (O_OLCUC(tty)) - *cp = toupper(*cp); + goto break_out; if (!iscntrl(*cp)) tty->column++; break; @@ -361,7 +353,7 @@ static ssize_t opost_block(struct tty_struct * tty, break_out: if (tty->driver->flush_chars) tty->driver->flush_chars(tty); - i = tty->driver->write(tty, 0, buf, i); + i = tty->driver->write(tty, buf, i); return i; } @@ -1435,9 +1427,9 @@ do_it_again: */ static ssize_t write_chan(struct tty_struct * tty, struct file * file, - const unsigned char __user * buf, size_t nr) + const unsigned char * buf, size_t nr) { - const unsigned char __user *b = buf; + const unsigned char *b = buf; DECLARE_WAITQUEUE(wait, current); int c; ssize_t retval = 0; @@ -1473,7 +1465,7 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file, nr -= num; if (nr == 0) break; - get_user(c, b); + c = *b; if (opost(c, tty) < 0) break; b++; nr--; @@ -1481,7 +1473,7 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file, if (tty->driver->flush_chars) tty->driver->flush_chars(tty); } else { - c = tty->driver->write(tty, 1, b, nr); + c = tty->driver->write(tty, b, nr); if (c < 0) { retval = c; goto break_out; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 522de1ec92c4..4d2cfa1778d0 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -1744,16 +1744,15 @@ static void mgslpc_flush_chars(struct tty_struct *tty) * Arguments: * * tty pointer to tty information structure - * from_user flag: 1 = from user process * buf pointer to buffer containing send data * count size of send data in bytes * * Returns: number of characters written */ -static int mgslpc_write(struct tty_struct * tty, int from_user, +static int mgslpc_write(struct tty_struct * tty, const unsigned char *buf, int count) { - int c, ret = 0, err; + int c, ret = 0; MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; unsigned long flags; @@ -1783,15 +1782,7 @@ static int mgslpc_write(struct tty_struct * tty, int from_user, if (c <= 0) break; - if (from_user) { - COPY_FROM_USER(err, info->tx_buf + info->tx_put, buf, c); - if (err) { - if (!ret) - ret = -EFAULT; - break; - } - } else - memcpy(info->tx_buf + info->tx_put, buf, c); + memcpy(info->tx_buf + info->tx_put, buf, c); spin_lock_irqsave(&info->lock,flags); info->tx_put = (info->tx_put + c) & (TXBUFSIZE-1); diff --git a/drivers/char/pcxx.c b/drivers/char/pcxx.c index d489a1322e0d..5a69b373b4b1 100644 --- a/drivers/char/pcxx.c +++ b/drivers/char/pcxx.c @@ -570,7 +570,7 @@ void pcxe_hangup(struct tty_struct *tty) -static int pcxe_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) +static int pcxe_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct channel *ch; volatile struct board_chan *bc; @@ -585,33 +585,6 @@ static int pcxe_write(struct tty_struct * tty, int from_user, const unsigned cha bc = ch->brdchan; size = ch->txbufsize; - if (from_user) { - - down(&ch->tmp_buf_sem); - save_flags(flags); - cli(); - globalwinon(ch); - head = bc->tin & (size - 1); - /* It seems to be necessary to make sure that the value is stable here somehow - This is a rather odd pice of code here. */ - do - { - tail = bc->tout; - } while (tail != bc->tout); - - tail &= (size - 1); - stlen = (head >= tail) ? (size - (head - tail) - 1) : (tail - head - 1); - count = min(stlen, count); - memoff(ch); - restore_flags(flags); - - if (count) - if (copy_from_user(ch->tmp_buf, buf, count)) - count = 0; - - buf = ch->tmp_buf; - } - /* * All data is now local */ @@ -658,9 +631,6 @@ static int pcxe_write(struct tty_struct * tty, int from_user, const unsigned cha memoff(ch); restore_flags(flags); - if(from_user) - up(&ch->tmp_buf_sem); - return(total); } diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 2e0eda2d40bf..92a13643812c 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -103,51 +103,18 @@ static void pty_unthrottle(struct tty_struct * tty) * not our partners. We can't just take the other one blindly without * risking deadlocks. There is also the small matter of TTY_DONT_FLIP */ -static int pty_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count) +static int pty_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct tty_struct *to = tty->link; - int c=0, n, room; - char *temp_buffer; + int c; if (!to || tty->stopped) return 0; - if (from_user) { - down(&tty->flip.pty_sem); - temp_buffer = &tty->flip.char_buf[0]; - while (count > 0) { - /* check space so we don't copy needlessly */ - n = to->ldisc.receive_room(to); - if (n > count) - n = count; - if (!n) break; - - n = min(n, PTY_BUF_SIZE); - n -= copy_from_user(temp_buffer, buf, n); - if (!n) { - if (!c) - c = -EFAULT; - break; - } - - /* check again in case the buffer filled up */ - room = to->ldisc.receive_room(to); - if (n > room) - n = room; - if (!n) break; - buf += n; - c += n; - count -= n; - to->ldisc.receive_buf(to, temp_buffer, NULL, n); - } - up(&tty->flip.pty_sem); - } else { - c = to->ldisc.receive_room(to); - if (c > count) - c = count; - to->ldisc.receive_buf(to, buf, NULL, c); - } + c = to->ldisc.receive_room(to); + if (c > count) + c = count; + to->ldisc.receive_buf(to, buf, NULL, c); return c; } diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 616ecc65a06b..55a3a0188eda 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -1139,7 +1139,7 @@ static void rc_close(struct tty_struct * tty, struct file * filp) out: restore_flags(flags); } -static int rc_write(struct tty_struct * tty, int from_user, +static int rc_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct riscom_port *port = (struct riscom_port *)tty->driver_data; @@ -1156,54 +1156,23 @@ static int rc_write(struct tty_struct * tty, int from_user, return 0; save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - cli(); - c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!total) - total = -EFAULT; - break; - } - - cli(); - c = min_t(int, c, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c); - port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - port->xmit_cnt += c; + while (1) { + cli(); + c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, + SERIAL_XMIT_SIZE - port->xmit_head)); + if (c <= 0) { restore_flags(flags); - - buf += c; - count -= c; - total += c; + break; } - up(&tmp_buf_sem); - } else { - while (1) { - cli(); - c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - 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; - restore_flags(flags); + memcpy(port->xmit_buf + port->xmit_head, buf, c); + port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + port->xmit_cnt += c; + restore_flags(flags); - buf += c; - count -= c; - total += c; - } + buf += c; + count -= c; + total += c; } cli(); diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 4a0840ed50c9..8b4c3107c219 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -1633,7 +1633,7 @@ static void rp_put_char(struct tty_struct *tty, unsigned char ch) * or get control of the CPU if the copy_from_user() blocks due to a page fault (swapped out). * Spinlocks protect the info xmit members. */ -static int rp_write(struct tty_struct *tty, int from_user, +static int rp_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct r_port *info = (struct r_port *) tty->driver_data; @@ -1662,16 +1662,6 @@ static int rp_write(struct tty_struct *tty, int from_user, if (!tty->stopped && !tty->hw_stopped && info->xmit_cnt == 0 && info->xmit_fifo_room > 0) { c = min(count, info->xmit_fifo_room); b = buf; - if (from_user) { - if (copy_from_user(info->xmit_buf, buf, c)) { - retval = -EFAULT; - goto end; - } - if (info->tty == 0) - goto end; - b = info->xmit_buf; - c = min(c, info->xmit_fifo_room); - } /* Push data into FIFO, 2 bytes at a time */ sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) b, c / 2); @@ -1703,14 +1693,7 @@ static int rp_write(struct tty_struct *tty, int from_user, break; b = buf; - if (from_user) { - if (copy_from_user(info->xmit_buf + info->xmit_head, b, c)) { - retval = -EFAULT; - goto end_intr; - } else { - memcpy(info->xmit_buf + info->xmit_head, b, c); - } - } + memcpy(info->xmit_buf + info->xmit_head, b, c); spin_lock_irqsave(&info->slock, flags); info->xmit_head = @@ -1723,7 +1706,6 @@ static int rp_write(struct tty_struct *tty, int from_user, retval += c; } -end_intr: if ((retval > 0) && !tty->stopped && !tty->hw_stopped) set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 028044f79045..9f94dbf8c492 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -1208,7 +1208,7 @@ cy_flush_chars(struct tty_struct *tty) port is already active, there is no need to kick it. */ static int -cy_write(struct tty_struct * tty, int from_user, +cy_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; @@ -1227,53 +1227,23 @@ cy_write(struct tty_struct * tty, int from_user, return 0; } - if (from_user) { - down(&tmp_buf_sem); - while (1) { - c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!total) - total = -EFAULT; - break; - } - - local_irq_save(flags); - c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt += c; + while (1) { + local_irq_save(flags); + c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { local_irq_restore(flags); - - buf += c; - count -= c; - total += c; + break; } - up(&tmp_buf_sem); - } else { - while (1) { - local_irq_save(flags); - c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) { - local_irq_restore(flags); - break; - } - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt += c; - local_irq_restore(flags); + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt += c; + local_irq_restore(flags); - buf += c; - count -= c; - total += c; - } + buf += c; + count -= c; + total += c; } if (info->xmit_cnt diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 568edc38313c..b7baa5a5f3f9 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -1479,7 +1479,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp) } -static int sx_write(struct tty_struct * tty, int from_user, +static int sx_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; @@ -1496,52 +1496,22 @@ static int sx_write(struct tty_struct * tty, int from_user, return 0; save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!total) - total = -EFAULT; - break; - } - - cli(); - c = min_t(int, c, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c); - port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - port->xmit_cnt += c; + while (1) { + cli(); + c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, + SERIAL_XMIT_SIZE - port->xmit_head)); + if (c <= 0) { restore_flags(flags); - - buf += c; - count -= c; - total += c; + break; } - up(&tmp_buf_sem); - } else { - while (1) { - cli(); - c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - 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; - restore_flags(flags); + memcpy(port->xmit_buf + port->xmit_head, buf, c); + port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + port->xmit_cnt += c; + restore_flags(flags); - buf += c; - count -= c; - total += c; - } + buf += c; + count -= c; + total += c; } cli(); diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 38a7e846b813..9a204da53446 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -482,7 +482,7 @@ static unsigned long stl_atol(char *str); int stl_init(void); static int stl_open(struct tty_struct *tty, struct file *filp); static void stl_close(struct tty_struct *tty, struct file *filp); -static int stl_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count); +static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count); static void stl_putchar(struct tty_struct *tty, unsigned char ch); static void stl_flushchars(struct tty_struct *tty); static int stl_writeroom(struct tty_struct *tty); @@ -1220,7 +1220,7 @@ static void stl_close(struct tty_struct *tty, struct file *filp) * If transmit interrupts are not running then start them. */ -static int stl_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count) +static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count) { stlport_t *portp; unsigned int len, stlen; @@ -1228,8 +1228,8 @@ static int stl_write(struct tty_struct *tty, int from_user, const unsigned char char *head, *tail; #ifdef DEBUG - printk("stl_write(tty=%x,from_user=%d,buf=%x,count=%d)\n", - (int) tty, from_user, (int) buf, count); + printk("stl_write(tty=%x,buf=%x,count=%d)\n", + (int) tty, (int) buf, count); #endif if ((tty == (struct tty_struct *) NULL) || @@ -1248,18 +1248,6 @@ static int stl_write(struct tty_struct *tty, int from_user, const unsigned char * copy it into the TX buffer. */ chbuf = (unsigned char *) buf; - if (from_user) { - head = portp->tx.head; - tail = portp->tx.tail; - len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : - (tail - head - 1); - count = MIN(len, count); - - down(&stl_tmpwritesem); - if (copy_from_user(stl_tmpwritebuf, chbuf, count)) - return -EFAULT; - chbuf = &stl_tmpwritebuf[0]; - } head = portp->tx.head; tail = portp->tx.tail; @@ -1290,9 +1278,6 @@ static int stl_write(struct tty_struct *tty, int from_user, const unsigned char clear_bit(ASYI_TXLOW, &portp->istate); stl_startrxtx(portp, -1, 1); - if (from_user) - up(&stl_tmpwritesem); - return(count); } diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 84224b99353f..af505edc1146 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -2140,16 +2140,15 @@ static void mgsl_flush_chars(struct tty_struct *tty) * Arguments: * * tty pointer to tty information structure - * from_user flag: 1 = from user process * buf pointer to buffer containing send data * count size of send data in bytes * * Return Value: number of characters written */ -static int mgsl_write(struct tty_struct * tty, int from_user, +static int mgsl_write(struct tty_struct * tty, const unsigned char *buf, int count) { - int c, ret = 0, err; + int c, ret = 0; struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; unsigned long flags; @@ -2186,20 +2185,7 @@ static int mgsl_write(struct tty_struct * tty, int from_user, /* queue transmit frame request */ ret = count; - if (from_user) { - down(&tmp_buf_sem); - COPY_FROM_USER(err,tmp_buf, buf, count); - if (err) { - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):mgsl_write(%s) sync user buf copy failed\n", - __FILE__,__LINE__,info->device_name); - ret = -EFAULT; - } else - save_tx_buffer_request(info,tmp_buf,count); - up(&tmp_buf_sem); - } - else - save_tx_buffer_request(info,buf,count); + save_tx_buffer_request(info,buf,count); /* if we have sufficient tx dma buffers, * load the next buffered tx request @@ -2239,70 +2225,26 @@ static int mgsl_write(struct tty_struct * tty, int from_user, __FILE__,__LINE__,info->device_name); ret = count; info->xmit_cnt = count; - if (from_user) { - down(&tmp_buf_sem); - COPY_FROM_USER(err,tmp_buf, buf, count); - if (err) { - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):mgsl_write(%s) sync user buf copy failed\n", - __FILE__,__LINE__,info->device_name); - ret = -EFAULT; - } else - mgsl_load_tx_dma_buffer(info,tmp_buf,count); - up(&tmp_buf_sem); - } - else - mgsl_load_tx_dma_buffer(info,buf,count); + mgsl_load_tx_dma_buffer(info,buf,count); } } else { - if (from_user) { - down(&tmp_buf_sem); - while (1) { - c = min_t(int, count, - min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) - break; - - COPY_FROM_USER(err,tmp_buf, buf, c); - c -= err; - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - spin_lock_irqsave(&info->irq_spinlock,flags); - c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - info->xmit_head = ((info->xmit_head + c) & - (SERIAL_XMIT_SIZE-1)); - info->xmit_cnt += c; - spin_unlock_irqrestore(&info->irq_spinlock,flags); - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - while (1) { - spin_lock_irqsave(&info->irq_spinlock,flags); - c = min_t(int, count, - min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) { - spin_unlock_irqrestore(&info->irq_spinlock,flags); - break; - } - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = ((info->xmit_head + c) & - (SERIAL_XMIT_SIZE-1)); - info->xmit_cnt += c; + while (1) { + spin_lock_irqsave(&info->irq_spinlock,flags); + c = min_t(int, count, + min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { spin_unlock_irqrestore(&info->irq_spinlock,flags); - buf += c; - count -= c; - ret += c; + break; } + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = ((info->xmit_head + c) & + (SERIAL_XMIT_SIZE-1)); + info->xmit_cnt += c; + spin_unlock_irqrestore(&info->irq_spinlock,flags); + buf += c; + count -= c; + ret += c; } } diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index cb4de2ebb15e..841c26a815d2 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -521,7 +521,7 @@ static void close(struct tty_struct *tty, struct file * filp); static void hangup(struct tty_struct *tty); static void set_termios(struct tty_struct *tty, struct termios *old_termios); -static int write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count); +static int write(struct tty_struct *tty, const unsigned char *buf, int count); static void put_char(struct tty_struct *tty, unsigned char ch); static void send_xchar(struct tty_struct *tty, char ch); static void wait_until_sent(struct tty_struct *tty, int timeout); @@ -971,16 +971,15 @@ static void set_termios(struct tty_struct *tty, struct termios *old_termios) * Arguments: * * tty pointer to tty information structure - * from_user flag: 1 = from user process * buf pointer to buffer containing send data * count size of send data in bytes * * Return Value: number of characters written */ -static int write(struct tty_struct *tty, int from_user, +static int write(struct tty_struct *tty, const unsigned char *buf, int count) { - int c, ret = 0, err; + int c, ret = 0; SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; unsigned long flags; @@ -1007,11 +1006,9 @@ static int write(struct tty_struct *tty, int from_user, tx_load_dma_buffer(info, info->tx_buf, info->tx_count); goto start; } - if (!from_user) { - ret = info->tx_count = count; - tx_load_dma_buffer(info, buf, count); - goto start; - } + ret = info->tx_count = count; + tx_load_dma_buffer(info, buf, count); + goto start; } for (;;) { @@ -1021,15 +1018,7 @@ static int write(struct tty_struct *tty, int from_user, if (c <= 0) break; - if (from_user) { - COPY_FROM_USER(err, info->tx_buf + info->tx_put, buf, c); - if (err) { - if (!ret) - ret = -EFAULT; - break; - } - } else - memcpy(info->tx_buf + info->tx_put, buf, c); + memcpy(info->tx_buf + info->tx_put, buf, c); spin_lock_irqsave(&info->lock,flags); info->tx_put += c; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index b27ae629e6e2..0b6a0b5fe6f4 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -168,6 +168,8 @@ static struct tty_struct *alloc_tty_struct(void) static inline void free_tty_struct(struct tty_struct *tty) { + if (tty->write_buf) + kfree(tty->write_buf); kfree(tty); } @@ -1019,41 +1021,71 @@ static ssize_t tty_read(struct file * file, char __user * buf, size_t count, * denial-of-service type attacks */ static inline ssize_t do_tty_write( - ssize_t (*write)(struct tty_struct *, struct file *, const unsigned char __user *, size_t), + ssize_t (*write)(struct tty_struct *, struct file *, const unsigned char *, size_t), struct tty_struct *tty, struct file *file, - const unsigned char __user *buf, + const char __user *buf, size_t count) { ssize_t ret = 0, written = 0; + unsigned int chunk; if (down_interruptible(&tty->atomic_write)) { return -ERESTARTSYS; } - if ( test_bit(TTY_NO_WRITE_SPLIT, &tty->flags) ) { + + /* + * We chunk up writes into a temporary buffer. This + * simplifies low-level drivers immensely, since they + * don't have locking issues and user mode accesses. + * + * But if TTY_NO_WRITE_SPLIT is set, we should use a + * big chunk-size.. + */ + chunk = 4096; + if (test_bit(TTY_NO_WRITE_SPLIT, &tty->flags)) + chunk = 65536; + if (count < chunk) + chunk = count; + + /* write_buf/write_cnt is protected by the atomic_write semaphore */ + if (tty->write_cnt < chunk) { + unsigned char *buf; + + if (chunk < 1024) + chunk = 1024; + + buf = kmalloc(chunk, GFP_KERNEL); + if (!buf) { + up(&tty->atomic_write); + return -ENOMEM; + } + tty->write_cnt = chunk; + tty->write_buf = buf; + } + + /* Do the write .. */ + for (;;) { + size_t size = count; + if (size > chunk) + size = chunk; + ret = -EFAULT; + if (copy_from_user(tty->write_buf, buf, size)) + break; lock_kernel(); - written = write(tty, file, buf, count); + ret = write(tty, file, tty->write_buf, size); unlock_kernel(); - } else { - for (;;) { - unsigned long size = max((unsigned long)PAGE_SIZE*2, 16384UL); - if (size > count) - size = count; - lock_kernel(); - ret = write(tty, file, buf, size); - unlock_kernel(); - if (ret <= 0) - break; - written += ret; - buf += ret; - count -= ret; - if (!count) - break; - ret = -ERESTARTSYS; - if (signal_pending(current)) - break; - cond_resched(); - } + if (ret <= 0) + break; + written += ret; + buf += ret; + count -= ret; + if (!count) + break; + ret = -ERESTARTSYS; + if (signal_pending(current)) + break; + cond_resched(); } if (written) { file->f_dentry->d_inode->i_mtime = CURRENT_TIME; @@ -1082,8 +1114,7 @@ static ssize_t tty_write(struct file * file, const char __user * buf, size_t cou if (!ld->write) ret = -EIO; else - ret = do_tty_write(ld->write, tty, file, - (const unsigned char __user *)buf, count); + ret = do_tty_write(ld->write, tty, file, buf, count); tty_ldisc_deref(ld); return ret; } @@ -2618,7 +2649,7 @@ static void initialize_tty_struct(struct tty_struct *tty) */ static void tty_default_put_char(struct tty_struct *tty, unsigned char ch) { - tty->driver->write(tty, 0, &ch, 1); + tty->driver->write(tty, &ch, 1); } static struct class_simple *tty_class; diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index d1060b2d5579..7145057e0a48 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -382,7 +382,7 @@ void send_prio_char(struct tty_struct *tty, char ch) } if (was_stopped) start_tty(tty); - tty->driver->write(tty, 0, &ch, 1); + tty->driver->write(tty, &ch, 1); if (was_stopped) stop_tty(tty); } diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c index dcfcef4be160..f0e7b03947e8 100644 --- a/drivers/char/viocons.c +++ b/drivers/char/viocons.c @@ -721,7 +721,7 @@ static void viotty_close(struct tty_struct *tty, struct file *filp) /* * TTY Write method */ -static int viotty_write(struct tty_struct *tty, int from_user, +static int viotty_write(struct tty_struct *tty, const unsigned char *buf, int count) { int ret; @@ -754,44 +754,7 @@ static int viotty_write(struct tty_struct *tty, int from_user, return count; } - /* - * If the viotty_write is invoked from user space we want to do the - * copy_from_user() into an event buffer from the cfu buffer before - * internal_write() is called because internal_write may need to buffer - * data which will need to grab a spin_lock and we shouldn't - * copy_from_user() while holding a spin_lock. Should internal_write() - * not need to buffer data then it'll just use the event we created here - * rather than checking one out from vio_get_event_buffer(). - */ - if (from_user) { - struct viocharlpevent *viochar; - int curlen; - const char *curbuf = buf; - - viochar = viocons_get_cfu_buffer(); - if (viochar == NULL) - return -EAGAIN; - initDataEvent(viochar, pi->lp); - while (count > 0) { - if (count > VIOCHAR_MAX_DATA) - curlen = VIOCHAR_MAX_DATA; - else - curlen = count; - viochar->len = curlen; - ret = copy_from_user(viochar->data, curbuf, curlen); - if (ret) - break; - ret = internal_write(pi, viochar->data, - viochar->len, viochar); - total += ret; - if (ret != curlen) - break; - count -= curlen; - curbuf += curlen; - } - viocons_free_cfu_buffer(viochar); - } else - total = internal_write(pi, buf, count, NULL); + total = internal_write(pi, buf, count, NULL); return total; } diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 185d19ab1214..f3d3698174dc 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -1889,8 +1889,7 @@ char con_buf[CON_BUF_SIZE]; DECLARE_MUTEX(con_buf_sem); /* acquires console_sem */ -static int do_con_write(struct tty_struct *tty, int from_user, - const unsigned char *buf, int count) +static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count) { #ifdef VT_BUF_VRAM_ONLY #define FLUSH do { } while(0); @@ -1938,22 +1937,6 @@ static int do_con_write(struct tty_struct *tty, int from_user, orig_buf = buf; orig_count = count; - if (from_user) { - - down(&con_buf_sem); - -again: - if (count > CON_BUF_SIZE) - count = CON_BUF_SIZE; - console_conditional_schedule(); - if (copy_from_user(con_buf, buf, count)) { - n = 0; /* ?? are error codes legal here ?? */ - goto out; - } - - buf = con_buf; - } - /* At this point 'buf' is guaranteed to be a kernel buffer * and therefore no access to userspace (and therefore sleeping) * will be needed. The con_buf_sem serializes all tty based @@ -2094,22 +2077,6 @@ again: release_console_sem(); out: - if (from_user) { - /* If the user requested something larger than - * the CON_BUF_SIZE, and the tty is not stopped, - * keep going. - */ - if ((orig_count > CON_BUF_SIZE) && !tty->stopped) { - orig_count -= CON_BUF_SIZE; - orig_buf += CON_BUF_SIZE; - count = orig_count; - buf = orig_buf; - goto again; - } - - up(&con_buf_sem); - } - return n; #undef FLUSH } @@ -2382,13 +2349,12 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) * /dev/ttyN handling */ -static int con_write(struct tty_struct *tty, int from_user, - const unsigned char *buf, int count) +static int con_write(struct tty_struct *tty, const unsigned char *buf, int count) { int retval; pm_access(pm_con); - retval = do_con_write(tty, from_user, buf, count); + retval = do_con_write(tty, buf, count); con_flush_chars(tty); return retval; @@ -2399,7 +2365,7 @@ static void con_put_char(struct tty_struct *tty, unsigned char ch) if (in_interrupt()) return; /* n_r3964 calls put_char() from interrupt context */ pm_access(pm_con); - do_con_write(tty, 0, &ch, 1); + do_con_write(tty, &ch, 1); } static int con_write_room(struct tty_struct *tty) diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 5582ee8227d5..4a8b7b72c48f 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c @@ -42,7 +42,7 @@ struct serport { static int serport_serio_write(struct serio *serio, unsigned char data) { struct serport *serport = serio->port_data; - return -(serport->tty->driver->write(serport->tty, 0, &data, 1) != 1); + return -(serport->tty->driver->write(serport->tty, &data, 1) != 1); } static void serport_serio_close(struct serio *serio) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 9370808bb328..4192b34b52e9 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -1044,16 +1044,14 @@ static void capinc_tty_close(struct tty_struct * tty, struct file * file) #endif } -static int capinc_tty_write(struct tty_struct * tty, int from_user, +static int capinc_tty_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct capiminor *mp = (struct capiminor *)tty->driver_data; struct sk_buff *skb; - int retval; #ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_write(from_user=%d,count=%d)\n", - from_user, count); + printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count); #endif if (!mp || !mp->nccip) { @@ -1077,18 +1075,7 @@ static int capinc_tty_write(struct tty_struct * tty, int from_user, } skb_reserve(skb, CAPI_DATA_B3_REQ_LEN); - if (from_user) { - retval = copy_from_user(skb_put(skb, count), buf, count); - if (retval) { - kfree_skb(skb); -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_write: copy_from_user=%d\n", retval); -#endif - return -EFAULT; - } - } else { - memcpy(skb_put(skb, count), buf, count); - } + memcpy(skb_put(skb, count), buf, count); skb_queue_tail(&mp->outqueue, skb); mp->outbytes += skb->len; diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 6b6d839930f1..e21007eca0f0 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -27,8 +27,8 @@ /* Prototypes */ -static int isdn_tty_edit_at(const char *, int, modem_info *, int); -static void isdn_tty_check_esc(const u_char *, u_char, int, int *, u_long *, int); +static int isdn_tty_edit_at(const char *, int, modem_info *); +static void isdn_tty_check_esc(const u_char *, u_char, int, int *, u_long *); static void isdn_tty_modem_reset_regs(modem_info *, int); static void isdn_tty_cmd_ATA(modem_info *); static void isdn_tty_flush_buffer(struct tty_struct *); @@ -391,15 +391,12 @@ isdn_tty_handleDLEdown(modem_info * info, atemu * m, int len) * ^S or ^Q is sent. */ static int -isdn_tty_end_vrx(const char *buf, int c, int from_user) +isdn_tty_end_vrx(const char *buf, int c) { char ch; while (c--) { - if (from_user) - get_user(ch, buf); - else - ch = *buf; + ch = *buf; if ((ch != 0x11) && (ch != 0x13)) return 1; buf++; @@ -1127,7 +1124,7 @@ isdn_tty_shutdown(modem_info * info) * - If dialing, abort dial. */ static int -isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int count) +isdn_tty_write(struct tty_struct *tty, const u_char * buf, int count) { int c; int total = 0; @@ -1136,8 +1133,6 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_write")) return 0; - if (from_user) - down(&info->write_sem); /* See isdn_tty_senddown() */ atomic_inc(&info->xmit_lock); while (1) { @@ -1158,12 +1153,8 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co #endif isdn_tty_check_esc(buf, m->mdmreg[REG_ESC], c, &(m->pluscount), - &(m->lastplus), - from_user); - if (from_user) - copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c); - else - memcpy(&(info->xmit_buf[info->xmit_count]), buf, c); + &(m->lastplus)); + memcpy(&(info->xmit_buf[info->xmit_count]), buf, c); #ifdef CONFIG_ISDN_AUDIO if (info->vonline) { int cc = isdn_tty_handleDLEdown(info, m, c); @@ -1182,7 +1173,7 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co /* Do NOT handle Ctrl-Q or Ctrl-S * when in full-duplex audio mode. */ - if (isdn_tty_end_vrx(buf, c, from_user)) { + if (isdn_tty_end_vrx(buf, c)) { info->vonline &= ~1; #ifdef ISDN_DEBUG_MODEM_VOICE printk(KERN_DEBUG @@ -1225,7 +1216,7 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co isdn_tty_modem_result(RESULT_NO_CARRIER, info); isdn_tty_modem_hup(info, 1); } else - c = isdn_tty_edit_at(buf, c, info, from_user); + c = isdn_tty_edit_at(buf, c, info); } buf += c; count -= c; @@ -1239,8 +1230,6 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co } isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1); } - if (from_user) - up(&info->write_sem); return total; } @@ -2467,10 +2456,8 @@ isdn_tty_off_hook(void) */ static void isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount, - u_long *lastplus, int from_user) + u_long *lastplus) { - char cbuf[3]; - if (plus > 127) return; if (count > 3) { @@ -2478,10 +2465,6 @@ isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount, count = 3; *pluscount = 0; } - if (from_user) { - copy_from_user(cbuf, p, count); - p = cbuf; - } while (count > 0) { if (*(p++) == plus) { if ((*pluscount)++) { @@ -3761,10 +3744,9 @@ isdn_tty_parse_at(modem_info * info) * p inputbuffer * count length of buffer * channel index to line (minor-device) - * user flag: buffer is in userspace */ static int -isdn_tty_edit_at(const char *p, int count, modem_info * info, int user) +isdn_tty_edit_at(const char *p, int count, modem_info * info) { atemu *m = &info->emu; int total = 0; @@ -3773,10 +3755,7 @@ isdn_tty_edit_at(const char *p, int count, modem_info * info, int user) int cnt; for (cnt = count; cnt > 0; p++, cnt--) { - if (user) - get_user(c, p); - else - c = *p; + c = *p; total++; if (c == m->mdmreg[REG_CR] || c == m->mdmreg[REG_LF]) { /* Separator (CR or LF) */ diff --git a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c index e35a141adaa6..ad0f620f04a0 100644 --- a/drivers/macintosh/macserial.c +++ b/drivers/macintosh/macserial.c @@ -1461,7 +1461,7 @@ static void rs_flush_chars(struct tty_struct *tty) spin_unlock_irqrestore(&info->lock, flags); } -static int rs_write(struct tty_struct * tty, int from_user, +static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) { int c, ret = 0; @@ -1474,51 +1474,22 @@ static int rs_write(struct tty_struct * tty, int from_user, if (!tty || !info->xmit_buf || !tmp_buf) return 0; - if (from_user) { - down(&tmp_buf_sem); - while (1) { - c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - spin_lock_irqsave(&info->lock, flags); - c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - info->xmit_head = ((info->xmit_head + c) & - (SERIAL_XMIT_SIZE-1)); - info->xmit_cnt += c; - spin_unlock_irqrestore(&info->lock, flags); - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - while (1) { - spin_lock_irqsave(&info->lock, flags); - c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) { - spin_unlock_irqrestore(&info->lock, flags); - break; - } - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = ((info->xmit_head + c) & - (SERIAL_XMIT_SIZE-1)); - info->xmit_cnt += c; + while (1) { + spin_lock_irqsave(&info->lock, flags); + c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { spin_unlock_irqrestore(&info->lock, flags); - buf += c; - count -= c; - ret += c; + break; } + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = ((info->xmit_head + c) & + (SERIAL_XMIT_SIZE-1)); + info->xmit_cnt += c; + spin_unlock_irqrestore(&info->lock, flags); + buf += c; + count -= c; + ret += c; } spin_lock_irqsave(&info->lock, flags); if (info->xmit_cnt && !tty->stopped && !info->tx_stopped diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 738cef65b728..85a875239595 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -152,13 +152,13 @@ static void sp_xmit_on_air(unsigned long channel) if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistence)) { sp->led_state = 0x70; - sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1); + sp->tty->driver->write(sp->tty, &sp->led_state, 1); sp->tx_enable = 1; - actual = sp->tty->driver->write(sp->tty, 0, sp->xbuff, sp->status2); + actual = sp->tty->driver->write(sp->tty, sp->xbuff, sp->status2); sp->xleft -= actual; sp->xhead += actual; sp->led_state = 0x60; - sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1); + sp->tty->driver->write(sp->tty, &sp->led_state, 1); sp->status2 = 0; } else sp_start_tx_timer(sp); @@ -229,13 +229,13 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len) */ if (sp->duplex == 1) { sp->led_state = 0x70; - sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1); + sp->tty->driver->write(sp->tty, &sp->led_state, 1); sp->tx_enable = 1; - actual = sp->tty->driver->write(sp->tty, 0, sp->xbuff, count); + actual = sp->tty->driver->write(sp->tty, sp->xbuff, count); sp->xleft = count - actual; sp->xhead = sp->xbuff + actual; sp->led_state = 0x60; - sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1); + sp->tty->driver->write(sp->tty, &sp->led_state, 1); } else { sp->xleft = count; sp->xhead = sp->xbuff; @@ -493,7 +493,7 @@ static void sixpack_write_wakeup(struct tty_struct *tty) } if (sp->tx_enable == 1) { - actual = tty->driver->write(tty, 0, sp->xhead, sp->xleft); + actual = tty->driver->write(tty, sp->xhead, sp->xleft); sp->xleft -= actual; sp->xhead += actual; } @@ -652,8 +652,8 @@ static void resync_tnc(unsigned long channel) /* resync the TNC */ sp->led_state = 0x60; - sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1); - sp->tty->driver->write(sp->tty, 0, &resync_cmd, 1); + sp->tty->driver->write(sp->tty, &sp->led_state, 1); + sp->tty->driver->write(sp->tty, &resync_cmd, 1); /* Start resync timer again -- the TNC might be still absent */ @@ -669,7 +669,7 @@ static inline int tnc_init(struct sixpack *sp) { unsigned char inbyte = 0xe8; - sp->tty->driver->write(sp->tty, 0, &inbyte, 1); + sp->tty->driver->write(sp->tty, &inbyte, 1); del_timer(&sp->resync_t); sp->resync_t.data = (unsigned long) sp; @@ -954,9 +954,9 @@ static void decode_prio_command(unsigned char cmd, struct sixpack *sp) } else { /* output watchdog char if idle */ if ((sp->status2 != 0) && (sp->duplex == 1)) { sp->led_state = 0x70; - sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1); + sp->tty->driver->write(sp->tty, &sp->led_state, 1); sp->tx_enable = 1; - actual = sp->tty->driver->write(sp->tty, 0, sp->xbuff, sp->status2); + actual = sp->tty->driver->write(sp->tty, sp->xbuff, sp->status2); sp->xleft -= actual; sp->xhead += actual; sp->led_state = 0x60; @@ -966,7 +966,7 @@ static void decode_prio_command(unsigned char cmd, struct sixpack *sp) } /* needed to trigger the TNC watchdog */ - sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1); + sp->tty->driver->write(sp->tty, &sp->led_state, 1); /* if the state byte has been received, the TNC is present, so the resync timer can be reset. */ @@ -996,12 +996,12 @@ static void decode_std_command(unsigned char cmd, struct sixpack *sp) if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK) { sp->led_state = 0x68; - sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1); + sp->tty->driver->write(sp->tty, &sp->led_state, 1); } } else { sp->led_state = 0x60; /* fill trailing bytes with zeroes */ - sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1); + sp->tty->driver->write(sp->tty, &sp->led_state, 1); rest = sp->rx_count; if (rest != 0) for (i = rest; i <= 3; i++) diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index d51712a17fd3..334079d28cf8 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -379,7 +379,7 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len) } ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); - actual = ax->tty->driver->write(ax->tty, 0, ax->xbuff, count); + actual = ax->tty->driver->write(ax->tty, ax->xbuff, count); ax->tx_packets++; ax->tx_bytes+=actual; ax->dev->trans_start = jiffies; @@ -411,7 +411,7 @@ static void ax25_write_wakeup(struct tty_struct *tty) return; } - actual = tty->driver->write(tty, 0, ax->xhead, ax->xleft); + actual = tty->driver->write(tty, ax->xhead, ax->xleft); ax->xleft -= actual; ax->xhead += actual; } diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 13b6e627a086..1a7dff9489ea 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -234,7 +234,7 @@ static int irtty_do_write(struct sir_dev *dev, const unsigned char *ptr, size_t } else writelen = len; - return tty->driver->write(tty, 0, ptr, writelen); + return tty->driver->write(tty, ptr, writelen); } /* ------------------------------------------------------- */ diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index b64f284c18f8..040b6566569d 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -254,7 +254,7 @@ ppp_asynctty_read(struct tty_struct *tty, struct file *file, */ static ssize_t ppp_asynctty_write(struct tty_struct *tty, struct file *file, - const unsigned char __user *buf, size_t count) + const unsigned char *buf, size_t count) { return -EAGAIN; } @@ -673,7 +673,7 @@ ppp_async_push(struct asyncppp *ap) if (!tty_stuffed && ap->optr < ap->olim) { avail = ap->olim - ap->optr; set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - sent = tty->driver->write(tty, 0, ap->optr, avail); + sent = tty->driver->write(tty, ap->optr, avail); if (sent < 0) goto flush; /* error, e.g. loss of CD */ ap->optr += sent; diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c index a59c8f354947..3103e0136479 100644 --- a/drivers/net/ppp_synctty.c +++ b/drivers/net/ppp_synctty.c @@ -301,7 +301,7 @@ ppp_sync_read(struct tty_struct *tty, struct file *file, */ static ssize_t ppp_sync_write(struct tty_struct *tty, struct file *file, - const unsigned char __user *buf, size_t count) + const unsigned char *buf, size_t count) { return -EAGAIN; } @@ -651,7 +651,7 @@ ppp_sync_push(struct syncppp *ap) tty_stuffed = 0; if (!tty_stuffed && ap->tpkt != 0) { set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - sent = tty->driver->write(tty, 0, ap->tpkt->data, ap->tpkt->len); + sent = tty->driver->write(tty, ap->tpkt->data, ap->tpkt->len); if (sent < 0) goto flush; /* error, e.g. loss of CD */ if (sent < ap->tpkt->len) { diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 01c2c3e1d102..67cc46b90afc 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -417,7 +417,7 @@ sl_encaps(struct slip *sl, unsigned char *icp, int len) * 14 Oct 1994 Dmitry Gorodchanin. */ sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); - actual = sl->tty->driver->write(sl->tty, 0, sl->xbuff, count); + actual = sl->tty->driver->write(sl->tty, sl->xbuff, count); #ifdef SL_CHECK_TRANSMIT sl->dev->trans_start = jiffies; #endif @@ -451,7 +451,7 @@ static void slip_write_wakeup(struct tty_struct *tty) return; } - actual = tty->driver->write(tty, 0, sl->xhead, sl->xleft); + actual = tty->driver->write(tty, sl->xhead, sl->xleft); sl->xleft -= actual; sl->xhead += actual; } @@ -1475,7 +1475,7 @@ static void sl_outfill(unsigned long sls) if (!netif_queue_stopped(sl->dev)) { /* if device busy no outfill */ - sl->tty->driver->write(sl->tty, 0, &s, 1); + sl->tty->driver->write(sl->tty, &s, 1); } } else diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c index 5539e27b1af2..29f84ad08730 100644 --- a/drivers/net/wan/pc300_tty.c +++ b/drivers/net/wan/pc300_tty.c @@ -120,8 +120,7 @@ int cpc_tty_unreg_flag = 0; /* TTY functions prototype */ static int cpc_tty_open(struct tty_struct *tty, struct file *flip); static void cpc_tty_close(struct tty_struct *tty, struct file *flip); -static int cpc_tty_write(struct tty_struct *tty, int from_user, - const unsigned char *buf, int count); +static int cpc_tty_write(struct tty_struct *tty, const unsigned char *buf, int count); static int cpc_tty_write_room(struct tty_struct *tty); static int cpc_tty_chars_in_buffer(struct tty_struct *tty); static void cpc_tty_flush_buffer(struct tty_struct *tty); @@ -427,8 +426,7 @@ static void cpc_tty_close(struct tty_struct *tty, struct file *flip) * o verify the DCD signal * o send characters to board and start the transmission */ -static int cpc_tty_write(struct tty_struct *tty, int from_user, - const unsigned char *buf, int count) +static int cpc_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) { st_cpc_tty_area *cpc_tty; pc300ch_t *pc300chan; @@ -454,8 +452,7 @@ static int cpc_tty_write(struct tty_struct *tty, int from_user, return -EINVAL; /* frame too big */ } - CPC_TTY_DBG("%s: cpc_tty_write %s data len=%i\n",cpc_tty->name, - (from_user)?"from user" : "from kernel",count); + CPC_TTY_DBG("%s: cpc_tty_write data len=%i\n",cpc_tty->name,count); pc300chan = (pc300ch_t *)((pc300dev_t*)cpc_tty->pc300dev)->chan; stats = hdlc_stats(((pc300dev_t*)cpc_tty->pc300dev)->dev); @@ -482,27 +479,10 @@ static int cpc_tty_write(struct tty_struct *tty, int from_user, return -EINVAL; } - if (from_user) { - unsigned char *buf_tmp; - - buf_tmp = cpc_tty->buf_tx; - if (copy_from_user(buf_tmp, buf, count)) { - /* failed to copy from user */ - CPC_TTY_DBG("%s: error in copy from user\n",cpc_tty->name); - return -EINVAL; - } - - if (cpc_tty_send_to_card(cpc_tty->pc300dev, (void*) buf_tmp,count)) { - /* failed to send */ - CPC_TTY_DBG("%s: transmission error\n",cpc_tty->name); - return 0; - } - } else { - if (cpc_tty_send_to_card(cpc_tty->pc300dev, (void*)buf, count)) { - /* failed to send */ - CPC_TTY_DBG("%s: trasmition error\n", cpc_tty->name); - return 0; - } + if (cpc_tty_send_to_card(cpc_tty->pc300dev, (void*)buf, count)) { + /* failed to send */ + CPC_TTY_DBG("%s: trasmition error\n", cpc_tty->name); + return 0; } return count; } diff --git a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c index e66c250ea8d4..afbe0024e3e1 100644 --- a/drivers/net/wan/sdla_chdlc.c +++ b/drivers/net/wan/sdla_chdlc.c @@ -3739,8 +3739,7 @@ static int wanpipe_tty_open(struct tty_struct *tty, struct file * filp) return 0; } -static int wanpipe_tty_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count) +static int wanpipe_tty_write(struct tty_struct * tty, const unsigned char *buf, int count) { unsigned long smp_flags=0; sdla_t *card=NULL; @@ -3784,58 +3783,16 @@ static int wanpipe_tty_write(struct tty_struct * tty, int from_user, return -EINVAL; } - if (from_user) { - - unsigned char *tmp_buf; - - if ((tmp_buf=card->tty_buf)==NULL){ - dbg_printk(KERN_INFO "No TTY BUF in Write\n"); - - clear_bit(SEND_CRIT,(void*)&card->wandev.critical); - - if(card->hw.type != SDLA_S514) - s508_unlock(card,&smp_flags); - - return -ENOMEM; - } - - if (copy_from_user(tmp_buf,buf,count)){ - dbg_printk(KERN_INFO "%s: Failed to copy from user!\n", - card->devname); - - clear_bit(SEND_CRIT,(void*)&card->wandev.critical); - - if(card->hw.type != SDLA_S514) - s508_unlock(card,&smp_flags); - - return -EINVAL; - } - - if (chdlc_send(card,(void*)tmp_buf,count)){ - dbg_printk(KERN_INFO "%s: Failed to send, retry later: user!\n", - card->devname); - - clear_bit(SEND_CRIT,(void*)&card->wandev.critical); - - wanpipe_tty_trigger_tx_irq(card); - - if(card->hw.type != SDLA_S514) - s508_unlock(card,&smp_flags); - return 0; - } + if (chdlc_send(card,(void*)buf,count)){ + dbg_printk(KERN_INFO "%s: Failed to send, retry later: kernel!\n", + card->devname); + clear_bit(SEND_CRIT,(void*)&card->wandev.critical); - }else{ - if (chdlc_send(card,(void*)buf,count)){ - dbg_printk(KERN_INFO "%s: Failed to send, retry later: kernel!\n", - card->devname); - clear_bit(SEND_CRIT,(void*)&card->wandev.critical); - - wanpipe_tty_trigger_tx_irq(card); - - if(card->hw.type != SDLA_S514) - s508_unlock(card,&smp_flags); - return 0; - } + wanpipe_tty_trigger_tx_irq(card); + + if(card->hw.type != SDLA_S514) + s508_unlock(card,&smp_flags); + return 0; } dbg_printk(KERN_INFO "%s: Packet sent OK: %i\n",card->devname,count); clear_bit(SEND_CRIT,(void*)&card->wandev.critical); diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index c29233115d3f..57e9758eb83f 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -253,7 +253,7 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len) * 14 Oct 1994 Dmitry Gorodchanin. */ sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); - actual = sl->tty->driver->write(sl->tty, 0, sl->xbuff, count); + actual = sl->tty->driver->write(sl->tty, sl->xbuff, count); sl->xleft = count - actual; sl->xhead = sl->xbuff + actual; /* VSV */ @@ -283,7 +283,7 @@ static void x25_asy_write_wakeup(struct tty_struct *tty) return; } - actual = tty->driver->write(tty, 0, sl->xhead, sl->xleft); + actual = tty->driver->write(tty, sl->xhead, sl->xleft); sl->xleft -= actual; sl->xhead += actual; } diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index 69c92876f7fd..b9cb7be40a95 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c @@ -1250,7 +1250,7 @@ static void ResetRadio(struct strip *strip_info) set_baud(tty, strip_info->user_baud); } - tty->driver->write(tty, 0, s.string, s.length); + tty->driver->write(tty, s.string, s.length); #ifdef EXT_COUNTERS strip_info->tx_ebytes += s.length; #endif @@ -1272,7 +1272,7 @@ static void strip_write_some_more(struct tty_struct *tty) if (strip_info->tx_left > 0) { int num_written = - tty->driver->write(tty, 0, strip_info->tx_head, + tty->driver->write(tty, strip_info->tx_head, strip_info->tx_left); strip_info->tx_left -= num_written; strip_info->tx_head += num_written; diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 9c72ffb655f8..f9fb773097f7 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -983,7 +983,7 @@ tty3215_write_room(struct tty_struct *tty) * String write routine for 3215 ttys */ static int -tty3215_write(struct tty_struct * tty, int from_user, +tty3215_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct raw3215_info *raw; @@ -992,26 +992,8 @@ tty3215_write(struct tty_struct * tty, int from_user, if (!tty) return 0; raw = (struct raw3215_info *) tty->driver_data; - if (!from_user) { - raw3215_write(raw, buf, count); - return count; - } - ret = 0; - while (count > 0) { - length = count < 80 ? count : 80; - length -= copy_from_user(raw->ubuffer, - (const unsigned char __user *)buf, length); - if (length == 0) { - if (!ret) - ret = -EFAULT; - break; - } - raw3215_write(raw, raw->ubuffer, count); - buf += length; - count -= length; - ret += length; - } - return ret; + raw3215_write(raw, buf, count); + return count; } /* diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index cd11cb171d15..f037a8706283 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c @@ -395,8 +395,7 @@ sclp_tty_write_string(const unsigned char *str, int count) * routine will return the number of characters actually accepted for writing. */ static int -sclp_tty_write(struct tty_struct *tty, int from_user, - const unsigned char *buf, int count) +sclp_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) { int length, ret; @@ -404,27 +403,8 @@ sclp_tty_write(struct tty_struct *tty, int from_user, sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count); sclp_tty_chars_count = 0; } - if (!from_user) { - sclp_tty_write_string(buf, count); - return count; - } - ret = 0; - while (count > 0) { - length = count < SCLP_TTY_BUF_SIZE ? - count : SCLP_TTY_BUF_SIZE; - length -= copy_from_user(sclp_tty_chars, - (const unsigned char __user *)buf, length); - if (length == 0) { - if (!ret) - ret = -EFAULT; - break; - } - sclp_tty_write_string(sclp_tty_chars, length); - buf += length; - count -= length; - ret += length; - } - return ret; + sclp_tty_write_string(buf, count); + return count; } /* diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index cc143fa9f506..69aed79f32cb 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c @@ -473,33 +473,9 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule, * number of characters actually accepted for writing. */ static int -sclp_vt220_write(struct tty_struct *tty, int from_user, - const unsigned char *buf, int count) +sclp_vt220_write(struct tty_struct *tty, const unsigned char *buf, int count) { - int length; - int ret; - - if (!from_user) - return __sclp_vt220_write(buf, count, 1, 0); - /* Use intermediate buffer to prevent calling copy_from_user() while - * holding a lock. */ - ret = 0; - while (count > 0) { - length = count < SCLP_VT220_BUF_SIZE ? - count : SCLP_VT220_BUF_SIZE; - length -= copy_from_user(tty->driver_data, - (const unsigned char __user *)buf, length); - if (length == 0) { - if (!ret) - return -EFAULT; - break; - } - length = __sclp_vt220_write(tty->driver_data, length, 1, 0); - buf += length; - count -= length; - ret += length; - } - return ret; + return __sclp_vt220_write(buf, count, 1, 0); } #define SCLP_VT220_SESSION_ENDED 0x01 diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index debc2b02c201..a96c5171506d 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c @@ -1599,7 +1599,7 @@ tty3270_do_write(struct tty3270 *tp, const unsigned char *buf, int count) * String write routine for 3270 ttys */ static int -tty3270_write(struct tty_struct * tty, int from_user, +tty3270_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct tty3270 *tp; @@ -1612,26 +1612,8 @@ tty3270_write(struct tty_struct * tty, int from_user, tty3270_do_write(tp, tp->char_buf, tp->char_count); tp->char_count = 0; } - if (!from_user) { - tty3270_do_write(tp, buf, count); - return count; - } - ret = 0; - while (count > 0) { - length = count < TTY3270_CHAR_BUF_SIZE ? - count : TTY3270_CHAR_BUF_SIZE; - length -= copy_from_user(tp->char_buf, buf, length); - if (length == 0) { - if (!ret) - ret = -EFAULT; - break; - } - tty3270_do_write(tp, tp->char_buf, count); - buf += length; - count -= length; - ret += length; - } - return ret; + tty3270_do_write(tp, buf, count); + return count; } /* diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c index 2806b2d156c3..a4fda34df749 100644 --- a/drivers/s390/net/ctctty.c +++ b/drivers/s390/net/ctctty.c @@ -489,7 +489,7 @@ ctc_tty_shutdown(ctc_tty_info * info) * - If dialing, abort dial. */ static int -ctc_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int count) +ctc_tty_write(struct tty_struct *tty, const u_char * buf, int count) { int c; int total = 0; @@ -506,8 +506,6 @@ ctc_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int cou total = -ENODEV; goto ex; } - if (from_user) - down(&info->write_sem); while (1) { struct sk_buff *skb; int skb_res; @@ -526,11 +524,7 @@ ctc_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int cou break; } skb_reserve(skb, skb_res); - if (from_user) - copy_from_user(skb_put(skb, c), - (const u_char __user *)buf, c); - else - memcpy(skb_put(skb, c), buf, c); + memcpy(skb_put(skb, c), buf, c); skb_queue_tail(&info->tx_queue, skb); buf += c; total += c; @@ -540,8 +534,6 @@ ctc_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int cou info->lsr &= ~UART_LSR_TEMT; tasklet_schedule(&info->tasklet); } - if (from_user) - up(&info->write_sem); ex: DBF_TEXT(trace, 6, __FUNCTION__); return total; diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c index db4c1c2b799c..ea29fcfac24f 100644 --- a/drivers/sbus/char/aurora.c +++ b/drivers/sbus/char/aurora.c @@ -1550,7 +1550,7 @@ static void aurora_close(struct tty_struct * tty, struct file * filp) #endif } -static int aurora_write(struct tty_struct * tty, int from_user, +static int aurora_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; @@ -1573,51 +1573,22 @@ static int aurora_write(struct tty_struct * tty, int from_user, return 0; save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!total) - total = -EFAULT; - break; - } - cli(); - c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c); - port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - port->xmit_cnt += c; + while (1) { + cli(); + c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, + SERIAL_XMIT_SIZE - port->xmit_head)); + if (c <= 0) { restore_flags(flags); - - buf += c; - count -= c; - total += c; + break; } - up(&tmp_buf_sem); - } else { - while (1) { - cli(); - c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - 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; - restore_flags(flags); + memcpy(port->xmit_buf + port->xmit_head, buf, c); + port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + port->xmit_cnt += c; + restore_flags(flags); - buf += c; - count -= c; - total += c; - } + buf += c; + count -= c; + total += c; } cli(); diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 299c2bcea221..cc8bf05f95a2 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c @@ -757,7 +757,7 @@ static void rs_flush_chars(struct tty_struct *tty) extern void console_printn(const char * b, int count); -static int rs_write(struct tty_struct * tty, int from_user, +static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) { int c, total = 0; @@ -779,15 +779,7 @@ static int rs_write(struct tty_struct * tty, int from_user, if (c <= 0) break; - if (from_user) { - down(&tmp_buf_sem); - copy_from_user(tmp_buf, buf, c); - c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - up(&tmp_buf_sem); - } else - memcpy(info->xmit_buf + info->xmit_head, buf, c); + memcpy(info->xmit_buf + info->xmit_head, buf, c); info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); info->xmit_cnt += c; restore_flags(flags); diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index cd2d62cd1582..26006220e306 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c @@ -1047,7 +1047,7 @@ static void rs_360_put_char(struct tty_struct *tty, unsigned char ch) } -static int rs_360_write(struct tty_struct * tty, int from_user, +static int rs_360_write(struct tty_struct * tty, const unsigned char *buf, int count) { int c, ret = 0; @@ -1079,16 +1079,8 @@ static int rs_360_write(struct tty_struct * tty, int from_user, break; } - if (from_user) { - if (copy_from_user((void *)bdp->buf, buf, c)) { - if (!ret) - ret = -EFAULT; - break; - } - } else { - /* memcpy(__va(bdp->buf), buf, c); */ - memcpy((void *)bdp->buf, buf, c); - } + /* memcpy(__va(bdp->buf), buf, c); */ + memcpy((void *)bdp->buf, buf, c); bdp->length = c; bdp->status |= BD_SC_READY; diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index 46bcd19f2c45..60aab54a7f01 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c @@ -735,7 +735,7 @@ static void mcfrs_flush_chars(struct tty_struct *tty) local_irq_restore(flags); } -static int mcfrs_write(struct tty_struct * tty, int from_user, +static int mcfrs_write(struct tty_struct * tty, const unsigned char *buf, int count) { volatile unsigned char *uartp; @@ -744,8 +744,8 @@ static int mcfrs_write(struct tty_struct * tty, int from_user, int c, total = 0; #if 0 - printk("%s(%d): mcfrs_write(tty=%x,from_user=%d,buf=%x,count=%d)\n", - __FILE__, __LINE__, (int)tty, from_user, (int)buf, count); + printk("%s(%d): mcfrs_write(tty=%x,buf=%x,count=%d)\n", + __FILE__, __LINE__, (int)tty, (int)buf, count); #endif if (serial_paranoia_check(info, tty->name, "mcfrs_write")) @@ -764,19 +764,7 @@ static int mcfrs_write(struct tty_struct * tty, int from_user, if (c <= 0) break; - if (from_user) { - down(&mcfrs_tmp_buf_sem); - if (copy_from_user(mcfrs_tmp_buf, buf, c)) - return -EFAULT; - - local_irq_disable(); - c = min(c, (int) min(((int)SERIAL_XMIT_SIZE) - info->xmit_cnt - 1, - ((int)SERIAL_XMIT_SIZE) - info->xmit_head)); - local_irq_restore(flags); - memcpy(info->xmit_buf + info->xmit_head, mcfrs_tmp_buf, c); - up(&mcfrs_tmp_buf_sem); - } else - memcpy(info->xmit_buf + info->xmit_head, buf, c); + memcpy(info->xmit_buf + info->xmit_head, buf, c); local_irq_disable(); info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 01bb77a57288..b8074b6af6be 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -528,8 +528,7 @@ static void uart_flush_chars(struct tty_struct *tty) } static int -uart_write(struct tty_struct *tty, int from_user, const unsigned char * buf, - int count) +uart_write(struct tty_struct *tty, const unsigned char * buf, int count) { struct uart_state *state = tty->driver_data; int ret; @@ -537,12 +536,8 @@ uart_write(struct tty_struct *tty, int from_user, const unsigned char * buf, if (!state->info->xmit.buf) return 0; - if (from_user) - ret = __uart_user_write(state->port, &state->info->xmit, - (const unsigned char __user *)buf, count); - else - ret = __uart_kern_write(state->port, &state->info->xmit, - buf, count); + ret = __uart_kern_write(state->port, &state->info->xmit, + buf, count); uart_start(tty); return ret; diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c index 74aea012129c..a8c4d1163e68 100644 --- a/drivers/tc/zs.c +++ b/drivers/tc/zs.c @@ -927,7 +927,7 @@ static void rs_flush_chars(struct tty_struct *tty) restore_flags(flags); } -static int rs_write(struct tty_struct * tty, int from_user, +static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) { int c, total = 0; @@ -948,15 +948,7 @@ static int rs_write(struct tty_struct * tty, int from_user, if (c <= 0) break; - if (from_user) { - down(&tmp_buf_sem); - copy_from_user(tmp_buf, buf, c); - c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - up(&tmp_buf_sem); - } else - memcpy(info->xmit_buf + info->xmit_head, buf, c); + memcpy(info->xmit_buf + info->xmit_head, buf, c); info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); info->xmit_cnt += c; restore_flags(flags); diff --git a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c index 6baf68badc06..6585faa2882d 100644 --- a/drivers/usb/class/bluetty.c +++ b/drivers/usb/class/bluetty.c @@ -207,7 +207,7 @@ struct usb_bluetooth { /* local function prototypes */ static int bluetooth_open (struct tty_struct *tty, struct file *filp); static void bluetooth_close (struct tty_struct *tty, struct file *filp); -static int bluetooth_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count); +static int bluetooth_write (struct tty_struct *tty, const unsigned char *buf, int count); static int bluetooth_write_room (struct tty_struct *tty); static int bluetooth_chars_in_buffer (struct tty_struct *tty); static void bluetooth_throttle (struct tty_struct *tty); @@ -433,7 +433,7 @@ static void bluetooth_close (struct tty_struct *tty, struct file * filp) } -static int bluetooth_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count) +static int bluetooth_write (struct tty_struct * tty, const unsigned char *buf, int count) { struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); struct urb *urb = NULL; @@ -471,21 +471,7 @@ static int bluetooth_write (struct tty_struct * tty, int from_user, const unsign printk ("\n"); #endif - if (from_user) { - temp_buffer = kmalloc (count, GFP_KERNEL); - if (temp_buffer == NULL) { - err ("%s - out of memory.", __FUNCTION__); - retval = -ENOMEM; - goto exit; - } - if (copy_from_user (temp_buffer, (void __user *)buf, count)) { - retval = -EFAULT; - goto exit; - } - current_buffer = temp_buffer; - } else { - current_buffer = buf; - } + current_buffer = buf; switch (*current_buffer) { /* First byte indicates the type of packet */ diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 0d0d49923bee..cf7fcf829450 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -335,11 +335,11 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp) up(&open_sem); } -static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count) +static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct acm *acm = tty->driver_data; int stat; - dbg("Entering acm_tty_write to write %d bytes from %s space,\n", count, from_user ? "user" : "kernel"); + dbg("Entering acm_tty_write to write %d bytes,\n", count); if (!ACM_READY(acm)) return -EINVAL; @@ -350,19 +350,15 @@ static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned c count = (count > acm->writesize) ? acm->writesize : count; - dbg("Get %d bytes from %s space...", count, from_user ? "user" : "kernel"); - if (from_user) { - if (copy_from_user(acm->write_buffer, (void __user *)buf, count)) - return -EFAULT; - } else - memcpy(acm->write_buffer, buf, count); + dbg("Get %d bytes...", count); + memcpy(acm->write_buffer, buf, count); dbg(" Successfully copied.\n"); acm->writeurb->transfer_buffer_length = count; acm->writeurb->dev = acm->dev; acm->ready_for_write = 0; - stat = usb_submit_urb(acm->writeurb, from_user ? GFP_KERNEL : GFP_ATOMIC); + stat = usb_submit_urb(acm->writeurb, GFP_ATOMIC); if (stat < 0) { dbg("usb_submit_urb(write bulk) failed"); acm->ready_for_write = 1; diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 1e18e92a6486..47a27bea2b87 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -152,7 +152,6 @@ do { \ #define GS_DEFAULT_WRITE_Q_SIZE 32 #define GS_DEFAULT_WRITE_BUF_SIZE 8192 -#define GS_TMP_BUF_SIZE 8192 #define GS_CLOSE_TIMEOUT 15 @@ -238,7 +237,7 @@ static void __exit gs_module_exit(void); /* tty driver */ static int gs_open(struct tty_struct *tty, struct file *file); static void gs_close(struct tty_struct *tty, struct file *file); -static int gs_write(struct tty_struct *tty, int from_user, +static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count); static void gs_put_char(struct tty_struct *tty, unsigned char ch); static void gs_flush_chars(struct tty_struct *tty); @@ -311,9 +310,6 @@ static unsigned int write_q_size = GS_DEFAULT_WRITE_Q_SIZE; static unsigned int write_buf_size = GS_DEFAULT_WRITE_BUF_SIZE; -static unsigned char gs_tmp_buf[GS_TMP_BUF_SIZE]; -static struct semaphore gs_tmp_buf_sem; - /* tty driver struct */ static struct tty_operations gs_tty_ops = { .open = gs_open, @@ -503,8 +499,6 @@ static int __init gs_module_init(void) for (i=0; i < GS_NUM_PORTS; i++) sema_init(&gs_open_close_sem[i], 1); - sema_init(&gs_tmp_buf_sem, 1); - retval = tty_register_driver(gs_tty_driver); if (retval) { usb_gadget_unregister_driver(&gs_gadget_driver); @@ -754,7 +748,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) /* * gs_write */ -static int gs_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count) +static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count) { unsigned long flags; struct gs_port *port = tty->driver_data; @@ -770,29 +764,12 @@ static int gs_write(struct tty_struct *tty, int from_user, const unsigned char * if (count == 0) return 0; - /* copy from user into tmp buffer, get tmp_buf semaphore */ - if (from_user) { - if (count > GS_TMP_BUF_SIZE) - count = GS_TMP_BUF_SIZE; - down(&gs_tmp_buf_sem); - if (copy_from_user(gs_tmp_buf, buf, count) != 0) { - up(&gs_tmp_buf_sem); - printk(KERN_ERR - "gs_write: (%d,%p) cannot copy from user space\n", - port->port_num, tty); - return -EFAULT; - } - buf = gs_tmp_buf; - } - spin_lock_irqsave(&port->port_lock, flags); if (port->port_dev == NULL) { printk(KERN_ERR "gs_write: (%d,%p) port is not connected\n", port->port_num, tty); spin_unlock_irqrestore(&port->port_lock, flags); - if (from_user) - up(&gs_tmp_buf_sem); return -EIO; } @@ -800,8 +777,6 @@ static int gs_write(struct tty_struct *tty, int from_user, const unsigned char * printk(KERN_ERR "gs_write: (%d,%p) port is closed\n", port->port_num, tty); spin_unlock_irqrestore(&port->port_lock, flags); - if (from_user) - up(&gs_tmp_buf_sem); return -EBADF; } @@ -809,9 +784,6 @@ static int gs_write(struct tty_struct *tty, int from_user, const unsigned char * spin_unlock_irqrestore(&port->port_lock, flags); - if (from_user) - up(&gs_tmp_buf_sem); - gs_send(gs_device); gs_debug("gs_write: (%d,%p) wrote %d bytes\n", port->port_num, tty, diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 6b5ec2af32ad..dc3ddb7939d5 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -57,8 +57,7 @@ static int cyberjack_startup (struct usb_serial *serial); static void cyberjack_shutdown (struct usb_serial *serial); static int cyberjack_open (struct usb_serial_port *port, struct file *filp); static void cyberjack_close (struct usb_serial_port *port, struct file *filp); -static int cyberjack_write (struct usb_serial_port *port, int from_user, - const unsigned char *buf, int count); +static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int cyberjack_write_room( struct usb_serial_port *port ); static void cyberjack_read_int_callback (struct urb *urb, struct pt_regs *regs); static void cyberjack_read_bulk_callback (struct urb *urb, struct pt_regs *regs); @@ -194,7 +193,7 @@ static void cyberjack_close (struct usb_serial_port *port, struct file *filp) } } -static int cyberjack_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; struct cyberjack_private *priv = usb_get_serial_port_data(port); @@ -203,7 +202,6 @@ static int cyberjack_write (struct usb_serial_port *port, int from_user, const u int wrexpected; dbg("%s - port %d", __FUNCTION__, port->number); - dbg("%s - from_user %d", __FUNCTION__, from_user); if (count == 0) { dbg("%s - write request of 0 bytes", __FUNCTION__); @@ -225,14 +223,7 @@ static int cyberjack_write (struct usb_serial_port *port, int from_user, const u } /* Copy data */ - if (from_user) { - if (copy_from_user(priv->wrbuf+priv->wrfilled, buf, count)) { - spin_unlock_irqrestore(&priv->lock, flags); - return -EFAULT; - } - } else { - memcpy (priv->wrbuf+priv->wrfilled, buf, count); - } + memcpy (priv->wrbuf+priv->wrfilled, buf, count); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, priv->wrbuf+priv->wrfilled); diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index b904bfcbffcf..4b59d75dbfb9 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -455,8 +455,7 @@ static int digi_ioctl( struct usb_serial_port *port, struct file *file, static int digi_tiocmget( struct usb_serial_port *port, struct file *file ); static int digi_tiocmset( struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear ); -static int digi_write( struct usb_serial_port *port, int from_user, - const unsigned char *buf, int count ); +static int digi_write( struct usb_serial_port *port, const unsigned char *buf, int count ); static void digi_write_bulk_callback( struct urb *urb, struct pt_regs *regs ); static int digi_write_room( struct usb_serial_port *port ); static int digi_chars_in_buffer( struct usb_serial_port *port ); @@ -1262,26 +1261,21 @@ dbg( "digi_ioctl: TOP: port=%d, cmd=0x%x", priv->dp_port_num, cmd ); } -static int digi_write( struct usb_serial_port *port, int from_user, - const unsigned char *buf, int count ) +static int digi_write( struct usb_serial_port *port, const unsigned char *buf, int count ) { int ret,data_len,new_len; struct digi_port *priv = usb_get_serial_port_data(port); unsigned char *data = port->write_urb->transfer_buffer; - unsigned char user_buf[64]; /* 64 bytes is max USB bulk packet */ unsigned long flags = 0; -dbg( "digi_write: TOP: port=%d, count=%d, from_user=%d, in_interrupt=%ld", -priv->dp_port_num, count, from_user, in_interrupt() ); +dbg( "digi_write: TOP: port=%d, count=%d, in_interrupt=%ld", +priv->dp_port_num, count, in_interrupt() ); /* copy user data (which can sleep) before getting spin lock */ count = min( count, port->bulk_out_size-2 ); count = min( 64, count); - if( from_user && copy_from_user( user_buf, buf, count ) ) { - return( -EFAULT ); - } /* be sure only one write proceeds at a time */ /* there are races on the port private buffer */ @@ -1294,8 +1288,7 @@ priv->dp_port_num, count, from_user, in_interrupt() ); /* buffer data if count is 1 (probably put_char) if possible */ if( count == 1 && priv->dp_out_buf_len < DIGI_OUT_BUF_SIZE ) { - priv->dp_out_buf[priv->dp_out_buf_len++] - = *(from_user ? user_buf : buf); + priv->dp_out_buf[priv->dp_out_buf_len++] = *buf; new_len = 1; } else { new_len = 0; @@ -1328,7 +1321,7 @@ priv->dp_port_num, count, from_user, in_interrupt() ); data += priv->dp_out_buf_len; /* copy in new data */ - memcpy( data, from_user ? user_buf : buf, new_len ); + memcpy( data, buf, new_len ); if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) { priv->dp_write_urb_in_use = 1; diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index e94113e0dd43..4d46394f351b 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -81,7 +81,6 @@ static int debug; static int empeg_open (struct usb_serial_port *port, struct file *filp); static void empeg_close (struct usb_serial_port *port, struct file *filp); static int empeg_write (struct usb_serial_port *port, - int from_user, const unsigned char *buf, int count); static int empeg_write_room (struct usb_serial_port *port); @@ -191,7 +190,7 @@ static void empeg_close (struct usb_serial_port *port, struct file * filp) } -static int empeg_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +static int empeg_write (struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; struct urb *urb; @@ -235,14 +234,7 @@ static int empeg_write (struct usb_serial_port *port, int from_user, const unsig transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE); - if (from_user) { - if (copy_from_user (urb->transfer_buffer, current_position, transfer_size)) { - bytes_sent = -EFAULT; - break; - } - } else { - memcpy (urb->transfer_buffer, current_position, transfer_size); - } + memcpy (urb->transfer_buffer, current_position, transfer_size); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size, urb->transfer_buffer); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index b1a985470e42..a037c31a4b6f 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -669,7 +669,7 @@ static int ftdi_HE_TIRA1_startup (struct usb_serial *serial); static void ftdi_shutdown (struct usb_serial *serial); static int ftdi_open (struct usb_serial_port *port, struct file *filp); static void ftdi_close (struct usb_serial_port *port, struct file *filp); -static int ftdi_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +static int ftdi_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int ftdi_write_room (struct usb_serial_port *port); static int ftdi_chars_in_buffer (struct usb_serial_port *port); static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs); @@ -1504,7 +1504,7 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp) * * The new devices do not require this byte */ -static int ftdi_write (struct usb_serial_port *port, int from_user, +static int ftdi_write (struct usb_serial_port *port, const unsigned char *buf, int count) { /* ftdi_write */ struct ftdi_private *priv = usb_get_serial_port_data(port); @@ -1561,17 +1561,8 @@ static int ftdi_write (struct usb_serial_port *port, int from_user, /* Write the control byte at the front of the packet*/ *first_byte = 1 | ((user_pktsz) << 2); /* Copy data for packet */ - if (from_user) { - if (copy_from_user (first_byte + data_offset, - current_position, user_pktsz)){ - kfree (buffer); - usb_free_urb (urb); - return -EFAULT; - } - } else { - memcpy (first_byte + data_offset, - current_position, user_pktsz); - } + memcpy (first_byte + data_offset, + current_position, user_pktsz); first_byte += user_pktsz + data_offset; current_position += user_pktsz; todo -= user_pktsz; @@ -1579,15 +1570,7 @@ static int ftdi_write (struct usb_serial_port *port, int from_user, } else { /* No control byte required. */ /* Copy in the data to send */ - if (from_user) { - if (copy_from_user (buffer, buf, count)) { - kfree (buffer); - usb_free_urb (urb); - return -EFAULT; - } - } else { - memcpy (buffer, buf, count); - } + memcpy (buffer, buf, count); } usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size, buffer); diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index c88885f8ca05..99214aa3cd19 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -159,7 +159,7 @@ void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp) generic_cleanup (port); } -int usb_serial_generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; int result; @@ -181,13 +181,7 @@ int usb_serial_generic_write (struct usb_serial_port *port, int from_user, const count = (count > port->bulk_out_size) ? port->bulk_out_size : count; - if (from_user) { - if (copy_from_user(port->write_urb->transfer_buffer, buf, count)) - return -EFAULT; - } - else { - memcpy (port->write_urb->transfer_buffer, buf, count); - } + memcpy (port->write_urb->transfer_buffer, buf, count); data = port->write_urb->transfer_buffer; usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, data); diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index b5d18c699a0e..34c70c1a4f5a 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -434,7 +434,7 @@ static void edge_bulk_out_cmd_callback (struct urb *urb, struct pt_regs *regs); /* function prototypes for the usbserial callbacks */ static int edge_open (struct usb_serial_port *port, struct file *filp); static void edge_close (struct usb_serial_port *port, struct file *filp); -static int edge_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +static int edge_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int edge_write_room (struct usb_serial_port *port); static int edge_chars_in_buffer (struct usb_serial_port *port); static void edge_throttle (struct usb_serial_port *port); @@ -1262,7 +1262,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp) * If successful, we return the number of bytes written, otherwise we return * a negative error number. *****************************************************************************/ -static int edge_write (struct usb_serial_port *port, int from_user, const unsigned char *data, int count) +static int edge_write (struct usb_serial_port *port, const unsigned char *data, int count) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct TxFifo *fifo; @@ -1302,12 +1302,7 @@ static int edge_write (struct usb_serial_port *port, int from_user, const unsign dbg("%s - copy %d bytes of %d into fifo ", __FUNCTION__, firsthalf, bytesleft); /* now copy our data */ - if (from_user) { - if (copy_from_user(&fifo->fifo[fifo->head], data, firsthalf)) - return -EFAULT; - } else { - memcpy(&fifo->fifo[fifo->head], data, firsthalf); - } + memcpy(&fifo->fifo[fifo->head], data, firsthalf); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, firsthalf, &fifo->fifo[fifo->head]); // update the index and size @@ -1323,12 +1318,7 @@ static int edge_write (struct usb_serial_port *port, int from_user, const unsign if (secondhalf) { dbg("%s - copy rest of data %d", __FUNCTION__, secondhalf); - if (from_user) { - if (copy_from_user(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf)) - return -EFAULT; - } else { - memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf); - } + memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, secondhalf, &fifo->fifo[fifo->head]); // update the index and size fifo->count += secondhalf; @@ -1556,7 +1546,7 @@ static void edge_throttle (struct usb_serial_port *port) /* if we are implementing XON/XOFF, send the stop character */ if (I_IXOFF(tty)) { unsigned char stop_char = STOP_CHAR(tty); - status = edge_write (port, 0, &stop_char, 1); + status = edge_write (port, &stop_char, 1); if (status <= 0) { return; } @@ -1605,7 +1595,7 @@ static void edge_unthrottle (struct usb_serial_port *port) /* if we are implementing XON/XOFF, send the start character */ if (I_IXOFF(tty)) { unsigned char start_char = START_CHAR(tty); - status = edge_write (port, 0, &start_char, 1); + status = edge_write (port, &start_char, 1); if (status <= 0) { return; } diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 359d3c0b8a15..78f7373c3fd6 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -1995,7 +1995,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp) dbg("%s - exited", __FUNCTION__); } -static int edge_write (struct usb_serial_port *port, int from_user, const unsigned char *data, int count) +static int edge_write (struct usb_serial_port *port, const unsigned char *data, int count) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); int result; @@ -2019,12 +2019,7 @@ static int edge_write (struct usb_serial_port *port, int from_user, const unsign count = min (count, port->bulk_out_size); - if (from_user) { - if (copy_from_user(port->write_urb->transfer_buffer, data, count)) - return -EFAULT; - } else { - memcpy (port->write_urb->transfer_buffer, data, count); - } + memcpy (port->write_urb->transfer_buffer, data, count); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer); @@ -2110,7 +2105,7 @@ static void edge_throttle (struct usb_serial_port *port) /* if we are implementing XON/XOFF, send the stop character */ if (I_IXOFF(tty)) { unsigned char stop_char = STOP_CHAR(tty); - status = edge_write (port, 0, &stop_char, 1); + status = edge_write (port, &stop_char, 1); if (status <= 0) { return; } @@ -2144,7 +2139,7 @@ static void edge_unthrottle (struct usb_serial_port *port) /* if we are implementing XON/XOFF, send the start character */ if (I_IXOFF(tty)) { unsigned char start_char = START_CHAR(tty); - status = edge_write (port, 0, &start_char, 1); + status = edge_write (port, &start_char, 1); if (status <= 0) { return; } diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 1a748b515112..c4be7f874151 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -77,9 +77,9 @@ static int ipaq_open (struct usb_serial_port *port, struct file *filp); static void ipaq_close (struct usb_serial_port *port, struct file *filp); static int ipaq_startup (struct usb_serial *serial); static void ipaq_shutdown (struct usb_serial *serial); -static int ipaq_write(struct usb_serial_port *port, int from_user, const unsigned char *buf, +static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf, int count); -static int ipaq_write_bulk(struct usb_serial_port *port, int from_user, const unsigned char *buf, +static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *buf, int count); static void ipaq_write_gather(struct usb_serial_port *port); static void ipaq_read_bulk_callback (struct urb *urb, struct pt_regs *regs); @@ -339,7 +339,7 @@ static void ipaq_read_bulk_callback(struct urb *urb, struct pt_regs *regs) return; } -static int ipaq_write(struct usb_serial_port *port, int from_user, const unsigned char *buf, +static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf, int count) { const unsigned char *current_position = buf; @@ -350,7 +350,7 @@ static int ipaq_write(struct usb_serial_port *port, int from_user, const unsigne while (count > 0) { transfer_size = min(count, PACKET_SIZE); - if (ipaq_write_bulk(port, from_user, current_position, transfer_size)) { + if (ipaq_write_bulk(port, current_position, transfer_size)) { break; } current_position += transfer_size; @@ -362,7 +362,7 @@ static int ipaq_write(struct usb_serial_port *port, int from_user, const unsigne return bytes_sent; } -static int ipaq_write_bulk(struct usb_serial_port *port, int from_user, const unsigned char *buf, +static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *buf, int count) { struct ipaq_private *priv = usb_get_serial_port_data(port); @@ -387,12 +387,7 @@ static int ipaq_write_bulk(struct usb_serial_port *port, int from_user, const un return -EAGAIN; } - if (from_user) { - if (copy_from_user(pkt->data, buf, count)) - return -EFAULT; - } else { - memcpy(pkt->data, buf, count); - } + memcpy(pkt->data, buf, count); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, pkt->data); pkt->len = count; diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 2fc04f905a5c..20977939271c 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -387,13 +387,13 @@ static void ipw_write_bulk_callback(struct urb *urb, struct pt_regs *regs) schedule_work(&port->work); } -static int ipw_write(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_device *dev = port->serial->dev; int ret; - dbg("%s: TOP: count=%d, from_user=%d, in_interrupt=%ld", __FUNCTION__, - count, from_user, in_interrupt() ); + dbg("%s: TOP: count=%d, in_interrupt=%ld", __FUNCTION__, + count, in_interrupt() ); if (count == 0) { dbg("%s - write request of 0 bytes", __FUNCTION__); @@ -405,12 +405,7 @@ static int ipw_write(struct usb_serial_port *port, int from_user, const unsigned return 0; count = min(count, port->bulk_out_size); - if (from_user) { - if (copy_from_user(port->bulk_out_buffer, buf, count)) - return -EFAULT; - } else { - memcpy(port->bulk_out_buffer, buf, count); - } + memcpy(port->bulk_out_buffer, buf, count); dbg("%s count now:%d", __FUNCTION__, count); diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index c2c536f194e0..3003cd04300e 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -105,7 +105,7 @@ static int xbof = -1; static int ir_startup (struct usb_serial *serial); static int ir_open (struct usb_serial_port *port, struct file *filep); static void ir_close (struct usb_serial_port *port, struct file *filep); -static int ir_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int count); static void ir_write_bulk_callback (struct urb *urb, struct pt_regs *regs); static void ir_read_bulk_callback (struct urb *urb, struct pt_regs *regs); static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios); @@ -325,7 +325,7 @@ static void ir_close (struct usb_serial_port *port, struct file * filp) usb_kill_urb(port->read_urb); } -static int ir_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int count) { unsigned char *transfer_buffer; int result; @@ -359,12 +359,7 @@ static int ir_write (struct usb_serial_port *port, int from_user, const unsigned *transfer_buffer = ir_xbof | ir_baud; ++transfer_buffer; - if (from_user) { - if (copy_from_user (transfer_buffer, buf, transfer_size)) - return -EFAULT; - } else { - memcpy (transfer_buffer, buf, transfer_size); - } + memcpy (transfer_buffer, buf, transfer_size); usb_fill_bulk_urb ( port->write_urb, diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 7b4f98407b4b..9c7467b7e763 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -342,7 +342,7 @@ static int keyspan_ioctl(struct usb_serial_port *port, struct file *file, /* Write function is similar for the four protocols used with only a minor change for usa90 (usa19hs) required */ -static int keyspan_write(struct usb_serial_port *port, int from_user, +static int keyspan_write(struct usb_serial_port *port, const unsigned char *buf, int count) { struct keyspan_port_private *p_priv; @@ -396,12 +396,7 @@ static int keyspan_write(struct usb_serial_port *port, int from_user, for now so set to zero */ ((char *)this_urb->transfer_buffer)[0] = 0; - if (from_user) { - if (copy_from_user(this_urb->transfer_buffer + dataOffset, buf, todo)) - return -EFAULT; - } else { - memcpy (this_urb->transfer_buffer + dataOffset, buf, todo); - } + memcpy (this_urb->transfer_buffer + dataOffset, buf, todo); buf += todo; /* send the data out the bulk port */ diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index 7b60835c4774..e9b45b768aca 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -46,7 +46,6 @@ static void keyspan_rx_unthrottle (struct usb_serial_port *port); static int keyspan_write_room (struct usb_serial_port *port); static int keyspan_write (struct usb_serial_port *port, - int from_user, const unsigned char *buf, int count); diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 0a979e208167..2f45c60bd25c 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -493,7 +493,7 @@ static int keyspan_pda_ioctl(struct usb_serial_port *port, struct file *file, return -ENOIOCTLCMD; } -static int keyspan_pda_write(struct usb_serial_port *port, int from_user, +static int keyspan_pda_write(struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; @@ -567,16 +567,7 @@ static int keyspan_pda_write(struct usb_serial_port *port, int from_user, if (count) { /* now transfer data */ - if (from_user) { - if( copy_from_user(port->write_urb->transfer_buffer, - buf, count) ) { - rc = -EFAULT; - goto exit; - } - } - else { - memcpy (port->write_urb->transfer_buffer, buf, count); - } + memcpy (port->write_urb->transfer_buffer, buf, count); /* send the data out the bulk port */ port->write_urb->transfer_buffer_length = count; diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 9e60b3476775..11d356a6c08d 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -79,7 +79,6 @@ static int klsi_105_open (struct usb_serial_port *port, static void klsi_105_close (struct usb_serial_port *port, struct file *filp); static int klsi_105_write (struct usb_serial_port *port, - int from_user, const unsigned char *buf, int count); static void klsi_105_write_bulk_callback (struct urb *urb, struct pt_regs *regs); @@ -484,7 +483,7 @@ static void klsi_105_close (struct usb_serial_port *port, struct file *filp) #define KLSI_105_DATA_OFFSET 2 /* in the bulk urb data block */ -static int klsi_105_write (struct usb_serial_port *port, int from_user, +static int klsi_105_write (struct usb_serial_port *port, const unsigned char *buf, int count) { struct klsi_105_private *priv = usb_get_serial_port_data(port); @@ -525,15 +524,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user, size = min (count, port->bulk_out_size - KLSI_105_DATA_OFFSET); size = min (size, URB_TRANSFER_BUFFER_SIZE - KLSI_105_DATA_OFFSET); - if (from_user) { - if (copy_from_user(urb->transfer_buffer - + KLSI_105_DATA_OFFSET, buf, size)) { - return -EFAULT; - } - } else { - memcpy (urb->transfer_buffer + KLSI_105_DATA_OFFSET, - buf, size); - } + memcpy (urb->transfer_buffer + KLSI_105_DATA_OFFSET, buf, size); /* write payload size into transfer buffer */ ((__u8 *)urb->transfer_buffer)[0] = (__u8) (size & 0xFF); diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 33539874bd0c..a37b28d134ce 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -73,7 +73,7 @@ static int kobil_startup (struct usb_serial *serial); static void kobil_shutdown (struct usb_serial *serial); static int kobil_open (struct usb_serial_port *port, struct file *filp); static void kobil_close (struct usb_serial_port *port, struct file *filp); -static int kobil_write (struct usb_serial_port *port, int from_user, +static int kobil_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int kobil_write_room(struct usb_serial_port *port); static int kobil_ioctl(struct usb_serial_port *port, struct file *file, @@ -418,7 +418,7 @@ static void kobil_write_callback( struct urb *purb, struct pt_regs *regs ) } -static int kobil_write (struct usb_serial_port *port, int from_user, +static int kobil_write (struct usb_serial_port *port, const unsigned char *buf, int count) { int length = 0; @@ -439,13 +439,7 @@ static int kobil_write (struct usb_serial_port *port, int from_user, } // Copy data to buffer - if (from_user) { - if (copy_from_user(priv->buf + priv->filled, buf, count)) { - return -EFAULT; - } - } else { - memcpy (priv->buf + priv->filled, buf, count); - } + memcpy (priv->buf + priv->filled, buf, count); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, priv->buf + priv->filled); diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 1d7c682aed7a..567911b65929 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -110,7 +110,6 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp); #ifdef FIX_WRITE_RETURN_CODE_PROBLEM static int mct_u232_write (struct usb_serial_port *port, - int from_user, const unsigned char *buf, int count); static void mct_u232_write_bulk_callback (struct urb *urb, struct pt_regs *regs); @@ -490,7 +489,7 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp) #ifdef FIX_WRITE_RETURN_CODE_PROBLEM /* The generic routines work fine otherwise */ -static int mct_u232_write (struct usb_serial_port *port, int from_user, +static int mct_u232_write (struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; @@ -519,14 +518,7 @@ static int mct_u232_write (struct usb_serial_port *port, int from_user, usb_serial_debug_data(debug, &port->dev, __FUNCTION__, size, buf); - if (from_user) { - if (copy_from_user(port->write_urb->transfer_buffer, buf, size)) { - return -EFAULT; - } - } - else { - memcpy (port->write_urb->transfer_buffer, buf, size); - } + memcpy (port->write_urb->transfer_buffer, buf, size); /* set up our urb */ usb_fill_bulk_urb(port->write_urb, serial->dev, diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 7032d5f7c6e1..a1cba4b5fa23 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -67,7 +67,7 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp); static void omninet_close (struct usb_serial_port *port, struct file *filp); static void omninet_read_bulk_callback (struct urb *urb, struct pt_regs *regs); static void omninet_write_bulk_callback (struct urb *urb, struct pt_regs *regs); -static int omninet_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +static int omninet_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int omninet_write_room (struct usb_serial_port *port); static void omninet_shutdown (struct usb_serial *serial); @@ -241,7 +241,7 @@ static void omninet_read_bulk_callback (struct urb *urb, struct pt_regs *regs) return; } -static int omninet_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +static int omninet_write (struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; struct usb_serial_port *wport = serial->port[1]; @@ -264,15 +264,7 @@ static int omninet_write (struct usb_serial_port *port, int from_user, const uns count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count; - if (from_user) { - if (copy_from_user(wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count) != 0) { - result = -EFAULT; - goto exit; - } - } - else { - memcpy (wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count); - } + memcpy (wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, wport->write_urb->transfer_buffer); @@ -291,7 +283,6 @@ static int omninet_write (struct usb_serial_port *port, int from_user, const uns else result = count; -exit: return result; } diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 5be9c370313b..75c590ce572b 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -65,7 +65,6 @@ static int debug; #define PL2303_BUF_SIZE 1024 #define PL2303_TMP_BUF_SIZE 1024 -static char pl2303_tmp_buf[PL2303_TMP_BUF_SIZE]; static DECLARE_MUTEX(pl2303_tmp_buf_sem); struct pl2303_buf { @@ -147,7 +146,7 @@ static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs); static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs); static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs); -static int pl2303_write (struct usb_serial_port *port, int from_user, +static int pl2303_write (struct usb_serial_port *port, const unsigned char *buf, int count); static void pl2303_send (struct usb_serial_port *port); static int pl2303_write_room(struct usb_serial_port *port); @@ -267,7 +266,7 @@ static int set_control_lines (struct usb_device *dev, u8 value) return retval; } -static int pl2303_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +static int pl2303_write (struct usb_serial_port *port, const unsigned char *buf, int count) { struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; @@ -277,24 +276,10 @@ static int pl2303_write (struct usb_serial_port *port, int from_user, const uns if (!count) return count; - if (from_user) { - if (count > PL2303_TMP_BUF_SIZE) - count = PL2303_TMP_BUF_SIZE; - down(&pl2303_tmp_buf_sem); - if (copy_from_user(pl2303_tmp_buf, buf, count)) { - up(&pl2303_tmp_buf_sem); - return -EFAULT; - } - buf = pl2303_tmp_buf; - } - spin_lock_irqsave(&priv->lock, flags); count = pl2303_buf_put(priv->buf, buf, count); spin_unlock_irqrestore(&priv->lock, flags); - if (from_user) - up(&pl2303_tmp_buf_sem); - pl2303_send(port); return count; diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index fa0abc4b625a..0e85ed6c6c19 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c @@ -273,7 +273,7 @@ static void safe_read_bulk_callback (struct urb *urb, struct pt_regs *regs) } } -static int safe_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +static int safe_write (struct usb_serial_port *port, const unsigned char *buf, int count) { unsigned char *data; int result; @@ -314,12 +314,7 @@ static int safe_write (struct usb_serial_port *port, int from_user, const unsign data = port->write_urb->transfer_buffer; memset (data, '0', packet_length); - if (from_user) { - if (copy_from_user (data, buf, count)) - return -EFAULT; - } else { - memcpy (data, buf, count); - } + memcpy (data, buf, count); if (safe) { __u16 fcs; diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index e3b7c1dd2f4c..e5a6f6d59958 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -554,7 +554,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp) kref_put(&port->serial->kref, destroy_serial); } -static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count) +static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) { struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; int retval = -EINVAL; @@ -567,7 +567,7 @@ static int serial_write (struct tty_struct * tty, int from_user, const unsigned } /* pass on to the driver specific version of this function */ - retval = port->serial->type->write(port, from_user, buf, count); + retval = port->serial->type->write(port, buf, count); exit: return retval; diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h index d3702957b609..49cc6a64e5b9 100644 --- a/drivers/usb/serial/usb-serial.h +++ b/drivers/usb/serial/usb-serial.h @@ -239,7 +239,7 @@ struct usb_serial_device_type { /* serial function calls */ int (*open) (struct usb_serial_port *port, struct file * filp); void (*close) (struct usb_serial_port *port, struct file * filp); - int (*write) (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); + int (*write) (struct usb_serial_port *port, const unsigned char *buf, int count); int (*write_room) (struct usb_serial_port *port); int (*ioctl) (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); void (*set_termios) (struct usb_serial_port *port, struct termios * old); @@ -278,7 +278,7 @@ static inline void usb_serial_console_exit (void) { } /* Functions needed by other parts of the usbserial core */ extern struct usb_serial *usb_serial_get_by_index (unsigned int minor); extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp); -extern int usb_serial_generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count); extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp); extern int usb_serial_generic_write_room (struct usb_serial_port *port); extern int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port); diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 0e5d90552789..bf60619a33ac 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -168,7 +168,7 @@ /* function prototypes for a handspring visor */ static int visor_open (struct usb_serial_port *port, struct file *filp); static void visor_close (struct usb_serial_port *port, struct file *filp); -static int visor_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +static int visor_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int visor_write_room (struct usb_serial_port *port); static int visor_chars_in_buffer (struct usb_serial_port *port); static void visor_throttle (struct usb_serial_port *port); @@ -466,7 +466,7 @@ static void visor_close (struct usb_serial_port *port, struct file * filp) } -static int visor_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +static int visor_write (struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; struct urb *urb; @@ -488,15 +488,7 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig return -ENOMEM; } - if (from_user) { - if (copy_from_user (buffer, buf, count)) { - kfree (buffer); - usb_free_urb (urb); - return -EFAULT; - } - } else { - memcpy (buffer, buf, count); - } + memcpy (buffer, buf, count); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer); diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 179a671a2770..dd7ed7b1760c 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -143,7 +143,7 @@ static int whiteheat_attach (struct usb_serial *serial); static void whiteheat_shutdown (struct usb_serial *serial); static int whiteheat_open (struct usb_serial_port *port, struct file *filp); static void whiteheat_close (struct usb_serial_port *port, struct file *filp); -static int whiteheat_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +static int whiteheat_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int whiteheat_write_room (struct usb_serial_port *port); static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); static void whiteheat_set_termios (struct usb_serial_port *port, struct termios * old); @@ -702,7 +702,7 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp) } -static int whiteheat_write(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +static int whiteheat_write(struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; struct whiteheat_private *info = usb_get_serial_port_data(port); @@ -734,12 +734,7 @@ static int whiteheat_write(struct usb_serial_port *port, int from_user, const un wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); urb = wrap->urb; bytes = (count > port->bulk_out_size) ? port->bulk_out_size : count; - if (from_user) { - if (copy_from_user(urb->transfer_buffer, buf + sent, bytes)) - return -EFAULT; - } else { - memcpy (urb->transfer_buffer, buf + sent, bytes); - } + memcpy (urb->transfer_buffer, buf + sent, bytes); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, bytes, urb->transfer_buffer); diff --git a/include/linux/generic_serial.h b/include/linux/generic_serial.h index f2bd22edba05..1c8417aff025 100644 --- a/include/linux/generic_serial.h +++ b/include/linux/generic_serial.h @@ -73,7 +73,7 @@ struct gs_port { void gs_put_char(struct tty_struct *tty, unsigned char ch); -int gs_write(struct tty_struct *tty, int from_user, +int gs_write(struct tty_struct *tty, const unsigned char *buf, int count); int gs_write_room(struct tty_struct *tty); int gs_chars_in_buffer(struct tty_struct *tty); diff --git a/include/linux/tty.h b/include/linux/tty.h index f9fd14991956..1b76106272d3 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -291,6 +291,8 @@ struct tty_struct { unsigned int canon_column; struct semaphore atomic_read; struct semaphore atomic_write; + unsigned char *write_buf; + int write_cnt; spinlock_t read_lock; /* If the tty has a pending do_SAK, queue it here - akpm */ struct work_struct SAK_work; diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index bbf6a3813fc8..b368b296d035 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h @@ -17,7 +17,7 @@ * * This routine is called when a particular tty device is closed. * - * int (*write)(struct tty_struct * tty, int from_user, + * int (*write)(struct tty_struct * tty, * const unsigned char *buf, int count); * * This routine is called by the kernel to write a series of @@ -124,7 +124,7 @@ struct tty_struct; struct tty_operations { int (*open)(struct tty_struct * tty, struct file * filp); void (*close)(struct tty_struct * tty, struct file * filp); - int (*write)(struct tty_struct * tty, int from_user, + int (*write)(struct tty_struct * tty, const unsigned char *buf, int count); void (*put_char)(struct tty_struct *tty, unsigned char ch); void (*flush_chars)(struct tty_struct *tty); @@ -186,7 +186,7 @@ struct tty_driver { */ int (*open)(struct tty_struct * tty, struct file * filp); void (*close)(struct tty_struct * tty, struct file * filp); - int (*write)(struct tty_struct * tty, int from_user, + int (*write)(struct tty_struct * tty, const unsigned char *buf, int count); void (*put_char)(struct tty_struct *tty, unsigned char ch); void (*flush_chars)(struct tty_struct *tty); diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index deacf01e50e8..6066afde5ce4 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -123,7 +123,7 @@ struct tty_ldisc { ssize_t (*read)(struct tty_struct * tty, struct file * file, unsigned char __user * buf, size_t nr); ssize_t (*write)(struct tty_struct * tty, struct file * file, - const unsigned char __user * buf, size_t nr); + const unsigned char * buf, size_t nr); int (*ioctl)(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg); void (*set_termios)(struct tty_struct *tty, struct termios * old); diff --git a/kernel/printk.c b/kernel/printk.c index 13c01c9be691..1b41c96f7151 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -858,7 +858,7 @@ EXPORT_SYMBOL(unregister_console); void tty_write_message(struct tty_struct *tty, char *msg) { if (tty && tty->driver->write) - tty->driver->write(tty, 0, msg, strlen(msg)); + tty->driver->write(tty, msg, strlen(msg)); return; } diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index ed8abeff351c..08907d32425e 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -645,32 +645,26 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp) rfcomm_dev_put(dev); } -static int rfcomm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count) +static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; struct rfcomm_dlc *dlc = dev->dlc; struct sk_buff *skb; int err = 0, sent = 0, size; - BT_DBG("tty %p from_user %d count %d", tty, from_user, count); + BT_DBG("tty %p count %d", tty, count); while (count) { size = min_t(uint, count, dlc->mtu); - if (from_user) - skb = rfcomm_wmalloc(dev, size + RFCOMM_SKB_RESERVE, GFP_KERNEL); - else - skb = rfcomm_wmalloc(dev, size + RFCOMM_SKB_RESERVE, GFP_ATOMIC); + skb = rfcomm_wmalloc(dev, size + RFCOMM_SKB_RESERVE, GFP_ATOMIC); if (!skb) break; skb_reserve(skb, RFCOMM_SKB_HEAD_RESERVE); - if (from_user) - copy_from_user(skb_put(skb, size), buf + sent, size); - else - memcpy(skb_put(skb, size), buf + sent, size); + memcpy(skb_put(skb, size), buf + sent, size); if ((err = rfcomm_dlc_send(dlc, skb)) < 0) { kfree_skb(skb); diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index f0c93caf601c..eb430e81d02f 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -52,7 +52,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp); static void ircomm_tty_close(struct tty_struct * tty, struct file *filp); -static int ircomm_tty_write(struct tty_struct * tty, int from_user, +static int ircomm_tty_write(struct tty_struct * tty, const unsigned char *buf, int count); static int ircomm_tty_write_room(struct tty_struct *tty); static void ircomm_tty_throttle(struct tty_struct *tty); @@ -662,14 +662,14 @@ static void ircomm_tty_do_softint(void *private_) } /* - * Function ircomm_tty_write (tty, from_user, buf, count) + * Function ircomm_tty_write (tty, buf, count) * * This routine is called by the kernel to write a series of characters * to the tty device. The characters may come from user space or kernel * space. This routine will return the number of characters actually * accepted for writing. This routine is mandatory. */ -static int ircomm_tty_write(struct tty_struct *tty, int from_user, +static int ircomm_tty_write(struct tty_struct *tty, const unsigned char *ubuf, int count) { struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; @@ -713,21 +713,8 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user, if (count < 1) return 0; - /* Additional copy to avoid copy_from_user() under spinlock. - * We tradeoff this extra copy to allow to pack more the - * IrCOMM frames. This is advantageous because the IrDA link - * is the bottleneck. */ - if (from_user) { - kbuf = kmalloc(count, GFP_KERNEL); - if (kbuf == NULL) - return -ENOMEM; - if (copy_from_user(kbuf, ubuf, count)) { - kfree(kbuf); - return -EFAULT; - } - } else - /* The buffer is already in kernel space */ - kbuf = (unsigned char *) ubuf; + /* The buffer is already in kernel space */ + kbuf = (unsigned char *) ubuf; /* Protect our manipulation of self->tx_skb and related */ spin_lock_irqsave(&self->spinlock, flags); @@ -781,8 +768,6 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user, self->max_header_size); if (!skb) { spin_unlock_irqrestore(&self->spinlock, flags); - if (from_user) - kfree(kbuf); return -ENOBUFS; } skb_reserve(skb, self->max_header_size); @@ -801,9 +786,6 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user, spin_unlock_irqrestore(&self->spinlock, flags); - if (from_user) - kfree(kbuf); - /* * Schedule a new thread which will transmit the frame as soon * as possible, but at a safe point in time. We do this so the -- cgit v1.2.3 From 74ad0fc69ce520c2c5e65543a581869e8b206805 Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Wed, 20 Oct 2004 20:57:15 -0700 Subject: [PATCH] x86_64: no TIOCSBRK/TIOCCBRK in ia32 emulation In ia32 emulation, the amd64 kernel refuses the ioctls TIOCSBRK and TIOCCBRK with EINVAL. I've attached a patch that adds them to the compatibility list. Since all architectures have these ioctls ("m68knommu" inherits them from "m68k", "um" from its host) and use the same code, I think adding them to compat_ioctl.h is the correct choice (as opposed to adding them to arch/x86_64/ia32/ia32_ioctl.c). Signed-off-by: Werner Almesberger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/compat_ioctl.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h index 71da7d1260cd..a9d099134bf2 100644 --- a/include/linux/compat_ioctl.h +++ b/include/linux/compat_ioctl.h @@ -23,6 +23,8 @@ COMPATIBLE_IOCTL(TCSETS) COMPATIBLE_IOCTL(TCSETSW) COMPATIBLE_IOCTL(TCSETSF) COMPATIBLE_IOCTL(TIOCLINUX) +COMPATIBLE_IOCTL(TIOCSBRK) +COMPATIBLE_IOCTL(TIOCCBRK) /* Little t */ COMPATIBLE_IOCTL(TIOCGETD) COMPATIBLE_IOCTL(TIOCSETD) -- cgit v1.2.3 From 6525a5216c4c27aaef41f2edc9b8b94e3a62468d Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 21 Oct 2004 20:30:23 +0200 Subject: [ide] remove broken pdc4030 driver Sigh, I broke it by accident 16 months ago and nobody has noticed (I suspect that it was non-functional even earlier). Additionally, this driver: * should be converted to use scatterlists * has verbose debugging enabled by default * needs hacks all over IDE code * is guilty of crimes against ide_hwifs[] Just remove it for now. Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/ide.txt | 4 +- drivers/ide/Kconfig | 13 - drivers/ide/ide-disk.c | 6 +- drivers/ide/ide-io.c | 12 - drivers/ide/ide-probe.c | 19 +- drivers/ide/ide-proc.c | 1 - drivers/ide/ide.c | 18 +- drivers/ide/legacy/Makefile | 1 - drivers/ide/legacy/pdc4030.c | 679 ------------------------------------------- drivers/ide/legacy/pdc4030.h | 70 ----- drivers/ide/pci/sgiioc4.c | 1 - include/linux/ide.h | 4 +- 12 files changed, 9 insertions(+), 819 deletions(-) delete mode 100644 drivers/ide/legacy/pdc4030.c delete mode 100644 drivers/ide/legacy/pdc4030.h (limited to 'include/linux') diff --git a/Documentation/ide.txt b/Documentation/ide.txt index 58853a4ef4f0..a1c34d3800c9 100644 --- a/Documentation/ide.txt +++ b/Documentation/ide.txt @@ -304,7 +304,7 @@ Summary of ide driver parameters for kernel command line "ide=reverse" : formerly called to pci sub-system, but now local. -The following are valid ONLY on ide0 (except dc4030), which usually corresponds +The following are valid ONLY on ide0, which usually corresponds to the first ATA interface found on the particular host, and the defaults for the base,ctl ports must not be altered. @@ -315,7 +315,7 @@ the base,ctl ports must not be altered. "ide0=qd65xx" : probe/support qd65xx interface "ide0=ali14xx" : probe/support ali14xx chipsets (ALI M1439/M1443/M1445) "ide0=umc8672" : probe/support umc8672 chipsets - "idex=dc4030" : probe/support Promise DC4030VL interface + "ide=doubler" : probe/support IDE doublers on Amiga There may be more options than shown -- use the source, Luke! diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 4305f7cc2a2a..67e9a49db96c 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -1007,19 +1007,6 @@ config BLK_DEV_HT6560B See the and files for more info. -config BLK_DEV_PDC4030 - tristate "PROMISE DC4030 support (EXPERIMENTAL)" - depends on BLK_DEV_IDEDISK && EXPERIMENTAL - help - This driver provides support for the secondary IDE interface and - cache of the original Promise IDE chipsets, e.g. DC4030 and DC5030. - It is nothing to do with the later range of Promise UDMA chipsets - - see the PDC_202XX support for these. CD-ROM and TAPE devices are not - supported (and probably never will be since I don't think the cards - support them). This driver is enabled at runtime using the "ide0=dc4030" - or "ide1=dc4030" kernel boot parameter. See the - file for more info. - config BLK_DEV_QD65XX tristate "QDI QD65xx support" help diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 6dc7a643e78c..320a2427e194 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -71,10 +71,6 @@ #include #include -/* FIXME: some day we shouldn't need to look in here! */ - -#include "legacy/pdc4030.h" - /* * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity" * value for this drive (from its reported identification information). @@ -863,6 +859,8 @@ static sector_t idedisk_capacity (ide_drive_t *drive) return drive->capacity64 - drive->sect0; } +#define IS_PDC4030_DRIVE 0 + static ide_startstop_t idedisk_special (ide_drive_t *drive) { special_t *s = &drive->special; diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 5663a6644e11..d05160722f73 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -1587,18 +1587,6 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio int where = ELEVATOR_INSERT_BACK, err; int must_wait = (action == ide_wait || action == ide_head_wait); -#ifdef CONFIG_BLK_DEV_PDC4030 - /* - * FIXME: there should be a drive or hwif->special - * handler that points here by default, not hacks - * in the ide-io.c code - * - * FIXME2: That code breaks power management if used with - * this chipset, that really doesn't belong here ! - */ - if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL) - return -ENOSYS; /* special drive cmds not supported */ -#endif rq->errors = 0; rq->rq_status = RQ_ACTIVE; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index f8a9d269a567..b618fd4481fc 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -180,12 +180,6 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) if (cmd == WIN_PIDENTIFY) { u8 type = (id->config >> 8) & 0x1f; printk("ATAPI "); -#ifdef CONFIG_BLK_DEV_PDC4030 - if (hwif->channel == 1 && hwif->chipset == ide_pdc4030) { - printk(" -- not supported on 2nd Promise port\n"); - goto err_misc; - } -#endif /* CONFIG_BLK_DEV_PDC4030 */ switch (type) { case ide_floppy: if (!strstr(id->model, "CD-ROM")) { @@ -297,13 +291,9 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) /* disable dma & overlap */ hwif->OUTB(0, IDE_FEATURE_REG); - if (hwif->identify != NULL) { - if (hwif->identify(drive)) - return 1; - } else { - /* ask drive for ID */ - hwif->OUTB(cmd, IDE_COMMAND_REG); - } + /* ask drive for ID */ + hwif->OUTB(cmd, IDE_COMMAND_REG); + timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; timeout += jiffies; do { @@ -676,9 +666,6 @@ static void probe_hwif(ide_hwif_t *hwif) return; if ((hwif->chipset != ide_4drives || !hwif->mate || !hwif->mate->present) && -#ifdef CONFIG_BLK_DEV_PDC4030 - (hwif->chipset != ide_pdc4030 || hwif->channel == 0) && -#endif /* CONFIG_BLK_DEV_PDC4030 */ (ide_hwif_request_regions(hwif))) { u16 msgout = 0; for (unit = 0; unit < MAX_DRIVES; ++unit) { diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 07c989bb18e2..145c34930adb 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -314,7 +314,6 @@ static int proc_ide_read_imodel case ide_qd65xx: name = "qd65xx"; break; case ide_umc8672: name = "umc8672"; break; case ide_ht6560b: name = "ht6560b"; break; - case ide_pdc4030: name = "pdc4030"; break; case ide_rz1000: name = "rz1000"; break; case ide_trm290: name = "trm290"; break; case ide_cmd646: name = "cmd646"; break; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 865b7878cac5..fc8f056a31fd 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -668,7 +668,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->cds = tmp_hwif->cds; #endif - hwif->identify = tmp_hwif->identify; hwif->tuneproc = tmp_hwif->tuneproc; hwif->speedproc = tmp_hwif->speedproc; hwif->selectproc = tmp_hwif->selectproc; @@ -1778,9 +1777,6 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m return 0; /* zero = nothing matched */ } -#ifdef CONFIG_BLK_DEV_PDC4030 -static int __initdata probe_pdc4030; -#endif #ifdef CONFIG_BLK_DEV_ALI14XX static int __initdata probe_ali14xx; extern int ali14xx_init(void); @@ -1949,7 +1945,7 @@ int __init ide_setup (char *s) "noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66", "minus8", "minus9", "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb", - "dtc2278", "umc8672", "ali14xx", "dc4030", NULL }; + "dtc2278", "umc8672", "ali14xx", NULL }; hw = s[3] - '0'; hwif = &ide_hwifs[hw]; i = match_parm(&s[4], ide_words, vals, 3); @@ -1975,11 +1971,6 @@ int __init ide_setup (char *s) } switch (i) { -#ifdef CONFIG_BLK_DEV_PDC4030 - case -18: /* "dc4030" */ - probe_pdc4030 = 1; - goto done; -#endif #ifdef CONFIG_BLK_DEV_ALI14XX case -17: /* "ali14xx" */ probe_ali14xx = 1; @@ -2114,13 +2105,6 @@ static void __init probe_for_hwifs (void) ide_probe_for_cmd640x(); } #endif /* CONFIG_BLK_DEV_CMD640 */ -#ifdef CONFIG_BLK_DEV_PDC4030 - { - extern int pdc4030_init(void); - if (probe_pdc4030) - (void)pdc4030_init(); - } -#endif /* CONFIG_BLK_DEV_PDC4030 */ #ifdef CONFIG_BLK_DEV_IDE_PMAC { extern void pmac_ide_probe(void); diff --git a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile index c0f353e57149..c7971061767e 100644 --- a/drivers/ide/legacy/Makefile +++ b/drivers/ide/legacy/Makefile @@ -2,7 +2,6 @@ obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o -obj-$(CONFIG_BLK_DEV_PDC4030) += pdc4030.o obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o diff --git a/drivers/ide/legacy/pdc4030.c b/drivers/ide/legacy/pdc4030.c deleted file mode 100644 index 86219e18f287..000000000000 --- a/drivers/ide/legacy/pdc4030.c +++ /dev/null @@ -1,679 +0,0 @@ -/* -*- linux-c -*- - * linux/drivers/ide/legacy/pdc4030.c Version 0.90 May 27, 1999 - * - * Copyright (C) 1995-2002 Linus Torvalds & authors (see below) - */ - -/* - * Principal Author/Maintainer: Peter Denison - * - * This file provides support for the second port and cache of Promise - * IDE interfaces, e.g. DC4030VL, DC4030VL-1 and DC4030VL-2. - * - * Thanks are due to Mark Lord for advice and patiently answering stupid - * questions, and all those mugs^H^H^H^Hbrave souls who've tested this, - * especially Andre Hedrick. - * - * Version 0.01 Initial version, #include'd in ide.c rather than - * compiled separately. - * Reads use Promise commands, writes as before. Drives - * on second channel are read-only. - * Version 0.02 Writes working on second channel, reads on both - * channels. Writes fail under high load. Suspect - * transfers of >127 sectors don't work. - * Version 0.03 Brought into line with ide.c version 5.27. - * Other minor changes. - * Version 0.04 Updated for ide.c version 5.30 - * Changed initialization strategy - * Version 0.05 Kernel integration. -ml - * Version 0.06 Ooops. Add hwgroup to direct call of ide_intr() -ml - * Version 0.07 Added support for DC4030 variants - * Secondary interface autodetection - * Version 0.08 Renamed to pdc4030.c - * Version 0.09 Obsolete - never released - did manual write request - * splitting before max_sectors[major][minor] available. - * Version 0.10 Updated for 2.1 series of kernels - * Version 0.11 Updated for 2.3 series of kernels - * Autodetection code added. - * - * Version 0.90 Transition to BETA code. No lost/unexpected interrupts - */ - -/* - * Once you've compiled it in, you'll have to also enable the interface - * setup routine from the kernel command line, as in - * - * 'linux ide0=dc4030' or 'linux ide1=dc4030' - * - * It should now work as a second controller also ('ide1=dc4030') but only - * if you DON'T have BIOS V4.44, which has a bug. If you have this version - * and EPROM programming facilities, you need to fix 4 bytes: - * 2496: 81 81 - * 2497: 3E 3E - * 2498: 22 98 * - * 2499: 06 05 * - * 249A: F0 F0 - * 249B: 01 01 - * ... - * 24A7: 81 81 - * 24A8: 3E 3E - * 24A9: 22 98 * - * 24AA: 06 05 * - * 24AB: 70 70 - * 24AC: 01 01 - * - * As of January 1999, Promise Technology Inc. have finally supplied me with - * some technical information which has shed a glimmer of light on some of the - * problems I was having, especially with writes. - * - * There are still potential problems with the robustness and efficiency of - * this driver because I still don't understand what the card is doing with - * interrupts, however, it has been stable for a while with no reports of ill - * effects. - */ - -#define DEBUG_READ -#define DEBUG_WRITE -#define __PROMISE_4030 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "pdc4030.h" - -static ide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block); - -/* - * promise_selectproc() is invoked by ide.c - * in preparation for access to the specified drive. - */ -static void promise_selectproc (ide_drive_t *drive) -{ - unsigned int number; - - number = (HWIF(drive)->channel << 1) + drive->select.b.unit; - HWIF(drive)->OUTB(number, IDE_FEATURE_REG); -} - -/* - * pdc4030_cmd handles the set of vendor specific commands that are initiated - * by command F0. They all have the same success/failure notification - - * 'P' (=0x50) on success, 'p' (=0x70) on failure. - */ -int pdc4030_cmd(ide_drive_t *drive, u8 cmd) -{ - unsigned long timeout; - u8 status_val; - - promise_selectproc(drive); /* redundant? */ - HWIF(drive)->OUTB(0xF3, IDE_SECTOR_REG); - HWIF(drive)->OUTB(cmd, IDE_SELECT_REG); - HWIF(drive)->OUTB(PROMISE_EXTENDED_COMMAND, IDE_COMMAND_REG); - timeout = HZ * 10; - timeout += jiffies; - do { - if(time_after(jiffies, timeout)) { - return 2; /* device timed out */ - } - /* Delays at least 10ms to give interface a chance */ - mdelay(10); - status_val = HWIF(drive)->INB(IDE_SECTOR_REG); - } while (status_val != 0x50 && status_val != 0x70); - - if(status_val == 0x50) - return 0; /* device returned success */ - else - return 1; /* device returned failure */ -} - -/* - * pdc4030_identify sends a vendor-specific IDENTIFY command to the drive - */ -int pdc4030_identify(ide_drive_t *drive) -{ - return pdc4030_cmd(drive, PROMISE_IDENTIFY); -} - -/* - * setup_pdc4030() - * Completes the setup of a Promise DC4030 controller card, once found. - */ -int __init setup_pdc4030(ide_hwif_t *hwif) -{ - ide_drive_t *drive; - ide_hwif_t *hwif2; - struct dc_ident ident; - int i; - ide_startstop_t startstop; - - if (!hwif) return 0; - - drive = &hwif->drives[0]; - hwif2 = &ide_hwifs[hwif->index+1]; - if (hwif->chipset == ide_pdc4030) /* we've already been found ! */ - return 1; - - if (hwif->INB(IDE_NSECTOR_REG) == 0xFF || - hwif->INB(IDE_SECTOR_REG) == 0xFF) { - return 0; - } - if (IDE_CONTROL_REG) - hwif->OUTB(0x08, IDE_CONTROL_REG); - if (pdc4030_cmd(drive,PROMISE_GET_CONFIG)) { - return 0; - } - if (ide_wait_stat(&startstop, drive,DATA_READY,BAD_W_STAT,WAIT_DRQ)) { - printk(KERN_INFO - "%s: Failed Promise read config!\n",hwif->name); - return 0; - } - hwif->ata_input_data(drive, &ident, SECTOR_WORDS); - if (ident.id[1] != 'P' || ident.id[0] != 'T') { - return 0; - } - printk(KERN_INFO "%s: Promise caching controller, ",hwif->name); - switch(ident.type) { - case 0x43: printk("DC4030VL-2, "); break; - case 0x41: printk("DC4030VL-1, "); break; - case 0x40: printk("DC4030VL, "); break; - default: - printk("unknown - type 0x%02x - please report!\n" - ,ident.type); - printk("Please e-mail the following data to " - "promise@pnd-pc.demon.co.uk along with\n" - "a description of your card and drives:\n"); - for (i=0; i < 0x90; i++) { - printk("%02x ", ((unsigned char *)&ident)[i]); - if ((i & 0x0f) == 0x0f) printk("\n"); - } - return 0; - } - printk("%dKB cache, ",(int)ident.cache_mem); - switch(ident.irq) { - case 0x00: hwif->irq = 14; break; - case 0x01: hwif->irq = 12; break; - default: hwif->irq = 15; break; - } - printk("on IRQ %d\n",hwif->irq); - - /* - * Once found and identified, we set up the next hwif in the array - * (hwif2 = ide_hwifs[hwif->index+1]) with the same io ports, irq - * and other settings as the main hwif. This gives us two "mated" - * hwifs pointing to the Promise card. - * - * We also have to shift the default values for the remaining - * interfaces "up by one" to make room for the second interface on the - * same set of values. - */ - - hwif->chipset = hwif2->chipset = ide_pdc4030; - hwif->mate = hwif2; - hwif2->mate = hwif; - hwif2->channel = 1; - hwif->rqsize = hwif2->rqsize = 127; - hwif->no_lba48 = hwif2->no_lba48 = 1; - hwif->selectproc = hwif2->selectproc = &promise_selectproc; - hwif->serialized = hwif2->serialized = 1; - /* DC4030 hosted drives need their own identify... */ - hwif->identify = hwif2->identify = &pdc4030_identify; - - /* Override the normal ide disk read/write. */ - hwif->rw_disk = promise_rw_disk; - hwif2->rw_disk = promise_rw_disk; - - /* Shift the remaining interfaces up by one */ - for (i=MAX_HWIFS-1 ; i > hwif->index+1 ; i--) { - ide_hwif_t *h = &ide_hwifs[i]; - -#ifdef DEBUG - printk(KERN_DEBUG "pdc4030: Shifting i/f %d values to i/f %d\n",i-1,i); -#endif /* DEBUG */ - ide_init_hwif_ports(&h->hw, (h-1)->io_ports[IDE_DATA_OFFSET], 0, NULL); - memcpy(h->io_ports, h->hw.io_ports, sizeof(h->io_ports)); - h->noprobe = (h-1)->noprobe; - } - ide_init_hwif_ports(&hwif2->hw, hwif->io_ports[IDE_DATA_OFFSET], 0, NULL); - memcpy(hwif2->io_ports, hwif->hw.io_ports, sizeof(hwif2->io_ports)); - hwif2->irq = hwif->irq; - hwif2->hw.irq = hwif->hw.irq = hwif->irq; - for (i=0; i<2 ; i++) { - hwif->drives[i].io_32bit = 3; - hwif2->drives[i].io_32bit = 3; - hwif->drives[i].keep_settings = 1; - hwif2->drives[i].keep_settings = 1; - if (!ident.current_tm[i].cyl) - hwif->drives[i].noprobe = 1; - if (!ident.current_tm[i+2].cyl) - hwif2->drives[i].noprobe = 1; - } - - probe_hwif_init(&ide_hwifs[hwif->index]); - probe_hwif_init(&ide_hwifs[hwif2->index]); - - return 1; -} - -/* - * detect_pdc4030() - * Tests for the presence of a DC4030 Promise card on this interface - * Returns: 1 if found, 0 if not found - */ -int __init detect_pdc4030(ide_hwif_t *hwif) -{ - ide_drive_t *drive = &hwif->drives[0]; - - if (IDE_DATA_REG == 0) { /* Skip test for non-existent interface */ - return 0; - } - hwif->OUTB(0xF3, IDE_SECTOR_REG); - hwif->OUTB(0x14, IDE_SELECT_REG); - hwif->OUTB(PROMISE_EXTENDED_COMMAND, IDE_COMMAND_REG); - - msleep(50); - - if (hwif->INB(IDE_ERROR_REG) == 'P' && - hwif->INB(IDE_NSECTOR_REG) == 'T' && - hwif->INB(IDE_SECTOR_REG) == 'I') { - return 1; - } else { - return 0; - } -} - -int __init pdc4030_init(void) -{ - unsigned int index; - ide_hwif_t *hwif; - - for (index = 0; index < MAX_HWIFS; index++) { - hwif = &ide_hwifs[index]; - if (hwif->chipset == ide_unknown && detect_pdc4030(hwif)) { - if (!setup_pdc4030(hwif)) - return -ENODEV; - return 0; - } - } - return -ENODEV; -} - -#ifdef MODULE -module_init(pdc4030_init); -#endif - -MODULE_AUTHOR("Peter Denison"); -MODULE_DESCRIPTION("Support of Promise 4030 VLB series IDE chipsets"); -MODULE_LICENSE("GPL"); - -/* - * promise_read_intr() is the handler for disk read/multread interrupts - */ -static ide_startstop_t promise_read_intr (ide_drive_t *drive) -{ - unsigned int sectors_left, sectors_avail, nsect; - struct request *rq = HWGROUP(drive)->rq; - ata_status_t status; - - status.all = HWIF(drive)->INB(IDE_STATUS_REG); - if (!OK_STAT(status.all, DATA_READY, BAD_R_STAT)) - return DRIVER(drive)->error(drive, __FUNCTION__, status.all); - -read_again: - do { - sectors_left = HWIF(drive)->INB(IDE_NSECTOR_REG); - HWIF(drive)->INB(IDE_SECTOR_REG); - } while (HWIF(drive)->INB(IDE_NSECTOR_REG) != sectors_left); - sectors_avail = rq->nr_sectors - sectors_left; - if (!sectors_avail) - goto read_again; - -read_next: - nsect = rq->current_nr_sectors; - if (nsect > sectors_avail) - nsect = sectors_avail; - sectors_avail -= nsect; - -#ifdef DEBUG_READ - printk(KERN_DEBUG "%s: %s: sectors(%lu-%lu), rem=%lu\n", - drive->name, __FUNCTION__, - (unsigned long)rq->sector, - (unsigned long)rq->sector + nsect - 1, - (unsigned long)rq->nr_sectors - nsect); -#endif /* DEBUG_READ */ - - HWIF(drive)->ata_input_data(drive, rq->buffer, nsect * SECTOR_WORDS); - rq->buffer += nsect<<9; - rq->sector += nsect; - rq->errors = 0; - rq->nr_sectors -= nsect; - if (!rq->current_nr_sectors) - DRIVER(drive)->end_request(drive, 1, 0); - -/* - * Now the data has been read in, do the following: - * - * if there are still sectors left in the request, - * if we know there are still sectors available from the interface, - * go back and read the next bit of the request. - * else if DRQ is asserted, there are more sectors available, so - * go back and find out how many, then read them in. - * else if BUSY is asserted, we are going to get an interrupt, so - * set the handler for the interrupt and just return - */ - if (rq->nr_sectors > 0) { - if (sectors_avail) - goto read_next; - status.all = HWIF(drive)->INB(IDE_STATUS_REG); - if (status.b.drq) - goto read_again; - if (status.b.bsy) { - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, - &promise_read_intr, - WAIT_CMD, - NULL); -#ifdef DEBUG_READ - printk(KERN_DEBUG "%s: promise_read: waiting for" - "interrupt\n", drive->name); -#endif /* DEBUG_READ */ - return ide_started; - } - printk(KERN_ERR "%s: Eeek! promise_read_intr: sectors left " - "!DRQ !BUSY\n", drive->name); - return DRIVER(drive)->error(drive, - "promise read intr", status.all); - } - return ide_stopped; -} - -/* - * promise_complete_pollfunc() - * This is the polling function for waiting (nicely!) until drive stops - * being busy. It is invoked at the end of a write, after the previous poll - * has finished. - * - * Once not busy, the end request is called. - */ -static ide_startstop_t promise_complete_pollfunc(ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - struct request *rq = &hwgroup->wrq; - struct bio *bio = rq->bio; - - if ((HWIF(drive)->INB(IDE_STATUS_REG)) & BUSY_STAT) { - if (time_before(jiffies, hwgroup->poll_timeout)) { - if (hwgroup->handler != NULL) - BUG(); - ide_set_handler(drive, - &promise_complete_pollfunc, - HZ/100, - NULL); - return ide_started; /* continue polling... */ - } - hwgroup->poll_timeout = 0; - printk(KERN_ERR "%s: completion timeout - still busy!\n", - drive->name); - return DRIVER(drive)->error(drive, "busy timeout", - HWIF(drive)->INB(IDE_STATUS_REG)); - } - - hwgroup->poll_timeout = 0; -#ifdef DEBUG_WRITE - printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name); -#endif /* DEBUG_WRITE */ - - bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments; - rq = hwgroup->rq; - DRIVER(drive)->end_request(drive, 1, rq->hard_nr_sectors); - - return ide_stopped; -} - -/* - * promise_multwrite() transfers a block of up to mcount sectors of data - * to a drive as part of a disk multiple-sector write operation. - */ -static void promise_multwrite (ide_drive_t *drive, unsigned int mcount) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - struct request *rq = &hwgroup->wrq; - - do { - char *buffer; - int nsect = rq->current_nr_sectors; - - if (nsect > mcount) - nsect = mcount; - mcount -= nsect; - buffer = rq->buffer; - - rq->sector += nsect; - rq->buffer += nsect << 9; - rq->nr_sectors -= nsect; - rq->current_nr_sectors -= nsect; - - /* Do we move to the next bh after this? */ - if (!rq->current_nr_sectors) { - struct bio *bio = rq->bio; - - /* - * only move to next bio, when we have processed - * all bvecs in this one. - */ - if (++bio->bi_idx >= bio->bi_vcnt) { - bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments; - bio = bio->bi_next; - } - - /* end early early we ran out of requests */ - if (!bio) { - mcount = 0; - } else { - rq->bio = bio; - rq->nr_cbio_segments = bio_segments(bio); - rq->current_nr_sectors = bio_cur_sectors(bio); - rq->hard_cur_sectors = rq->current_nr_sectors; - } - } - - /* - * Ok, we're all setup for the interrupt - * re-entering us on the last transfer. - */ - taskfile_output_data(drive, buffer, nsect<<7); - } while (mcount); -} - -/* - * promise_write_pollfunc() is the handler for disk write completion polling. - */ -static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - struct request *rq = &hwgroup->wrq; - struct bio *bio = rq->bio; - - if (HWIF(drive)->INB(IDE_NSECTOR_REG) != 0) { - if (time_before(jiffies, hwgroup->poll_timeout)) { - if (hwgroup->handler != NULL) - BUG(); - ide_set_handler(drive, - &promise_write_pollfunc, - HZ/100, - NULL); - return ide_started; /* continue polling... */ - } - hwgroup->poll_timeout = 0; - printk(KERN_ERR "%s: write timed-out!\n",drive->name); - bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments; - return DRIVER(drive)->error(drive, "write timeout", - HWIF(drive)->INB(IDE_STATUS_REG)); - } - - /* - * Now write out last 4 sectors and poll for not BUSY - */ - promise_multwrite(drive, 4); - hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - if (hwgroup->handler != NULL) - BUG(); - ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL); -#ifdef DEBUG_WRITE - printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n", - drive->name, HWIF(drive)->INB(IDE_STATUS_REG)); -#endif /* DEBUG_WRITE */ - return ide_started; -} - -/* - * promise_write() transfers a block of one or more sectors of data to a - * drive as part of a disk write operation. All but 4 sectors are transferred - * in the first attempt, then the interface is polled (nicely!) for completion - * before the final 4 sectors are transferred. There is no interrupt generated - * on writes (at least on the DC4030VL-2), we just have to poll for NOT BUSY. - */ -static ide_startstop_t promise_write (ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - struct request *rq = &hwgroup->wrq; - -#ifdef DEBUG_WRITE - printk(KERN_DEBUG "%s: %s: sectors(%lu-%lu)\n", - drive->name, __FUNCTION__, - (unsigned long)rq->sector, - (unsigned long)rq->sector + rq->nr_sectors - 1); -#endif /* DEBUG_WRITE */ - - /* - * If there are more than 4 sectors to transfer, do n-4 then go into - * the polling strategy as defined above. - */ - if (rq->nr_sectors > 4) { - promise_multwrite(drive, rq->nr_sectors - 4); - hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - if (hwgroup->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL); - return ide_started; - } else { - /* - * There are 4 or fewer sectors to transfer, do them all in one go - * and wait for NOT BUSY. - */ - promise_multwrite(drive, rq->nr_sectors); - hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - if (hwgroup->handler != NULL) - BUG(); - ide_set_handler(drive, - &promise_complete_pollfunc, - HZ/100, - NULL); - -#ifdef DEBUG_WRITE - printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, " - "status = %02x\n", drive->name, - HWIF(drive)->INB(IDE_STATUS_REG)); -#endif /* DEBUG_WRITE */ - return ide_started; - } -} - -/* - * do_pdc4030_io() is called from promise_rw_disk, having had the block number - * already set up. It issues a READ or WRITE command to the Promise - * controller, assuming LBA has been used to set up the block number. - */ -ide_startstop_t do_pdc4030_io (ide_drive_t *drive, struct request *rq) -{ - ide_startstop_t startstop; - unsigned long timeout; - u8 stat = 0; - - if (rq_data_dir(rq) == READ) { - HWIF(drive)->OUTB(PROMISE_READ, IDE_COMMAND_REG); -/* - * The card's behaviour is odd at this point. If the data is - * available, DRQ will be true, and no interrupt will be - * generated by the card. If this is the case, we need to call the - * "interrupt" handler (promise_read_intr) directly. Otherwise, if - * an interrupt is going to occur, bit0 of the SELECT register will - * be high, so we can set the handler the just return and be interrupted. - * If neither of these is the case, we wait for up to 50ms (badly I'm - * afraid!) until one of them is. - */ - timeout = jiffies + HZ/20; /* 50ms wait */ - do { - stat = HWIF(drive)->INB(IDE_STATUS_REG); - if (stat & DRQ_STAT) { - udelay(1); - return promise_read_intr(drive); - } - if (HWIF(drive)->INB(IDE_SELECT_REG) & 0x01) { -#ifdef DEBUG_READ - printk(KERN_DEBUG "%s: read: waiting for " - "interrupt\n", drive->name); -#endif /* DEBUG_READ */ - ide_set_handler(drive, - &promise_read_intr, - WAIT_CMD, - NULL); - return ide_started; - } - udelay(1); - } while (time_before(jiffies, timeout)); - - printk(KERN_ERR "%s: reading: No DRQ and not " - "waiting - Odd!\n", drive->name); - return ide_stopped; - } else { - HWIF(drive)->OUTB(PROMISE_WRITE, IDE_COMMAND_REG); - if (ide_wait_stat(&startstop, drive, DATA_READY, - drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing " - "PROMISE_WRITE\n", drive->name); - return startstop; - } - if (!drive->unmask) - local_irq_disable(); - HWGROUP(drive)->wrq = *rq; /* scratchpad */ - return promise_write(drive); - } -} - -static ide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block) -{ - /* The four drives on the two logical (one physical) interfaces - are distinguished by writing the drive number (0-3) to the - Feature register. - FIXME: Is promise_selectproc now redundant?? - */ - ide_hwif_t *hwif = HWIF(drive); - int drive_number = (hwif->channel << 1) + drive->select.b.unit; - - BUG_ON(rq->nr_sectors > 127); - - if (IDE_CONTROL_REG) - hwif->OUTB(drive->ctl, IDE_CONTROL_REG); - hwif->OUTB(drive_number, IDE_FEATURE_REG); - hwif->OUTB(rq->nr_sectors, IDE_NSECTOR_REG); - hwif->OUTB(block,IDE_SECTOR_REG); - hwif->OUTB(block>>=8,IDE_LCYL_REG); - hwif->OUTB(block>>=8,IDE_HCYL_REG); - hwif->OUTB(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG); - - return do_pdc4030_io(drive, rq); -} diff --git a/drivers/ide/legacy/pdc4030.h b/drivers/ide/legacy/pdc4030.h deleted file mode 100644 index ffae5bf7e2f4..000000000000 --- a/drivers/ide/legacy/pdc4030.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * linux/drivers/ide/legacy/pdc4030.h - * - * Copyright (C) 1995-1998 Linus Torvalds & authors - */ - -/* - * Principal author: Peter Denison - */ - -#ifndef IDE_PROMISE_H -#define IDE_PROMISE_H - -#include - -#ifndef CONFIG_BLK_DEV_PDC4030 -# ifdef _IDE_DISK - -# define IS_PDC4030_DRIVE (0) /* auto-NULLs out pdc4030 code */ - -ide_startstop_t promise_rw_disk(ide_drive_t *, struct request *, unsigned long); - -ide_startstop_t promise_rw_disk(ide_drive_t *drive, struct request *rq, unsigned long block) -{ - return ide_stopped; -} -# endif /* _IDE_DISK */ -#else /* CONFIG_BLK_DEV_PDC4030 */ -# ifdef _IDE_DISK -# define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030) - -ide_startstop_t promise_rw_disk(ide_drive_t *, struct request *, unsigned long); - -# endif /* _IDE_DISK */ -#endif /* CONFIG_BLK_DEV_PDC4030 */ - -#ifdef __PROMISE_4030 -#define PROMISE_EXTENDED_COMMAND 0xF0 -#define PROMISE_READ 0xF2 -#define PROMISE_WRITE 0xF3 -/* Extended commands - main command code = 0xf0 */ -#define PROMISE_GET_CONFIG 0x10 -#define PROMISE_IDENTIFY 0x20 - -struct translation_mode { - u16 cyl; - u8 head; - u8 sect; -}; - -struct dc_ident { - u8 type; - u8 unknown1; - u8 hw_revision; - u8 firmware_major; - u8 firmware_minor; - u8 bios_address; - u8 irq; - u8 unknown2; - u16 cache_mem; - u16 unknown3; - u8 id[2]; - u16 info; - struct translation_mode current_tm[4]; - u8 pad[SECTOR_WORDS*4 - 32]; -}; - -#endif /* __PROMISE_4030 */ - -#endif /* IDE_PROMISE_H */ diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 9edeea2f4c5b..88ca26a2c245 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -602,7 +602,6 @@ ide_init_sgiioc4(ide_hwif_t * hwif) hwif->ultra_mask = 0x0; /* Disable Ultra DMA */ hwif->mwdma_mask = 0x2; /* Multimode-2 DMA */ hwif->swdma_mask = 0x2; - hwif->identify = NULL; hwif->tuneproc = NULL; /* Sets timing for PIO mode */ hwif->speedproc = NULL; /* Sets timing for DMA &/or PIO modes */ hwif->selectproc = NULL;/* Use the default routine to select drive */ diff --git a/include/linux/ide.h b/include/linux/ide.h index 10d947f64cb2..f4bafe0cd0fb 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -242,7 +242,7 @@ typedef int (ide_ack_intr_t)(struct hwif_s *); typedef enum { ide_unknown, ide_generic, ide_pci, ide_cmd640, ide_dtc2278, ide_ali14xx, ide_qd65xx, ide_umc8672, ide_ht6560b, - ide_pdc4030, ide_rz1000, ide_trm290, + ide_rz1000, ide_trm290, ide_cmd646, ide_cy82c693, ide_4drives, ide_pmac, ide_etrax100, ide_acorn, ide_forced @@ -832,8 +832,6 @@ typedef struct hwif_s { #if 0 ide_hwif_ops_t *hwifops; #else - /* routine is for HBA specific IDENTITY operations */ - int (*identify)(ide_drive_t *); /* routine to tune PIO mode for drives */ void (*tuneproc)(ide_drive_t *, u8); /* routine to retune DMA modes for drives */ -- cgit v1.2.3 From 2067e38ba4112b93db96e3ad1c89abd8434a787f Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 22 Oct 2004 05:22:42 +0200 Subject: [block] remove bio walking All users of this code were fixed to use scatterlists. Acked by Jens. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/block/ll_rw_blk.c | 114 ++-------------------------------------------- include/linux/blkdev.h | 36 +-------------- 2 files changed, 5 insertions(+), 145 deletions(-) (limited to 'include/linux') diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 40dff89509de..6880e48dc6b4 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -2360,9 +2360,7 @@ again: break; bio->bi_next = req->bio; - req->cbio = req->bio = bio; - req->nr_cbio_segments = bio_segments(bio); - req->nr_cbio_sectors = bio_sectors(bio); + req->bio = bio; /* * may not be valid. if the low level driver said @@ -2434,11 +2432,9 @@ get_rq: req->current_nr_sectors = req->hard_cur_sectors = cur_nr_sectors; req->nr_phys_segments = bio_phys_segments(q, bio); req->nr_hw_segments = bio_hw_segments(q, bio); - req->nr_cbio_segments = bio_segments(bio); - req->nr_cbio_sectors = bio_sectors(bio); req->buffer = bio_data(bio); /* see ->buffer comment above */ req->waiting = NULL; - req->cbio = req->bio = req->biotail = bio; + req->bio = req->biotail = bio; req->rq_disk = bio->bi_bdev->bd_disk; req->start_time = jiffies; @@ -2685,83 +2681,6 @@ void submit_bio(int rw, struct bio *bio) EXPORT_SYMBOL(submit_bio); -/** - * blk_rq_next_segment - * @rq: the request being processed - * - * Description: - * Points to the next segment in the request if the current segment - * is complete. Leaves things unchanged if this segment is not over - * or if no more segments are left in this request. - * - * Meant to be used for bio traversal during I/O submission - * Does not affect any I/O completions or update completion state - * in the request, and does not modify any bio fields. - * - * Decrementing rq->nr_sectors, rq->current_nr_sectors and - * rq->nr_cbio_sectors as data is transferred is the caller's - * responsibility and should be done before calling this routine. - **/ -void blk_rq_next_segment(struct request *rq) -{ - if (rq->current_nr_sectors > 0) - return; - - if (rq->nr_cbio_sectors > 0) { - --rq->nr_cbio_segments; - rq->current_nr_sectors = blk_rq_vec(rq)->bv_len >> 9; - } else { - if ((rq->cbio = rq->cbio->bi_next)) { - rq->nr_cbio_segments = bio_segments(rq->cbio); - rq->nr_cbio_sectors = bio_sectors(rq->cbio); - rq->current_nr_sectors = bio_cur_sectors(rq->cbio); - } - } - - /* remember the size of this segment before we start I/O */ - rq->hard_cur_sectors = rq->current_nr_sectors; -} - -/** - * process_that_request_first - process partial request submission - * @req: the request being processed - * @nr_sectors: number of sectors I/O has been submitted on - * - * Description: - * May be used for processing bio's while submitting I/O without - * signalling completion. Fails if more data is requested than is - * available in the request in which case it doesn't advance any - * pointers. - * - * Assumes a request is correctly set up. No sanity checks. - * - * Return: - * 0 - no more data left to submit (not processed) - * 1 - data available to submit for this request (processed) - **/ -int process_that_request_first(struct request *req, unsigned int nr_sectors) -{ - unsigned int nsect; - - if (req->nr_sectors < nr_sectors) - return 0; - - req->nr_sectors -= nr_sectors; - req->sector += nr_sectors; - while (nr_sectors) { - nsect = min_t(unsigned, req->current_nr_sectors, nr_sectors); - req->current_nr_sectors -= nsect; - nr_sectors -= nsect; - if (req->cbio) { - req->nr_cbio_sectors -= nsect; - blk_rq_next_segment(req); - } - } - return 1; -} - -EXPORT_SYMBOL(process_that_request_first); - void blk_recalc_rq_segments(struct request *rq) { struct bio *bio, *prevbio = NULL; @@ -2797,8 +2716,7 @@ void blk_recalc_rq_sectors(struct request *rq, int nsect) rq->hard_nr_sectors -= nsect; /* - * Move the I/O submission pointers ahead if required, - * i.e. for drivers not aware of rq->cbio. + * Move the I/O submission pointers ahead if required. */ if ((rq->nr_sectors >= rq->hard_nr_sectors) && (rq->sector <= rq->hard_sector)) { @@ -2806,11 +2724,7 @@ void blk_recalc_rq_sectors(struct request *rq, int nsect) rq->nr_sectors = rq->hard_nr_sectors; rq->hard_cur_sectors = bio_cur_sectors(rq->bio); rq->current_nr_sectors = rq->hard_cur_sectors; - rq->nr_cbio_segments = bio_segments(rq->bio); - rq->nr_cbio_sectors = bio_sectors(rq->bio); rq->buffer = bio_data(rq->bio); - - rq->cbio = rq->bio; } /* @@ -3022,33 +2936,13 @@ void blk_rq_bio_prep(request_queue_t *q, struct request *rq, struct bio *bio) rq->current_nr_sectors = bio_cur_sectors(bio); rq->hard_cur_sectors = rq->current_nr_sectors; rq->hard_nr_sectors = rq->nr_sectors = bio_sectors(bio); - rq->nr_cbio_segments = bio_segments(bio); - rq->nr_cbio_sectors = bio_sectors(bio); rq->buffer = bio_data(bio); - rq->cbio = rq->bio = rq->biotail = bio; + rq->bio = rq->biotail = bio; } EXPORT_SYMBOL(blk_rq_bio_prep); -void blk_rq_prep_restart(struct request *rq) -{ - struct bio *bio; - - bio = rq->cbio = rq->bio; - if (bio) { - rq->nr_cbio_segments = bio_segments(bio); - rq->nr_cbio_sectors = bio_sectors(bio); - rq->hard_cur_sectors = bio_cur_sectors(bio); - rq->buffer = bio_data(bio); - } - rq->sector = rq->hard_sector; - rq->nr_sectors = rq->hard_nr_sectors; - rq->current_nr_sectors = rq->hard_cur_sectors; -} - -EXPORT_SYMBOL(blk_rq_prep_restart); - int kblockd_schedule_work(struct work_struct *work) { return queue_work(kblockd_workqueue, work); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index b2059869cb92..944d1088902e 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -125,13 +125,7 @@ struct request { /* no. of sectors left to complete in the current segment */ unsigned int hard_cur_sectors; - /* no. of segments left to submit in the current bio */ - unsigned short nr_cbio_segments; - /* no. of sectors left to submit in the current bio */ - unsigned long nr_cbio_sectors; - - struct bio *cbio; /* next bio to submit */ - struct bio *bio; /* next unfinished bio to complete */ + struct bio *bio; struct bio *biotail; void *elevator_private; @@ -465,32 +459,6 @@ static inline void blk_clear_queue_full(struct request_queue *q, int rw) */ #define blk_queue_headactive(q, head_active) -/* current index into bio being processed for submission */ -#define blk_rq_idx(rq) ((rq)->cbio->bi_vcnt - (rq)->nr_cbio_segments) - -/* current bio vector being processed */ -#define blk_rq_vec(rq) (bio_iovec_idx((rq)->cbio, blk_rq_idx(rq))) - -/* current offset with respect to start of the segment being submitted */ -#define blk_rq_offset(rq) \ - (((rq)->hard_cur_sectors - (rq)->current_nr_sectors) << 9) - -/* - * temporarily mapping a (possible) highmem bio (typically for PIO transfer) - */ - -/* Assumes rq->cbio != NULL */ -static inline char * rq_map_buffer(struct request *rq, unsigned long *flags) -{ - return (__bio_kmap_irq(rq->cbio, blk_rq_idx(rq), flags) - + blk_rq_offset(rq)); -} - -static inline void rq_unmap_buffer(char *buffer, unsigned long *flags) -{ - __bio_kunmap_irq(buffer, flags); -} - /* * q->prep_rq_fn return values */ @@ -589,7 +557,6 @@ static inline void blk_run_address_space(struct address_space *mapping) extern int end_that_request_first(struct request *, int, int); extern int end_that_request_chunk(struct request *, int, int); extern void end_that_request_last(struct request *); -extern int process_that_request_first(struct request *, unsigned int); extern void end_request(struct request *req, int uptodate); /* @@ -660,7 +627,6 @@ extern void blk_queue_invalidate_tags(request_queue_t *); extern long blk_congestion_wait(int rw, long timeout); extern void blk_rq_bio_prep(request_queue_t *, struct request *, struct bio *); -extern void blk_rq_prep_restart(struct request *); extern int blkdev_issue_flush(struct block_device *, sector_t *); #define MAX_PHYS_SEGMENTS 128 -- cgit v1.2.3