From c21dc6a0491a84a433f9e97712609b298b509fea Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 27 Oct 2004 10:18:06 -0400 Subject: [CPUFREQ] 2.4 API clarification. Clarify that cpufreq_set() and cpufreq_setmax() are parts of the 2.4. API to the userspace governor which will be removed soon after 2005-01-01. Signed-off-by: Dominik Brodowski Signed-off-by: Dave Jones --- include/linux/cpufreq.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index f8543228663f..c5d2badc31d5 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -261,8 +261,8 @@ int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpu *********************************************************************/ #ifdef CONFIG_CPU_FREQ_24_API -int cpufreq_setmax(unsigned int cpu); -int cpufreq_set(unsigned int kHz, unsigned int cpu); +int __deprecated cpufreq_setmax(unsigned int cpu); +int __deprecated cpufreq_set(unsigned int kHz, unsigned int cpu); /* /proc/sys/cpu */ -- cgit v1.2.3 From 40e74f0a7b5cd7bf21b99cba71b431025838e68a Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 27 Oct 2004 10:19:28 -0400 Subject: [CPUFREQ] Add a unified cpufreq debug infrastructure. cpufreq_debug_printk will print messages if a) debugging for the specified part is activated (add 1 for core, 2 for drivers, 4 for governors and pass value as cpufreq.debug= on the kernel command line). b) and either b1) printk_ratelimit() allows it to be printed, b2) the user disables ratelimit'ing by passing cpufreq.debug_ratelimit=0 on the kernel command line, _or_ b3) during driver initialization [unless a different driver has been initialized successfully] and unloading, and whenever a new policy is set. The last point may cause for numerous messages if an userspace-based dynamic governor is used which mis-uses the policy interface to set specific frequencies. Oh, the ACPI processor.c interface to the file "performance" uses the same trick, but that interface is marked deprecated as well, so I don't care. And debugging isn't activated normally, you know... Signed-off-by: Dominik Brodowski Signed-off-by: Dave Jones --- drivers/cpufreq/Kconfig | 14 ++++++ drivers/cpufreq/cpufreq.c | 116 ++++++++++++++++++++++++++++++++++++++++++++-- include/linux/cpufreq.h | 19 ++++++++ 3 files changed, 146 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 002088f314d8..aa8eaca6e2ea 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -13,6 +13,20 @@ config CPU_FREQ If in doubt, say N. +config CPU_FREQ_DEBUG + bool "Enable CPUfreq debugging" + depends on CPU_FREQ + help + Say Y here to enable CPUfreq subsystem (including drivers) + debugging. You will need to activate it via the kernel + command line by passing + cpufreq.debug= + + To get , add + 1 to activate CPUfreq core debugging, + 2 to activate CPUfreq drivers debugging, and + 4 to activate CPUfreq governor debugging + config CPU_FREQ_PROC_INTF tristate "/proc/cpufreq interface (deprecated)" depends on CPU_FREQ && PROC_FS diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index da6f1f6ff817..7b42237a9e55 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -107,6 +107,90 @@ static void cpufreq_cpu_put(struct cpufreq_policy *data) module_put(cpufreq_driver->owner); } + +/********************************************************************* + * UNIFIED DEBUG HELPERS * + *********************************************************************/ +#ifdef CONFIG_CPU_FREQ_DEBUG + +/* what part(s) of the CPUfreq subsystem are debugged? */ +static unsigned int debug; + +/* is the debug output ratelimit'ed using printk_ratelimit? User can + * set or modify this value. + */ +static unsigned int debug_ratelimit = 1; + +/* is the printk_ratelimit'ing enabled? It's enabled after a successful + * loading of a cpufreq driver, temporarily disabled when a new policy + * is set, and disabled upon cpufreq driver removal + */ +static unsigned int disable_ratelimit = 1; +static spinlock_t disable_ratelimit_lock = SPIN_LOCK_UNLOCKED; + +static inline void cpufreq_debug_enable_ratelimit(void) +{ + unsigned long flags; + + spin_lock_irqsave(&disable_ratelimit_lock, flags); + if (disable_ratelimit) + disable_ratelimit--; + spin_unlock_irqrestore(&disable_ratelimit_lock, flags); +} + +static inline void cpufreq_debug_disable_ratelimit(void) +{ + unsigned long flags; + + spin_lock_irqsave(&disable_ratelimit_lock, flags); + disable_ratelimit++; + spin_unlock_irqrestore(&disable_ratelimit_lock, flags); +} + +void cpufreq_debug_printk(unsigned int type, const char *prefix, const char *fmt, ...) +{ + char s[256]; + va_list args; + unsigned int len; + unsigned long flags; + + WARN_ON(!prefix); + if (type & debug) { + spin_lock_irqsave(&disable_ratelimit_lock, flags); + if (!disable_ratelimit && debug_ratelimit && !printk_ratelimit()) { + spin_unlock_irqrestore(&disable_ratelimit_lock, flags); + return; + } + spin_unlock_irqrestore(&disable_ratelimit_lock, flags); + + len = snprintf(s, 256, KERN_DEBUG "%s: ", prefix); + + va_start(args, fmt); + len += vsnprintf(&s[len], (256 - len), fmt, args); + va_end(args); + + printk(s); + + WARN_ON(len < 5); + } +} +EXPORT_SYMBOL(cpufreq_debug_printk); + + +module_param(debug, uint, 0644); +MODULE_PARM_DESC(debug, "CPUfreq debugging: add 1 to debug core, 2 to debug drivers, and 4 to debug governors."); + +module_param(debug_ratelimit, uint, 0644); +MODULE_PARM_DESC(debug_ratelimit, "CPUfreq debugging: set to 0 to disable ratelimiting."); + +#else /* !CONFIG_CPU_FREQ_DEBUG */ + +static inline void cpufreq_debug_enable_ratelimit(void) { return; } +static inline void cpufreq_debug_disable_ratelimit(void) { return; } + +#endif /* CONFIG_CPU_FREQ_DEBUG */ + + /********************************************************************* * EXTERNALLY AFFECTING FREQUENCY CHANGES * *********************************************************************/ @@ -468,6 +552,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) unsigned long flags; unsigned int j; + cpufreq_debug_disable_ratelimit(); + #ifdef CONFIG_SMP /* check whether a different CPU already registered this * CPU because it is in the same boat. */ @@ -475,12 +561,15 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) if (unlikely(policy)) { cpu_sys_devices[cpu] = sys_dev; sysfs_create_link(&sys_dev->kobj, &policy->kobj, "cpufreq"); + cpufreq_debug_enable_ratelimit(); return 0; } #endif - if (!try_module_get(cpufreq_driver->owner)) - return -EINVAL; + if (!try_module_get(cpufreq_driver->owner)) { + ret = -EINVAL; + goto module_out; + } policy = kmalloc(sizeof(struct cpufreq_policy), GFP_KERNEL); if (!policy) { @@ -541,6 +630,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) module_put(cpufreq_driver->owner); cpu_sys_devices[cpu] = sys_dev; + cpufreq_debug_enable_ratelimit(); + return 0; @@ -558,6 +649,8 @@ err_out: nomem_out: module_put(cpufreq_driver->owner); + module_out: + cpufreq_debug_enable_ratelimit(); return ret; } @@ -576,12 +669,15 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) unsigned int j; #endif + cpufreq_debug_disable_ratelimit(); + spin_lock_irqsave(&cpufreq_driver_lock, flags); data = cpufreq_cpu_data[cpu]; if (!data) { spin_unlock_irqrestore(&cpufreq_driver_lock, flags); cpu_sys_devices[cpu] = NULL; + cpufreq_debug_enable_ratelimit(); return -EINVAL; } cpufreq_cpu_data[cpu] = NULL; @@ -596,6 +692,7 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) sysfs_remove_link(&sys_dev->kobj, "cpufreq"); cpu_sys_devices[cpu] = NULL; cpufreq_cpu_put(data); + cpufreq_debug_enable_ratelimit(); return 0; } #endif @@ -604,6 +701,7 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) if (!kobject_get(&data->kobj)) { spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + cpufreq_debug_enable_ratelimit(); return -EFAULT; } @@ -654,6 +752,8 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) kfree(data); + cpufreq_debug_enable_ratelimit(); + return 0; } @@ -1024,6 +1124,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli { int ret = 0; + cpufreq_debug_disable_ratelimit(); + memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo)); @@ -1089,6 +1191,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli } error_out: + cpufreq_debug_enable_ratelimit(); return ret; } @@ -1218,6 +1321,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) } } + if (!ret) + cpufreq_debug_enable_ratelimit(); + return (ret); } EXPORT_SYMBOL_GPL(cpufreq_register_driver); @@ -1235,8 +1341,12 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver) { unsigned long flags; - if (!cpufreq_driver || (driver != cpufreq_driver)) + cpufreq_debug_disable_ratelimit(); + + if (!cpufreq_driver || (driver != cpufreq_driver)) { + cpufreq_debug_enable_ratelimit(); return -EINVAL; + } sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index c5d2badc31d5..060cf3bba586 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -360,4 +360,23 @@ void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, void cpufreq_frequency_table_put_attr(unsigned int cpu); +/********************************************************************* + * UNIFIED DEBUG HELPERS * + *********************************************************************/ + +#define CPUFREQ_DEBUG_CORE 1 +#define CPUFREQ_DEBUG_DRIVER 2 +#define CPUFREQ_DEBUG_GOVERNOR 4 + +#ifdef CONFIG_CPU_FREQ_DEBUG + +extern void cpufreq_debug_printk(unsigned int type, const char *prefix, + const char *fmt, ...); + +#else + +#define cpufreq_debug_printk(msg...) do { } while(0) + +#endif /* CONFIG_CPU_FREQ_DEBUG */ + #endif /* _LINUX_CPUFREQ_H */ -- cgit v1.2.3 From edab27326a7dd646758d2787095b951330b4c8ec Mon Sep 17 00:00:00 2001 From: Dely Sy Date: Sun, 31 Oct 2004 22:51:06 -0800 Subject: [PATCH] PCI: Updated patch to add ExpressCard support This patch adds ExpressCard support to pciehp driver. It also includes the code that implements _OSC method call in driver/pci/pci-acpi.c for use by the drivers. Signed-off-by: Dely Sy Signed-off-by: Greg Kroah-Hartman --- drivers/pci/Makefile | 5 + drivers/pci/hotplug/pciehp.h | 21 +- drivers/pci/hotplug/pciehp_core.c | 18 +- drivers/pci/hotplug/pciehp_ctrl.c | 380 +++++++++++++++++++++++------------- drivers/pci/hotplug/pciehp_hpc.c | 30 ++- drivers/pci/hotplug/pciehprm_acpi.c | 43 +++- drivers/pci/pci-acpi.c | 209 ++++++++++++++++++++ include/linux/pci-acpi.h | 61 ++++++ 8 files changed, 600 insertions(+), 167 deletions(-) create mode 100644 drivers/pci/pci-acpi.c create mode 100644 include/linux/pci-acpi.h (limited to 'include/linux') diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 474eacd34741..7006354e98b0 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -28,6 +28,11 @@ obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o obj-$(CONFIG_X86_VISWS) += setup-irq.o obj-$(CONFIG_PCI_MSI) += msi.o +# +# ACPI Related PCI FW Functions +# +obj-$(CONFIG_ACPI) += pci-acpi.o + # Cardbus & CompactPCI use setup-bus obj-$(CONFIG_HOTPLUG) += setup-bus.o diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 09827fbab293..6b3d698e2708 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -127,8 +127,7 @@ struct controller { enum pci_bus_speed speed; u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */ u8 slot_bus; /* Bus where the slots handled by this controller sit */ - u8 push_flag; - u16 ctlrcap; + u8 ctrlcap; u16 vendor_id; }; @@ -180,6 +179,21 @@ struct resource_lists { #define DISABLE_CARD 1 +/* Field definitions in Slot Capabilities Register */ +#define ATTN_BUTTN_PRSN 0x00000001 +#define PWR_CTRL_PRSN 0x00000002 +#define MRL_SENS_PRSN 0x00000004 +#define ATTN_LED_PRSN 0x00000008 +#define PWR_LED_PRSN 0x00000010 +#define HP_SUPR_RM_SUP 0x00000020 + +#define ATTN_BUTTN(cap) (cap & ATTN_BUTTN_PRSN) +#define POWER_CTRL(cap) (cap & PWR_CTRL_PRSN) +#define MRL_SENS(cap) (cap & MRL_SENS_PRSN) +#define ATTN_LED(cap) (cap & ATTN_LED_PRSN) +#define PWR_LED(cap) (cap & PWR_LED_PRSN) +#define HP_SUPR_RM(cap) (cap & HP_SUPR_RM_SUP) + /* * error Messages */ @@ -312,8 +326,7 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl, int *num_ctlr_slots, int *first_device_num, int *physical_slot_num, - int *updown, - int *flags); + u8 *ctrlcap); struct hpc_ops { int (*power_on_slot) (struct slot *slot); diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 0d1eb271f23a..cb8569e0bbfa 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -204,11 +204,10 @@ static int get_ctlr_slot_config(struct controller *ctrl) int num_ctlr_slots; /* Not needed; PCI Express has 1 slot per port*/ int first_device_num; /* Not needed */ int physical_slot_num; - int updown; /* Not needed */ + u8 ctrlcap; int rc; - int flags; /* Not needed */ - rc = pcie_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &updown, &flags); + rc = pcie_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &ctrlcap); if (rc) { err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device); return (-1); @@ -217,10 +216,10 @@ static int get_ctlr_slot_config(struct controller *ctrl) ctrl->num_slots = num_ctlr_slots; /* PCI Express has 1 slot per port */ ctrl->slot_device_offset = first_device_num; ctrl->first_slot = physical_slot_num; - ctrl->slot_num_inc = updown; /* Not needed */ /* either -1 or 1 */ + ctrl->ctrlcap = ctrlcap; - dbg("%s: bus(0x%x) num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d (%x:%x)\n", - __FUNCTION__, ctrl->slot_bus, num_ctlr_slots, first_device_num, physical_slot_num, updown, + dbg("%s: bus(0x%x) num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) ctrlcap(%x) for b:d (%x:%x)\n", + __FUNCTION__, ctrl->slot_bus, num_ctlr_slots, first_device_num, physical_slot_num, ctrlcap, ctrl->bus, ctrl->device); return (0); @@ -237,7 +236,9 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); hotplug_slot->info->attention_status = status; - slot->hpc_ops->set_attention_status(slot, status); + + if (ATTN_LED(slot->ctrl->ctrlcap)) + slot->hpc_ops->set_attention_status(slot, status); return 0; } @@ -451,7 +452,8 @@ static int pcie_probe(struct pci_dev *pdev, const struct pci_device_id *ent) t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ dbg("%s: adpater value %x\n", __FUNCTION__, value); - if (!value) { + + if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ if (rc) { /* Done with exclusive hardware access */ diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 2015af915618..2adcd76d9bdd 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -51,6 +51,7 @@ static struct semaphore event_semaphore; /* mutex for process loop (up if someth static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */ static int event_finished; static unsigned long pushbutton_pending; /* = 0 */ +static unsigned long surprise_rm_pending; /* = 0 */ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) { @@ -1063,25 +1064,29 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); - /* turn off slot, turn on Amber LED, turn off Green LED */ - if (pslot->hpc_ops->power_off_slot(pslot)) { - err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); - return; + /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ + if (POWER_CTRL(ctrl->ctrlcap)) { + if (pslot->hpc_ops->power_off_slot(pslot)) { + err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); + up(&ctrl->crit_sect); + return; + } + wait_for_ctrl_irq (ctrl); } - wait_for_ctrl_irq (ctrl); - pslot->hpc_ops->green_led_off(pslot); - - wait_for_ctrl_irq (ctrl); + if (PWR_LED(ctrl->ctrlcap)) { + pslot->hpc_ops->green_led_off(pslot); + wait_for_ctrl_irq (ctrl); + } - /* turn on Amber LED */ - if (pslot->hpc_ops->set_attention_status(pslot, 1)) { - err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); - return; + if (ATTN_LED(ctrl->ctrlcap)) { + if (pslot->hpc_ops->set_attention_status(pslot, 1)) { + err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); + up(&ctrl->crit_sect); + return; + } + wait_for_ctrl_irq (ctrl); } - wait_for_ctrl_irq (ctrl); /* Done with exclusive hardware access */ up(&ctrl->crit_sect); @@ -1112,20 +1117,24 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); - /* Power on slot */ - rc = p_slot->hpc_ops->power_on_slot(p_slot); - if (rc) { - up(&ctrl->crit_sect); - return -1; - } + if (POWER_CTRL(ctrl->ctrlcap)) { + /* Power on slot */ + rc = p_slot->hpc_ops->power_on_slot(p_slot); + if (rc) { + up(&ctrl->crit_sect); + return -1; + } - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } - p_slot->hpc_ops->green_led_blink(p_slot); + if (PWR_LED(ctrl->ctrlcap)) { + p_slot->hpc_ops->green_led_blink(p_slot); - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } /* Done with exclusive hardware access */ up(&ctrl->crit_sect); @@ -1211,19 +1220,19 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) pciehp_configure_device(ctrl, new_func); } } while (new_func); - - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - p_slot->hpc_ops->green_led_on(p_slot); - - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - + + if (PWR_LED(ctrl->ctrlcap)) { + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + p_slot->hpc_ops->green_led_on(p_slot); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + } } else { set_slot_off(ctrl, p_slot); return -1; @@ -1289,21 +1298,25 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl) /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); - /* power off slot */ - rc = p_slot->hpc_ops->power_off_slot(p_slot); - if (rc) { - err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); - return rc; + if (POWER_CTRL(ctrl->ctrlcap)) { + /* power off slot */ + rc = p_slot->hpc_ops->power_off_slot(p_slot); + if (rc) { + err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); + up(&ctrl->crit_sect); + return rc; + } + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); } - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - /* turn off Green LED */ - p_slot->hpc_ops->green_led_off(p_slot); + if (PWR_LED(ctrl->ctrlcap)) { + /* turn off Green LED */ + p_slot->hpc_ops->green_led_off(p_slot); - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } /* Done with exclusive hardware access */ up(&ctrl->crit_sect); @@ -1368,7 +1381,6 @@ static void pushbutton_helper_thread(unsigned long data) up(&event_semaphore); } - /** * pciehp_pushbutton_thread * @@ -1399,7 +1411,55 @@ static void pciehp_pushbutton_thread(unsigned long slot) p_slot->state = POWERON_STATE; dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); - if (pciehp_enable_slot(p_slot)) { + if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { + /* Wait for exclusive access to hardware */ + down(&p_slot->ctrl->crit_sect); + + p_slot->hpc_ops->green_led_off(p_slot); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (p_slot->ctrl); + + /* Done with exclusive hardware access */ + up(&p_slot->ctrl->crit_sect); + } + p_slot->state = STATIC_STATE; + } + + return; +} + +/** + * pciehp_surprise_rm_thread + * + * Scheduled procedure to handle blocking stuff for the surprise removal + * Handles all pending events and exits. + * + */ +static void pciehp_surprise_rm_thread(unsigned long slot) +{ + struct slot *p_slot = (struct slot *) slot; + u8 getstatus; + + surprise_rm_pending = 0; + + if (!p_slot) { + dbg("%s: Error! slot NULL\n", __FUNCTION__); + return; + } + + p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); + if (!getstatus) { + p_slot->state = POWEROFF_STATE; + dbg("In removing board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); + + pciehp_disable_slot(p_slot); + p_slot->state = STATIC_STATE; + } else { + p_slot->state = POWERON_STATE; + dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); + + if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { /* Wait for exclusive access to hardware */ down(&p_slot->ctrl->crit_sect); @@ -1418,6 +1478,7 @@ static void pciehp_pushbutton_thread(unsigned long slot) } + /* this is the main worker thread */ static int event_thread(void* data) { @@ -1436,6 +1497,8 @@ static int event_thread(void* data) /* Do stuff here */ if (pushbutton_pending) pciehp_pushbutton_thread(pushbutton_pending); + else if (surprise_rm_pending) + pciehp_surprise_rm_thread(surprise_rm_pending); else for (ctrl = pciehp_ctrl_list; ctrl; ctrl=ctrl->next) interrupt_event_handler(ctrl); @@ -1528,16 +1591,18 @@ static void interrupt_event_handler(struct controller *ctrl) case BLINKINGOFF_STATE: /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); - - p_slot->hpc_ops->green_led_on(p_slot); - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - p_slot->hpc_ops->set_attention_status(p_slot, 0); - - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - + + if (PWR_LED(ctrl->ctrlcap)) { + p_slot->hpc_ops->green_led_on(p_slot); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } + if (ATTN_LED(ctrl->ctrlcap)) { + p_slot->hpc_ops->set_attention_status(p_slot, 0); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } /* Done with exclusive hardware access */ up(&ctrl->crit_sect); break; @@ -1545,14 +1610,16 @@ static void interrupt_event_handler(struct controller *ctrl) /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); - p_slot->hpc_ops->green_led_off(p_slot); - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - p_slot->hpc_ops->set_attention_status(p_slot, 0); - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - + if (PWR_LED(ctrl->ctrlcap)) { + p_slot->hpc_ops->green_led_off(p_slot); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } + if (ATTN_LED(ctrl->ctrlcap)){ + p_slot->hpc_ops->set_attention_status(p_slot, 0); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } /* Done with exclusive hardware access */ up(&ctrl->crit_sect); @@ -1566,59 +1633,83 @@ static void interrupt_event_handler(struct controller *ctrl) } /* ***********Button Pressed (No action on 1st press...) */ else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) { - dbg("Button pressed\n"); - - p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (getstatus) { - /* slot is on */ - dbg("slot is on\n"); - p_slot->state = BLINKINGOFF_STATE; - info(msg_button_off, p_slot->number); - } else { - /* slot is off */ - dbg("slot is off\n"); - p_slot->state = BLINKINGON_STATE; - info(msg_button_on, p_slot->number); - } + + if (ATTN_BUTTN(ctrl->ctrlcap)) { + dbg("Button pressed\n"); + p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (getstatus) { + /* slot is on */ + dbg("slot is on\n"); + p_slot->state = BLINKINGOFF_STATE; + info(msg_button_off, p_slot->number); + } else { + /* slot is off */ + dbg("slot is off\n"); + p_slot->state = BLINKINGON_STATE; + info(msg_button_on, p_slot->number); + } + + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + /* blink green LED and turn off amber */ + if (PWR_LED(ctrl->ctrlcap)) { + p_slot->hpc_ops->green_led_blink(p_slot); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } - /* blink green LED and turn off amber */ - p_slot->hpc_ops->green_led_blink(p_slot); - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - p_slot->hpc_ops->set_attention_status(p_slot, 0); + if (ATTN_LED(ctrl->ctrlcap)) { + p_slot->hpc_ops->set_attention_status(p_slot, 0); - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); - init_timer(&p_slot->task_event); - p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ - p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; - p_slot->task_event.data = (unsigned long) p_slot; + init_timer(&p_slot->task_event); + p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ + p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; + p_slot->task_event.data = (unsigned long) p_slot; - dbg("add_timer p_slot = %p\n", (void *) p_slot); - add_timer(&p_slot->task_event); + dbg("add_timer p_slot = %p\n", (void *) p_slot); + add_timer(&p_slot->task_event); + } } /***********POWER FAULT********************/ else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { - dbg("power fault\n"); - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + if (POWER_CTRL(ctrl->ctrlcap)) { + dbg("power fault\n"); + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); - p_slot->hpc_ops->set_attention_status(p_slot, 1); - wait_for_ctrl_irq (ctrl); - - p_slot->hpc_ops->green_led_off(p_slot); - wait_for_ctrl_irq (ctrl); + if (ATTN_LED(ctrl->ctrlcap)) { + p_slot->hpc_ops->set_attention_status(p_slot, 1); + wait_for_ctrl_irq (ctrl); + } - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + if (PWR_LED(ctrl->ctrlcap)) { + p_slot->hpc_ops->green_led_off(p_slot); + wait_for_ctrl_irq (ctrl); + } + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + } + } + /***********SURPRISE REMOVAL********************/ + else if ((ctrl->event_queue[loop].event_type == INT_PRESENCE_ON) || + (ctrl->event_queue[loop].event_type == INT_PRESENCE_OFF)) { + if (HP_SUPR_RM(ctrl->ctrlcap)) { + dbg("Surprise Removal\n"); + if (p_slot) { + surprise_rm_pending = (unsigned long) p_slot; + up(&event_semaphore); + update_slot_info(p_slot); + } + } } else { /* refresh notification */ if (p_slot) @@ -1648,25 +1739,29 @@ int pciehp_enable_slot(struct slot *p_slot) /* Check to see if (latch closed, card present, power off) */ down(&p_slot->ctrl->crit_sect); + rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (rc || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); return 1; } - - rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - if (rc || getstatus) { - info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); - return 1; + if (MRL_SENS(p_slot->ctrl->ctrlcap)) { + rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + if (rc || getstatus) { + info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return 1; + } } - rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (rc || getstatus) { - info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); - return 1; + if (POWER_CTRL(p_slot->ctrl->ctrlcap)) { + rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (rc || getstatus) { + info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return 1; + } } up(&p_slot->ctrl->crit_sect); @@ -1735,26 +1830,33 @@ int pciehp_disable_slot(struct slot *p_slot) /* Check to see if (latch closed, card present, power on) */ down(&p_slot->ctrl->crit_sect); - ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); - if (ret || !getstatus) { - info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); - return 1; + if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) { + ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); + if (ret || !getstatus) { + info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return 1; + } } - ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - if (ret || getstatus) { - info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); - return 1; + if (MRL_SENS(p_slot->ctrl->ctrlcap)) { + ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + if (ret || getstatus) { + info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return 1; + } } - ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (ret || !getstatus) { - info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); - return 1; + if (POWER_CTRL(p_slot->ctrl->ctrlcap)) { + ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (ret || !getstatus) { + info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return 1; + } } + up(&p_slot->ctrl->crit_sect); func = pciehp_slot_find(p_slot->bus, p_slot->device, index++); diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index b8ca99b42601..7930c5d6121b 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -182,7 +182,7 @@ static int pcie_cap_base = 0; /* Base of the PCI Express capability item struct #define MRL_SENS_PRSN 0x00000004 #define ATTN_LED_PRSN 0x00000008 #define PWR_LED_PRSN 0x00000010 -#define HP_SUPR_RM 0x00000020 +#define HP_SUPR_RM_SUP 0x00000020 #define HP_CAP 0x00000040 #define SLOT_PWR_VALUE 0x000003F8 #define SLOT_PWR_LIMIT 0x00000C00 @@ -237,8 +237,8 @@ struct php_ctlr_state_s { static spinlock_t hpc_event_lock; DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ -static struct php_ctlr_state_s *php_ctlr_list_head; /* HPC state linked list */ -static int ctlr_seq_num; /* Controller sequence # */ +static struct php_ctlr_state_s *php_ctlr_list_head = 0; /* HPC state linked list */ +static int ctlr_seq_num = 0; /* Controller sequence # */ static spinlock_t list_lock; static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs); @@ -691,8 +691,7 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl, int *num_ctlr_slots, /* number of slots in this HPC; only 1 in PCIE */ int *first_device_num, /* PCI dev num of the first slot in this PCIE */ int *physical_slot_num, /* phy slot num of the first slot in this PCIE */ - int *updown, /* physical_slot_num increament: 1 or -1 */ - int *flags) + u8 *ctrlcap) { struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; u32 slot_cap; @@ -716,8 +715,9 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl, } *physical_slot_num = slot_cap >> 19; - - *updown = -1; + dbg("%s: PSN %d \n", __FUNCTION__, *physical_slot_num); + + *ctrlcap = slot_cap & 0x0000007f; DBG_LEAVE_ROUTINE return 0; @@ -1259,7 +1259,7 @@ int pcie_init(struct controller * ctrl, static int first = 1; u16 temp_word; u16 cap_reg; - u16 intr_enable; + u16 intr_enable = 0; u32 slot_cap; int cap_base, saved_cap_base; u16 slot_status, slot_ctrl; @@ -1412,6 +1412,7 @@ int pcie_init(struct controller * ctrl, } else php_ctlr->irq = pdev->irq; } + rc = request_irq(php_ctlr->irq, pcie_isr, SA_SHIRQ, MY_NAME, (void *) ctrl); dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc); if (rc) { @@ -1426,9 +1427,18 @@ int pcie_init(struct controller * ctrl, goto abort_free_ctlr; } dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word); + dbg("%s: slot_cap %x\n", __FUNCTION__, slot_cap); - intr_enable = ATTN_BUTTN_ENABLE | PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | - PRSN_DETECT_ENABLE; + intr_enable = intr_enable | PRSN_DETECT_ENABLE; + + if (ATTN_BUTTN(slot_cap)) + intr_enable = intr_enable | ATTN_BUTTN_ENABLE; + + if (POWER_CTRL(slot_cap)) + intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE; + + if (MRL_SENS(slot_cap)) + intr_enable = intr_enable | MRL_DETECT_ENABLE; temp_word = (temp_word & ~intr_enable) | intr_enable; diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c index b127575ec985..424e7ac61746 100644 --- a/drivers/pci/hotplug/pciehprm_acpi.c +++ b/drivers/pci/hotplug/pciehprm_acpi.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #ifdef CONFIG_IA64 @@ -50,6 +51,14 @@ #define METHOD_NAME__HPP "_HPP" #define METHOD_NAME_OSHP "OSHP" +/* Status code for running acpi method to gain native control */ +#define NC_NOT_RUN 0 +#define OSC_NOT_EXIST 1 +#define OSC_RUN_FAILED 2 +#define OSHP_NOT_EXIST 3 +#define OSHP_RUN_FAILED 4 +#define NC_RUN_SUCCESS 5 + #define PHP_RES_BUS 0xA0 #define PHP_RES_IO 0xA1 #define PHP_RES_MEM 0xA2 @@ -125,7 +134,9 @@ static u8 * acpi_path_name( acpi_handle handle) } static void acpi_get__hpp ( struct acpi_bridge *ab); -static void acpi_run_oshp ( struct acpi_bridge *ab); +static int acpi_run_oshp ( struct acpi_bridge *ab); +static int osc_run_status = NC_NOT_RUN; +static int oshp_run_status = NC_NOT_RUN; static int acpi_add_slot_to_php_slots( struct acpi_bridge *ab, @@ -158,8 +169,9 @@ static int acpi_add_slot_to_php_slots( ab->scanned += 1; if (!ab->_hpp) acpi_get__hpp(ab); - - acpi_run_oshp(ab); + + if (osc_run_status == OSC_NOT_EXIST) + oshp_run_status = acpi_run_oshp(ab); if (sun != samesun) { info("acpi_pciehprm: Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n", @@ -238,7 +250,7 @@ free_and_return: kfree(ret_buf.pointer); } -static void acpi_run_oshp ( struct acpi_bridge *ab) +static int acpi_run_oshp ( struct acpi_bridge *ab) { acpi_status status; u8 *path_name = acpi_path_name(ab->handle); @@ -248,9 +260,13 @@ static void acpi_run_oshp ( struct acpi_bridge *ab) status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, &ret_buf); if (ACPI_FAILURE(status)) { err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status); - } else + oshp_run_status = (status == AE_NOT_FOUND) ? OSHP_NOT_EXIST : OSHP_RUN_FAILED; + } else { + oshp_run_status = NC_RUN_SUCCESS; dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status); - return; + dbg("acpi_pciehprm:%s oshp_run_status =0x%x\n", path_name, oshp_run_status); + } + return oshp_run_status; } static acpi_status acpi_evaluate_crs( @@ -1056,6 +1072,16 @@ static struct acpi_bridge * add_host_bridge( kfree(ab); return NULL; } + + status = pci_osc_control_set (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); + if (ACPI_FAILURE(status)) { + err("%s: status %x\n", __FUNCTION__, status); + osc_run_status = (status == AE_NOT_FOUND) ? OSC_NOT_EXIST : OSC_RUN_FAILED; + } else { + osc_run_status = NC_RUN_SUCCESS; + } + dbg("%s: osc_run_status %x\n", __FUNCTION__, osc_run_status); + build_a_bridge(ab, ab); return ab; @@ -1141,6 +1167,11 @@ int pciehprm_init(enum php_ctlr_type ctlr_type) if (rc) return rc; + if ((oshp_run_status != NC_RUN_SUCCESS) && (osc_run_status != NC_RUN_SUCCESS)) { + err("Fails to gain control of native hot-plug\n"); + rc = -ENODEV; + } + dbg("pciehprm ACPI init %s\n", (rc)?"fail":"success"); return rc; } diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c new file mode 100644 index 000000000000..968eb32f292d --- /dev/null +++ b/drivers/pci/pci-acpi.c @@ -0,0 +1,209 @@ +/* + * File: pci-acpi.c + * Purpose: Provide PCI supports in ACPI + * + * Copyright (C) 2004 Intel + * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static u32 ctrlset_buf[3] = {0, 0, 0}; +static u32 global_ctrlsets = 0; +u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; + +static acpi_status +acpi_query_osc ( + acpi_handle handle, + u32 level, + void *context, + void **retval ) +{ + acpi_status status; + struct acpi_object_list input; + union acpi_object in_params[4]; + struct acpi_buffer output; + union acpi_object out_obj; + u32 osc_dw0; + + /* Setting up output buffer */ + output.length = sizeof(out_obj) + 3*sizeof(u32); + output.pointer = &out_obj; + + /* Setting up input parameters */ + input.count = 4; + input.pointer = in_params; + in_params[0].type = ACPI_TYPE_BUFFER; + in_params[0].buffer.length = 16; + in_params[0].buffer.pointer = OSC_UUID; + in_params[1].type = ACPI_TYPE_INTEGER; + in_params[1].integer.value = 1; + in_params[2].type = ACPI_TYPE_INTEGER; + in_params[2].integer.value = 3; + in_params[3].type = ACPI_TYPE_BUFFER; + in_params[3].buffer.length = 12; + in_params[3].buffer.pointer = (u8 *)context; + + status = acpi_evaluate_object(handle, "_OSC", &input, &output); + if (ACPI_FAILURE (status)) { + printk(KERN_DEBUG + "Evaluate _OSC Set fails. Status = 0x%04x\n", status); + return status; + } + if (out_obj.type != ACPI_TYPE_BUFFER) { + printk(KERN_DEBUG + "Evaluate _OSC returns wrong type\n"); + return AE_TYPE; + } + osc_dw0 = *((u32 *) out_obj.buffer.pointer); + if (osc_dw0) { + if (osc_dw0 & OSC_REQUEST_ERROR) + printk(KERN_DEBUG "_OSC request fails\n"); + if (osc_dw0 & OSC_INVALID_UUID_ERROR) + printk(KERN_DEBUG "_OSC invalid UUID\n"); + if (osc_dw0 & OSC_INVALID_REVISION_ERROR) + printk(KERN_DEBUG "_OSC invalid revision\n"); + if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { + /* Update Global Control Set */ + global_ctrlsets = *((u32 *)(out_obj.buffer.pointer+8)); + return AE_OK; + } + return AE_ERROR; + } + + /* Update Global Control Set */ + global_ctrlsets = *((u32 *)(out_obj.buffer.pointer + 8)); + return AE_OK; +} + + +static acpi_status +acpi_run_osc ( + acpi_handle handle, + u32 level, + void *context, + void **retval ) +{ + acpi_status status; + struct acpi_object_list input; + union acpi_object in_params[4]; + struct acpi_buffer output; + union acpi_object out_obj; + u32 osc_dw0; + + /* Setting up output buffer */ + output.length = sizeof(out_obj) + 3*sizeof(u32); + output.pointer = &out_obj; + + /* Setting up input parameters */ + input.count = 4; + input.pointer = in_params; + in_params[0].type = ACPI_TYPE_BUFFER; + in_params[0].buffer.length = 16; + in_params[0].buffer.pointer = OSC_UUID; + in_params[1].type = ACPI_TYPE_INTEGER; + in_params[1].integer.value = 1; + in_params[2].type = ACPI_TYPE_INTEGER; + in_params[2].integer.value = 3; + in_params[3].type = ACPI_TYPE_BUFFER; + in_params[3].buffer.length = 12; + in_params[3].buffer.pointer = (u8 *)context; + + status = acpi_evaluate_object(handle, "_OSC", &input, &output); + if (ACPI_FAILURE (status)) { + printk(KERN_DEBUG + "Evaluate _OSC Set fails. Status = 0x%04x\n", status); + return status; + } + if (out_obj.type != ACPI_TYPE_BUFFER) { + printk(KERN_DEBUG + "Evaluate _OSC returns wrong type\n"); + return AE_TYPE; + } + osc_dw0 = *((u32 *) out_obj.buffer.pointer); + if (osc_dw0) { + if (osc_dw0 & OSC_REQUEST_ERROR) + printk(KERN_DEBUG "_OSC request fails\n"); + if (osc_dw0 & OSC_INVALID_UUID_ERROR) + printk(KERN_DEBUG "_OSC invalid UUID\n"); + if (osc_dw0 & OSC_INVALID_REVISION_ERROR) + printk(KERN_DEBUG "_OSC invalid revision\n"); + if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { + printk(KERN_DEBUG "_OSC FW not grant req. control\n"); + return AE_SUPPORT; + } + return AE_ERROR; + } + return AE_OK; +} + +/** + * pci_osc_support_set - register OS support to Firmware + * @flags: OS support bits + * + * Update OS support fields and doing a _OSC Query to obtain an update + * from Firmware on supported control bits. + **/ +acpi_status pci_osc_support_set(u32 flags) +{ + u32 temp; + + if (!(flags & OSC_SUPPORT_MASKS)) { + return AE_TYPE; + } + ctrlset_buf[OSC_SUPPORT_TYPE] |= (flags & OSC_SUPPORT_MASKS); + + /* do _OSC query for all possible controls */ + temp = ctrlset_buf[OSC_CONTROL_TYPE]; + ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; + ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; + acpi_get_devices ( PCI_ROOT_HID_STRING, + acpi_query_osc, + ctrlset_buf, + NULL ); + ctrlset_buf[OSC_QUERY_TYPE] = !OSC_QUERY_ENABLE; + ctrlset_buf[OSC_CONTROL_TYPE] = temp; + return AE_OK; +} +EXPORT_SYMBOL(pci_osc_support_set); + +/** + * pci_osc_control_set - commit requested control to Firmware + * @flags: driver's requested control bits + * + * Attempt to take control from Firmware on requested control bits. + **/ +acpi_status pci_osc_control_set(u32 flags) +{ + acpi_status status; + u32 ctrlset; + + ctrlset = (flags & OSC_CONTROL_MASKS); + if (!ctrlset) { + return AE_TYPE; + } + if (ctrlset_buf[OSC_SUPPORT_TYPE] && + ((global_ctrlsets & ctrlset) != ctrlset)) { + return AE_SUPPORT; + } + ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset; + status = acpi_get_devices ( PCI_ROOT_HID_STRING, + acpi_run_osc, + ctrlset_buf, + NULL ); + if (ACPI_FAILURE (status)) { + ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset; + } + + return status; +} +EXPORT_SYMBOL(pci_osc_control_set); diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h new file mode 100644 index 000000000000..857126a36ecc --- /dev/null +++ b/include/linux/pci-acpi.h @@ -0,0 +1,61 @@ +/* + * File pci-acpi.h + * + * Copyright (C) 2004 Intel + * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) + */ + +#ifndef _PCI_ACPI_H_ +#define _PCI_ACPI_H_ + +#define OSC_QUERY_TYPE 0 +#define OSC_SUPPORT_TYPE 1 +#define OSC_CONTROL_TYPE 2 +#define OSC_SUPPORT_MASKS 0x1f + +/* + * _OSC DW0 Definition + */ +#define OSC_QUERY_ENABLE 1 +#define OSC_REQUEST_ERROR 2 +#define OSC_INVALID_UUID_ERROR 4 +#define OSC_INVALID_REVISION_ERROR 8 +#define OSC_CAPABILITIES_MASK_ERROR 16 + +/* + * _OSC DW1 Definition (OS Support Fields) + */ +#define OSC_EXT_PCI_CONFIG_SUPPORT 1 +#define OSC_ACTIVE_STATE_PWR_SUPPORT 2 +#define OSC_CLOCK_PWR_CAPABILITY_SUPPORT 4 +#define OSC_PCI_SEGMENT_GROUPS_SUPPORT 8 +#define OSC_MSI_SUPPORT 16 + +/* + * _OSC DW1 Definition (OS Control Fields) + */ +#define OSC_PCI_EXPRESS_NATIVE_HP_CONTROL 1 +#define OSC_SHPC_NATIVE_HP_CONTROL 2 +#define OSC_PCI_EXPRESS_PME_CONTROL 4 +#define OSC_PCI_EXPRESS_AER_CONTROL 8 +#define OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL 16 + +#define OSC_CONTROL_MASKS (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | \ + OSC_SHPC_NATIVE_HP_CONTROL | \ + OSC_PCI_EXPRESS_PME_CONTROL | \ + OSC_PCI_EXPRESS_AER_CONTROL | \ + OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL) + +#ifdef CONFIG_ACPI +extern acpi_status pci_osc_control_set(u32 flags); +extern acpi_status pci_osc_support_set(u32 flags); +#else +#if !defined(acpi_status) +typedef u32 acpi_status; +#define AE_ERROR (acpi_status) (0x0001) +#endif +static inline acpi_status pci_osc_control_set(u32 flags) {return AE_ERROR;} +static inline acpi_status pci_osc_support_set(u32 flags) {return AE_ERROR;} +#endif + +#endif /* _PCI_ACPI_H_ */ -- cgit v1.2.3 From ad7983864e824e926f106bb57b13df1b0c3acf79 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 4 Nov 2004 23:05:24 -0800 Subject: [PATCH] PCI: add pci_fixup_early Port Ivan's early PCI fixups patch to 2.6.10-rc1. Also fix some indentation to make it less than 80 columns. From: Ivan Kokshaysky Signed-off-by: Greg Kroah-Hartman --- drivers/pci/probe.c | 3 +++ include/asm-generic/vmlinux.lds.h | 3 +++ include/linux/pci.h | 34 ++++++++++++++++++---------------- 3 files changed, 24 insertions(+), 16 deletions(-) (limited to 'include/linux') diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 683ba8b10551..1d2f4c8646d9 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -478,6 +478,9 @@ static int pci_setup_device(struct pci_dev * dev) /* "Unknown power state" */ dev->current_state = 4; + /* Early fixups, before probing the BARs */ + pci_fixup_device(pci_fixup_early, dev); + switch (dev->hdr_type) { /* header type */ case PCI_HEADER_TYPE_NORMAL: /* standard header */ if (class == PCI_CLASS_BRIDGE_PCI) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index da1b3ba89b3e..99cef06a364a 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -18,6 +18,9 @@ \ /* PCI quirks */ \ .pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \ + VMLINUX_SYMBOL(__start_pci_fixups_early) = .; \ + *(.pci_fixup_early) \ + VMLINUX_SYMBOL(__end_pci_fixups_early) = .; \ VMLINUX_SYMBOL(__start_pci_fixups_header) = .; \ *(.pci_fixup_header) \ VMLINUX_SYMBOL(__end_pci_fixups_header) = .; \ diff --git a/include/linux/pci.h b/include/linux/pci.h index e7fa282ddede..2bc81cf429a0 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -989,31 +989,33 @@ static inline char *pci_name(struct pci_dev *pdev) */ struct pci_fixup { - u16 vendor, device; /* You can use PCI_ANY_ID here of course */ + u16 vendor, device; /* You can use PCI_ANY_ID here of course */ void (*hook)(struct pci_dev *dev); }; enum pci_fixup_pass { - pci_fixup_header, /* Called immediately after reading configuration header */ + pci_fixup_early, /* Before probing BARs */ + pci_fixup_header, /* After reading configuration header */ pci_fixup_final, /* Final phase of device fixups */ pci_fixup_enable, /* pci_enable_device() time */ }; /* Anonymous variables would be nice... */ -#define DECLARE_PCI_FIXUP_HEADER(vendor, device, hook) \ - static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__ \ - __attribute__((__section__(".pci_fixup_header"))) = { \ - vendor, device, hook }; - -#define DECLARE_PCI_FIXUP_FINAL(vendor, device, hook) \ - static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__ \ - __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 }; +#define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, hook) \ + static struct pci_fixup __pci_fixup_##name __attribute_used__ \ + __attribute__((__section__(#section))) = { vendor, device, hook }; +#define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook) \ + DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early, \ + vendor##device##hook, vendor, device, hook) +#define DECLARE_PCI_FIXUP_HEADER(vendor, device, hook) \ + DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header, \ + vendor##device##hook, vendor, device, hook) +#define DECLARE_PCI_FIXUP_FINAL(vendor, device, hook) \ + DECLARE_PCI_FIXUP_SECTION(.pci_fixup_final, \ + vendor##device##hook, vendor, device, hook) +#define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook) \ + DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable, \ + vendor##device##hook, vendor, device, hook) void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev); -- cgit v1.2.3 From 67f4660b72f27c77b9e0e4fc24a1938a30f98108 Mon Sep 17 00:00:00 2001 From: Dely Sy Date: Thu, 4 Nov 2004 23:06:04 -0800 Subject: [PATCH] PCI: ASPM patch for This is the ASPM patch against 2.6.10-rc1-mm2. As mentioned in my last email, this patch has a slight difference than the one for 2.6.10-rc1, because the irqbalance quirk was moved from drivers/pci/quirks.c in 2.6.10-rc1 to arch/i386/kernel/quirks.c in 2.6.10-rc1-mm2. Signed-off-by: Dely Sy Signed-off-by: Greg Kroah-Hartman --- arch/i386/kernel/quirks.c | 4 +- arch/i386/pci/fixup.c | 91 +++++++++++++++++++++++++++++++++++++++ drivers/pci/hotplug/pciehp_ctrl.c | 9 +++- drivers/pci/hotplug/pciehp_hpc.c | 6 ++- drivers/pci/hotplug/pciehp_pci.c | 8 ++++ drivers/pci/hotplug/shpchp_hpc.c | 1 + drivers/pci/pci.h | 2 +- drivers/pci/quirks.c | 18 +++++--- include/linux/pci_ids.h | 8 +++- 9 files changed, 133 insertions(+), 14 deletions(-) (limited to 'include/linux') diff --git a/arch/i386/kernel/quirks.c b/arch/i386/kernel/quirks.c index 45aab3a8b265..65d5ee76731c 100644 --- a/arch/i386/kernel/quirks.c +++ b/arch/i386/kernel/quirks.c @@ -6,7 +6,7 @@ #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) -void __init quirk_intel_irqbalance(struct pci_dev *dev) +void __devinit quirk_intel_irqbalance(struct pci_dev *dev) { u8 config, rev; u32 word; @@ -45,5 +45,5 @@ void __init quirk_intel_irqbalance(struct pci_dev *dev) } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_intel_irqbalance); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SMCH, quirk_intel_irqbalance); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_intel_irqbalance); #endif diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c index bfcecdc55ee9..8e2b2d48a2fe 100644 --- a/arch/i386/pci/fixup.c +++ b/arch/i386/pci/fixup.c @@ -255,3 +255,94 @@ static void __init pci_fixup_nforce2(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2); +/* Max PCI Express root ports */ +#define MAX_PCIEROOT 6 +static int quirk_aspm_offset[MAX_PCIEROOT << 3]; + +#define GET_INDEX(a, b) (((a - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + b) + +static int quirk_pcie_aspm_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) +{ + return raw_pci_ops->read(0, bus->number, devfn, where, size, value); +} + +/* + * Replace the original pci bus ops for write with a new one that will filter + * the request to insure ASPM cannot be enabled. + */ +static int quirk_pcie_aspm_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) +{ + u8 offset; + + offset = quirk_aspm_offset[GET_INDEX(bus->self->device, devfn)]; + + if ((offset) && (where == offset)) + value = value & 0xfffffffc; + + return raw_pci_ops->write(0, bus->number, devfn, where, size, value); +} + +struct pci_ops quirk_pcie_aspm_ops = { + .read = quirk_pcie_aspm_read, + .write = quirk_pcie_aspm_write, +}; + +/* + * Prevents PCI Express ASPM (Active State Power Management) being enabled. + * + * Save the register offset, where the ASPM control bits are located, + * for each PCI Express device that is in the device list of + * the root port in an array for fast indexing. Replace the bus ops + * with the modified one. + */ +void pcie_rootport_aspm_quirk(struct pci_dev *pdev) +{ + int cap_base, i; + struct pci_bus *pbus; + struct pci_dev *dev; + + if ((pbus = pdev->subordinate) == NULL) + return; + + /* + * Check if the DID of pdev matches one of the six root ports. This + * check is needed in the case this function is called directly by the + * hot-plug driver. + */ + if ((pdev->device < PCI_DEVICE_ID_INTEL_MCH_PA) || + (pdev->device > PCI_DEVICE_ID_INTEL_MCH_PC1)) + return; + + if (list_empty(&pbus->devices)) { + /* + * If no device is attached to the root port at power-up or + * after hot-remove, the pbus->devices is empty and this code + * will set the offsets to zero and the bus ops to parent's bus + * ops, which is unmodified. + */ + for (i= GET_INDEX(pdev->device, 0); i <= GET_INDEX(pdev->device, 7); ++i) + quirk_aspm_offset[i] = 0; + + pbus->ops = pbus->parent->ops; + } else { + /* + * If devices are attached to the root port at power-up or + * after hot-add, the code loops through the device list of + * each root port to save the register offsets and replace the + * bus ops. + */ + list_for_each_entry(dev, &pbus->devices, bus_list) { + /* There are 0 to 8 devices attached to this bus */ + cap_base = pci_find_capability(dev, PCI_CAP_ID_EXP); + quirk_aspm_offset[GET_INDEX(pdev->device, dev->devfn)]= cap_base + 0x10; + } + pbus->ops = &quirk_pcie_aspm_ops; + } +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PA, pcie_rootport_aspm_quirk ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PA1, pcie_rootport_aspm_quirk ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PB, pcie_rootport_aspm_quirk ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PB1, pcie_rootport_aspm_quirk ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC, pcie_rootport_aspm_quirk ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_rootport_aspm_quirk ); + diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 2adcd76d9bdd..279f53d78608 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -38,6 +38,7 @@ #include #include #include +#include "../pci.h" #include "pciehp.h" #include "pciehprm.h" @@ -1220,7 +1221,13 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) pciehp_configure_device(ctrl, new_func); } } while (new_func); - + + /* + * Some PCI Express root ports require fixup after hot-plug operation. + */ + if (pcie_mch_quirk) + pci_fixup_device(pci_fixup_final, ctrl->pci_dev); + if (PWR_LED(ctrl->ctrlcap)) { /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 7930c5d6121b..10d488cb6673 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -741,6 +741,8 @@ static void hpc_release_ctlr(struct controller *ctrl) if (php_ctlr->irq) { free_irq(php_ctlr->irq, ctrl); php_ctlr->irq = 0; + if (!pcie_mch_quirk) + pci_disable_msi(php_ctlr->pci_dev); } } if (php_ctlr->pci_dev) @@ -1402,8 +1404,8 @@ int pcie_init(struct controller * ctrl, start_int_poll_timer( php_ctlr, 10 ); /* start with 10 second delay */ } else { /* Installs the interrupt handler */ - dbg("%s: pciehp_msi_quirk = %x\n", __FUNCTION__, pciehp_msi_quirk); - if (!pciehp_msi_quirk) { + dbg("%s: pcie_mch_quirk = %x\n", __FUNCTION__, pcie_mch_quirk); + if (!pcie_mch_quirk) { rc = pci_enable_msi(pdev); if (rc) { info("Can't get msi for the hotplug controller\n"); diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 8aa17540f26d..723b12c0bb7c 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -82,9 +82,11 @@ int pciehp_unconfigure_device(struct pci_func* func) { int rc = 0; int j; + struct pci_bus *pbus; dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, func->device, func->function); + pbus = func->pci_dev->bus; for (j=0; j<8 ; j++) { struct pci_dev* temp = pci_find_slot(func->bus, @@ -93,6 +95,12 @@ int pciehp_unconfigure_device(struct pci_func* func) pci_remove_bus_device(temp); } } + /* + * Some PCI Express root ports require fixup after hot-plug operation. + */ + if (pcie_mch_quirk) + pci_fixup_device(pci_fixup_final, pbus->self); + return rc; } diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 85ce29156647..c799ca007977 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -792,6 +792,7 @@ static void hpc_release_ctlr(struct controller *ctrl) if (php_ctlr->irq) { free_irq(php_ctlr->irq, ctrl); php_ctlr->irq = 0; + pci_disable_msi(php_ctlr->pci_dev); } } if (php_ctlr->pci_dev) { diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 0c58b65e9c30..c7e526d64256 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -61,7 +61,7 @@ extern int pci_visit_dev(struct pci_visit *fn, /* Lock for read/write access to pci device and bus lists */ extern spinlock_t pci_bus_lock; -extern int pciehp_msi_quirk; +extern int pcie_mch_quirk; extern struct device_attribute pci_dev_attrs[]; /** diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 04e49a4e24f6..dcc5a53439f5 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1135,7 +1135,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_a #endif #ifdef CONFIG_SCSI_SATA -static void __init quirk_intel_ide_combined(struct pci_dev *pdev) +static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev) { u8 prog, comb, tmp; int ich = 0; @@ -1209,14 +1209,15 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_intel_ide_co #endif /* CONFIG_SCSI_SATA */ -int pciehp_msi_quirk; +int pcie_mch_quirk; -static void __devinit quirk_pciehp_msi(struct pci_dev *pdev) +static void __devinit quirk_pcie_mch(struct pci_dev *pdev) { - pciehp_msi_quirk = 1; + pcie_mch_quirk = 1; } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SMCH, quirk_pciehp_msi ); - +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_pcie_mch ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_pcie_mch ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_pcie_mch ); static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) { @@ -1265,4 +1266,7 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) pci_do_fixups(dev, start, end); } -EXPORT_SYMBOL(pciehp_msi_quirk); +EXPORT_SYMBOL(pcie_mch_quirk); +#ifdef CONFIG_HOTPLUG +EXPORT_SYMBOL(pci_fixup_device); +#endif diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 35bb32b752bb..a068c74e8580 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2206,8 +2206,14 @@ #define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577 #define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580 #define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582 -#define PCI_DEVICE_ID_INTEL_SMCH 0x3590 +#define PCI_DEVICE_ID_INTEL_E7520_MCH 0x3590 #define PCI_DEVICE_ID_INTEL_E7320_MCH 0x3592 +#define PCI_DEVICE_ID_INTEL_MCH_PA 0x3595 +#define PCI_DEVICE_ID_INTEL_MCH_PA1 0x3596 +#define PCI_DEVICE_ID_INTEL_MCH_PB 0x3597 +#define PCI_DEVICE_ID_INTEL_MCH_PB1 0x3598 +#define PCI_DEVICE_ID_INTEL_MCH_PC 0x3599 +#define PCI_DEVICE_ID_INTEL_MCH_PC1 0x359a #define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e #define PCI_DEVICE_ID_INTEL_80310 0x530d #define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000 -- cgit v1.2.3 From f6d553444da20cd1e44f2c4864c2d0c56c934e0a Mon Sep 17 00:00:00 2001 From: Jon Smirl Date: Thu, 4 Nov 2004 23:06:26 -0800 Subject: [PATCH] PCI: add PCI ROMs to sysfs Linus has requested that the sysfs rom attribute be changed to require enabling before it works. echo "0" to the attribute to disable, echoing anything else enables the rom output. The concern is that something like a file browser could inadvertently read the attribute and change the state of the hardware without the user's knowledge. The attached patch includes the previous patch plus the enabling logic. [root@smirl 0000:02:02.0]# [root@smirl 0000:02:02.0]# cat rom cat: rom: Invalid argument [root@smirl 0000:02:02.0]# echo "1" >rom [root@smirl 0000:02:02.0]# hexdump -C -n 20 rom 00000000 55 aa 60 e9 d6 01 00 00 00 00 00 00 00 00 00 00 |U.`.............| 00000010 00 00 00 00 |....| 00000014 [root@smirl 0000:02:02.0]# echo "0" >rom [root@smirl 0000:02:02.0]# hexdump -C -n 20 rom hexdump: rom: Invalid argument [root@smirl 0000:02:02.0]# Signed-off-by: Jon Smirl Signed-off-by: Greg Kroah-Hartman --- arch/i386/pci/fixup.c | 38 ++++++++ drivers/pci/Makefile | 3 +- drivers/pci/pci-sysfs.c | 120 +++++++++++++++++++++++++- drivers/pci/pci.h | 4 +- drivers/pci/probe.c | 2 +- drivers/pci/remove.c | 2 + drivers/pci/rom.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/pci/setup-res.c | 2 +- include/linux/ioport.h | 5 ++ include/linux/pci.h | 8 ++ 10 files changed, 404 insertions(+), 5 deletions(-) create mode 100644 drivers/pci/rom.c (limited to 'include/linux') diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c index 8e2b2d48a2fe..f5a345118b76 100644 --- a/arch/i386/pci/fixup.c +++ b/arch/i386/pci/fixup.c @@ -346,3 +346,41 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PB1, pcie_r DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC, pcie_rootport_aspm_quirk ); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_rootport_aspm_quirk ); +/* + * Fixup to mark boot BIOS video selected by BIOS before it changes + * + * From information provided by "Jon Smirl" + * + * The standard boot ROM sequence for an x86 machine uses the BIOS + * to select an initial video card for boot display. This boot video + * card will have it's BIOS copied to C0000 in system RAM. + * IORESOURCE_ROM_SHADOW is used to associate the boot video + * card with this copy. On laptops this copy has to be used since + * the main ROM may be compressed or combined with another image. + * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW + * is marked here since the boot video device will be the only enabled + * video device at this point. + * + */static void __devinit pci_fixup_video(struct pci_dev *pdev) +{ + struct pci_dev *bridge; + struct pci_bus *bus; + u16 l; + + if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) + return; + + /* Is VGA routed to us? */ + bus = pdev->bus; + while (bus) { + bridge = bus->self; + if (bridge) { + pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &l); + if (!(l & PCI_BRIDGE_CTL_VGA)) + return; + } + bus = bus->parent; + } + pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; +} +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 7006354e98b0..9410012d7e39 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -3,7 +3,8 @@ # obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \ - names.o pci-driver.o search.o pci-sysfs.o + names.o pci-driver.o search.o pci-sysfs.o \ + rom.o obj-$(CONFIG_PROC_FS) += proc.o ifndef CONFIG_SPARC64 diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 120a441a88d6..84728283f0d5 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -5,6 +5,8 @@ * (C) Copyright 2002-2004 IBM Corp. * (C) Copyright 2003 Matthew Wilcox * (C) Copyright 2003 Hewlett-Packard + * (C) Copyright 2004 Jon Smirl + * (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes * * File attributes for PCI devices * @@ -20,6 +22,8 @@ #include "pci.h" +static int sysfs_initialized; /* = 0 */ + /* show configuration fields */ #define pci_config_attr(field, format_string) \ static ssize_t \ @@ -164,6 +168,65 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count) return count; } +/** + * pci_write_rom - used to enable access to the PCI ROM display + * @kobj: kernel object handle + * @buf: user input + * @off: file offset + * @count: number of byte in input + * + * writing anything except 0 enables it + */ +static ssize_t +pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count) +{ + struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); + + if ((off == 0) && (*buf == '0') && (count == 2)) + pdev->rom_attr_enabled = 0; + else + pdev->rom_attr_enabled = 1; + + return count; +} + +/** + * pci_read_rom - read a PCI ROM + * @kobj: kernel object handle + * @buf: where to put the data we read from the ROM + * @off: file offset + * @count: number of bytes to read + * + * Put @count bytes starting at @off into @buf from the ROM in the PCI + * device corresponding to @kobj. + */ +static ssize_t +pci_read_rom(struct kobject *kobj, char *buf, loff_t off, size_t count) +{ + struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); + void __iomem *rom; + size_t size; + + if (!pdev->rom_attr_enabled) + return -EINVAL; + + rom = pci_map_rom(pdev, &size); /* size starts out as PCI window size */ + if (!rom) + return 0; + + if (off >= size) + count = 0; + else { + if (off + count > size) + count = size - off; + + memcpy_fromio(buf, rom + off, count); + } + pci_unmap_rom(pdev, rom); + + return count; +} + static struct bin_attribute pci_config_attr = { .attr = { .name = "config", @@ -186,13 +249,68 @@ static struct bin_attribute pcie_config_attr = { .write = pci_write_config, }; -void pci_create_sysfs_dev_files (struct pci_dev *pdev) +int pci_create_sysfs_dev_files (struct pci_dev *pdev) { + if (!sysfs_initialized) + return -EACCES; + if (pdev->cfg_size < 4096) sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr); else sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr); + /* If the device has a ROM, try to expose it in sysfs. */ + if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) { + struct bin_attribute *rom_attr; + + rom_attr = kmalloc(sizeof(*rom_attr), GFP_ATOMIC); + if (rom_attr) { + pdev->rom_attr = rom_attr; + rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE); + rom_attr->attr.name = "rom"; + rom_attr->attr.mode = S_IRUSR; + rom_attr->attr.owner = THIS_MODULE; + rom_attr->read = pci_read_rom; + rom_attr->write = pci_write_rom; + sysfs_create_bin_file(&pdev->dev.kobj, rom_attr); + } + } /* add platform-specific attributes */ pcibios_add_platform_entries(pdev); + + return 0; +} + +/** + * pci_remove_sysfs_dev_files - cleanup PCI specific sysfs files + * @pdev: device whose entries we should free + * + * Cleanup when @pdev is removed from sysfs. + */ +void pci_remove_sysfs_dev_files(struct pci_dev *pdev) +{ + if (pdev->cfg_size < 4096) + sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); + else + sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr); + + if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) { + if (pdev->rom_attr) { + sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); + kfree(pdev->rom_attr); + } + } } + +static int __init pci_sysfs_init(void) +{ + struct pci_dev *pdev = NULL; + + sysfs_initialized = 1; + while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) + pci_create_sysfs_dev_files(pdev); + + return 0; +} + +__initcall(pci_sysfs_init); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index c7e526d64256..afa4164d5a37 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -2,7 +2,9 @@ extern int pci_hotplug (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); -extern void pci_create_sysfs_dev_files(struct pci_dev *pdev); +extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); +extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev); +extern void pci_cleanup_rom(struct pci_dev *dev); extern int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, unsigned long size, unsigned long align, unsigned long min, unsigned int type_mask, diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 1d2f4c8646d9..dcbb493191d7 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -170,7 +170,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) if (sz && sz != 0xffffffff) { sz = pci_size(l, sz, PCI_ROM_ADDRESS_MASK); if (sz) { - res->flags = (l & PCI_ROM_ADDRESS_ENABLE) | + res->flags = (l & IORESOURCE_ROM_ENABLE) | IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_READONLY | IORESOURCE_CACHEABLE; res->start = l & PCI_ROM_ADDRESS_MASK; diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index 889b2e3ac840..b2942c4b3bfc 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c @@ -16,6 +16,7 @@ static void pci_free_resources(struct pci_dev *dev) msi_remove_pci_irq_vectors(dev); + pci_cleanup_rom(dev); for (i = 0; i < PCI_NUM_RESOURCES; i++) { struct resource *res = dev->resource + i; if (res->parent) @@ -26,6 +27,7 @@ static void pci_free_resources(struct pci_dev *dev) static void pci_destroy_dev(struct pci_dev *dev) { pci_proc_detach_device(dev); + pci_remove_sysfs_dev_files(dev); device_unregister(&dev->dev); /* Remove the device from the device lists, and prevent any further diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c new file mode 100644 index 000000000000..54e4ba790858 --- /dev/null +++ b/drivers/pci/rom.c @@ -0,0 +1,225 @@ +/* + * drivers/pci/rom.c + * + * (C) Copyright 2004 Jon Smirl + * (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes + * + * PCI ROM access routines + * + */ + + +#include +#include +#include + +#include "pci.h" + +/** + * pci_enable_rom - enable ROM decoding for a PCI device + * @dev: PCI device to enable + * + * Enable ROM decoding on @dev. This involves simply turning on the last + * bit of the PCI ROM BAR. Note that some cards may share address decoders + * between the ROM and other resources, so enabling it may disable access + * to MMIO registers or other card memory. + */ +static void +pci_enable_rom(struct pci_dev *pdev) +{ + u32 rom_addr; + + pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr); + rom_addr |= PCI_ROM_ADDRESS_ENABLE; + pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr); +} + +/** + * pci_disable_rom - disable ROM decoding for a PCI device + * @dev: PCI device to disable + * + * Disable ROM decoding on a PCI device by turning off the last bit in the + * ROM BAR. + */ +static void +pci_disable_rom(struct pci_dev *pdev) +{ + u32 rom_addr; + pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr); + rom_addr &= ~PCI_ROM_ADDRESS_ENABLE; + pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr); +} + +/** + * pci_map_rom - map a PCI ROM to kernel space + * @dev: pointer to pci device struct + * @size: pointer to receive size of pci window over ROM + * @return: kernel virtual pointer to image of ROM + * + * Map a PCI ROM into kernel space. If ROM is boot video ROM, + * the shadow BIOS copy will be returned instead of the + * actual ROM. + */ +void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) +{ + struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; + loff_t start; + void __iomem *rom; + void __iomem *image; + int last_image; + + if (res->flags & IORESOURCE_ROM_SHADOW) { /* IORESOURCE_ROM_SHADOW only set on x86 */ + start = (loff_t)0xC0000; /* primary video rom always starts here */ + *size = 0x20000; /* cover C000:0 through E000:0 */ + } else { + if (res->flags & IORESOURCE_ROM_COPY) { + *size = pci_resource_len(pdev, PCI_ROM_RESOURCE); + return (void __iomem *)pci_resource_start(pdev, PCI_ROM_RESOURCE); + } else { + /* assign the ROM an address if it doesn't have one */ + if (res->parent == NULL) + pci_assign_resource(pdev, PCI_ROM_RESOURCE); + + start = pci_resource_start(pdev, PCI_ROM_RESOURCE); + *size = pci_resource_len(pdev, PCI_ROM_RESOURCE); + if (*size == 0) + return NULL; + + /* Enable ROM space decodes */ + pci_enable_rom(pdev); + } + } + + rom = ioremap(start, *size); + if (!rom) { + /* restore enable if ioremap fails */ + if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW | IORESOURCE_ROM_COPY))) + pci_disable_rom(pdev); + return NULL; + } + + /* Try to find the true size of the ROM since sometimes the PCI window */ + /* size is much larger than the actual size of the ROM. */ + /* True size is important if the ROM is going to be copied. */ + image = rom; + do { + void __iomem *pds; + /* Standard PCI ROMs start out with these bytes 55 AA */ + if (readb(image) != 0x55) + break; + if (readb(image + 1) != 0xAA) + break; + /* get the PCI data structure and check its signature */ + pds = image + readw(image + 24); + if (readb(pds) != 'P') + break; + if (readb(pds + 1) != 'C') + break; + if (readb(pds + 2) != 'I') + break; + if (readb(pds + 3) != 'R') + break; + last_image = readb(pds + 21) & 0x80; + /* this length is reliable */ + image += readw(pds + 16) * 512; + } while (!last_image); + + *size = image - rom; + + return rom; +} + +/** + * pci_map_rom_copy - map a PCI ROM to kernel space, create a copy + * @dev: pointer to pci device struct + * @size: pointer to receive size of pci window over ROM + * @return: kernel virtual pointer to image of ROM + * + * Map a PCI ROM into kernel space. If ROM is boot video ROM, + * the shadow BIOS copy will be returned instead of the + * actual ROM. + */ +void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size) +{ + struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; + void __iomem *rom; + + rom = pci_map_rom(pdev, size); + if (!rom) + return NULL; + + if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_SHADOW)) + return rom; + + res->start = (unsigned long)kmalloc(*size, GFP_KERNEL); + if (!res->start) + return rom; + + res->end = res->start + *size; + memcpy_fromio((void*)res->start, rom, *size); + pci_unmap_rom(pdev, rom); + res->flags |= IORESOURCE_ROM_COPY; + + return (void __iomem *)res->start; +} + +/** + * pci_unmap_rom - unmap the ROM from kernel space + * @dev: pointer to pci device struct + * @rom: virtual address of the previous mapping + * + * Remove a mapping of a previously mapped ROM + */ +void +pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom) +{ + struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; + + if (res->flags & IORESOURCE_ROM_COPY) + return; + + iounmap(rom); + + /* Disable again before continuing, leave enabled if pci=rom */ + if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW))) + pci_disable_rom(pdev); +} + +/** + * pci_remove_rom - disable the ROM and remove its sysfs attribute + * @dev: pointer to pci device struct + * + */ +void +pci_remove_rom(struct pci_dev *pdev) +{ + struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; + + if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) + sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); + if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW | IORESOURCE_ROM_COPY))) + pci_disable_rom(pdev); +} + +/** + * pci_cleanup_rom - internal routine for freeing the ROM copy created + * by pci_map_rom_copy called from remove.c + * @dev: pointer to pci device struct + * + */ +void +pci_cleanup_rom(struct pci_dev *pdev) +{ + struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; + if (res->flags & IORESOURCE_ROM_COPY) { + kfree((void*)res->start); + res->flags &= ~IORESOURCE_ROM_COPY; + res->start = 0; + res->end = 0; + } +} + +EXPORT_SYMBOL(pci_map_rom); +EXPORT_SYMBOL(pci_map_rom_copy); +EXPORT_SYMBOL(pci_unmap_rom); +EXPORT_SYMBOL(pci_remove_rom); diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 42a5ad47773f..9fbf0d2d5a2d 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -56,7 +56,7 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) if (resno < 6) { reg = PCI_BASE_ADDRESS_0 + 4 * resno; } else if (resno == PCI_ROM_RESOURCE) { - new |= res->flags & PCI_ROM_ADDRESS_ENABLE; + new |= res->flags & IORESOURCE_ROM_ENABLE; reg = dev->rom_base_reg; } else { /* Hmm, non-standard resource. */ diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 363aef7268c6..62d042099e89 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -82,6 +82,11 @@ struct resource_list { #define IORESOURCE_MEM_SHADOWABLE (1<<5) /* dup: IORESOURCE_SHADOWABLE */ #define IORESOURCE_MEM_EXPANSIONROM (1<<6) +/* PCI ROM control bits (IORESOURCE_BITS) */ +#define IORESOURCE_ROM_ENABLE (1<<0) /* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */ +#define IORESOURCE_ROM_SHADOW (1<<1) /* ROM is copy at C000:0 */ +#define IORESOURCE_ROM_COPY (1<<2) /* ROM is alloc'd copy, resource field overlaid */ + /* PC/ISA/whatever - the normal PC address spaces: IO and memory */ extern struct resource ioport_resource; extern struct resource iomem_resource; diff --git a/include/linux/pci.h b/include/linux/pci.h index 2bc81cf429a0..75a5e93cfe8c 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -537,6 +537,8 @@ struct pci_dev { unsigned int is_busmaster:1; /* device is busmaster */ u32 saved_config_space[16]; /* config space saved at suspend time */ + struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */ + int rom_attr_enabled; /* has display of the rom attribute been enabled? */ #ifdef CONFIG_PCI_NAMES #define PCI_NAME_SIZE 96 #define PCI_NAME_HALF __stringify(43) /* less than half to handle slop */ @@ -785,6 +787,12 @@ int pci_dac_set_dma_mask(struct pci_dev *dev, u64 mask); int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask); int pci_assign_resource(struct pci_dev *dev, int i); +/* ROM control related routines */ +void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size); +void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size); +void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom); +void pci_remove_rom(struct pci_dev *pdev); + /* Power management related routines */ int pci_save_state(struct pci_dev *dev); int pci_restore_state(struct pci_dev *dev); -- cgit v1.2.3 From f1d390a2c2c38f030e47fc6035dece6dc3428818 Mon Sep 17 00:00:00 2001 From: Luca Risolia Date: Thu, 11 Nov 2004 03:03:53 -0800 Subject: [PATCH] USB: SN9C10x driver updates SN9C10x driver updates. The most important change is the addition of the "SN9C10x" vendor-specific pixel format, which is used by the applications or libraries to get "raw" compressed data from the SN9C10x controllers. This also means that V4L2 should be smart enough for the decompression to be handled in userland. You can consider this patch as a further response to the discussion we had on the lkml about the submission of the PWC driver including decompression in kernelspace, which is present in the Alan Cox's tree. Changes: (+ new, - removed, * cleanup, @ bugfix) @ Fix VIDIOC_TRY_FMT ioctl @ Fix SOF/EOF problems with TAS5130D1B image sensor @ Fix VIDIOC_ENUM_FMT ioctl * Replace wait_event_interruptible() with wait_event_timeout() * Use msecs_to_jiffies() for timeouts in jiffies * Use usb_make_path() on VIDIOC_QUERYCAP for device path in the usb tree * read() returns buf.bytesused instead of buf.length on success - Remove brightness control from PAS106B and PAS202BCB, since it has no effect on the active pixel area (it's just for window border lines) + Implement VIDIOC_G_PARM and VIDIOC_S_PARM ioctl's + Add DAC magnitude, DAC sign, green balance and exposure controls for PAS106B and PAS202BCB image sensors + Add an additional pixel format for compressed video: V4L2_PIX_FMT_SN9C10X + VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP are used to set or get the current compression quality + New documentation note in "Notes for V4L2 application developers" paragraph about video formats and compressed data. + Documentation updates about the new features Signed-off-by: Luca Risolia Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/sn9c102.txt | 122 ++++++++----- drivers/usb/media/sn9c102.h | 14 +- drivers/usb/media/sn9c102_core.c | 324 +++++++++++++++++++++++---------- drivers/usb/media/sn9c102_pas106b.c | 113 +++++++++--- drivers/usb/media/sn9c102_pas202bcb.c | 95 ++++++++-- drivers/usb/media/sn9c102_sensor.h | 25 ++- drivers/usb/media/sn9c102_tas5110c1b.c | 4 +- drivers/usb/media/sn9c102_tas5130d1b.c | 8 +- include/linux/videodev2.h | 1 + 9 files changed, 507 insertions(+), 199 deletions(-) (limited to 'include/linux') diff --git a/Documentation/usb/sn9c102.txt b/Documentation/usb/sn9c102.txt index 40c2f73a707f..18ceabdb36e4 100644 --- a/Documentation/usb/sn9c102.txt +++ b/Documentation/usb/sn9c102.txt @@ -9,28 +9,32 @@ Index ===== 1. Copyright -2. License -3. Overview -4. Module dependencies -5. Module loading -6. Module parameters -7. Optional device control through "sysfs" -8. Supported devices -9. How to add support for new image sensors -10. Notes for V4L2 application developers -11. Contact information -12. Credits +2. Disclaimer +3. License +4. Overview +5. Driver installation +6. Module loading +7. Module parameters +8. Optional device control through "sysfs" +9. Supported devices +10. How to add support for new image sensors +11. Notes for V4L2 application developers +12. Contact information +13. Credits 1. Copyright ============ Copyright (C) 2004 by Luca Risolia + +2. Disclaimer +============= SONiX is a trademark of SONiX Technology Company Limited, inc. -This driver is not sponsored or developed by SONiX. +This software is not sponsored or developed by SONiX. -2. License +3. License ========== 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,29 +51,52 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -3. Overview +4. Overview =========== This driver attempts to support the video and audio streaming capabilities of the devices mounting the SONiX SN9C101, SN9C102 and SN9C103 (or SUI-102) PC Camera Controllers. -- It's worth to note that SONiX has never collaborated with me during the +It's worth to note that SONiX has never collaborated with the author during the development of this project, despite several requests for enough detailed specifications of the register tables, compression engine and video data format -of the above chips - - -Up to 64 cameras can be handled at the same time. They can be connected and -disconnected from the host many times without turning off the computer, if -your system supports hotplugging. +of the above chips. The driver relies on the Video4Linux2 and USB core modules. It has been designed to run properly on SMP systems as well. The latest version of the SN9C10x driver can be found at the following URL: -http://go.lamarinapunto.com/ - - -4. Module dependencies +http://www.linux-projects.org/ + +Some of the features of the driver are: + +- full compliance with the Video4Linux2 API (see also "Notes for V4L2 + application developers" paragraph); +- available mmap or read/poll methods for video streaming through isochronous + data transfers; +- automatic detection of image sensor; +- support for any window resolutions and optional panning within the maximum + pixel area of image sensor; +- image downscaling with arbitrary scaling factors from 1, 2 and 4 in both + directions (see "Notes for V4L2 application developers" paragraph); +- two different video formats for uncompressed or compressed data (see also + "Notes for V4L2 application developers" paragraph); +- full support for the capabilities of many of the possible image sensors that + can be connected to the SN9C10x bridges, including, for istance, red, green, + blue and global gain adjustments and exposure (see "Supported devices" + paragraph for details); +- use of default color settings for sunlight conditions; +- dynamic I/O interface for both SN9C10x and image sensor control (see + "Optional device control through 'sysfs'" paragraph); +- dynamic driver control thanks to various module parameters (see "Module + parameters" paragraph); +- up to 64 cameras can be handled at the same time; they can be connected and + disconnected from the host many times without turning off the computer, if + your system supports hotplugging; +- no known bugs. + + +5. Module dependencies ====================== For it to work properly, the driver needs kernel support for Video4Linux and USB. @@ -101,7 +128,7 @@ And finally: CONFIG_USB_SN9C102=m -5. Module loading +6. Module loading ================= To use the driver, it is necessary to load the "sn9c102" module into memory after every other module required: "videodev", "usbcore" and, depending on @@ -109,7 +136,6 @@ the USB host controller you have, "ehci-hcd", "uhci-hcd" or "ohci-hcd". Loading can be done as shown below: - [root@localhost home]# modprobe usbcore [root@localhost home]# modprobe sn9c102 At this point the devices should be recognized. You can invoke "dmesg" to @@ -118,7 +144,7 @@ analyze kernel messages and verify that the loading process has gone well: [user@localhost home]$ dmesg -6. Module parameters +7. Module parameters ==================== Module parameters are listed below: ------------------------------------------------------------------------------- @@ -144,12 +170,14 @@ Description: Debugging information level, from 0 to 3: 2 = significant informations 3 = more verbose messages Level 3 is useful for testing only, when only one device - is used. + is used. It also shows some more informations about the + hardware being detected. This parameter can be changed at + runtime thanks to the /sys filesystem. Default: 2 ------------------------------------------------------------------------------- -7. Optional device control through "sysfs" +8. Optional device control through "sysfs" ========================================== It is possible to read and write both the SN9C10x and the image sensor registers by using the "sysfs" filesystem interface. @@ -191,10 +219,10 @@ Note that the SN9C10x always returns 0 when some of its registers are read. To avoid race conditions, all the I/O accesses to the files are serialized. -8. Supported devices +9. Supported devices ==================== -- I won't mention any of the names of the companies as well as their products -here. They have never collaborated with me, so no advertising - +None of the names of the companies as well as their products will be mentioned +here. They have never collaborated with the author, so no advertising. From the point of view of a driver, what unambiguously identify a device are its vendor and product USB identifiers. Below is a list of known identifiers of @@ -241,7 +269,7 @@ Vendor ID Product ID 0x0c45 0x60bc 0x0c45 0x60be -The list above does NOT imply that all those devices work with this driver: up +The list above does not imply that all those devices work with this driver: up until now only the ones that mount the following image sensors are supported; kernel messages will always tell you whether this is the case: @@ -259,16 +287,16 @@ If you think your camera is based on the above hardware and is not actually listed in the above table, you may try to add the specific USB VendorID and ProductID identifiers to the sn9c102_id_table[] in the file "sn9c102_sensor.h"; then compile, load the module again and look at the kernel output. -If this works, please send an email to me reporting the kernel messages, so -that I can add a new entry in the list of supported devices. +If this works, please send an email to the author reporting the kernel +messages, so that a new entry in the list of supported devices can be added. Donations of new models for further testing and support would be much -appreciated. I won't add official support for hardware that I don't actually -have. +appreciated. Non-available hardware won't be supported by the author of this +driver. -9. How to add support for new image sensors -=========================================== +10. How to add support for new image sensors +============================================ It should be easy to write code for new sensors by using the small API that I have created for this purpose, which is present in "sn9c102_sensor.h" (documentation is included there). As an example, have a look at the code in @@ -278,7 +306,7 @@ At the moment, possible unsupported image sensors are: HV7131x series (VGA), MI03x series (VGA), OV7620 (VGA), OV7630 (VGA), CIS-VF10 (VGA). -10. Notes for V4L2 application developers +11. Notes for V4L2 application developers ========================================= This driver follows the V4L2 API specifications. In particular, it enforces two rules: @@ -301,8 +329,18 @@ factor can be chosen arbitrarily by the "negotiation" of the "source" and that, during the negotiation, whenever the "VIDIOC_S_CROP" ioctl is issued, the scaling factor is restored to 1. +This driver supports two different video formats: the first one is the "8-bit +Sequential Bayer" format and can be used to obtain uncompressed video data +from the device through the current I/O method, while the second one provides +"raw" compressed video data (without the initial and final frame headers). The +compression quality may vary from 0 to 1 and can be selected or queried thanks +to the VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2 ioctl's. For maximum +flexibility, the default active video format depends on how the image sensor +being used is initialized (as described in the documentation of the API for the +image sensors supplied by this driver). + -11. Contact information +12. Contact information ======================= I may be contacted by e-mail at . @@ -311,7 +349,7 @@ My public 1024-bit key should be available at any keyserver; the fingerprint is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'. -12. Credits +13. Credits =========== I would thank the following persons: diff --git a/drivers/usb/media/sn9c102.h b/drivers/usb/media/sn9c102.h index a682dfc2f747..a58ff2e9efa3 100644 --- a/drivers/usb/media/sn9c102.h +++ b/drivers/usb/media/sn9c102.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -45,7 +46,8 @@ #define SN9C102_URBS 2 #define SN9C102_ISO_PACKETS 7 #define SN9C102_ALTERNATE_SETTING 8 -#define SN9C102_CTRL_TIMEOUT 10*HZ +#define SN9C102_URB_TIMEOUT msecs_to_jiffies(3) +#define SN9C102_CTRL_TIMEOUT msecs_to_jiffies(100) /*****************************************************************************/ @@ -53,8 +55,8 @@ #define SN9C102_MODULE_AUTHOR "(C) 2004 Luca Risolia" #define SN9C102_AUTHOR_EMAIL "" #define SN9C102_MODULE_LICENSE "GPL" -#define SN9C102_MODULE_VERSION "1:1.12" -#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 12) +#define SN9C102_MODULE_VERSION "1:1.19" +#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 19) enum sn9c102_bridge { BRIDGE_SN9C101 = 0x01, @@ -100,7 +102,7 @@ enum sn9c102_stream_state { }; struct sn9c102_sysfs_attr { - u8 reg, val, i2c_reg, i2c_val; + u8 reg, i2c_reg; }; static DECLARE_MUTEX(sn9c102_sysfs_lock); @@ -121,11 +123,13 @@ struct sn9c102_device { struct sn9c102_frame_t *frame_current, frame[SN9C102_MAX_FRAMES]; struct list_head inqueue, outqueue; - u32 frame_count, nbuffers; + u32 frame_count, nbuffers, nreadbuffers; enum sn9c102_io_method io; enum sn9c102_stream_state stream; + struct v4l2_jpegcompression compression; + struct sn9c102_sysfs_attr sysfs; u16 reg[32]; diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c index dee36973f0b6..e4c44fa873f4 100644 --- a/drivers/usb/media/sn9c102_core.c +++ b/drivers/usb/media/sn9c102_core.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -100,6 +99,7 @@ static sn9c102_eof_header_t sn9c102_eof_header[] = { }; /*****************************************************************************/ + static void* rvmalloc(size_t size) { void* mem; @@ -424,7 +424,8 @@ int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value) /*****************************************************************************/ -static void* sn9c102_find_sof_header(void* mem, size_t len) +static void* +sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) { size_t soflen = sizeof(sn9c102_sof_header_t), i; u8 j, n = sizeof(sn9c102_sof_header) / soflen; @@ -440,11 +441,15 @@ static void* sn9c102_find_sof_header(void* mem, size_t len) } -static void* sn9c102_find_eof_header(void* mem, size_t len) +static void* +sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len) { size_t eoflen = sizeof(sn9c102_eof_header_t), i; unsigned j, n = sizeof(sn9c102_eof_header) / eoflen; + if (cam->sensor->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) + return NULL; /* EOF header does not exist in compressed data */ + for (i = 0; (len >= eoflen) && (i <= len - eoflen); i++) for (j = 0; j < n; j++) if (!memcmp(mem + i, sn9c102_eof_header[j], eoflen)) @@ -509,9 +514,9 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs) */ redo: - sof = sn9c102_find_sof_header(pos, len); + sof = sn9c102_find_sof_header(cam, pos, len); if (!sof) { - eof = sn9c102_find_eof_header(pos, len); + eof = sn9c102_find_eof_header(cam, pos, len); if ((*f)->state == F_GRABBING) { end_of_frame: img = len; @@ -539,7 +544,9 @@ end_of_frame: (*f)->buf.bytesused += img; - if ((*f)->buf.bytesused == (*f)->buf.length) { + if ((*f)->buf.bytesused == (*f)->buf.length || + (cam->sensor->pix_format.pixelformat == + V4L2_PIX_FMT_SN9C10X && eof)) { u32 b = (*f)->buf.bytesused; (*f)->state = F_DONE; (*f)->buf.sequence= ++cam->frame_count; @@ -592,14 +599,20 @@ start_of_frame: goto redo; } else if ((*f)->state == F_GRABBING) { - eof = sn9c102_find_eof_header(pos, len); + eof = sn9c102_find_eof_header(cam, pos, len); if (eof && eof < sof) goto end_of_frame; /* (1) */ else { - DBG(3, "SOF before expected EOF after %lu " - "bytes of image data", - (unsigned long)((*f)->buf.bytesused)) - goto start_of_frame; + if (cam->sensor->pix_format.pixelformat == + V4L2_PIX_FMT_SN9C10X) { + eof = sof-sizeof(sn9c102_sof_header_t); + goto end_of_frame; + } else { + DBG(3, "SOF before expected EOF after " + "%lu bytes of image data", + (unsigned long)((*f)->buf.bytesused)) + goto start_of_frame; + } } } } @@ -723,6 +736,29 @@ static int sn9c102_stop_transfer(struct sn9c102_device* cam) return err; } + +int sn9c102_stream_interrupt(struct sn9c102_device* cam) +{ + int err = 0; + + cam->stream = STREAM_INTERRUPT; + err = wait_event_timeout(cam->wait_stream, + (cam->stream == STREAM_OFF) || + (cam->state & DEV_DISCONNECTED), + SN9C102_URB_TIMEOUT); + if (err) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "The camera is misconfigured. To use " + "it, close and open /dev/video%d " + "again.", cam->v4ldev->minor) + return err; + } + if (cam->state & DEV_DISCONNECTED) + return -ENODEV; + + return 0; +} + /*****************************************************************************/ static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count) @@ -1127,6 +1163,35 @@ static void sn9c102_create_sysfs(struct sn9c102_device* cam) /*****************************************************************************/ +static int +sn9c102_set_format(struct sn9c102_device* cam, struct v4l2_pix_format* fmt) +{ + int err = 0; + + if (fmt->pixelformat == V4L2_PIX_FMT_SN9C10X) + err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, 0x18); + else + err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, 0x18); + + return err ? -EIO : 0; +} + + +static int +sn9c102_set_compression(struct sn9c102_device* cam, + struct v4l2_jpegcompression* compression) +{ + int err = 0; + + if (compression->quality == 0) + err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, 0x17); + else if (compression->quality == 1) + err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, 0x17); + + return err ? -EIO : 0; +} + + static int sn9c102_set_scale(struct sn9c102_device* cam, u8 scale) { u8 r = 0; @@ -1204,6 +1269,20 @@ static int sn9c102_init(struct sn9c102_device* cam) } } + if (!(cam->state & DEV_INITIALIZED)) + cam->compression.quality = cam->reg[0x17] & 0x01 ? 0 : 1; + else + err += sn9c102_set_compression(cam, &cam->compression); + err += sn9c102_set_format(cam, &s->pix_format); + if (err) + return err; + + if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) + DBG(3, "Compressed video format is active, quality %d", + cam->compression.quality) + else + DBG(3, "Uncompressed video format is active") + if (s->set_crop) if ((err = s->set_crop(cam, rect))) { DBG(3, "set_crop() failed") @@ -1219,9 +1298,12 @@ static int sn9c102_init(struct sn9c102_device* cam) ctrl.value = qctrl[i].default_value; err = s->set_ctrl(cam, &ctrl); if (err) { - DBG(3, "Set control failed") + DBG(3, "Set %s control failed", + s->qctrl[i].name) return err; } + DBG(3, "Image sensor supports '%s' control", + s->qctrl[i].name) } } @@ -1230,6 +1312,7 @@ static int sn9c102_init(struct sn9c102_device* cam) spin_lock_init(&cam->queue_lock); init_waitqueue_head(&cam->wait_frame); init_waitqueue_head(&cam->wait_stream); + cam->nreadbuffers = 2; memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl)); memcpy(&(s->_rect), &(s->cropcap.defrect), sizeof(struct v4l2_rect)); @@ -1387,7 +1470,7 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) } if (cam->io == IO_NONE) { - if (!sn9c102_request_buffers(cam, 2)) { + if (!sn9c102_request_buffers(cam, cam->nreadbuffers)) { DBG(1, "read() failed, not enough memory") up(&cam->fileop_sem); return -ENOMEM; @@ -1431,8 +1514,8 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) sn9c102_queue_unusedframes(cam); - if (count > f->buf.length) - count = f->buf.length; + if (count > f->buf.bytesused) + count = f->buf.bytesused; if (copy_to_user(buf, f->bufmem, count)) { up(&cam->fileop_sem); @@ -1553,11 +1636,15 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) return -EINVAL; } + /* VM_IO is eventually going to replace PageReserved altogether */ + vma->vm_flags |= VM_IO; + vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ + pos = (unsigned long)cam->frame[i].bufmem; while (size > 0) { /* size is page-aligned */ page = vmalloc_to_pfn((void *)pos); if (remap_pfn_range(vma, start, page, PAGE_SIZE, - vma->vm_page_prot)) { + vma->vm_page_prot)) { up(&cam->fileop_sem); return -EAGAIN; } @@ -1567,8 +1654,6 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) } vma->vm_ops = &sn9c102_vm_ops; - vma->vm_flags &= ~VM_IO; /* not I/O memory */ - vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ vma->vm_private_data = &cam->frame[i]; sn9c102_vm_open(vma); @@ -1593,11 +1678,14 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, .version = SN9C102_MODULE_VERSION_CODE, .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING, + V4L2_CAP_STREAMING, }; strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); - strlcpy(cap.bus_info, cam->dev.bus_id, sizeof(cap.bus_info)); + if (usb_make_path(cam->usbdev, cap.bus_info, + sizeof(cap.bus_info)) < 0) + strlcpy(cap.bus_info, cam->dev.bus_id, + sizeof(cap.bus_info)); if (copy_to_user(arg, &cap, sizeof(cap))) return -EFAULT; @@ -1707,6 +1795,9 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, s->_qctrl[i].default_value = ctrl.value; + PDBGG("VIDIOC_S_CTRL: id %lu, value %lu", + (unsigned long)ctrl.id, (unsigned long)ctrl.value) + return 0; } @@ -1803,22 +1894,9 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, } else scale = 1; - if (cam->stream == STREAM_ON) { - cam->stream = STREAM_INTERRUPT; - err = wait_event_interruptible - ( cam->wait_stream, - (cam->stream == STREAM_OFF) || - (cam->state & DEV_DISCONNECTED) ); - if (err) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "The camera is misconfigured. To use " - "it, close and open /dev/video%d " - "again.", cam->v4ldev->minor) + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) return err; - } - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - } if (copy_to_user(arg, &crop, sizeof(crop))) { cam->stream = stream; @@ -1859,20 +1937,23 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, case VIDIOC_ENUM_FMT: { - struct sn9c102_sensor* s = cam->sensor; struct v4l2_fmtdesc fmtd; if (copy_from_user(&fmtd, arg, sizeof(fmtd))) return -EFAULT; - if (fmtd.index != 0) + if (fmtd.index == 0) { + strcpy(fmtd.description, "bayer rgb"); + fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; + } else if (fmtd.index == 1) { + strcpy(fmtd.description, "compressed"); + fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X; + fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; + } else return -EINVAL; - memset(&fmtd, 0, sizeof(fmtd)); - fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strcpy(fmtd.description, "bayer rgb"); - fmtd.pixelformat = s->pix_format.pixelformat; + memset(&fmtd.reserved, 0, sizeof(fmtd.reserved)); if (copy_to_user(arg, &fmtd, sizeof(fmtd))) return -EFAULT; @@ -1891,8 +1972,9 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - pfmt->bytesperline = (pfmt->width * pfmt->priv) / 8; - pfmt->sizeimage = pfmt->height * pfmt->bytesperline; + pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X) + ? 0 : (pfmt->width * pfmt->priv) / 8; + pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); pfmt->field = V4L2_FIELD_NONE; memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); @@ -1961,15 +2043,21 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, pix->width = rect.width / scale; pix->height = rect.height / scale; - pix->pixelformat = pfmt->pixelformat; + if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X && + pix->pixelformat != V4L2_PIX_FMT_SBGGR8) + pix->pixelformat = pfmt->pixelformat; pix->priv = pfmt->priv; /* bpp */ pix->colorspace = pfmt->colorspace; - pix->bytesperline = (pix->width * pix->priv) / 8; - pix->sizeimage = pix->height * pix->bytesperline; + pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) + ? 0 : (pix->width * pix->priv) / 8; + pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); pix->field = V4L2_FIELD_NONE; - if (cmd == VIDIOC_TRY_FMT) + if (cmd == VIDIOC_TRY_FMT) { + if (copy_to_user(arg, &format, sizeof(format))) + return -EFAULT; return 0; + } for (i = 0; i < cam->nbuffers; i++) if (cam->frame[i].vma_use_count) { @@ -1978,22 +2066,9 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, return -EINVAL; } - if (cam->stream == STREAM_ON) { - cam->stream = STREAM_INTERRUPT; - err = wait_event_interruptible - ( cam->wait_stream, - (cam->stream == STREAM_OFF) || - (cam->state & DEV_DISCONNECTED) ); - if (err) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "The camera is misconfigured. To use " - "it, close and open /dev/video%d " - "again.", cam->v4ldev->minor) + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) return err; - } - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - } if (copy_to_user(arg, &format, sizeof(format))) { cam->stream = stream; @@ -2002,7 +2077,8 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, sn9c102_release_buffers(cam); - err = sn9c102_set_crop(cam, &rect); + err += sn9c102_set_format(cam, pix); + err += sn9c102_set_crop(cam, &rect); if (s->set_crop) err += s->set_crop(cam, &rect); err += sn9c102_set_scale(cam, scale); @@ -2031,6 +2107,47 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, return 0; } + case VIDIOC_G_JPEGCOMP: + { + if (copy_to_user(arg, &cam->compression, + sizeof(cam->compression))) + return -EFAULT; + + return 0; + } + + case VIDIOC_S_JPEGCOMP: + { + struct v4l2_jpegcompression jc; + const enum sn9c102_stream_state stream = cam->stream; + int err = 0; + + if (copy_from_user(&jc, arg, sizeof(jc))) + return -EFAULT; + + if (jc.quality != 0 && jc.quality != 1) + return -EINVAL; + + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) + return err; + + err += sn9c102_set_compression(cam, &jc); + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " + "problems. To use the camera, close and open " + "/dev/video%d again.", cam->v4ldev->minor) + return -EIO; + } + + cam->compression.quality = jc.quality; + + cam->stream = stream; + + return 0; + } + case VIDIOC_REQBUFS: { struct v4l2_requestbuffers rb; @@ -2057,22 +2174,9 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, return -EINVAL; } - if (cam->stream == STREAM_ON) { - cam->stream = STREAM_INTERRUPT; - err = wait_event_interruptible - ( cam->wait_stream, - (cam->stream == STREAM_OFF) || - (cam->state & DEV_DISCONNECTED) ); - if (err) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "The camera is misconfigured. To use " - "it, close and open /dev/video%d " - "again.", cam->v4ldev->minor) + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) return err; - } - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - } sn9c102_empty_framequeues(cam); @@ -2222,22 +2326,9 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) return -EINVAL; - if (cam->stream == STREAM_ON) { - cam->stream = STREAM_INTERRUPT; - err = wait_event_interruptible - ( cam->wait_stream, - (cam->stream == STREAM_OFF) || - (cam->state & DEV_DISCONNECTED) ); - if (err) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "The camera is misconfigured. To use " - "it, close and open /dev/video%d " - "again.", cam->v4ldev->minor) + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) return err; - } - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - } sn9c102_empty_framequeues(cam); @@ -2246,13 +2337,56 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, return 0; } + case VIDIOC_G_PARM: + { + struct v4l2_streamparm sp; + + if (copy_from_user(&sp, arg, sizeof(sp))) + return -EFAULT; + + if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + sp.parm.capture.extendedmode = 0; + sp.parm.capture.readbuffers = cam->nreadbuffers; + + if (copy_to_user(arg, &sp, sizeof(sp))) + return -EFAULT; + + return 0; + } + + case VIDIOC_S_PARM: + { + struct v4l2_streamparm sp; + + if (copy_from_user(&sp, arg, sizeof(sp))) + return -EFAULT; + + if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + sp.parm.capture.extendedmode = 0; + + if (sp.parm.capture.readbuffers == 0) + sp.parm.capture.readbuffers = cam->nreadbuffers; + + if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES) + sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES; + + if (copy_to_user(arg, &sp, sizeof(sp))) + return -EFAULT; + + cam->nreadbuffers = sp.parm.capture.readbuffers; + + return 0; + } + case VIDIOC_G_STD: case VIDIOC_S_STD: case VIDIOC_QUERYSTD: case VIDIOC_ENUMSTD: case VIDIOC_QUERYMENU: - case VIDIOC_G_PARM: - case VIDIOC_S_PARM: return -EINVAL; default: diff --git a/drivers/usb/media/sn9c102_pas106b.c b/drivers/usb/media/sn9c102_pas106b.c index 8453409ea125..54942d607a93 100644 --- a/drivers/usb/media/sn9c102_pas106b.c +++ b/drivers/usb/media/sn9c102_pas106b.c @@ -1,5 +1,5 @@ /*************************************************************************** - * Driver for PAS106B image sensor connected to the SN9C10x PC Camera * + * Plug-in for PAS106B image sensor connected to the SN9C10x PC Camera * * Controllers * * * * Copyright (C) 2004 by Luca Risolia * @@ -38,14 +38,9 @@ static int pas106b_init(struct sn9c102_device* cam) err += sn9c102_write_reg(cam, 0x09, 0x18); err += sn9c102_i2c_write(cam, 0x02, 0x0c); - err += sn9c102_i2c_write(cam, 0x03, 0x12); - err += sn9c102_i2c_write(cam, 0x04, 0x05); err += sn9c102_i2c_write(cam, 0x05, 0x5a); err += sn9c102_i2c_write(cam, 0x06, 0x88); err += sn9c102_i2c_write(cam, 0x07, 0x80); - err += sn9c102_i2c_write(cam, 0x08, 0x01); - err += sn9c102_i2c_write(cam, 0x0a, 0x01); - err += sn9c102_i2c_write(cam, 0x0b, 0x00); err += sn9c102_i2c_write(cam, 0x10, 0x06); err += sn9c102_i2c_write(cam, 0x11, 0x06); err += sn9c102_i2c_write(cam, 0x12, 0x00); @@ -62,6 +57,15 @@ static int pas106b_get_ctrl(struct sn9c102_device* cam, struct v4l2_control* ctrl) { switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + { + int r1 = sn9c102_i2c_read(cam, 0x03), + r2 = sn9c102_i2c_read(cam, 0x04); + if (r1 < 0 || r2 < 0) + return -EIO; + ctrl->value = (r1 << 4) | (r2 & 0x0f); + } + return 0; case V4L2_CID_RED_BALANCE: if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0) return -EIO; @@ -77,16 +81,26 @@ static int pas106b_get_ctrl(struct sn9c102_device* cam, return -EIO; ctrl->value &= 0x1f; return 0; - case V4L2_CID_BRIGHTNESS: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x0d)) < 0) - return -EIO; - ctrl->value &= 0x1f; - return 0; case V4L2_CID_CONTRAST: if ((ctrl->value = sn9c102_i2c_read(cam, 0x0f)) < 0) return -EIO; ctrl->value &= 0x07; return 0; + case SN9C102_V4L2_CID_GREEN_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x0a)) < 0) + return -EIO; + ctrl->value = (ctrl->value & 0x1f) << 1; + return 0; + case SN9C102_V4L2_CID_DAC_MAGNITUDE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0) + return -EIO; + ctrl->value &= 0xf8; + return 0; + case SN9C102_V4L2_CID_DAC_SIGN: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x07)) < 0) + return -EIO; + ctrl->value &= 0x01; + return 0; default: return -EINVAL; } @@ -99,6 +113,10 @@ static int pas106b_set_ctrl(struct sn9c102_device* cam, int err = 0; switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + err += sn9c102_i2c_write(cam, 0x03, ctrl->value >> 4); + err += sn9c102_i2c_write(cam, 0x04, ctrl->value & 0x0f); + break; case V4L2_CID_RED_BALANCE: err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); break; @@ -108,12 +126,23 @@ static int pas106b_set_ctrl(struct sn9c102_device* cam, case V4L2_CID_GAIN: err += sn9c102_i2c_write(cam, 0x0e, ctrl->value); break; - case V4L2_CID_BRIGHTNESS: - err += sn9c102_i2c_write(cam, 0x0d, 0x1f - ctrl->value); - break; case V4L2_CID_CONTRAST: err += sn9c102_i2c_write(cam, 0x0f, ctrl->value); break; + case SN9C102_V4L2_CID_GREEN_BALANCE: + err += sn9c102_i2c_write(cam, 0x0a, ctrl->value >> 1); + err += sn9c102_i2c_write(cam, 0x0b, ctrl->value >> 1); + break; + case SN9C102_V4L2_CID_DAC_MAGNITUDE: + err += sn9c102_i2c_write(cam, 0x08, ctrl->value << 3); + break; + case SN9C102_V4L2_CID_DAC_SIGN: + { + int r; + err += (r = sn9c102_i2c_read(cam, 0x07)) < 0 ? r : 0; + err += sn9c102_i2c_write(cam, 0x07, r | ctrl->value); + } + break; default: return -EINVAL; } @@ -147,6 +176,36 @@ static struct sn9c102_sensor pas106b = { .slave_write_id = 0x40, .init = &pas106b_init, .qctrl = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x125, + .maximum = 0xfff, + .step = 0x01, + .default_value = 0x140, + .flags = 0, + }, + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0x1f, + .step = 0x01, + .default_value = 0x0d, + .flags = 0, + }, + { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "contrast", + .minimum = 0x00, + .maximum = 0x07, + .step = 0x01, + .default_value = 0x00, /* 0x00~0x03 have same effect */ + .flags = 0, + }, { .id = V4L2_CID_RED_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -168,33 +227,33 @@ static struct sn9c102_sensor pas106b = { .flags = 0, }, { - .id = V4L2_CID_GAIN, + .id = SN9C102_V4L2_CID_GREEN_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", + .name = "green balance", .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x0d, + .maximum = 0x3e, + .step = 0x02, + .default_value = 0x02, .flags = 0, }, { - .id = V4L2_CID_BRIGHTNESS, + .id = SN9C102_V4L2_CID_DAC_MAGNITUDE, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "brightness", + .name = "DAC magnitude", .minimum = 0x00, .maximum = 0x1f, .step = 0x01, - .default_value = 0x1f, + .default_value = 0x01, .flags = 0, }, { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "contrast", + .id = SN9C102_V4L2_CID_DAC_SIGN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "DAC sign", .minimum = 0x00, - .maximum = 0x07, + .maximum = 0x01, .step = 0x01, - .default_value = 0x00, /* 0x00~0x03 have same effect */ + .default_value = 0x00, .flags = 0, }, }, diff --git a/drivers/usb/media/sn9c102_pas202bcb.c b/drivers/usb/media/sn9c102_pas202bcb.c index 72063e885871..3e2fd5a6f281 100644 --- a/drivers/usb/media/sn9c102_pas202bcb.c +++ b/drivers/usb/media/sn9c102_pas202bcb.c @@ -1,11 +1,14 @@ /*************************************************************************** - * Driver for PAS202BCB image sensor connected to the SN9C10x PC Camera * + * Plug-in for PAS202BCB image sensor connected to the SN9C10x PC Camera * * Controllers * * * * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio * * * * http://cadu.homelinux.com:8080/ * * * + * DAC Magnitude, DAC sign, exposure and green gain controls added by * + * Luca Risolia * + * * * 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 * @@ -41,14 +44,10 @@ static int pas202bcb_init(struct sn9c102_device* cam) err += sn9c102_i2c_write(cam, 0x02, 0x14); err += sn9c102_i2c_write(cam, 0x03, 0x40); - err += sn9c102_i2c_write(cam, 0x04, 0x07); - err += sn9c102_i2c_write(cam, 0x05, 0x25); err += sn9c102_i2c_write(cam, 0x0d, 0x2c); err += sn9c102_i2c_write(cam, 0x0e, 0x01); err += sn9c102_i2c_write(cam, 0x0f, 0xa9); err += sn9c102_i2c_write(cam, 0x10, 0x08); - err += sn9c102_i2c_write(cam, 0x0b, 0x01); - err += sn9c102_i2c_write(cam, 0x0c, 0x04); err += sn9c102_i2c_write(cam, 0x13, 0x63); err += sn9c102_i2c_write(cam, 0x15, 0x70); err += sn9c102_i2c_write(cam, 0x11, 0x01); @@ -63,6 +62,15 @@ static int pas202bcb_get_ctrl(struct sn9c102_device* cam, struct v4l2_control* ctrl) { switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + { + int r1 = sn9c102_i2c_read(cam, 0x04), + r2 = sn9c102_i2c_read(cam, 0x05); + if (r1 < 0 || r2 < 0) + return -EIO; + ctrl->value = (r1 << 6) | (r2 & 0x3f); + } + return 0; case V4L2_CID_RED_BALANCE: if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0) return -EIO; @@ -78,11 +86,20 @@ static int pas202bcb_get_ctrl(struct sn9c102_device* cam, return -EIO; ctrl->value &= 0x1f; return 0; - case V4L2_CID_BRIGHTNESS: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x06)) < 0) + case SN9C102_V4L2_CID_GREEN_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0) return -EIO; ctrl->value &= 0x0f; return 0; + case SN9C102_V4L2_CID_DAC_MAGNITUDE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0) + return -EIO; + return 0; + case SN9C102_V4L2_CID_DAC_SIGN: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x0b)) < 0) + return -EIO; + ctrl->value &= 0x01; + return 0; default: return -EINVAL; } @@ -95,6 +112,10 @@ static int pas202bcb_set_ctrl(struct sn9c102_device* cam, int err = 0; switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6); + err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f); + break; case V4L2_CID_RED_BALANCE: err += sn9c102_i2c_write(cam, 0x09, ctrl->value); break; @@ -104,8 +125,18 @@ static int pas202bcb_set_ctrl(struct sn9c102_device* cam, case V4L2_CID_GAIN: err += sn9c102_i2c_write(cam, 0x10, ctrl->value); break; - case V4L2_CID_BRIGHTNESS: - err += sn9c102_i2c_write(cam, 0x06, 0x0f - ctrl->value); + case SN9C102_V4L2_CID_GREEN_BALANCE: + err += sn9c102_i2c_write(cam, 0x08, ctrl->value); + break; + case SN9C102_V4L2_CID_DAC_MAGNITUDE: + err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); + break; + case SN9C102_V4L2_CID_DAC_SIGN: + { + int r; + err += (r = sn9c102_i2c_read(cam, 0x0b)) < 0 ? r : 0; + err += sn9c102_i2c_write(cam, 0x0b, r | ctrl->value); + } break; default: return -EINVAL; @@ -141,6 +172,26 @@ static struct sn9c102_sensor pas202bcb = { .slave_write_id = 0x40, .init = &pas202bcb_init, .qctrl = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x01e5, + .maximum = 0x3fff, + .step = 0x01, + .default_value = 0x01e5, + .flags = 0, + }, + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0x1f, + .step = 0x01, + .default_value = 0x0c, + .flags = 0, + }, { .id = V4L2_CID_RED_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -162,23 +213,33 @@ static struct sn9c102_sensor pas202bcb = { .flags = 0, }, { - .id = V4L2_CID_GAIN, + .id = SN9C102_V4L2_CID_GREEN_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", + .name = "green balance", .minimum = 0x00, - .maximum = 0x1f, + .maximum = 0x0f, .step = 0x01, - .default_value = 0x0c, + .default_value = 0x00, .flags = 0, }, { - .id = V4L2_CID_BRIGHTNESS, + .id = SN9C102_V4L2_CID_DAC_MAGNITUDE, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "brightness", + .name = "DAC magnitude", .minimum = 0x00, - .maximum = 0x0f, + .maximum = 0xff, .step = 0x01, - .default_value = 0x0f, + .default_value = 0x04, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_DAC_SIGN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "DAC sign", + .minimum = 0x00, + .maximum = 0x01, + .step = 0x01, + .default_value = 0x01, .flags = 0, }, }, diff --git a/drivers/usb/media/sn9c102_sensor.h b/drivers/usb/media/sn9c102_sensor.h index 01bcad14ca6d..ebafc280911d 100644 --- a/drivers/usb/media/sn9c102_sensor.h +++ b/drivers/usb/media/sn9c102_sensor.h @@ -98,7 +98,7 @@ static const struct usb_device_id sn9c102_id_table[] = { \ { USB_DEVICE(0x0c45, 0x6028), }, /* PAS202BCB */ \ { USB_DEVICE(0x0c45, 0x6029), }, /* PAS106B */ \ { USB_DEVICE(0x0c45, 0x602a), }, /* HV7131[D|E1] */ \ - { USB_DEVICE(0x0c45, 0x602b), }, \ + { USB_DEVICE(0x0c45, 0x602b), }, /* MI-0343 */ \ { USB_DEVICE(0x0c45, 0x602c), }, /* OV7620 */ \ { USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */ \ { USB_DEVICE(0x0c45, 0x6080), }, \ @@ -292,21 +292,25 @@ struct sn9c102_sensor { NOTE: in case, you must program the SN9C10X chip to get rid of blank pixels or blank lines at the _start_ of each line or frame after each HSYNC or VSYNC, so that the image starts with - real RGB data (see regs 0x12,0x13) (having set H_SIZE and, + real RGB data (see regs 0x12, 0x13) (having set H_SIZE and, V_SIZE you don't have to care about blank pixels or blank lines at the end of each line or frame). */ struct v4l2_pix_format pix_format; /* - What you have to define here are: initial 'width' and 'height' of - the target rectangle, the bayer 'pixelformat' and 'priv' which we'll - be used to indicate the number of bits per pixel, 8 or 9. - Nothing more. + What you have to define here are: 1) initial 'width' and 'height' of + the target rectangle 2) the initial 'pixelformat', which can be + either V4L2_PIX_FMT_SN9C10X (for compressed video) or + V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate the + number of bits per pixel for uncompressed video, 8 or 9 (despite the + current value of 'pixelformat'). NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4 of cropcap.defrect.width and cropcap.defrect.height. I suggest 1/1. - NOTE 2: as said above, you have to program the SN9C10X chip to get + NOTE 2: The initial compression quality is defined by the first bit + of reg 0x17 during the initialization of the image sensor. + NOTE 3: as said above, you have to program the SN9C10X chip to get rid of any blank pixels, so that the output of the sensor matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR). */ @@ -333,4 +337,11 @@ struct sn9c102_sensor { struct v4l2_rect _rect; }; +/*****************************************************************************/ + +/* Private ioctl's for control settings supported by some image sensors */ +#define SN9C102_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE +#define SN9C102_V4L2_CID_DAC_SIGN V4L2_CID_PRIVATE_BASE + 1 +#define SN9C102_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 2 + #endif /* _SN9C102_SENSOR_H_ */ diff --git a/drivers/usb/media/sn9c102_tas5110c1b.c b/drivers/usb/media/sn9c102_tas5110c1b.c index ce8b47b59a75..03153cae2db3 100644 --- a/drivers/usb/media/sn9c102_tas5110c1b.c +++ b/drivers/usb/media/sn9c102_tas5110c1b.c @@ -1,5 +1,5 @@ /*************************************************************************** - * Driver for TAS5110C1B image sensor connected to the SN9C10x PC Camera * + * Plug-in for TAS5110C1B image sensor connected to the SN9C10x PC Camera * * Controllers * * * * Copyright (C) 2004 by Luca Risolia * @@ -150,7 +150,7 @@ int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam) /* This sensor has no identifiers, so let's attach it anyway */ sn9c102_attach_sensor(cam, &tas5110c1b); - /* At the moment, sensor detection is based on USB pid/vid */ + /* Sensor detection is based on USB pid/vid */ if (tas5110c1b.usbdev->descriptor.idProduct != 0x6001 && tas5110c1b.usbdev->descriptor.idProduct != 0x6005 && tas5110c1b.usbdev->descriptor.idProduct != 0x60ab) diff --git a/drivers/usb/media/sn9c102_tas5130d1b.c b/drivers/usb/media/sn9c102_tas5130d1b.c index 0048e9c20d80..36b00d12a6e5 100644 --- a/drivers/usb/media/sn9c102_tas5130d1b.c +++ b/drivers/usb/media/sn9c102_tas5130d1b.c @@ -1,5 +1,5 @@ /*************************************************************************** - * Driver for TAS5130D1B image sensor connected to the SN9C10x PC Camera * + * Plug-in for TAS5130D1B image sensor connected to the SN9C10x PC Camera * * Controllers * * * * Copyright (C) 2004 by Luca Risolia * @@ -96,8 +96,8 @@ static int tas5130d1b_set_crop(struct sn9c102_device* cam, err += sn9c102_write_reg(cam, v_start, 0x13); /* Do NOT change! */ - err += sn9c102_write_reg(cam, 0x1d, 0x1a); - err += sn9c102_write_reg(cam, 0x10, 0x1b); + err += sn9c102_write_reg(cam, 0x1f, 0x1a); + err += sn9c102_write_reg(cam, 0x1a, 0x1b); err += sn9c102_write_reg(cam, 0xf3, 0x19); return err; @@ -165,7 +165,7 @@ int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam) /* This sensor has no identifiers, so let's attach it anyway */ sn9c102_attach_sensor(cam, &tas5130d1b); - /* At the moment, sensor detection is based on USB pid/vid */ + /* Sensor detection is based on USB pid/vid */ if (tas5130d1b.usbdev->descriptor.idProduct != 0x6025 && tas5130d1b.usbdev->descriptor.idProduct != 0x60aa) return -ENODEV; diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 819e211f60be..a86882b84127 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -219,6 +219,7 @@ struct v4l2_pix_format /* Vendor-specific formats */ #define V4L2_PIX_FMT_WNVA v4l2_fourcc('W','N','V','A') /* Winnov hw compress */ +#define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S','9','1','0') /* SN9C10x compression */ /* * F O R M A T E N U M E R A T I O N -- cgit v1.2.3 From 9a92429171a6d3988523db977a5adc502eeacc1a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 10 Nov 2004 22:40:27 -0800 Subject: [NET]: Remove net_init.c ifdef clutter. Signed-off-by: David S. Miller --- drivers/net/net_init.c | 341 ---------------------------------------------- include/linux/netdevice.h | 5 +- net/802/fc.c | 32 +++++ net/802/fddi.c | 41 ++++++ net/802/hippi.c | 89 ++++++++++++ net/802/tr.c | 38 ++++++ net/appletalk/Makefile | 2 +- net/ethernet/eth.c | 61 +++++++++ 8 files changed, 263 insertions(+), 346 deletions(-) (limited to 'include/linux') diff --git a/drivers/net/net_init.c b/drivers/net/net_init.c index 854bc2b70cee..1f9e0ddf95ca 100644 --- a/drivers/net/net_init.c +++ b/drivers/net/net_init.c @@ -105,260 +105,6 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *mask, } EXPORT_SYMBOL(alloc_netdev); -/** - * alloc_etherdev - Allocates and sets up an ethernet device - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this ethernet device - * - * Fill in the fields of the device structure with ethernet-generic - * values. Basically does everything except registering the device. - * - * Constructs a new net device, complete with a private data area of - * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for - * this private data area. - */ - -struct net_device *alloc_etherdev(int sizeof_priv) -{ - return alloc_netdev(sizeof_priv, "eth%d", ether_setup); -} - -EXPORT_SYMBOL(alloc_etherdev); - -static int eth_mac_addr(struct net_device *dev, void *p) -{ - struct sockaddr *addr=p; - if (netif_running(dev)) - return -EBUSY; - memcpy(dev->dev_addr, addr->sa_data,dev->addr_len); - return 0; -} - -static int eth_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > 1500)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - -#ifdef CONFIG_FDDI - -/** - * alloc_fddidev - Register FDDI device - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this FDDI device - * - * Fill in the fields of the device structure with FDDI-generic values. - * - * Constructs a new net device, complete with a private data area of - * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for - * this private data area. - */ - -struct net_device *alloc_fddidev(int sizeof_priv) -{ - return alloc_netdev(sizeof_priv, "fddi%d", fddi_setup); -} - -EXPORT_SYMBOL(alloc_fddidev); - -static int fddi_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < FDDI_K_SNAP_HLEN) || (new_mtu > FDDI_K_SNAP_DLEN)) - return(-EINVAL); - dev->mtu = new_mtu; - return(0); -} - -#endif /* CONFIG_FDDI */ - -#ifdef CONFIG_HIPPI - -static int hippi_change_mtu(struct net_device *dev, int new_mtu) -{ - /* - * HIPPI's got these nice large MTUs. - */ - if ((new_mtu < 68) || (new_mtu > 65280)) - return -EINVAL; - dev->mtu = new_mtu; - return(0); -} - - -/* - * For HIPPI we will actually use the lower 4 bytes of the hardware - * address as the I-FIELD rather than the actual hardware address. - */ -static int hippi_mac_addr(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - if (netif_running(dev)) - return -EBUSY; - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - return 0; -} - -static int hippi_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p) -{ - /* Never send broadcast/multicast ARP messages */ - p->mcast_probes = 0; - - /* In IPv6 unicast probes are valid even on NBMA, - * because they are encapsulated in normal IPv6 protocol. - * Should be a generic flag. - */ - if (p->tbl->family != AF_INET6) - p->ucast_probes = 0; - return 0; -} - -static void hippi_setup(struct net_device *dev) -{ - dev->set_multicast_list = NULL; - dev->change_mtu = hippi_change_mtu; - dev->hard_header = hippi_header; - dev->rebuild_header = hippi_rebuild_header; - dev->set_mac_address = hippi_mac_addr; - dev->hard_header_parse = NULL; - dev->hard_header_cache = NULL; - dev->header_cache_update = NULL; - dev->neigh_setup = hippi_neigh_setup_dev; - - /* - * We don't support HIPPI `ARP' for the time being, and probably - * never will unless someone else implements it. However we - * still need a fake ARPHRD to make ifconfig and friends play ball. - */ - dev->type = ARPHRD_HIPPI; - dev->hard_header_len = HIPPI_HLEN; - dev->mtu = 65280; - dev->addr_len = HIPPI_ALEN; - dev->tx_queue_len = 25 /* 5 */; - memset(dev->broadcast, 0xFF, HIPPI_ALEN); - - - /* - * HIPPI doesn't support broadcast+multicast and we only use - * static ARP tables. ARP is disabled by hippi_neigh_setup_dev. - */ - dev->flags = 0; -} - -/** - * alloc_hippi_dev - Register HIPPI device - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this HIPPI device - * - * Fill in the fields of the device structure with HIPPI-generic values. - * - * Constructs a new net device, complete with a private data area of - * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for - * this private data area. - */ - -struct net_device *alloc_hippi_dev(int sizeof_priv) -{ - return alloc_netdev(sizeof_priv, "hip%d", hippi_setup); -} - -EXPORT_SYMBOL(alloc_hippi_dev); - -#endif /* CONFIG_HIPPI */ - -void ether_setup(struct net_device *dev) -{ - /* Fill in the fields of the device structure with ethernet-generic values. - This should be in a common file instead of per-driver. */ - - dev->change_mtu = eth_change_mtu; - dev->hard_header = eth_header; - dev->rebuild_header = eth_rebuild_header; - dev->set_mac_address = eth_mac_addr; - dev->hard_header_cache = eth_header_cache; - dev->header_cache_update= eth_header_cache_update; - dev->hard_header_parse = eth_header_parse; - - dev->type = ARPHRD_ETHER; - dev->hard_header_len = ETH_HLEN; - dev->mtu = 1500; /* eth_mtu */ - dev->addr_len = ETH_ALEN; - dev->tx_queue_len = 1000; /* Ethernet wants good queues */ - - memset(dev->broadcast,0xFF, ETH_ALEN); - - /* New-style flags. */ - dev->flags = IFF_BROADCAST|IFF_MULTICAST; -} -EXPORT_SYMBOL(ether_setup); - -#ifdef CONFIG_FDDI - -void fddi_setup(struct net_device *dev) -{ - /* - * Fill in the fields of the device structure with FDDI-generic values. - * This should be in a common file instead of per-driver. - */ - - dev->change_mtu = fddi_change_mtu; - dev->hard_header = fddi_header; - dev->rebuild_header = fddi_rebuild_header; - - dev->type = ARPHRD_FDDI; - dev->hard_header_len = FDDI_K_SNAP_HLEN+3; /* Assume 802.2 SNAP hdr len + 3 pad bytes */ - dev->mtu = FDDI_K_SNAP_DLEN; /* Assume max payload of 802.2 SNAP frame */ - dev->addr_len = FDDI_K_ALEN; - dev->tx_queue_len = 100; /* Long queues on FDDI */ - - memset(dev->broadcast, 0xFF, FDDI_K_ALEN); - - /* New-style flags */ - dev->flags = IFF_BROADCAST | IFF_MULTICAST; -} -EXPORT_SYMBOL(fddi_setup); - -#endif /* CONFIG_FDDI */ - -#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE) - -static int ltalk_change_mtu(struct net_device *dev, int mtu) -{ - return -EINVAL; -} - -static int ltalk_mac_addr(struct net_device *dev, void *addr) -{ - return -EINVAL; -} - - -void ltalk_setup(struct net_device *dev) -{ - /* Fill in the fields of the device structure with localtalk-generic values. */ - - dev->change_mtu = ltalk_change_mtu; - dev->hard_header = NULL; - dev->rebuild_header = NULL; - dev->set_mac_address = ltalk_mac_addr; - dev->hard_header_cache = NULL; - dev->header_cache_update= NULL; - - dev->type = ARPHRD_LOCALTLK; - dev->hard_header_len = LTALK_HLEN; - dev->mtu = LTALK_MTU; - dev->addr_len = LTALK_ALEN; - dev->tx_queue_len = 10; - - dev->broadcast[0] = 0xFF; - - dev->flags = IFF_BROADCAST|IFF_MULTICAST|IFF_NOARP; -} -EXPORT_SYMBOL(ltalk_setup); - -#endif /* CONFIG_ATALK || CONFIG_ATALK_MODULE */ - int register_netdev(struct net_device *dev) { int err; @@ -404,90 +150,3 @@ void unregister_netdev(struct net_device *dev) EXPORT_SYMBOL(register_netdev); EXPORT_SYMBOL(unregister_netdev); - -#ifdef CONFIG_TR - -void tr_setup(struct net_device *dev) -{ - /* - * Configure and register - */ - - dev->hard_header = tr_header; - dev->rebuild_header = tr_rebuild_header; - - dev->type = ARPHRD_IEEE802_TR; - dev->hard_header_len = TR_HLEN; - dev->mtu = 2000; - dev->addr_len = TR_ALEN; - dev->tx_queue_len = 100; /* Long queues on tr */ - - memset(dev->broadcast,0xFF, TR_ALEN); - - /* New-style flags. */ - dev->flags = IFF_BROADCAST | IFF_MULTICAST ; -} - -/** - * alloc_trdev - Register token ring device - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this token ring device - * - * Fill in the fields of the device structure with token ring-generic values. - * - * Constructs a new net device, complete with a private data area of - * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for - * this private data area. - */ - -struct net_device *alloc_trdev(int sizeof_priv) -{ - return alloc_netdev(sizeof_priv, "tr%d", tr_setup); -} - -EXPORT_SYMBOL(tr_setup); -EXPORT_SYMBOL(alloc_trdev); - -#endif /* CONFIG_TR */ - -#ifdef CONFIG_NET_FC - -void fc_setup(struct net_device *dev) -{ - dev->hard_header = fc_header; - dev->rebuild_header = fc_rebuild_header; - - dev->type = ARPHRD_IEEE802; - dev->hard_header_len = FC_HLEN; - dev->mtu = 2024; - dev->addr_len = FC_ALEN; - dev->tx_queue_len = 100; /* Long queues on fc */ - - memset(dev->broadcast,0xFF, FC_ALEN); - - /* New-style flags. */ - dev->flags = IFF_BROADCAST; -} - -/** - * alloc_fcdev - Register fibre channel device - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this fibre channel device - * - * Fill in the fields of the device structure with fibre channel-generic values. - * - * Constructs a new net device, complete with a private data area of - * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for - * this private data area. - */ - -struct net_device *alloc_fcdev(int sizeof_priv) -{ - return alloc_netdev(sizeof_priv, "fc%d", fc_setup); -} - -EXPORT_SYMBOL(fc_setup); -EXPORT_SYMBOL(alloc_fcdev); - -#endif /* CONFIG_NET_FC */ - diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 9fa9c7ead784..c880b0ee02b3 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -902,10 +902,7 @@ static inline void netif_tx_disable(struct net_device *dev) /* These functions live elsewhere (drivers/net/net_init.c, but related) */ extern void ether_setup(struct net_device *dev); -extern void fddi_setup(struct net_device *dev); -extern void tr_setup(struct net_device *dev); -extern void fc_setup(struct net_device *dev); -extern void fc_freedev(struct net_device *dev); + /* Support for loadable net-drivers */ extern struct net_device *alloc_netdev(int sizeof_priv, const char *name, void (*setup)(struct net_device *)); diff --git a/net/802/fc.c b/net/802/fc.c index e7009186a822..9a502820f7f8 100644 --- a/net/802/fc.c +++ b/net/802/fc.c @@ -129,3 +129,35 @@ fc_type_trans(struct sk_buff *skb, struct net_device *dev) return ntohs(ETH_P_802_2); } + +static void fc_setup(struct net_device *dev) +{ + dev->hard_header = fc_header; + dev->rebuild_header = fc_rebuild_header; + + dev->type = ARPHRD_IEEE802; + dev->hard_header_len = FC_HLEN; + dev->mtu = 2024; + dev->addr_len = FC_ALEN; + dev->tx_queue_len = 100; /* Long queues on fc */ + dev->flags = IFF_BROADCAST; + + memset(dev->broadcast, 0xFF, FC_ALEN); +} + +/** + * alloc_fcdev - Register fibre channel device + * @sizeof_priv: Size of additional driver-private structure to be allocated + * for this fibre channel device + * + * Fill in the fields of the device structure with fibre channel-generic values. + * + * Constructs a new net device, complete with a private data area of + * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for + * this private data area. + */ +struct net_device *alloc_fcdev(int sizeof_priv) +{ + return alloc_netdev(sizeof_priv, "fc%d", fc_setup); +} +EXPORT_SYMBOL(alloc_fcdev); diff --git a/net/802/fddi.c b/net/802/fddi.c index 066025f39fd9..752d77d37d3e 100644 --- a/net/802/fddi.c +++ b/net/802/fddi.c @@ -166,3 +166,44 @@ unsigned short fddi_type_trans(struct sk_buff *skb, struct net_device *dev) } EXPORT_SYMBOL(fddi_type_trans); + +static int fddi_change_mtu(struct net_device *dev, int new_mtu) +{ + if ((new_mtu < FDDI_K_SNAP_HLEN) || (new_mtu > FDDI_K_SNAP_DLEN)) + return(-EINVAL); + dev->mtu = new_mtu; + return(0); +} + +static void fddi_setup(struct net_device *dev) +{ + dev->change_mtu = fddi_change_mtu; + dev->hard_header = fddi_header; + dev->rebuild_header = fddi_rebuild_header; + + dev->type = ARPHRD_FDDI; + dev->hard_header_len = FDDI_K_SNAP_HLEN+3; /* Assume 802.2 SNAP hdr len + 3 pad bytes */ + dev->mtu = FDDI_K_SNAP_DLEN; /* Assume max payload of 802.2 SNAP frame */ + dev->addr_len = FDDI_K_ALEN; + dev->tx_queue_len = 100; /* Long queues on FDDI */ + dev->flags = IFF_BROADCAST | IFF_MULTICAST; + + memset(dev->broadcast, 0xFF, FDDI_K_ALEN); +} + +/** + * alloc_fddidev - Register FDDI device + * @sizeof_priv: Size of additional driver-private structure to be allocated + * for this FDDI device + * + * Fill in the fields of the device structure with FDDI-generic values. + * + * Constructs a new net device, complete with a private data area of + * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for + * this private data area. + */ +struct net_device *alloc_fddidev(int sizeof_priv) +{ + return alloc_netdev(sizeof_priv, "fddi%d", fddi_setup); +} +EXPORT_SYMBOL(alloc_fddidev); diff --git a/net/802/hippi.c b/net/802/hippi.c index 7ae2797eef25..bb66e0315276 100644 --- a/net/802/hippi.c +++ b/net/802/hippi.c @@ -154,3 +154,92 @@ unsigned short hippi_type_trans(struct sk_buff *skb, struct net_device *dev) } EXPORT_SYMBOL(hippi_type_trans); + +static int hippi_change_mtu(struct net_device *dev, int new_mtu) +{ + /* + * HIPPI's got these nice large MTUs. + */ + if ((new_mtu < 68) || (new_mtu > 65280)) + return -EINVAL; + dev->mtu = new_mtu; + return(0); +} + +/* + * For HIPPI we will actually use the lower 4 bytes of the hardware + * address as the I-FIELD rather than the actual hardware address. + */ +static int hippi_mac_addr(struct net_device *dev, void *p) +{ + struct sockaddr *addr = p; + if (netif_running(dev)) + return -EBUSY; + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + return 0; +} + +static int hippi_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p) +{ + /* Never send broadcast/multicast ARP messages */ + p->mcast_probes = 0; + + /* In IPv6 unicast probes are valid even on NBMA, + * because they are encapsulated in normal IPv6 protocol. + * Should be a generic flag. + */ + if (p->tbl->family != AF_INET6) + p->ucast_probes = 0; + return 0; +} + +static void hippi_setup(struct net_device *dev) +{ + dev->set_multicast_list = NULL; + dev->change_mtu = hippi_change_mtu; + dev->hard_header = hippi_header; + dev->rebuild_header = hippi_rebuild_header; + dev->set_mac_address = hippi_mac_addr; + dev->hard_header_parse = NULL; + dev->hard_header_cache = NULL; + dev->header_cache_update = NULL; + dev->neigh_setup = hippi_neigh_setup_dev; + + /* + * We don't support HIPPI `ARP' for the time being, and probably + * never will unless someone else implements it. However we + * still need a fake ARPHRD to make ifconfig and friends play ball. + */ + dev->type = ARPHRD_HIPPI; + dev->hard_header_len = HIPPI_HLEN; + dev->mtu = 65280; + dev->addr_len = HIPPI_ALEN; + dev->tx_queue_len = 25 /* 5 */; + memset(dev->broadcast, 0xFF, HIPPI_ALEN); + + + /* + * HIPPI doesn't support broadcast+multicast and we only use + * static ARP tables. ARP is disabled by hippi_neigh_setup_dev. + */ + dev->flags = 0; +} + +/** + * alloc_hippi_dev - Register HIPPI device + * @sizeof_priv: Size of additional driver-private structure to be allocated + * for this HIPPI device + * + * Fill in the fields of the device structure with HIPPI-generic values. + * + * Constructs a new net device, complete with a private data area of + * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for + * this private data area. + */ + +struct net_device *alloc_hippi_dev(int sizeof_priv) +{ + return alloc_netdev(sizeof_priv, "hip%d", hippi_setup); +} + +EXPORT_SYMBOL(alloc_hippi_dev); diff --git a/net/802/tr.c b/net/802/tr.c index bd22ae2aabff..c3a659d4ee7e 100644 --- a/net/802/tr.c +++ b/net/802/tr.c @@ -583,6 +583,43 @@ static struct file_operations rif_seq_fops = { #endif +static void tr_setup(struct net_device *dev) +{ + /* + * Configure and register + */ + + dev->hard_header = tr_header; + dev->rebuild_header = tr_rebuild_header; + + dev->type = ARPHRD_IEEE802_TR; + dev->hard_header_len = TR_HLEN; + dev->mtu = 2000; + dev->addr_len = TR_ALEN; + dev->tx_queue_len = 100; /* Long queues on tr */ + + memset(dev->broadcast,0xFF, TR_ALEN); + + /* New-style flags. */ + dev->flags = IFF_BROADCAST | IFF_MULTICAST ; +} + +/** + * alloc_trdev - Register token ring device + * @sizeof_priv: Size of additional driver-private structure to be allocated + * for this token ring device + * + * Fill in the fields of the device structure with token ring-generic values. + * + * Constructs a new net device, complete with a private data area of + * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for + * this private data area. + */ +struct net_device *alloc_trdev(int sizeof_priv) +{ + return alloc_netdev(sizeof_priv, "tr%d", tr_setup); +} + /* * Called during bootup. We don't actually have to initialise * too much for this. @@ -604,3 +641,4 @@ module_init(rif_init); EXPORT_SYMBOL(tr_source_route); EXPORT_SYMBOL(tr_type_trans); +EXPORT_SYMBOL(alloc_trdev); diff --git a/net/appletalk/Makefile b/net/appletalk/Makefile index d179728ad522..5cda56edef57 100644 --- a/net/appletalk/Makefile +++ b/net/appletalk/Makefile @@ -4,6 +4,6 @@ obj-$(CONFIG_ATALK) += appletalk.o -appletalk-y := aarp.o ddp.o +appletalk-y := aarp.o ddp.o dev.o appletalk-$(CONFIG_PROC_FS) += atalk_proc.o appletalk-$(CONFIG_SYSCTL) += sysctl_net_atalk.o diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index a238f92ec37c..5a3a14a72e6d 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -245,3 +245,64 @@ void eth_header_cache_update(struct hh_cache *hh, struct net_device *dev, unsign } EXPORT_SYMBOL(eth_type_trans); + +static int eth_mac_addr(struct net_device *dev, void *p) +{ + struct sockaddr *addr=p; + if (netif_running(dev)) + return -EBUSY; + memcpy(dev->dev_addr, addr->sa_data,dev->addr_len); + return 0; +} + +static int eth_change_mtu(struct net_device *dev, int new_mtu) +{ + if ((new_mtu < 68) || (new_mtu > 1500)) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + +/* + * Fill in the fields of the device structure with ethernet-generic values. + */ +void ether_setup(struct net_device *dev) +{ + dev->change_mtu = eth_change_mtu; + dev->hard_header = eth_header; + dev->rebuild_header = eth_rebuild_header; + dev->set_mac_address = eth_mac_addr; + dev->hard_header_cache = eth_header_cache; + dev->header_cache_update= eth_header_cache_update; + dev->hard_header_parse = eth_header_parse; + + dev->type = ARPHRD_ETHER; + dev->hard_header_len = ETH_HLEN; + dev->mtu = 1500; /* eth_mtu */ + dev->addr_len = ETH_ALEN; + dev->tx_queue_len = 1000; /* Ethernet wants good queues */ + dev->flags = IFF_BROADCAST|IFF_MULTICAST; + + memset(dev->broadcast,0xFF, ETH_ALEN); + +} +EXPORT_SYMBOL(ether_setup); + +/** + * alloc_etherdev - Allocates and sets up an ethernet device + * @sizeof_priv: Size of additional driver-private structure to be allocated + * for this ethernet device + * + * Fill in the fields of the device structure with ethernet-generic + * values. Basically does everything except registering the device. + * + * Constructs a new net device, complete with a private data area of + * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for + * this private data area. + */ + +struct net_device *alloc_etherdev(int sizeof_priv) +{ + return alloc_netdev(sizeof_priv, "eth%d", ether_setup); +} +EXPORT_SYMBOL(alloc_etherdev); -- cgit v1.2.3 From 909ef4877adef308bf8aceea40bc4621ffafb533 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 10 Nov 2004 22:52:44 -0800 Subject: [PKT_SCHED]: Fix overflow on 64bit in times reported to userspace. This patch fixes on overflow in tc actions times reported to userspace on 64 bit architectures. struct tcf_t only contains 32-bit timestamps, but they are initialized to jiffies. When jiffies is larger than 2^32-1 only the low 32 bit are saved, and the diff between jiffies and the current timestamp becomes very large. This happens immediately after boottime since jiffies is initialized to 2^32-300. It was invisible until now because only the lower 32bit were reported to userspace, but with the USER_HZ conversion the reported times start somewhere around 4294967s. This patch extends the timestamps to 64bit. It breaks userspace compatibility for actions, but considering that most of this is not even in iproute yet this should be acceptable. Signed-off-by: Patrick McHardy ACK'd by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/linux/pkt_cls.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h index de9e1311ecbf..45ac289f1bbf 100644 --- a/include/linux/pkt_cls.h +++ b/include/linux/pkt_cls.h @@ -138,9 +138,9 @@ struct tc_police struct tcf_t { - __u32 install; - __u32 lastuse; - __u32 expires; + __u64 install; + __u64 lastuse; + __u64 expires; }; struct tc_cnt -- cgit v1.2.3 From f322f273c27c327551ea978b4a070abb3bd0d2f9 Mon Sep 17 00:00:00 2001 From: Jan Dittmer Date: Thu, 11 Nov 2004 00:32:25 -0800 Subject: [PATCH] fakephp: introduce pci_bus_add_device fakephp needs to add newly discovered devices to the global pci list. Therefore seperate out the appropriate chunk from pci_bus_add_devices to pci_bus_add_device to add a single device to sysfs, procfs and the global device list. Signed-off-by: Jan Dittmer Signed-off-by: Greg Kroah-Hartman --- drivers/pci/bus.c | 31 +++++++++++++++++++++---------- include/linux/pci.h | 1 + 2 files changed, 22 insertions(+), 10 deletions(-) (limited to 'include/linux') diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index e94a854c40f1..dbd33605cc10 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -68,6 +68,25 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, return ret; } +/** + * add a single device + * @dev: device to add + * + * This adds a single pci device to the global + * device list and adds sysfs and procfs entries + */ +void __devinit pci_bus_add_device(struct pci_dev *dev) +{ + device_add(&dev->dev); + + spin_lock(&pci_bus_lock); + list_add_tail(&dev->global_list, &pci_devices); + spin_unlock(&pci_bus_lock); + + pci_proc_attach_device(dev); + pci_create_sysfs_dev_files(dev); +} + /** * pci_bus_add_devices - insert newly discovered PCI devices * @bus: bus to check for new devices @@ -91,16 +110,7 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus) */ if (!list_empty(&dev->global_list)) continue; - - device_add(&dev->dev); - - spin_lock(&pci_bus_lock); - list_add_tail(&dev->global_list, &pci_devices); - spin_unlock(&pci_bus_lock); - - pci_proc_attach_device(dev); - pci_create_sysfs_dev_files(dev); - + pci_bus_add_device(dev); } list_for_each_entry(dev, &bus->devices, bus_list) { @@ -136,5 +146,6 @@ void pci_enable_bridges(struct pci_bus *bus) } EXPORT_SYMBOL(pci_bus_alloc_resource); +EXPORT_SYMBOL_GPL(pci_bus_add_device); EXPORT_SYMBOL(pci_bus_add_devices); EXPORT_SYMBOL(pci_enable_bridges); diff --git a/include/linux/pci.h b/include/linux/pci.h index 75a5e93cfe8c..6e0973f334b1 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -715,6 +715,7 @@ static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *s int pci_scan_slot(struct pci_bus *bus, int devfn); struct pci_dev * pci_scan_single_device(struct pci_bus *bus, int devfn); unsigned int pci_scan_child_bus(struct pci_bus *bus); +void pci_bus_add_device(struct pci_dev *dev); void pci_bus_add_devices(struct pci_bus *bus); void pci_name_device(struct pci_dev *dev); char *pci_class_name(u32 class); -- cgit v1.2.3 From 05997f1618e3169d425a906d5a2ee4813eda8574 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 11 Nov 2004 19:41:25 -0800 Subject: [PATCH] driver core: shrink struct device a bit This patch removes two fields from "struct device" that are duplicated in "struct dev_pm_info": power_state (which should probably vanish) and "saved_state". There were only two "real" uses of saved_state; both are now switched over to use dev_pm_info. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- arch/arm/common/locomo.c | 3 --- arch/arm/common/sa1111.c | 23 +++++++++++++++-------- arch/arm/mach-sa1100/neponset.c | 23 +++++++++++++++-------- include/linux/device.h | 5 ----- 4 files changed, 30 insertions(+), 24 deletions(-) (limited to 'include/linux') diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index 32e114c834a6..b86e288c678c 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c @@ -627,9 +627,6 @@ static int locomo_remove(struct device *dev) if (lchip) { __locomo_remove(lchip); dev_set_drvdata(dev, NULL); - - kfree(dev->saved_state); - dev->saved_state = NULL; } return 0; diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index acc7d1af7da0..b968a092cb3a 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -797,6 +797,8 @@ struct sa1111_save_data { unsigned int wakeen1; }; +#ifdef CONFIG_PM + static int sa1111_suspend(struct device *dev, u32 state, u32 level) { struct sa1111 *sachip = dev_get_drvdata(dev); @@ -808,11 +810,10 @@ static int sa1111_suspend(struct device *dev, u32 state, u32 level) if (level != SUSPEND_DISABLE) return 0; - dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL); - if (!dev->saved_state) + save = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL); + if (!save) return -ENOMEM; - - save = (struct sa1111_save_data *)dev->saved_state; + dev->power.saved_state = save; spin_lock_irqsave(&sachip->lock, flags); @@ -870,7 +871,7 @@ static int sa1111_resume(struct device *dev, u32 level) if (level != RESUME_ENABLE) return 0; - save = (struct sa1111_save_data *)dev->saved_state; + save = (struct sa1111_save_data *)dev->power.saved_state; if (!save) return 0; @@ -915,12 +916,18 @@ static int sa1111_resume(struct device *dev, u32 level) spin_unlock_irqrestore(&sachip->lock, flags); - dev->saved_state = NULL; + dev->power.saved_state = NULL; kfree(save); return 0; } +#else /* !CONFIG_PM */ +#define sa1111_resume NULL +#define sa1111_suspend NULL +#endif /* !CONFIG_PM */ + + static int sa1111_probe(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -943,8 +950,8 @@ static int sa1111_remove(struct device *dev) __sa1111_remove(sachip); dev_set_drvdata(dev, NULL); - kfree(dev->saved_state); - dev->saved_state = NULL; + kfree(dev->power.saved_state); + dev->power.saved_state = NULL; } return 0; diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c index a747fd0bd89a..a23142995f09 100644 --- a/arch/arm/mach-sa1100/neponset.c +++ b/arch/arm/mach-sa1100/neponset.c @@ -173,6 +173,8 @@ static int neponset_probe(struct device *dev) return 0; } +#ifdef CONFIG_PM + /* * LDM power management. */ @@ -184,12 +186,12 @@ static int neponset_suspend(struct device *dev, u32 state, u32 level) if (level == SUSPEND_SAVE_STATE || level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN) { - if (!dev->saved_state) - dev->saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL); - if (!dev->saved_state) + if (!dev->power.saved_state) + dev->power.saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL); + if (!dev->power.saved_state) return -ENOMEM; - *(unsigned int *)dev->saved_state = NCR_0; + *(unsigned int *)dev->power.saved_state = NCR_0; } return 0; @@ -198,16 +200,21 @@ static int neponset_suspend(struct device *dev, u32 state, u32 level) static int neponset_resume(struct device *dev, u32 level) { if (level == RESUME_RESTORE_STATE || level == RESUME_ENABLE) { - if (dev->saved_state) { - NCR_0 = *(unsigned int *)dev->saved_state; - kfree(dev->saved_state); - dev->saved_state = NULL; + if (dev->power.saved_state) { + NCR_0 = *(unsigned int *)dev->power.saved_state; + kfree(dev->power.saved_state); + dev->power.saved_state = NULL; } } return 0; } +#else +#define neponset_suspend NULL +#define neponset_resume NULL +#endif + static struct device_driver neponset_device_driver = { .name = "neponset", .bus = &platform_bus_type, diff --git a/include/linux/device.h b/include/linux/device.h index 49a01033a304..c64cec37dd69 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -268,12 +268,7 @@ struct device { void *platform_data; /* Platform specific data (e.g. ACPI, BIOS data relevant to device) */ struct dev_pm_info power; - u32 power_state; /* Current operating state. In - ACPI-speak, this is D0-D3, D0 - being fully functional, and D3 - being off. */ - unsigned char *saved_state; /* saved device state */ u32 detach_state; /* State to enter when device is detached from its driver. */ -- cgit v1.2.3 From 3441a749f59f69631a859798e6da456857dba7f1 Mon Sep 17 00:00:00 2001 From: Anil Keshavamurthy Date: Thu, 11 Nov 2004 19:42:28 -0800 Subject: [PATCH] Add KOBJ_ONLINE I am trying to fix the current ACPI container.ko and processor.ko to use kobject_hotplug() for notification. For this I would be requiring the KOBJ_ONLINE definitions to be added to kobject_action. Signed-off-by: Anil Keshavamurty Signed-off-by: Greg Kroah-Hartman --- include/linux/kobject_uevent.h | 1 + lib/kobject_uevent.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'include/linux') diff --git a/include/linux/kobject_uevent.h b/include/linux/kobject_uevent.h index 91405f7300a1..aa664fe7e561 100644 --- a/include/linux/kobject_uevent.h +++ b/include/linux/kobject_uevent.h @@ -28,6 +28,7 @@ enum kobject_action { KOBJ_MOUNT = (__force kobject_action_t) 0x04, /* mount event for block devices */ KOBJ_UMOUNT = (__force kobject_action_t) 0x05, /* umount event for block devices */ KOBJ_OFFLINE = (__force kobject_action_t) 0x06, /* offline event for hotplug devices */ + KOBJ_ONLINE = (__force kobject_action_t) 0x07, /* online event for hotplug devices */ }; diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index 78a6e026c298..d317c02f21d8 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -42,6 +42,8 @@ static char *action_to_string(enum kobject_action action) return "umount"; case KOBJ_OFFLINE: return "offline"; + case KOBJ_ONLINE: + return "online"; default: return NULL; } -- cgit v1.2.3 From 95e475c924efd3b429df1ca3af2accf8eeac90cf Mon Sep 17 00:00:00 2001 From: Gabriel Paubert Date: Thu, 11 Nov 2004 21:21:22 -0800 Subject: [PATCH] I2C: Recent I2C "dead code removal" breaks pmac sound. > Put the function back, and change the pmac.h file to delete the #define, > and replace the snd_pmac_keywest_write function with a real call to > i2c_smbus_write_block_data so things like this don't happen again. > > Care to write a patch to do this? It follows, along with an update of the include/linux/i2c.h to only declare functions that actually exist, but grepping the whole sound subtree shows that at least sound/oss/dmasound/tas_common.h defines a few inline functions that call i2c_smbus_write_{byte,block}_data. [I2C part] Ressuscitate i2c_smbus_write_block_data since it's actually used. Update include/linux/i2c.h to reflect the existing functions. [Sound part] Remove snd_pmac_keywest_write* wrapper macros and directly call the i2c_smbus_* functions instead. Signed-off-by: Gabriel Paubert Signed-off-by: Greg Kroah-Hartman ===== include/linux/i2c.h 1.41 vs edited ===== --- drivers/i2c/i2c-core.c | 17 +++++++++++++++++ include/linux/i2c.h | 16 ++++------------ sound/ppc/daca.c | 24 +++++++++++++----------- sound/ppc/pmac.h | 2 -- sound/ppc/tumbler.c | 41 +++++++++++++++++++++++------------------ 5 files changed, 57 insertions(+), 43 deletions(-) (limited to 'include/linux') diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index d86339ca7ca0..72e6707eceaa 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1021,6 +1021,22 @@ s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value) I2C_SMBUS_WORD_DATA,&data); } +/* Returns the number of bytes transferred */ +s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, + u8 length, u8 *values) +{ + union i2c_smbus_data data; + int i; + if (length > I2C_SMBUS_BLOCK_MAX) + length = I2C_SMBUS_BLOCK_MAX; + for (i = 1; i <= length; i++) + data.block[i] = values[i-1]; + data.block[0] = length; + return i2c_smbus_xfer(client->adapter,client->addr,client->flags, + I2C_SMBUS_WRITE,command, + I2C_SMBUS_BLOCK_DATA,&data); +} + /* Returns the number of read bytes */ s32 i2c_smbus_block_process_call(struct i2c_client *client, u8 command, u8 length, u8 *values) { @@ -1279,6 +1295,7 @@ EXPORT_SYMBOL(i2c_smbus_read_byte_data); EXPORT_SYMBOL(i2c_smbus_write_byte_data); EXPORT_SYMBOL(i2c_smbus_read_word_data); EXPORT_SYMBOL(i2c_smbus_write_word_data); +EXPORT_SYMBOL(i2c_smbus_write_block_data); EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data); EXPORT_SYMBOL(i2c_get_functionality); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index bd2735bdca6b..3000c102171e 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -88,20 +88,12 @@ extern s32 i2c_smbus_write_byte_data(struct i2c_client * client, extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command); extern s32 i2c_smbus_write_word_data(struct i2c_client * client, u8 command, u16 value); -extern s32 i2c_smbus_process_call(struct i2c_client * client, - u8 command, u16 value); -/* Returns the number of read bytes */ -extern s32 i2c_smbus_read_block_data(struct i2c_client * client, - u8 command, u8 *values); +/* Returns the number of bytes transferred */ extern s32 i2c_smbus_write_block_data(struct i2c_client * client, - u8 command, u8 length, - u8 *values); + u8 command, u8 length, + u8 *values); extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client, - u8 command, u8 *values); -extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client, - u8 command, u8 length, - u8 *values); - + u8 command, u8 *values); /* * A driver is capable of handling one or more physical devices present on diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c index 6629b6bde12e..f24a91693616 100644 --- a/sound/ppc/daca.c +++ b/sound/ppc/daca.c @@ -56,10 +56,11 @@ static int daca_init_client(pmac_keywest_t *i2c) unsigned short wdata = 0x00; /* SR: no swap, 1bit delay, 32-48kHz */ /* GCFG: power amp inverted, DAC on */ - if (snd_pmac_keywest_write_byte(i2c, DACA_REG_SR, 0x08) < 0 || - snd_pmac_keywest_write_byte(i2c, DACA_REG_GCFG, 0x05) < 0) + if (i2c_smbus_write_byte_data(i2c->client, DACA_REG_SR, 0x08) < 0 || + i2c_smbus_write_byte_data(i2c->client, DACA_REG_GCFG, 0x05) < 0) return -EINVAL; - return snd_pmac_keywest_write(i2c, DACA_REG_AVOL, 2, (unsigned char*)&wdata); + return i2c_smbus_write_block_data(i2c->client, DACA_REG_AVOL, + 2, (unsigned char*)&wdata); } /* @@ -81,9 +82,10 @@ static int daca_set_volume(pmac_daca_t *mix) else data[1] = mix->right_vol; data[1] |= mix->deemphasis ? 0x40 : 0; - if (snd_pmac_keywest_write(&mix->i2c, DACA_REG_AVOL, 2, data) < 0) { - snd_printk("failed to set volume \n"); - return -EINVAL; + if (i2c_smbus_write_block_data(mix->i2c.client, DACA_REG_AVOL, + 2, data) < 0) { + snd_printk("failed to set volume \n"); + return -EINVAL; } return 0; } @@ -188,8 +190,8 @@ static int daca_put_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol change = mix->amp_on != ucontrol->value.integer.value[0]; if (change) { mix->amp_on = ucontrol->value.integer.value[0]; - snd_pmac_keywest_write_byte(&mix->i2c, DACA_REG_GCFG, - mix->amp_on ? 0x05 : 0x04); + i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_GCFG, + mix->amp_on ? 0x05 : 0x04); } return change; } @@ -220,9 +222,9 @@ static snd_kcontrol_new_t daca_mixers[] = { static void daca_resume(pmac_t *chip) { pmac_daca_t *mix = chip->mixer_data; - snd_pmac_keywest_write_byte(&mix->i2c, DACA_REG_SR, 0x08); - snd_pmac_keywest_write_byte(&mix->i2c, DACA_REG_GCFG, - mix->amp_on ? 0x05 : 0x04); + i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_SR, 0x08); + i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_GCFG, + mix->amp_on ? 0x05 : 0x04); daca_set_volume(mix); } #endif /* CONFIG_PMAC_PBOOK */ diff --git a/sound/ppc/pmac.h b/sound/ppc/pmac.h index 9521a4106dc8..7b14906cef0e 100644 --- a/sound/ppc/pmac.h +++ b/sound/ppc/pmac.h @@ -199,8 +199,6 @@ typedef struct snd_pmac_keywest { int snd_pmac_keywest_init(pmac_keywest_t *i2c); void snd_pmac_keywest_cleanup(pmac_keywest_t *i2c); -#define snd_pmac_keywest_write(i2c,cmd,len,data) i2c_smbus_write_block_data((i2c)->client, cmd, len, data) -#define snd_pmac_keywest_write_byte(i2c,cmd,data) i2c_smbus_write_byte_data((i2c)->client, cmd, data) /* misc */ int snd_pmac_boolean_stereo_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo); diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 8d985b034507..7d10385f0a76 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c @@ -109,7 +109,8 @@ static int send_init_client(pmac_keywest_t *i2c, unsigned int *regs) while (*regs > 0) { int err, count = 10; do { - err = snd_pmac_keywest_write_byte(i2c, regs[0], regs[1]); + err = i2c_smbus_write_byte_data(i2c->client, + regs[0], regs[1]); if (err >= 0) break; mdelay(10); @@ -220,9 +221,10 @@ static int tumbler_set_master_volume(pmac_tumbler_t *mix) block[4] = (right_vol >> 8) & 0xff; block[5] = (right_vol >> 0) & 0xff; - if (snd_pmac_keywest_write(&mix->i2c, TAS_REG_VOL, 6, block) < 0) { - snd_printk("failed to set volume \n"); - return -EINVAL; + if (i2c_smbus_write_block_data(mix->i2c.client, TAS_REG_VOL, + 6, block) < 0) { + snd_printk("failed to set volume \n"); + return -EINVAL; } return 0; } @@ -320,9 +322,10 @@ static int tumbler_set_drc(pmac_tumbler_t *mix) val[1] = 0; } - if (snd_pmac_keywest_write(&mix->i2c, TAS_REG_DRC, 2, val) < 0) { - snd_printk("failed to set DRC\n"); - return -EINVAL; + if (i2c_smbus_write_block_data(mix->i2c.client, TAS_REG_DRC, + 2, val) < 0) { + snd_printk("failed to set DRC\n"); + return -EINVAL; } return 0; } @@ -355,9 +358,10 @@ static int snapper_set_drc(pmac_tumbler_t *mix) val[4] = 0x60; val[5] = 0xa0; - if (snd_pmac_keywest_write(&mix->i2c, TAS_REG_DRC, 6, val) < 0) { - snd_printk("failed to set DRC\n"); - return -EINVAL; + if (i2c_smbus_write_block_data(mix->i2c.client, TAS_REG_DRC, + 6, val) < 0) { + snd_printk("failed to set DRC\n"); + return -EINVAL; } return 0; } @@ -459,9 +463,10 @@ static int tumbler_set_mono_volume(pmac_tumbler_t *mix, struct tumbler_mono_vol vol = info->table[vol]; for (i = 0; i < info->bytes; i++) block[i] = (vol >> ((info->bytes - i - 1) * 8)) & 0xff; - if (snd_pmac_keywest_write(&mix->i2c, info->reg, info->bytes, block) < 0) { - snd_printk("failed to set mono volume %d\n", info->index); - return -EINVAL; + if (i2c_smbus_write_block_data(mix->i2c.client, info->reg, + info->bytes, block) < 0) { + snd_printk("failed to set mono volume %d\n", info->index); + return -EINVAL; } return 0; } @@ -588,9 +593,9 @@ static int snapper_set_mix_vol1(pmac_tumbler_t *mix, int idx, int ch, int reg) for (j = 0; j < 3; j++) block[i * 3 + j] = (vol >> ((2 - j) * 8)) & 0xff; } - if (snd_pmac_keywest_write(&mix->i2c, reg, 9, block) < 0) { - snd_printk("failed to set mono volume %d\n", reg); - return -EINVAL; + if (i2c_smbus_write_block_data(mix->i2c.client, reg, 9, block) < 0) { + snd_printk("failed to set mono volume %d\n", reg); + return -EINVAL; } return 0; } @@ -689,8 +694,8 @@ static int snapper_set_capture_source(pmac_tumbler_t *mix) { if (! mix->i2c.client) return -ENODEV; - return snd_pmac_keywest_write_byte(&mix->i2c, TAS_REG_ACS, - mix->capture_source ? 2 : 0); + return i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, + mix->capture_source ? 2 : 0); } static int snapper_info_capture_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) -- cgit v1.2.3 From b5625ce6fb2a3b46d68b7b3c32a10eed8f5c686c Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 12 Nov 2004 09:01:32 -0500 Subject: [libata] remove dependence on PCI Most of this work was done by "Mat Loikkanen" . * use struct device rather than struct pci_dev * use generic DMA routines (dma_xxx) and generic struct device routines (dev_xxx) * isolate PCI-specific helpers inside CONFIG_PCI --- drivers/scsi/ahci.c | 16 +++++------ drivers/scsi/ata_piix.c | 13 +++++---- drivers/scsi/libata-core.c | 70 +++++++++++++++++++++++++-------------------- drivers/scsi/libata-scsi.c | 2 +- drivers/scsi/sata_nv.c | 10 ++++--- drivers/scsi/sata_promise.c | 10 +++---- drivers/scsi/sata_sil.c | 2 +- drivers/scsi/sata_sis.c | 6 ++-- drivers/scsi/sata_svw.c | 2 +- drivers/scsi/sata_sx4.c | 10 +++---- drivers/scsi/sata_uli.c | 6 ++-- drivers/scsi/sata_vsc.c | 2 +- include/linux/libata.h | 44 +++++++++++++++++++--------- 13 files changed, 112 insertions(+), 81 deletions(-) (limited to 'include/linux') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index df7bbeb3c5e4..cf556efdacae 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -270,7 +270,7 @@ static void ahci_host_stop(struct ata_host_set *host_set) static int ahci_port_start(struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct device *dev = ap->host_set->dev; struct ahci_host_priv *hpriv = ap->host_set->private_data; struct ahci_port_priv *pp; int rc; @@ -289,7 +289,7 @@ static int ahci_port_start(struct ata_port *ap) } memset(pp, 0, sizeof(*pp)); - mem = pci_alloc_consistent(pdev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma); + mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL); if (!mem) { rc = -ENOMEM; goto err_out_kfree; @@ -353,7 +353,7 @@ err_out: static void ahci_port_stop(struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct device *dev = ap->host_set->dev; struct ahci_port_priv *pp = ap->private_data; void *mmio = ap->host_set->mmio_base; void *port_mmio = ahci_port_base(mmio, ap->port_no); @@ -370,8 +370,8 @@ static void ahci_port_stop(struct ata_port *ap) msleep(500); ap->private_data = NULL; - pci_free_consistent(pdev, AHCI_PORT_PRIV_DMA_SZ, - pp->cmd_slot, pp->cmd_slot_dma); + dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, + pp->cmd_slot, pp->cmd_slot_dma); kfree(pp); ata_port_stop(ap); } @@ -703,7 +703,7 @@ static void ahci_setup_port(struct ata_ioports *port, unsigned long base, static int ahci_host_init(struct ata_probe_ent *probe_ent) { struct ahci_host_priv *hpriv = probe_ent->private_data; - struct pci_dev *pdev = probe_ent->pdev; + struct pci_dev *pdev = to_pci_dev(probe_ent->dev); void __iomem *mmio = probe_ent->mmio_base; u32 tmp, cap_save; u16 tmp16; @@ -861,7 +861,7 @@ static void pci_enable_intx(struct pci_dev *pdev) static void ahci_print_info(struct ata_probe_ent *probe_ent) { struct ahci_host_priv *hpriv = probe_ent->private_data; - struct pci_dev *pdev = probe_ent->pdev; + struct pci_dev *pdev = to_pci_dev(probe_ent->dev); void *mmio = probe_ent->mmio_base; u32 vers, cap, impl, speed; const char *speed_s; @@ -965,7 +965,7 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) } memset(probe_ent, 0, sizeof(*probe_ent)); - probe_ent->pdev = pdev; + probe_ent->dev = pci_dev_to_dev(pdev); INIT_LIST_HEAD(&probe_ent->node); mmio_base = ioremap(pci_resource_start(pdev, AHCI_PCI_BAR), diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index c4dc4f978287..ff2da379d4ad 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -260,7 +260,7 @@ MODULE_DEVICE_TABLE(pci, piix_pci_tbl); */ static void piix_pata_cbl_detect(struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); u8 tmp, mask; /* no 80c support in host controller? */ @@ -293,8 +293,9 @@ cbl40: static void piix_pata_phy_reset(struct ata_port *ap) { - if (!pci_test_config_bits(ap->host_set->pdev, - &piix_enable_bits[ap->hard_port_no])) { + struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); + + if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) { ata_port_disable(ap); printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); return; @@ -322,7 +323,7 @@ static void piix_pata_phy_reset(struct ata_port *ap) */ static int piix_sata_probe (struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); int combined = (ap->flags & ATA_FLAG_SLAVE_POSS); int orig_mask, mask, i; u8 pcs; @@ -392,7 +393,7 @@ static void piix_sata_phy_reset(struct ata_port *ap) static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev) { unsigned int pio = adev->pio_mode - XFER_PIO_0; - struct pci_dev *dev = ap->host_set->pdev; + struct pci_dev *dev = to_pci_dev(ap->host_set->dev); unsigned int is_slave = (adev->devno != 0); unsigned int master_port= ap->hard_port_no ? 0x42 : 0x40; unsigned int slave_port = 0x44; @@ -444,7 +445,7 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev) static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev) { unsigned int udma = adev->dma_mode; /* FIXME: MWDMA too */ - struct pci_dev *dev = ap->host_set->pdev; + struct pci_dev *dev = to_pci_dev(ap->host_set->dev); u8 maslave = ap->hard_port_no ? 0x42 : 0x40; u8 speed = udma; unsigned int drive_dn = (ap->hard_port_no ? 2 : 0) + adev->devno; diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index ec87710cb363..7f90d47e6ca0 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1017,7 +1017,7 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) BUG_ON(qc == NULL); ata_sg_init_one(qc, dev->id, sizeof(dev->id)); - qc->pci_dma_dir = PCI_DMA_FROMDEVICE; + qc->dma_dir = DMA_FROM_DEVICE; qc->tf.protocol = ATA_PROT_PIO; qc->nsect = 1; @@ -1849,7 +1849,7 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct scatterlist *sg = qc->sg; - int dir = qc->pci_dma_dir; + int dir = qc->dma_dir; assert(qc->flags & ATA_QCFLAG_DMAMAP); assert(sg != NULL); @@ -1860,9 +1860,9 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) DPRINTK("unmapping %u sg elements\n", qc->n_elem); if (qc->flags & ATA_QCFLAG_SG) - pci_unmap_sg(ap->host_set->pdev, sg, qc->n_elem, dir); + dma_unmap_sg(ap->host_set->dev, sg, qc->n_elem, dir); else - pci_unmap_single(ap->host_set->pdev, sg_dma_address(&sg[0]), + dma_unmap_single(ap->host_set->dev, sg_dma_address(&sg[0]), sg_dma_len(&sg[0]), dir); qc->flags &= ~ATA_QCFLAG_DMAMAP; @@ -1973,13 +1973,13 @@ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, static int ata_sg_setup_one(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - int dir = qc->pci_dma_dir; + int dir = qc->dma_dir; struct scatterlist *sg = qc->sg; dma_addr_t dma_address; - dma_address = pci_map_single(ap->host_set->pdev, qc->buf_virt, + dma_address = dma_map_single(ap->host_set->dev, qc->buf_virt, sg_dma_len(sg), dir); - if (pci_dma_mapping_error(dma_address)) + if (dma_mapping_error(dma_address)) return -1; sg_dma_address(sg) = dma_address; @@ -2010,8 +2010,8 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) VPRINTK("ENTER, ata%u\n", ap->id); assert(qc->flags & ATA_QCFLAG_SG); - dir = qc->pci_dma_dir; - n_elem = pci_map_sg(ap->host_set->pdev, sg, qc->n_elem, dir); + dir = qc->dma_dir; + n_elem = dma_map_sg(ap->host_set->dev, sg, qc->n_elem, dir); if (n_elem < 1) return -1; @@ -2416,7 +2416,7 @@ static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev, memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer)); - qc->pci_dma_dir = PCI_DMA_FROMDEVICE; + qc->dma_dir = DMA_FROM_DEVICE; memset(&qc->cdb, 0, sizeof(ap->cdb_len)); qc->cdb[0] = REQUEST_SENSE; @@ -3104,9 +3104,9 @@ err_out: int ata_port_start (struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct device *dev = ap->host_set->dev; - ap->prd = pci_alloc_consistent(pdev, ATA_PRD_TBL_SZ, &ap->prd_dma); + ap->prd = dma_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, GFP_KERNEL); if (!ap->prd) return -ENOMEM; @@ -3117,9 +3117,9 @@ int ata_port_start (struct ata_port *ap) void ata_port_stop (struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct device *dev = ap->host_set->dev; - pci_free_consistent(pdev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); + dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); } /** @@ -3165,7 +3165,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, host->max_channel = 1; host->unique_id = ata_unique_id++; host->max_cmd_len = 12; - scsi_set_device(host, &ent->pdev->dev); + scsi_set_device(host, ent->dev); scsi_assign_lock(host, &host_set->lock); ap->flags = ATA_FLAG_PORT_DISABLED; @@ -3252,7 +3252,7 @@ err_out: int ata_device_add(struct ata_probe_ent *ent) { unsigned int count = 0, i; - struct pci_dev *pdev = ent->pdev; + struct device *dev = ent->dev; struct ata_host_set *host_set; DPRINTK("ENTER\n"); @@ -3264,7 +3264,7 @@ int ata_device_add(struct ata_probe_ent *ent) memset(host_set, 0, sizeof(struct ata_host_set) + (ent->n_ports * sizeof(void *))); spin_lock_init(&host_set->lock); - host_set->pdev = pdev; + host_set->dev = dev; host_set->n_ports = ent->n_ports; host_set->irq = ent->irq; host_set->mmio_base = ent->mmio_base; @@ -3332,7 +3332,7 @@ int ata_device_add(struct ata_probe_ent *ent) */ } - rc = scsi_add_host(ap->host, &pdev->dev); + rc = scsi_add_host(ap->host, dev); if (rc) { printk(KERN_ERR "ata%u: scsi_add_host failed\n", ap->id); @@ -3352,7 +3352,7 @@ int ata_device_add(struct ata_probe_ent *ent) scsi_scan_host(ap->host); } - pci_set_drvdata(pdev, host_set); + dev_set_drvdata(dev, host_set); VPRINTK("EXIT, returning %u\n", ent->n_ports); return ent->n_ports; /* success */ @@ -3413,7 +3413,7 @@ void ata_std_ports(struct ata_ioports *ioaddr) } static struct ata_probe_ent * -ata_probe_ent_alloc(int n, struct pci_dev *pdev, struct ata_port_info **port) +ata_probe_ent_alloc(int n, struct device *dev, struct ata_port_info **port) { struct ata_probe_ent *probe_ent; int i; @@ -3421,7 +3421,7 @@ ata_probe_ent_alloc(int n, struct pci_dev *pdev, struct ata_port_info **port) probe_ent = kmalloc(sizeof(*probe_ent) * n, GFP_KERNEL); if (!probe_ent) { printk(KERN_ERR DRV_NAME "(%s): out of memory\n", - pci_name(pdev)); + kobject_name(&(dev->kobj))); return NULL; } @@ -3429,7 +3429,7 @@ ata_probe_ent_alloc(int n, struct pci_dev *pdev, struct ata_port_info **port) for (i = 0; i < n; i++) { INIT_LIST_HEAD(&probe_ent[i].node); - probe_ent[i].pdev = pdev; + probe_ent[i].dev = dev; probe_ent[i].sht = port[i]->sht; probe_ent[i].host_flags = port[i]->host_flags; @@ -3443,10 +3443,12 @@ ata_probe_ent_alloc(int n, struct pci_dev *pdev, struct ata_port_info **port) return probe_ent; } +#ifdef CONFIG_PCI struct ata_probe_ent * ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port) { - struct ata_probe_ent *probe_ent = ata_probe_ent_alloc(1, pdev, port); + struct ata_probe_ent *probe_ent = + ata_probe_ent_alloc(1, pci_dev_to_dev(pdev), port); if (!probe_ent) return NULL; @@ -3475,7 +3477,8 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port) struct ata_probe_ent * ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port) { - struct ata_probe_ent *probe_ent = ata_probe_ent_alloc(2, pdev, port); + struct ata_probe_ent *probe_ent = + ata_probe_ent_alloc(2, pci_dev_to_dev(pdev), port); if (!probe_ent) return NULL; @@ -3651,7 +3654,8 @@ err_out: void ata_pci_remove_one (struct pci_dev *pdev) { - struct ata_host_set *host_set = pci_get_drvdata(pdev); + struct device *dev = pci_dev_to_dev(pdev); + struct ata_host_set *host_set = dev_get_drvdata(dev); struct ata_port *ap; unsigned int i; @@ -3692,7 +3696,7 @@ void ata_pci_remove_one (struct pci_dev *pdev) kfree(host_set); pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); + dev_set_drvdata(dev, NULL); } /* move to PCI subsystem */ @@ -3728,6 +3732,7 @@ int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits) return (tmp == bits->val) ? 1 : 0; } +#endif /* CONFIG_PCI */ /** @@ -3764,7 +3769,6 @@ module_exit(ata_exit); * Do not depend on ABI/API stability. */ -EXPORT_SYMBOL_GPL(pci_test_config_bits); EXPORT_SYMBOL_GPL(ata_std_bios_param); EXPORT_SYMBOL_GPL(ata_std_ports); EXPORT_SYMBOL_GPL(ata_device_add); @@ -3779,8 +3783,6 @@ EXPORT_SYMBOL_GPL(ata_noop_dev_select); EXPORT_SYMBOL_GPL(ata_std_dev_select); EXPORT_SYMBOL_GPL(ata_tf_to_fis); EXPORT_SYMBOL_GPL(ata_tf_from_fis); -EXPORT_SYMBOL_GPL(ata_pci_init_legacy_mode); -EXPORT_SYMBOL_GPL(ata_pci_init_native_mode); EXPORT_SYMBOL_GPL(ata_check_status); EXPORT_SYMBOL_GPL(ata_exec_command); EXPORT_SYMBOL_GPL(ata_port_start); @@ -3795,8 +3797,6 @@ EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); EXPORT_SYMBOL_GPL(ata_port_disable); -EXPORT_SYMBOL_GPL(ata_pci_init_one); -EXPORT_SYMBOL_GPL(ata_pci_remove_one); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); EXPORT_SYMBOL_GPL(ata_scsi_error); @@ -3806,3 +3806,11 @@ EXPORT_SYMBOL_GPL(ata_host_intr); EXPORT_SYMBOL_GPL(ata_dev_classify); EXPORT_SYMBOL_GPL(ata_dev_id_string); EXPORT_SYMBOL_GPL(ata_scsi_simulate); + +#ifdef CONFIG_PCI +EXPORT_SYMBOL_GPL(pci_test_config_bits); +EXPORT_SYMBOL_GPL(ata_pci_init_legacy_mode); +EXPORT_SYMBOL_GPL(ata_pci_init_native_mode); +EXPORT_SYMBOL_GPL(ata_pci_init_one); +EXPORT_SYMBOL_GPL(ata_pci_remove_one); +#endif /* CONFIG_PCI */ diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 31360d47f5bb..c9cc659faea4 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -678,7 +678,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, ata_sg_init_one(qc, cmd->request_buffer, cmd->request_bufflen); - qc->pci_dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); + qc->dma_dir = cmd->sc_data_direction; } qc->complete_fn = ata_scsi_qc_complete; diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 259f678d3a6b..b90c064359f7 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -454,12 +454,13 @@ static void nv_check_hotplug(struct ata_host_set *host_set) static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent) { + struct pci_dev *pdev = to_pci_dev(probe_ent->dev); u8 intr_mask; u8 regval; - pci_read_config_byte(probe_ent->pdev, NV_MCP_SATA_CFG_20, ®val); + pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN; - pci_write_config_byte(probe_ent->pdev, NV_MCP_SATA_CFG_20, regval); + pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); writeb(NV_INT_STATUS_HOTPLUG, probe_ent->mmio_base + NV_INT_STATUS_CK804); @@ -471,6 +472,7 @@ static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent) static void nv_disable_hotplug_ck804(struct ata_host_set *host_set) { + struct pci_dev *pdev = to_pci_dev(host_set->dev); u8 intr_mask; u8 regval; @@ -480,9 +482,9 @@ static void nv_disable_hotplug_ck804(struct ata_host_set *host_set) writeb(intr_mask, host_set->mmio_base + NV_INT_ENABLE_CK804); - pci_read_config_byte(host_set->pdev, NV_MCP_SATA_CFG_20, ®val); + pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); regval &= ~NV_MCP_SATA_CFG_20_SATA_SPACE_EN; - pci_write_config_byte(host_set->pdev, NV_MCP_SATA_CFG_20, regval); + pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); } static void nv_check_hotplug_ck804(struct ata_host_set *host_set) diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index c54a268d0827..b4568af3ce43 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -174,7 +174,7 @@ static struct pci_driver pdc_ata_pci_driver = { static int pdc_port_start(struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct device *dev = ap->host_set->dev; struct pdc_port_priv *pp; int rc; @@ -189,7 +189,7 @@ static int pdc_port_start(struct ata_port *ap) } memset(pp, 0, sizeof(*pp)); - pp->pkt = pci_alloc_consistent(pdev, 128, &pp->pkt_dma); + pp->pkt = dma_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL); if (!pp->pkt) { rc = -ENOMEM; goto err_out_kfree; @@ -209,11 +209,11 @@ err_out: static void pdc_port_stop(struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct device *dev = ap->host_set->dev; struct pdc_port_priv *pp = ap->private_data; ap->private_data = NULL; - pci_free_consistent(pdev, 128, pp->pkt, pp->pkt_dma); + dma_free_coherent(dev, 128, pp->pkt, pp->pkt_dma); kfree(pp); ata_port_stop(ap); } @@ -577,7 +577,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e } memset(probe_ent, 0, sizeof(*probe_ent)); - probe_ent->pdev = pdev; + probe_ent->dev = pci_dev_to_dev(pdev); INIT_LIST_HEAD(&probe_ent->node); mmio_base = ioremap(pci_resource_start(pdev, 3), diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index b534a84be0ee..eb1e4db6ca13 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -363,7 +363,7 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) memset(probe_ent, 0, sizeof(*probe_ent)); INIT_LIST_HEAD(&probe_ent->node); - probe_ent->pdev = pdev; + probe_ent->dev = pci_dev_to_dev(pdev); probe_ent->port_ops = sil_port_info[ent->driver_data].port_ops; probe_ent->sht = sil_port_info[ent->driver_data].sht; probe_ent->n_ports = (ent->driver_data == sil_3114) ? 4 : 2; diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index 17eb7ed5aad9..d43c8ca061bc 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -140,22 +140,24 @@ static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg) static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) { + struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg); u32 val; if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */ return 0xffffffff; - pci_read_config_dword(ap->host_set->pdev, cfg_addr, &val); + pci_read_config_dword(pdev, cfg_addr, &val); return val; } static void sis_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val) { + struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr); if (scr == SCR_ERROR) /* doesn't exist in PCI cfg space */ return; - pci_write_config_dword(ap->host_set->pdev, cfg_addr, val); + pci_write_config_dword(pdev, cfg_addr, val); } static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg) diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index fd01225a74c0..33dff1fa63d5 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -376,7 +376,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e } memset(probe_ent, 0, sizeof(*probe_ent)); - probe_ent->pdev = pdev; + probe_ent->dev = pci_dev_to_dev(pdev); INIT_LIST_HEAD(&probe_ent->node); mmio_base = ioremap(pci_resource_start(pdev, 5), diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index ca28b80bee3d..6990c62d9be1 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -248,7 +248,7 @@ static void pdc20621_host_stop(struct ata_host_set *host_set) static int pdc_port_start(struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct device *dev = ap->host_set->dev; struct pdc_port_priv *pp; int rc; @@ -263,7 +263,7 @@ static int pdc_port_start(struct ata_port *ap) } memset(pp, 0, sizeof(*pp)); - pp->pkt = pci_alloc_consistent(pdev, 128, &pp->pkt_dma); + pp->pkt = dma_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL); if (!pp->pkt) { rc = -ENOMEM; goto err_out_kfree; @@ -283,11 +283,11 @@ err_out: static void pdc_port_stop(struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct device *dev = ap->host_set->dev; struct pdc_port_priv *pp = ap->private_data; ap->private_data = NULL; - pci_free_consistent(pdev, 128, pp->pkt, pp->pkt_dma); + dma_free_coherent(dev, 128, pp->pkt, pp->pkt_dma); kfree(pp); ata_port_stop(ap); } @@ -1397,7 +1397,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * } memset(probe_ent, 0, sizeof(*probe_ent)); - probe_ent->pdev = pdev; + probe_ent->dev = pci_dev_to_dev(pdev); INIT_LIST_HEAD(&probe_ent->node); mmio_base = ioremap(pci_resource_start(pdev, 3), diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index a7c12799ccf4..67179edd1f59 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -149,18 +149,20 @@ static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg) static u32 uli_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) { + struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg); u32 val; - pci_read_config_dword(ap->host_set->pdev, cfg_addr, &val); + pci_read_config_dword(pdev, cfg_addr, &val); return val; } static void uli_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val) { + struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr); - pci_write_config_dword(ap->host_set->pdev, cfg_addr, val); + pci_write_config_dword(pdev, cfg_addr, val); } static u32 uli_scr_read (struct ata_port *ap, unsigned int sc_reg) diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 1b2bf9aac1d9..d778aeed919b 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -293,7 +293,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d goto err_out_regions; } memset(probe_ent, 0, sizeof(*probe_ent)); - probe_ent->pdev = pdev; + probe_ent->dev = pci_dev_to_dev(pdev); INIT_LIST_HEAD(&probe_ent->node); mmio_base = ioremap(pci_resource_start(pdev, 0), diff --git a/include/linux/libata.h b/include/linux/libata.h index 79145d1a807a..605e0a728c0e 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -68,6 +69,12 @@ /* defines only for the constants which don't work well as enums */ #define ATA_TAG_POISON 0xfafbfcfdU +/* move to PCI layer? */ +static inline struct device *pci_dev_to_dev(struct pci_dev *pdev) +{ + return &pdev->dev; +} + enum { /* various global constants */ LIBATA_MAX_PRD = ATA_MAX_PRD / 2, @@ -184,7 +191,7 @@ struct ata_ioports { struct ata_probe_ent { struct list_head node; - struct pci_dev *pdev; + struct device *dev; struct ata_port_operations *port_ops; Scsi_Host_Template *sht; struct ata_ioports port[ATA_MAX_PORTS]; @@ -203,7 +210,7 @@ struct ata_probe_ent { struct ata_host_set { spinlock_t lock; - struct pci_dev *pdev; + struct device *dev; unsigned long irq; void __iomem *mmio_base; unsigned int n_ports; @@ -226,7 +233,7 @@ struct ata_queued_cmd { unsigned int tag; unsigned int n_elem; - int pci_dma_dir; + int dma_dir; unsigned int nsect; unsigned int cursect; @@ -361,12 +368,6 @@ struct ata_port_info { struct ata_port_operations *port_ops; }; -struct pci_bits { - unsigned int reg; /* PCI config register to read */ - unsigned int width; /* 1 (8 bit), 2 (16 bit), 4 (32 bit) */ - unsigned long mask; - unsigned long val; -}; extern void ata_port_probe(struct ata_port *); extern void __sata_phy_reset(struct ata_port *ap); @@ -374,9 +375,11 @@ extern void sata_phy_reset(struct ata_port *ap); extern void ata_bus_reset(struct ata_port *ap); extern void ata_port_disable(struct ata_port *); extern void ata_std_ports(struct ata_ioports *ioaddr); +#ifdef CONFIG_PCI extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, unsigned int n_ports); extern void ata_pci_remove_one (struct pci_dev *pdev); +#endif /* CONFIG_PCI */ extern int ata_device_add(struct ata_probe_ent *ent); extern int ata_scsi_detect(Scsi_Host_Template *sht); extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); @@ -398,10 +401,6 @@ extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf); extern int ata_port_start (struct ata_port *ap); extern void ata_port_stop (struct ata_port *ap); extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs); -extern struct ata_probe_ent * -ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port); -extern struct ata_probe_ent * -ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port); extern void ata_qc_prep(struct ata_queued_cmd *qc); extern int ata_qc_issue_prot(struct ata_queued_cmd *qc); extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, @@ -414,7 +413,6 @@ extern void ata_dev_id_string(u16 *id, unsigned char *s, extern void ata_bmdma_setup (struct ata_queued_cmd *qc); extern void ata_bmdma_start (struct ata_queued_cmd *qc); extern void ata_bmdma_irq_clear(struct ata_port *ap); -extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits); extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat); extern void ata_eng_timeout(struct ata_port *ap); extern void ata_scsi_simulate(u16 *id, struct scsi_cmnd *cmd, @@ -424,6 +422,24 @@ extern int ata_std_bios_param(struct scsi_device *sdev, sector_t capacity, int geom[]); extern int ata_scsi_slave_config(struct scsi_device *sdev); + +#ifdef CONFIG_PCI +struct pci_bits { + unsigned int reg; /* PCI config register to read */ + unsigned int width; /* 1 (8 bit), 2 (16 bit), 4 (32 bit) */ + unsigned long mask; + unsigned long val; +}; + +extern struct ata_probe_ent * +ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port); +extern struct ata_probe_ent * +ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port); +extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits); + +#endif /* CONFIG_PCI */ + + static inline unsigned int ata_tag_valid(unsigned int tag) { return (tag < ATA_MAX_QUEUE) ? 1 : 0; -- cgit v1.2.3 From e8c5f64c21e2633e6cde4be4e5e82bd3876adfd5 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 13 Nov 2004 04:43:08 -0500 Subject: Parenthize nth_page() macro arg, in linux/mm.h. --- include/linux/mm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/mm.h b/include/linux/mm.h index 49a1aee2119e..04fa8eea9268 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -41,7 +41,7 @@ extern int sysctl_legacy_va_layout; #define MM_VM_SIZE(mm) TASK_SIZE #endif -#define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + n) +#define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n)) /* * Linux kernel virtual memory manager primitives. -- cgit v1.2.3 From 28eb41dd719d26bee49adf34a85e7793f88b70be Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 13 Nov 2004 16:01:38 +0000 Subject: [SERIAL] Add sparse __iomem annotations. --- drivers/serial/8250_pci.c | 6 +++--- include/linux/serial_core.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 544c435d6545..0e56087742ee 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -283,7 +283,7 @@ static int __devinit pci_plx9050_init(struct pci_dev *dev) static void __devexit pci_plx9050_exit(struct pci_dev *dev) { - u8 *p; + u8 __iomem *p; if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) return; @@ -336,7 +336,7 @@ sbs_setup(struct pci_dev *dev, struct pci_board *board, static int __devinit sbs_init(struct pci_dev *dev) { - u8 * p; + u8 __iomem *p; p = ioremap(pci_resource_start(dev, 0),pci_resource_len(dev,0)); @@ -360,7 +360,7 @@ static int __devinit sbs_init(struct pci_dev *dev) static void __devexit sbs_exit(struct pci_dev *dev) { - u8 * p; + u8 __iomem *p; p = ioremap(pci_resource_start(dev, 0),pci_resource_len(dev,0)); if (p != NULL) { diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index bba805dd7a39..ae0b9948c269 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -171,7 +171,7 @@ struct uart_icount { struct uart_port { spinlock_t lock; /* port lock */ unsigned int iobase; /* in/out[bwl] */ - char *membase; /* read/write[bwl] */ + unsigned char __iomem *membase; /* read/write[bwl] */ unsigned int irq; /* irq number */ unsigned int uartclk; /* base uart clock */ unsigned char fifosize; /* tx fifo size */ -- cgit v1.2.3 From 4b355b37533a900531a02df6e8714a2838033018 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Sat, 13 Nov 2004 18:56:57 +0000 Subject: [ARM PATCH] 2237/1: S3C2410 - new serial driver - update serial_core.h (4/4) Patch from Ben Dooks Add PORT_S3C2440 to include/linux/serial_core.h Signed-off-by: Ben Dooks Signed-off-by: Russell King --- include/linux/serial_core.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/linux') diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index ae0b9948c269..3fad76b0873c 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -94,6 +94,9 @@ /*IBM icom*/ #define PORT_ICOM 60 +/* Samsung S3C2440 SoC */ +#define PORT_S3C2440 61 + #ifdef __KERNEL__ #include -- cgit v1.2.3 From ccc893f12db7aaca6670ce631ddc3ac27ee29b8a Mon Sep 17 00:00:00 2001 From: "Andries E. Brouwer" Date: Sat, 13 Nov 2004 04:59:55 -0800 Subject: [PATCH] __init in mm/slab.c The below removes an __initdata (for initarray_generic that is referenced in non-init code). --- include/linux/slab.h | 3 ++- mm/slab.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/slab.h b/include/linux/slab.h index 7c81a7863b99..93c8264fe67b 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -13,6 +13,7 @@ typedef struct kmem_cache_s kmem_cache_t; #include /* kmalloc_sizes.h needs CONFIG_ options */ #include +#include #include #include /* kmalloc_sizes.h needs PAGE_SIZE */ #include /* kmalloc_sizes.h needs L1_CACHE_BYTES */ @@ -53,7 +54,7 @@ typedef struct kmem_cache_s kmem_cache_t; #define SLAB_CTOR_VERIFY 0x004UL /* tell constructor it's a verify call */ /* prototypes */ -extern void kmem_cache_init(void); +extern void __init kmem_cache_init(void); extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned long, void (*)(void *, kmem_cache_t *, unsigned long), diff --git a/mm/slab.c b/mm/slab.c index 958d22d78383..816ad01ed806 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -509,7 +509,7 @@ static struct cache_names __initdata cache_names[] = { static struct arraycache_init initarray_cache __initdata = { { 0, BOOT_CPUCACHE_ENTRIES, 1, 0} }; -static struct arraycache_init initarray_generic __initdata = +static struct arraycache_init initarray_generic = { { 0, BOOT_CPUCACHE_ENTRIES, 1, 0} }; /* internal cache of cache description objs */ -- cgit v1.2.3 From 82347bd71f780f18027fab22c7aa9e3d6ba3cc1b Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 13 Nov 2004 15:27:50 +0100 Subject: [NET]: Move rx timestamp functions to net/core/dev.c Signed-off-by: Patrick McHardy --- include/linux/netdevice.h | 3 +++ include/net/sock.h | 12 ------------ net/core/dev.c | 25 +++++++++++++++++++++++++ net/core/sock.c | 7 ++----- 4 files changed, 30 insertions(+), 17 deletions(-) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 9fa9c7ead784..39ce54fe88cf 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -928,6 +928,9 @@ extern unsigned long netdev_fc_xoff; extern atomic_t netdev_dropping; extern int netdev_set_master(struct net_device *dev, struct net_device *master); extern int skb_checksum_help(struct sk_buff *skb, int inward); +/* rx skb timestamps */ +extern void net_enable_timestamp(void); +extern void net_disable_timestamp(void); #ifdef CONFIG_SYSCTL extern char *net_sysctl_strdup(const char *s); diff --git a/include/net/sock.h b/include/net/sock.h index c9e1bad6f067..acfb1be16b41 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1270,19 +1270,7 @@ static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb) __kfree_skb(skb); } -extern atomic_t netstamp_needed; extern void sock_enable_timestamp(struct sock *sk); - -static inline void net_timestamp(struct timeval *stamp) -{ - if (atomic_read(&netstamp_needed)) - do_gettimeofday(stamp); - else { - stamp->tv_sec = 0; - stamp->tv_usec = 0; - } -} - extern int sock_get_timestamp(struct sock *, struct timeval __user *); /* diff --git a/net/core/dev.c b/net/core/dev.c index 9a8c377f8c7b..ad6f08aeea80 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1001,6 +1001,29 @@ int call_netdevice_notifiers(unsigned long val, void *v) return notifier_call_chain(&netdev_chain, val, v); } +/* When > 0 there are consumers of rx skb time stamps */ +static atomic_t netstamp_needed = ATOMIC_INIT(0); + +void net_enable_timestamp(void) +{ + atomic_inc(&netstamp_needed); +} + +void net_disable_timestamp(void) +{ + atomic_dec(&netstamp_needed); +} + +static inline void net_timestamp(struct timeval *stamp) +{ + if (atomic_read(&netstamp_needed)) + do_gettimeofday(stamp); + else { + stamp->tv_sec = 0; + stamp->tv_usec = 0; + } +} + /* * Support routine. Sends outgoing frames to any network * taps currently in use. @@ -3215,6 +3238,8 @@ EXPORT_SYMBOL(skb_checksum_help); EXPORT_SYMBOL(synchronize_net); EXPORT_SYMBOL(unregister_netdevice); EXPORT_SYMBOL(unregister_netdevice_notifier); +EXPORT_SYMBOL(net_enable_timestamp); +EXPORT_SYMBOL(net_disable_timestamp); #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) EXPORT_SYMBOL(br_handle_frame_hook); diff --git a/net/core/sock.c b/net/core/sock.c index 9e970c64ee2d..8312e839dd63 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -179,7 +179,7 @@ static void sock_disable_timestamp(struct sock *sk) { if (sock_flag(sk, SOCK_TIMESTAMP)) { sock_reset_flag(sk, SOCK_TIMESTAMP); - atomic_dec(&netstamp_needed); + net_disable_timestamp(); } } @@ -1226,9 +1226,6 @@ void fastcall release_sock(struct sock *sk) } EXPORT_SYMBOL(release_sock); -/* When > 0 there are consumers of rx skb time stamps */ -atomic_t netstamp_needed = ATOMIC_INIT(0); - int sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp) { if (!sock_flag(sk, SOCK_TIMESTAMP)) @@ -1246,7 +1243,7 @@ void sock_enable_timestamp(struct sock *sk) { if (!sock_flag(sk, SOCK_TIMESTAMP)) { sock_set_flag(sk, SOCK_TIMESTAMP); - atomic_inc(&netstamp_needed); + net_enable_timestamp(); } } EXPORT_SYMBOL(sock_enable_timestamp); -- cgit v1.2.3 From d70bfc856dcd33699685e4056988389e5386d1d5 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 13 Nov 2004 16:41:16 +0100 Subject: [NETFILTER]: associate locally generated icmp errors with conntrack of original packet Signed-off-by: Patrick McHardy --- include/linux/netfilter.h | 2 ++ net/core/netfilter.c | 18 ++++++++++++++---- net/ipv4/icmp.c | 2 ++ net/ipv4/netfilter/ipt_REJECT.c | 18 ++---------------- 4 files changed, 20 insertions(+), 20 deletions(-) (limited to 'include/linux') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index ced66929126c..b0ee19e302de 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -173,6 +173,7 @@ extern void nf_reinject(struct sk_buff *skb, unsigned int verdict); extern void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *); +extern void nf_ct_attach(struct sk_buff *, struct sk_buff *); #ifdef CONFIG_NETFILTER_DEBUG extern void nf_dump_skb(int pf, struct sk_buff *skb); @@ -183,6 +184,7 @@ extern void nf_invalidate_cache(int pf); #else /* !CONFIG_NETFILTER */ #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb) +static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {} #endif /*CONFIG_NETFILTER*/ #endif /*__KERNEL__*/ diff --git a/net/core/netfilter.c b/net/core/netfilter.c index b7f017877f7b..075f3b1aee27 100644 --- a/net/core/netfilter.c +++ b/net/core/netfilter.c @@ -802,12 +802,21 @@ EXPORT_SYMBOL(nf_log_register); EXPORT_SYMBOL(nf_log_unregister); EXPORT_SYMBOL(nf_log_packet); -/* This does not belong here, but ipt_REJECT needs it if connection - tracking in use: without this, connection may not be in hash table, - and hence manufactured ICMP or RST packets will not be associated - with it. */ +/* This does not belong here, but locally generated errors need it if connection + tracking in use: without this, connection may not be in hash table, and hence + manufactured ICMP or RST packets will not be associated with it. */ void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *); +void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) +{ + void (*attach)(struct sk_buff *, struct sk_buff *); + + if (skb->nfct && (attach = ip_ct_attach) != NULL) { + mb(); /* Just to be sure: must be read before executing this */ + attach(new, skb); + } +} + void __init netfilter_init(void) { int i, h; @@ -819,6 +828,7 @@ void __init netfilter_init(void) } EXPORT_SYMBOL(ip_ct_attach); +EXPORT_SYMBOL(nf_ct_attach); EXPORT_SYMBOL(nf_getsockopt); EXPORT_SYMBOL(nf_hook_slow); EXPORT_SYMBOL(nf_hooks); diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 062589289b4f..74089ab9f74e 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -338,6 +338,8 @@ int icmp_glue_bits(void *from, char *to, int offset, int len, int odd, to, len, 0); skb->csum = csum_block_add(skb->csum, csum, odd); + if (icmp_pointers[icmp_param->data.icmph.type].error) + nf_ct_attach(skb, icmp_param->skb); return 0; } diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index b2e05746a528..811aec6f67d8 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -38,20 +38,6 @@ MODULE_DESCRIPTION("iptables REJECT target module"); #define DEBUGP(format, args...) #endif -/* If the original packet is part of a connection, but the connection - is not confirmed, our manufactured reply will not be associated - with it, so we need to do this manually. */ -static void connection_attach(struct sk_buff *new_skb, struct sk_buff *skb) -{ - void (*attach)(struct sk_buff *, struct sk_buff *); - - /* Avoid module unload race with ip_ct_attach being NULLed out */ - if (skb->nfct && (attach = ip_ct_attach) != NULL) { - mb(); /* Just to be sure: must be read before executing this */ - attach(new_skb, skb); - } -} - static inline struct rtable *route_reverse(struct sk_buff *skb, int hook) { struct iphdr *iph = skb->nh.iph; @@ -209,7 +195,7 @@ static void send_reset(struct sk_buff *oldskb, int hook) if (nskb->len > dst_pmtu(nskb->dst)) goto free_nskb; - connection_attach(nskb, oldskb); + nf_ct_attach(nskb, oldskb); NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev, ip_finish_output); @@ -360,7 +346,7 @@ static void send_unreach(struct sk_buff *skb_in, int code) icmph->checksum = ip_compute_csum((unsigned char *)icmph, length - sizeof(struct iphdr)); - connection_attach(nskb, skb_in); + nf_ct_attach(nskb, skb_in); NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev, ip_finish_output); -- cgit v1.2.3 From b803d5f51dbd2da941e6f37301a23be67c129601 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 13 Nov 2004 19:01:15 +0100 Subject: [NETFILTER]: Fix invalid tcp/udp checksums within NATed icmp errors Signed-off-by: Patrick McHardy --- include/linux/netfilter_ipv4/ip_nat_protocol.h | 2 +- net/ipv4/netfilter/ip_nat_core.c | 2 +- net/ipv4/netfilter/ip_nat_proto_icmp.c | 4 +++- net/ipv4/netfilter/ip_nat_proto_tcp.c | 8 +++++--- net/ipv4/netfilter/ip_nat_proto_udp.c | 8 +++++--- net/ipv4/netfilter/ip_nat_proto_unknown.c | 2 +- 6 files changed, 16 insertions(+), 10 deletions(-) (limited to 'include/linux') diff --git a/include/linux/netfilter_ipv4/ip_nat_protocol.h b/include/linux/netfilter_ipv4/ip_nat_protocol.h index e81795806ee3..f343239cd4ea 100644 --- a/include/linux/netfilter_ipv4/ip_nat_protocol.h +++ b/include/linux/netfilter_ipv4/ip_nat_protocol.h @@ -18,7 +18,7 @@ struct ip_nat_protocol /* Do a packet translation according to the ip_nat_proto_manip * and manip type. Return true if succeeded. */ int (*manip_pkt)(struct sk_buff **pskb, - unsigned int hdroff, + unsigned int iphdroff, const struct ip_conntrack_manip *manip, enum ip_nat_manip_type maniptype); diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index 2a58e33c42ae..f1a1058c94df 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -687,7 +687,7 @@ manip_pkt(u_int16_t proto, iph = (void *)(*pskb)->data + iphdroff; /* Manipulate protcol part. */ - if (!ip_nat_find_proto(proto)->manip_pkt(pskb, iphdroff + iph->ihl*4, + if (!ip_nat_find_proto(proto)->manip_pkt(pskb, iphdroff, manip, maniptype)) return 0; diff --git a/net/ipv4/netfilter/ip_nat_proto_icmp.c b/net/ipv4/netfilter/ip_nat_proto_icmp.c index 6fb50dee520c..7cbe08819b0e 100644 --- a/net/ipv4/netfilter/ip_nat_proto_icmp.c +++ b/net/ipv4/netfilter/ip_nat_proto_icmp.c @@ -53,11 +53,13 @@ icmp_unique_tuple(struct ip_conntrack_tuple *tuple, static int icmp_manip_pkt(struct sk_buff **pskb, - unsigned int hdroff, + unsigned int iphdroff, const struct ip_conntrack_manip *manip, enum ip_nat_manip_type maniptype) { + struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); struct icmphdr *hdr; + unsigned int hdroff = iphdroff + iph->ihl*4; if (!skb_ip_make_writable(pskb, hdroff + sizeof(*hdr))) return 0; diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c index 197bd01e2166..281e19a520eb 100644 --- a/net/ipv4/netfilter/ip_nat_proto_tcp.c +++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c @@ -84,11 +84,13 @@ tcp_unique_tuple(struct ip_conntrack_tuple *tuple, static int tcp_manip_pkt(struct sk_buff **pskb, - unsigned int hdroff, + unsigned int iphdroff, const struct ip_conntrack_manip *manip, enum ip_nat_manip_type maniptype) { + struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); struct tcphdr *hdr; + unsigned int hdroff = iphdroff + iph->ihl*4; u_int32_t oldip; u_int16_t *portptr, oldport; int hdrsize = 8; /* TCP connection tracking guarantees this much */ @@ -106,11 +108,11 @@ tcp_manip_pkt(struct sk_buff **pskb, if (maniptype == IP_NAT_MANIP_SRC) { /* Get rid of src ip and src pt */ - oldip = (*pskb)->nh.iph->saddr; + oldip = iph->saddr; portptr = &hdr->source; } else { /* Get rid of dst ip and dst pt */ - oldip = (*pskb)->nh.iph->daddr; + oldip = iph->daddr; portptr = &hdr->dest; } diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c index 240004eede81..12c19bfe5ad3 100644 --- a/net/ipv4/netfilter/ip_nat_proto_udp.c +++ b/net/ipv4/netfilter/ip_nat_proto_udp.c @@ -83,11 +83,13 @@ udp_unique_tuple(struct ip_conntrack_tuple *tuple, static int udp_manip_pkt(struct sk_buff **pskb, - unsigned int hdroff, + unsigned int iphdroff, const struct ip_conntrack_manip *manip, enum ip_nat_manip_type maniptype) { + struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); struct udphdr *hdr; + unsigned int hdroff = iphdroff + iph->ihl*4; u_int32_t oldip; u_int16_t *portptr; @@ -97,11 +99,11 @@ udp_manip_pkt(struct sk_buff **pskb, hdr = (void *)(*pskb)->data + hdroff; if (maniptype == IP_NAT_MANIP_SRC) { /* Get rid of src ip and src pt */ - oldip = (*pskb)->nh.iph->saddr; + oldip = iph->saddr; portptr = &hdr->source; } else { /* Get rid of dst ip and dst pt */ - oldip = (*pskb)->nh.iph->daddr; + oldip = iph->daddr; portptr = &hdr->dest; } if (hdr->check) /* 0 is a special case meaning no checksum */ diff --git a/net/ipv4/netfilter/ip_nat_proto_unknown.c b/net/ipv4/netfilter/ip_nat_proto_unknown.c index b57103fa907c..8f2e7ddbbdc8 100644 --- a/net/ipv4/netfilter/ip_nat_proto_unknown.c +++ b/net/ipv4/netfilter/ip_nat_proto_unknown.c @@ -39,7 +39,7 @@ static int unknown_unique_tuple(struct ip_conntrack_tuple *tuple, static int unknown_manip_pkt(struct sk_buff **pskb, - unsigned int hdroff, + unsigned int iphdroff, const struct ip_conntrack_manip *manip, enum ip_nat_manip_type maniptype) { -- cgit v1.2.3 From df0d9094a3a94de6fcc63cbb6bc4a6d370dbdb11 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 14 Nov 2004 02:27:09 -0800 Subject: [PATCH] allow arch override of BIOVEC_PHYS_MERGEABLE This patch is from the Xen crew - it allows override of deciding whether two given pages can be considered physically contigous or not. This is similar to how we handle iommu and virtual merging. Signed-off-by: Jens Axboe Signed-off-by: Linus Torvalds --- include/linux/bio.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/linux') diff --git a/include/linux/bio.h b/include/linux/bio.h index 2585402c2b8b..cd8d47bf34b4 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -188,8 +188,15 @@ struct bio { #define __BVEC_END(bio) bio_iovec_idx((bio), (bio)->bi_vcnt - 1) #define __BVEC_START(bio) bio_iovec_idx((bio), (bio)->bi_idx) + +/* + * allow arch override, for eg virtualized architectures (put in asm/io.h) + */ +#ifndef BIOVEC_PHYS_MERGEABLE #define BIOVEC_PHYS_MERGEABLE(vec1, vec2) \ ((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2))) +#endif + #define BIOVEC_VIRT_MERGEABLE(vec1, vec2) \ ((((bvec_to_phys((vec1)) + (vec1)->bv_len) | bvec_to_phys((vec2))) & (BIO_VMERGE_BOUNDARY - 1)) == 0) #define __BIO_SEG_BOUNDARY(addr1, addr2, mask) \ -- cgit v1.2.3 From 772b3c3f35276d24e17e3d58eeb0c6268ec2c70b Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Sun, 14 Nov 2004 02:56:35 -0800 Subject: [PATCH] alpha sysrq compile fix missing extern declaration in -Werror land... Add the proper declaration to sysrq.h. --- include/linux/sysrq.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h index 94cbe97bd8e6..b8415f065ef8 100644 --- a/include/linux/sysrq.h +++ b/include/linux/sysrq.h @@ -33,6 +33,7 @@ void handle_sysrq(int, struct pt_regs *, struct tty_struct *); void __handle_sysrq(int, struct pt_regs *, struct tty_struct *); int register_sysrq_key(int, struct sysrq_key_op *); int unregister_sysrq_key(int, struct sysrq_key_op *); +struct sysrq_key_op *__sysrq_get_key_op(int key); #else -- cgit v1.2.3 From 0801654757a6613350633abd0720c995a9652bdc Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 14 Nov 2004 23:41:51 -0800 Subject: [TG3]: 5753 support and a bug fix. Add support for 5753 chips which is mostly just adding in the appropriate PCI ids and recognizing that these chips do not use GPIO2 for Vaux switching. Also do not set DMA read water mark on PCI Express. In such configurations these bits are reserved. Signed-off-by: David S. Miller --- drivers/net/tg3.c | 70 +++++++++++++++++++++++++++++++++++-------------- drivers/net/tg3.h | 1 + include/linux/pci_ids.h | 6 ++++- 3 files changed, 56 insertions(+), 21 deletions(-) (limited to 'include/linux') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 6bd0f97a76d7..78a289c1616f 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -206,6 +206,14 @@ static struct pci_device_id tg3_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX, @@ -881,34 +889,54 @@ static void tg3_frob_aux_power(struct tg3 *tp) GRC_LCLCTRL_GPIO_OUTPUT1)); udelay(100); } else { + int no_gpio2; + u32 grc_local_ctrl; + if (tp_peer != tp && (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0) return; + /* On 5753 and variants, GPIO2 cannot be used. */ + no_gpio2 = (tp->nic_sram_data_cfg & + NIC_SRAM_DATA_CFG_NO_GPIO2) != 0; + + grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | + GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT1 | + GRC_LCLCTRL_GPIO_OUTPUT2; + if (no_gpio2) { + grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT2); + } tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | - (GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT1 | - GRC_LCLCTRL_GPIO_OUTPUT2)); + grc_local_ctrl); udelay(100); + grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | + GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT0 | + GRC_LCLCTRL_GPIO_OUTPUT1 | + GRC_LCLCTRL_GPIO_OUTPUT2; + if (no_gpio2) { + grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT2); + } tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | - (GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT0 | - GRC_LCLCTRL_GPIO_OUTPUT1 | - GRC_LCLCTRL_GPIO_OUTPUT2)); + grc_local_ctrl); udelay(100); - tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | - (GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT0 | - GRC_LCLCTRL_GPIO_OUTPUT1)); - udelay(100); + grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | + GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT0 | + GRC_LCLCTRL_GPIO_OUTPUT1; + if (!no_gpio2) { + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + grc_local_ctrl); + udelay(100); + } } } else { if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && @@ -7619,7 +7647,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 || tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) || (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM && - tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F)) + (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F || + tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F))) tp->tg3_flags |= TG3_FLAG_10_100_ONLY; err = tg3_phy_probe(tp); @@ -7926,7 +7955,8 @@ static int __devinit tg3_test_dma(struct tg3 *tp) #endif if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { - tp->dma_rwctrl |= 0x001f0000; + /* DMA read watermark not used on PCIE */ + tp->dma_rwctrl |= 0x00180000; } else if (!(tp->tg3_flags & TG3_FLAG_PCIX_MODE)) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 6f7e17cd7ae0..3b22f53d2579 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1436,6 +1436,7 @@ #define NIC_SRAM_DATA_CFG_EEPROM_WP 0x00000100 #define NIC_SRAM_DATA_CFG_MINI_PCI 0x00001000 #define NIC_SRAM_DATA_CFG_FIBER_WOL 0x00004000 +#define NIC_SRAM_DATA_CFG_NO_GPIO2 0x00100000 #define NIC_SRAM_DATA_PHY_ID 0x00000b74 #define NIC_SRAM_DATA_PHY_ID1_MASK 0xffff0000 diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index a068c74e8580..c53d4c6e5824 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1918,11 +1918,15 @@ #define PCI_DEVICE_ID_TIGON3_5704S 0x16a8 #define PCI_DEVICE_ID_TIGON3_5702A3 0x16c6 #define PCI_DEVICE_ID_TIGON3_5703A3 0x16c7 +#define PCI_DEVICE_ID_TIGON3_5781 0x16dd +#define PCI_DEVICE_ID_TIGON3_5753 0x16f7 +#define PCI_DEVICE_ID_TIGON3_5753M 0x16fd +#define PCI_DEVICE_ID_TIGON3_5753F 0x16fe #define PCI_DEVICE_ID_TIGON3_5901 0x170d +#define PCI_DEVICE_ID_BCM4401B1 0x170c #define PCI_DEVICE_ID_TIGON3_5901_2 0x170e #define PCI_DEVICE_ID_BCM4401 0x4401 #define PCI_DEVICE_ID_BCM4401B0 0x4402 -#define PCI_DEVICE_ID_BCM4401B1 0x170c #define PCI_VENDOR_ID_ENE 0x1524 #define PCI_DEVICE_ID_ENE_1211 0x1211 -- cgit v1.2.3 From b93ddaf80b8184c1def38a8518b8fdbdd78e73e1 Mon Sep 17 00:00:00 2001 From: "Alasdair G. Kergon" Date: Mon, 15 Nov 2004 04:09:40 -0800 Subject: [PATCH] device-mapper: Add DM_TARGET_MSG Add DM_TARGET_MSG ioctl so data can be passed to a dm target after its table has been loaded. Signed-Off-By: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-ioctl.c | 66 ++++++++++++++++++++++++++++++++++++++++++- drivers/md/dm-table.c | 5 ++-- drivers/md/dm.h | 3 ++ include/linux/compat_ioctl.h | 2 ++ include/linux/device-mapper.h | 4 +++ include/linux/dm-ioctl.h | 21 ++++++++++++-- 6 files changed, 96 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index e1703f77c196..bcecafe8431c 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2001, 2002 Sistina Software (UK) Limited. + * Copyright (C) 2004 Red Hat, Inc. All rights reserved. * * This file is released under the GPL. */ @@ -1097,6 +1098,67 @@ static int table_status(struct dm_ioctl *param, size_t param_size) return r; } +/* + * Pass a message to the target that's at the supplied device offset. + */ +static int target_message(struct dm_ioctl *param, size_t param_size) +{ + int r, argc; + char **argv; + struct mapped_device *md; + struct dm_table *table; + struct dm_target *ti; + struct dm_target_msg *tmsg = (void *) param + param->data_start; + + md = find_device(param); + if (!md) + return -ENXIO; + + r = __dev_status(md, param); + if (r) + goto out; + + if (tmsg < (struct dm_target_msg *) (param + 1) || + invalid_str(tmsg->message, (void *) param + param_size)) { + DMWARN("Invalid target message parameters."); + r = -EINVAL; + goto out; + } + + r = dm_split_args(&argc, &argv, tmsg->message); + if (r) { + DMWARN("Failed to split target message parameters"); + goto out; + } + + table = dm_get_table(md); + if (!table) + goto out_argv; + + if (tmsg->sector >= dm_table_get_size(table)) { + DMWARN("Target message sector outside device."); + r = -EINVAL; + goto out_table; + } + + ti = dm_table_find_target(table, tmsg->sector); + if (ti->type->message) + r = ti->type->message(ti, argc, argv); + else { + DMWARN("Target type does not support messages"); + r = -EINVAL; + } + + out_table: + dm_table_put(table); + out_argv: + kfree(argv); + out: + param->data_size = 0; + dm_put(md); + return r; +} + /*----------------------------------------------------------------- * Implementation of open/close/ioctl on the special char * device. @@ -1123,7 +1185,9 @@ static ioctl_fn lookup_ioctl(unsigned int cmd) {DM_TABLE_DEPS_CMD, table_deps}, {DM_TABLE_STATUS_CMD, table_status}, - {DM_LIST_VERSIONS_CMD, list_versions} + {DM_LIST_VERSIONS_CMD, list_versions}, + + {DM_TARGET_MSG_CMD, target_message} }; return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn; diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 32e274537d1a..764c74ad6e38 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2001 Sistina Software (UK) Limited. + * Copyright (C) 2004 Red Hat, Inc. All rights reserved. * * This file is released under the GPL. */ @@ -575,7 +576,7 @@ static char **realloc_argv(unsigned *array_size, char **old_argv) /* * Destructively splits up the argument list to pass to ctr. */ -static int split_args(int *argc, char ***argvp, char *input) +int dm_split_args(int *argc, char ***argvp, char *input) { char *start, *end = input, *out, **argv = NULL; unsigned array_size = 0; @@ -688,7 +689,7 @@ int dm_table_add_target(struct dm_table *t, const char *type, goto bad; } - r = split_args(&argc, &argv, params); + r = dm_split_args(&argc, &argv, params); if (r) { tgt->error = "couldn't split parameters (insufficient memory)"; goto bad; diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 2daa03332d3d..165251cdd8dd 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -2,6 +2,7 @@ * Internal header file for device mapper * * Copyright (C) 2001, 2002 Sistina Software + * Copyright (C) 2004 Red Hat, Inc. All rights reserved. * * This file is released under the LGPL. */ @@ -165,6 +166,8 @@ static inline unsigned long to_bytes(sector_t n) return (n << 9); } +int dm_split_args(int *argc, char ***argvp, char *input); + /* * The device-mapper can be driven through one of two interfaces; * ioctl or filesystem, depending which patch you have applied. diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h index c8c2cea10623..ab091956f248 100644 --- a/include/linux/compat_ioctl.h +++ b/include/linux/compat_ioctl.h @@ -140,6 +140,7 @@ COMPATIBLE_IOCTL(DM_TABLE_CLEAR_32) COMPATIBLE_IOCTL(DM_TABLE_DEPS_32) COMPATIBLE_IOCTL(DM_TABLE_STATUS_32) COMPATIBLE_IOCTL(DM_LIST_VERSIONS_32) +COMPATIBLE_IOCTL(DM_TARGET_MSG_32) COMPATIBLE_IOCTL(DM_VERSION) COMPATIBLE_IOCTL(DM_REMOVE_ALL) COMPATIBLE_IOCTL(DM_LIST_DEVICES) @@ -154,6 +155,7 @@ COMPATIBLE_IOCTL(DM_TABLE_CLEAR) COMPATIBLE_IOCTL(DM_TABLE_DEPS) COMPATIBLE_IOCTL(DM_TABLE_STATUS) COMPATIBLE_IOCTL(DM_LIST_VERSIONS) +COMPATIBLE_IOCTL(DM_TARGET_MSG) /* Big K */ COMPATIBLE_IOCTL(PIO_FONT) COMPATIBLE_IOCTL(GIO_FONT) diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 7abe54e3ee70..a6282ab22b8c 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2001 Sistina Software (UK) Limited. + * Copyright (C) 2004 Red Hat, Inc. All rights reserved. * * This file is released under the LGPL. */ @@ -57,6 +58,8 @@ typedef void (*dm_resume_fn) (struct dm_target *ti); typedef int (*dm_status_fn) (struct dm_target *ti, status_type_t status_type, char *result, unsigned int maxlen); +typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv); + void dm_error(const char *message); /* @@ -82,6 +85,7 @@ struct target_type { dm_suspend_fn suspend; dm_resume_fn resume; dm_status_fn status; + dm_message_fn message; }; struct io_restrictions { diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h index 03f99db7ad7b..a1f659508c30 100644 --- a/include/linux/dm-ioctl.h +++ b/include/linux/dm-ioctl.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2001 - 2003 Sistina Software (UK) Limited. + * Copyright (C) 2004 Red Hat, Inc. All rights reserved. * * This file is released under the LGPL. */ @@ -76,6 +77,9 @@ * * DM_TABLE_STATUS: * Return the targets status for the 'active' table. + * + * DM_TARGET_MSG: + * Pass a message string to the target at a specific offset of a device. */ /* @@ -178,6 +182,15 @@ struct dm_target_versions { char name[0]; }; +/* + * Used to pass message to a target + */ +struct dm_target_msg { + uint64_t sector; /* Device sector */ + + char message[0]; +}; + /* * If you change this make sure you make the corresponding change * to dm-ioctl.c:lookup_ioctl() @@ -204,6 +217,7 @@ enum { /* Added later */ DM_LIST_VERSIONS_CMD, + DM_TARGET_MSG_CMD, }; /* @@ -232,6 +246,7 @@ typedef char ioctl_struct[308]; #define DM_TABLE_DEPS_32 _IOWR(DM_IOCTL, DM_TABLE_DEPS_CMD, ioctl_struct) #define DM_TABLE_STATUS_32 _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, ioctl_struct) #define DM_LIST_VERSIONS_32 _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, ioctl_struct) +#define DM_TARGET_MSG_32 _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, ioctl_struct) #endif #define DM_IOCTL 0xfd @@ -254,10 +269,12 @@ typedef char ioctl_struct[308]; #define DM_LIST_VERSIONS _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, struct dm_ioctl) +#define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl) + #define DM_VERSION_MAJOR 4 -#define DM_VERSION_MINOR 1 +#define DM_VERSION_MINOR 2 #define DM_VERSION_PATCHLEVEL 0 -#define DM_VERSION_EXTRA "-ioctl (2003-12-10)" +#define DM_VERSION_EXTRA "-ioctl (2004-06-08)" /* Status bits */ #define DM_READONLY_FLAG (1 << 0) /* In/Out */ -- cgit v1.2.3 From 30b81706fb10abd310579954438f3bb0cd3dd91b Mon Sep 17 00:00:00 2001 From: "Alasdair G. Kergon" Date: Mon, 15 Nov 2004 04:09:53 -0800 Subject: [PATCH] device-mapper: Allow referencing by device number Currently userspace code using the dm ioctls must refer to a mapped device by either its name or its uuid. But in some circumstances you know neither of those directly. This patch lets you reference devices by their major/minor numbers as an alternative. Signed-Off-By: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-ioctl.c | 29 +++++++++++++++++------------ drivers/md/dm.c | 41 +++++++++++++++++++++++++++++++++++------ drivers/md/dm.h | 2 ++ include/linux/dm-ioctl.h | 4 ++-- 4 files changed, 56 insertions(+), 20 deletions(-) (limited to 'include/linux') diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index bcecafe8431c..9f0073f4e0c4 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -18,7 +18,7 @@ #include -#define DM_DRIVER_EMAIL "dm@uk.sistina.com" +#define DM_DRIVER_EMAIL "dm-devel@redhat.com" /*----------------------------------------------------------------- * The ioctl interface needs to be able to look up devices by @@ -225,6 +225,7 @@ static int dm_hash_insert(const char *name, const char *uuid, struct mapped_devi } register_with_devfs(cell); dm_get(md); + dm_set_mdptr(md, cell); up_write(&_hash_lock); return 0; @@ -241,6 +242,7 @@ static void __hash_remove(struct hash_cell *hc) list_del(&hc->uuid_list); list_del(&hc->name_list); unregister_with_devfs(hc); + dm_set_mdptr(hc->md, NULL); dm_put(hc->md); if (hc->new_map) dm_table_put(hc->new_map); @@ -580,12 +582,16 @@ static int dev_create(struct dm_ioctl *param, size_t param_size) } /* - * Always use UUID for lookups if it's present, otherwise use name. + * Always use UUID for lookups if it's present, otherwise use name or dev. */ static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) { - return *param->uuid ? - __get_uuid_cell(param->uuid) : __get_name_cell(param->name); + if (*param->uuid) + return __get_uuid_cell(param->uuid); + else if (*param->name) + return __get_name_cell(param->name); + else + return dm_get_mdptr(huge_decode_dev(param->dev)); } static inline struct mapped_device *find_device(struct dm_ioctl *param) @@ -597,6 +603,7 @@ static inline struct mapped_device *find_device(struct dm_ioctl *param) hc = __find_device_hash_cell(param); if (hc) { md = hc->md; + dm_get(md); /* * Sneakily write in both the name and the uuid @@ -612,8 +619,6 @@ static inline struct mapped_device *find_device(struct dm_ioctl *param) param->flags |= DM_INACTIVE_PRESENT_FLAG; else param->flags &= ~DM_INACTIVE_PRESENT_FLAG; - - dm_get(md); } up_read(&_hash_lock); @@ -1266,14 +1271,14 @@ static int validate_params(uint cmd, struct dm_ioctl *param) cmd == DM_LIST_VERSIONS_CMD) return 0; - /* Unless creating, either name or uuid but not both */ - if (cmd != DM_DEV_CREATE_CMD) { - if ((!*param->uuid && !*param->name) || - (*param->uuid && *param->name)) { - DMWARN("one of name or uuid must be supplied, cmd(%u)", - cmd); + if ((cmd == DM_DEV_CREATE_CMD)) { + if (!*param->name) { + DMWARN("name not supplied when creating device"); return -EINVAL; } + } else if ((*param->uuid && *param->name)) { + DMWARN("only supply one of name or uuid, cmd(%u)", cmd); + return -EINVAL; } /* Ensure strings are terminated */ diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 31a68d3b6ef2..bf99fec5d222 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2001, 2002 Sistina Software (UK) Limited. + * Copyright (C) 2004 Red Hat, Inc. All rights reserved. * * This file is released under the GPL. */ @@ -59,6 +60,8 @@ struct mapped_device { request_queue_t *queue; struct gendisk *disk; + void *interface_ptr; + /* * A list of ios that arrived while we were suspended. */ @@ -640,7 +643,7 @@ static void free_minor(unsigned int minor) /* * See if the device with a specific minor # is free. */ -static int specific_minor(unsigned int minor) +static int specific_minor(struct mapped_device *md, unsigned int minor) { int r, m; @@ -660,7 +663,7 @@ static int specific_minor(unsigned int minor) goto out; } - r = idr_get_new_above(&_minor_idr, specific_minor, minor, &m); + r = idr_get_new_above(&_minor_idr, md, minor, &m); if (r) { goto out; } @@ -676,7 +679,7 @@ out: return r; } -static int next_free_minor(unsigned int *minor) +static int next_free_minor(struct mapped_device *md, unsigned int *minor) { int r; unsigned int m; @@ -689,7 +692,7 @@ static int next_free_minor(unsigned int *minor) goto out; } - r = idr_get_new(&_minor_idr, next_free_minor, &m); + r = idr_get_new(&_minor_idr, md, &m); if (r) { goto out; } @@ -723,7 +726,7 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent) } /* get a minor number for the dev */ - r = persistent ? specific_minor(minor) : next_free_minor(&minor); + r = persistent ? specific_minor(md, minor) : next_free_minor(md, &minor); if (r < 0) goto bad1; @@ -880,6 +883,32 @@ int dm_create_with_minor(unsigned int minor, struct mapped_device **result) return create_aux(minor, 1, result); } +void *dm_get_mdptr(dev_t dev) +{ + struct mapped_device *md; + void *mdptr = NULL; + unsigned minor = MINOR(dev); + + if (MAJOR(dev) != _major || minor >= (1 << MINORBITS)) + return NULL; + + down(&_minor_lock); + + md = idr_find(&_minor_idr, minor); + + if (md && (dm_disk(md)->first_minor == minor)) + mdptr = md->interface_ptr; + + up(&_minor_lock); + + return mdptr; +} + +void dm_set_mdptr(struct mapped_device *md, void *ptr) +{ + md->interface_ptr = ptr; +} + void dm_get(struct mapped_device *md) { atomic_inc(&md->holders); @@ -1139,5 +1168,5 @@ module_exit(dm_exit); module_param(major, uint, 0); MODULE_PARM_DESC(major, "The major number of the device mapper"); MODULE_DESCRIPTION(DM_NAME " driver"); -MODULE_AUTHOR("Joe Thornber "); +MODULE_AUTHOR("Joe Thornber "); MODULE_LICENSE("GPL"); diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 165251cdd8dd..4ff5be590b0c 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -55,6 +55,8 @@ struct mapped_device; *---------------------------------------------------------------*/ int dm_create(struct mapped_device **md); int dm_create_with_minor(unsigned int minor, struct mapped_device **md); +void dm_set_mdptr(struct mapped_device *md, void *ptr); +void *dm_get_mdptr(dev_t dev); /* * Reference counting for md. diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h index a1f659508c30..183e777d7786 100644 --- a/include/linux/dm-ioctl.h +++ b/include/linux/dm-ioctl.h @@ -272,9 +272,9 @@ typedef char ioctl_struct[308]; #define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl) #define DM_VERSION_MAJOR 4 -#define DM_VERSION_MINOR 2 +#define DM_VERSION_MINOR 3 #define DM_VERSION_PATCHLEVEL 0 -#define DM_VERSION_EXTRA "-ioctl (2004-06-08)" +#define DM_VERSION_EXTRA "-ioctl (2004-09-30)" /* Status bits */ #define DM_READONLY_FLAG (1 << 0) /* In/Out */ -- cgit v1.2.3 From 1163d2c331b166bb234ae7100b7883cbcda3e136 Mon Sep 17 00:00:00 2001 From: Markus Lidel Date: Mon, 15 Nov 2004 04:12:00 -0800 Subject: [PATCH] i2o: changed code with BUG() to BUG_ON() - changed code with BUG() to use BUG_ON() which could be optimized by some platforms (original from Milton Miller) Signed-off-by: Markus Lidel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/i2o.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/i2o.h b/include/linux/i2o.h index f571709b0443..a8ac18b36bea 100644 --- a/include/linux/i2o.h +++ b/include/linux/i2o.h @@ -515,10 +515,8 @@ static inline void i2o_flush_reply(struct i2o_controller *c, u32 m) 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(); + BUG_ON(m < c->out_queue.phys + || m >= c->out_queue.phys + c->out_queue.len); return c->out_queue.virt + (m - c->out_queue.phys); }; -- cgit v1.2.3 From 1e0fa7a2dbdf88eb0bdf95ee17bf7cc3d8663da1 Mon Sep 17 00:00:00 2001 From: Markus Lidel Date: Mon, 15 Nov 2004 04:12:13 -0800 Subject: [PATCH] i2o: remove unused code and make needlessly global code static - remove unused code - make needlessly global code static Signed-off-by: Adrian Bunk Signed-off-by: Markus Lidel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/message/i2o/debug.c | 108 ++------------------------------------- drivers/message/i2o/device.c | 46 +---------------- drivers/message/i2o/exec-osm.c | 5 +- drivers/message/i2o/i2o_config.c | 3 +- drivers/message/i2o/i2o_proc.c | 38 +++++++------- drivers/message/i2o/i2o_scsi.c | 6 +-- drivers/message/i2o/iop.c | 7 +-- include/linux/i2o.h | 3 -- 8 files changed, 36 insertions(+), 180 deletions(-) (limited to 'include/linux') diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c index f8093b978bd9..2a5d478fc60e 100644 --- a/drivers/message/i2o/debug.c +++ b/drivers/message/i2o/debug.c @@ -4,40 +4,14 @@ #include #include -static int verbose; extern struct i2o_driver **i2o_drivers; extern unsigned int i2o_max_drivers; static void i2o_report_util_cmd(u8 cmd); static void i2o_report_exec_cmd(u8 cmd); -void i2o_report_fail_status(u8 req_status, u32 * msg); -void i2o_report_common_status(u8 req_status); +static void i2o_report_fail_status(u8 req_status, u32 * msg); +static void i2o_report_common_status(u8 req_status); static void i2o_report_common_dsc(u16 detailed_status); -void i2o_dump_status_block(i2o_status_block * sb) -{ - pr_debug("Organization ID: %d\n", sb->org_id); - pr_debug("IOP ID: %d\n", sb->iop_id); - pr_debug("Host Unit ID: %d\n", sb->host_unit_id); - pr_debug("Segment Number: %d\n", sb->segment_number); - pr_debug("I2O Version: %d\n", sb->i2o_version); - pr_debug("IOP State: %d\n", sb->iop_state); - pr_debug("Messanger Type: %d\n", sb->msg_type); - pr_debug("Inbound Frame Size: %d\n", sb->inbound_frame_size); - pr_debug("Init Code: %d\n", sb->init_code); - pr_debug("Max Inbound MFrames: %d\n", sb->max_inbound_frames); - pr_debug("Current Inbound MFrames: %d\n", sb->cur_inbound_frames); - pr_debug("Max Outbound MFrames: %d\n", sb->max_outbound_frames); - pr_debug("Product ID String: %s\n", sb->product_id); - pr_debug("Expected LCT Size: %d\n", sb->expected_lct_size); - pr_debug("IOP Capabilities: %d\n", sb->iop_capabilities); - pr_debug("Desired Private MemSize: %d\n", sb->desired_mem_size); - pr_debug("Current Private MemSize: %d\n", sb->current_mem_size); - pr_debug("Current Private MemBase: %d\n", sb->current_mem_base); - pr_debug("Desired Private IO Size: %d\n", sb->desired_io_size); - pr_debug("Current Private IO Size: %d\n", sb->current_io_size); - pr_debug("Current Private IO Base: %d\n", sb->current_io_base); -}; - /* * Used for error reporting/debugging purposes. * Report Cmd name, Request status, Detailed Status. @@ -91,71 +65,12 @@ void i2o_dump_message(struct i2o_message *m) #endif } -/** - * i2o_report_controller_unit - print information about a tid - * @c: controller - * @d: device - * - * Dump an information block associated with a given unit (TID). The - * tables are read and a block of text is output to printk that is - * formatted intended for the user. - */ - -void i2o_report_controller_unit(struct i2o_controller *c, struct i2o_device *d) -{ - char buf[64]; - char str[22]; - int ret; - - if (verbose == 0) - return; - - printk(KERN_INFO "Target ID %03x.\n", d->lct_data.tid); - if ((ret = i2o_parm_field_get(d, 0xF100, 3, buf, 16)) >= 0) { - buf[16] = 0; - printk(KERN_INFO " Vendor: %s\n", buf); - } - if ((ret = i2o_parm_field_get(d, 0xF100, 4, buf, 16)) >= 0) { - buf[16] = 0; - printk(KERN_INFO " Device: %s\n", buf); - } - if (i2o_parm_field_get(d, 0xF100, 5, buf, 16) >= 0) { - buf[16] = 0; - printk(KERN_INFO " Description: %s\n", buf); - } - if ((ret = i2o_parm_field_get(d, 0xF100, 6, buf, 8)) >= 0) { - buf[8] = 0; - printk(KERN_INFO " Rev: %s\n", buf); - } - - printk(KERN_INFO " Class: "); - //sprintf(str, "%-21s", i2o_get_class_name(d->lct_data.class_id)); - printk(KERN_DEBUG "%s\n", str); - - printk(KERN_INFO " Subclass: 0x%04X\n", d->lct_data.sub_class); - printk(KERN_INFO " Flags: "); - - if (d->lct_data.device_flags & (1 << 0)) - printk(KERN_DEBUG "C"); // ConfigDialog requested - if (d->lct_data.device_flags & (1 << 1)) - printk(KERN_DEBUG "U"); // Multi-user capable - if (!(d->lct_data.device_flags & (1 << 4))) - printk(KERN_DEBUG "P"); // Peer service enabled! - if (!(d->lct_data.device_flags & (1 << 5))) - printk(KERN_DEBUG "M"); // Mgmt service enabled! - printk(KERN_DEBUG "\n"); -} - -/* -module_param(verbose, int, 0644); -MODULE_PARM_DESC(verbose, "Verbose diagnostics"); -*/ /* * Used for error reporting/debugging purposes. * Following fail status are common to all classes. * The preserved message must be handled in the reply handler. */ -void i2o_report_fail_status(u8 req_status, u32 * msg) +static void i2o_report_fail_status(u8 req_status, u32 * msg) { static char *FAIL_STATUS[] = { "0x80", /* not used */ @@ -213,7 +128,7 @@ void i2o_report_fail_status(u8 req_status, u32 * msg) * Used for error reporting/debugging purposes. * Following reply status are common to all classes. */ -void i2o_report_common_status(u8 req_status) +static void i2o_report_common_status(u8 req_status) { static char *REPLY_STATUS[] = { "SUCCESS", @@ -476,20 +391,6 @@ void i2o_debug_state(struct i2o_controller *c) } }; -void i2o_systab_debug(struct i2o_sys_tbl *sys_tbl) -{ - u32 *table; - int count; - u32 size; - - table = (u32 *) sys_tbl; - size = sizeof(struct i2o_sys_tbl) + sys_tbl->num_entries - * sizeof(struct i2o_sys_tbl_entry); - - for (count = 0; count < (size >> 2); count++) - printk(KERN_INFO "sys_tbl[%d] = %0#10x\n", count, table[count]); -} - void i2o_dump_hrt(struct i2o_controller *c) { u32 *rows = (u32 *) c->hrt.virt; @@ -577,5 +478,4 @@ void i2o_dump_hrt(struct i2o_controller *c) } } -EXPORT_SYMBOL(i2o_dump_status_block); EXPORT_SYMBOL(i2o_dump_message); diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c index def6ea54416e..474d80615a1c 100644 --- a/drivers/message/i2o/device.c +++ b/drivers/message/i2o/device.c @@ -211,8 +211,8 @@ static struct i2o_device *i2o_device_alloc(void) * Returns a pointer to the I2O device on success or negative error code * on failure. */ -struct i2o_device *i2o_device_add(struct i2o_controller *c, - i2o_lct_entry * entry) +static struct i2o_device *i2o_device_add(struct i2o_controller *c, + i2o_lct_entry * entry) { struct i2o_device *dev; @@ -546,47 +546,6 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, return size; } -/* - * Set a scalar group value or a whole group. - */ -int i2o_parm_field_set(struct i2o_device *i2o_dev, int group, int field, - void *buf, int buflen) -{ - u16 *opblk; - u8 resblk[8 + buflen]; /* 8 bytes for header */ - int size; - - opblk = kmalloc(buflen + 64, GFP_KERNEL); - if (opblk == NULL) { - printk(KERN_ERR "i2o: no memory for operation buffer.\n"); - return -ENOMEM; - } - - opblk[0] = 1; /* operation count */ - opblk[1] = 0; /* pad */ - opblk[2] = I2O_PARAMS_FIELD_SET; - opblk[3] = group; - - if (field == -1) { /* whole group */ - opblk[4] = -1; - memcpy(opblk + 5, buf, buflen); - } else { /* single field */ - - opblk[4] = 1; - opblk[5] = field; - memcpy(opblk + 6, buf, buflen); - } - - size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_SET, opblk, - 12 + buflen, resblk, sizeof(resblk)); - - kfree(opblk); - if (size > buflen) - return buflen; - - return size; -} - /* * if oper == I2O_PARAMS_TABLE_GET, get from all rows * if fieldcount == -1 return all fields @@ -669,6 +628,5 @@ void i2o_device_exit(void) EXPORT_SYMBOL(i2o_device_claim); EXPORT_SYMBOL(i2o_device_claim_release); EXPORT_SYMBOL(i2o_parm_field_get); -EXPORT_SYMBOL(i2o_parm_field_set); EXPORT_SYMBOL(i2o_parm_table_get); EXPORT_SYMBOL(i2o_parm_issue); diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 6d865f89642f..34aece2864d2 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c @@ -33,6 +33,8 @@ struct i2o_driver i2o_exec_driver; +static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind); + /* Module internal functions from other sources */ extern int i2o_device_parse_lct(struct i2o_controller *); @@ -436,7 +438,7 @@ int i2o_exec_lct_get(struct i2o_controller *c) * replies immediately after the request. If change_ind > 0 the reply is * send after change indicator of the LCT is > change_ind. */ -int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) +static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) { i2o_status_block *sb = c->status_block.virt; struct device *dev; @@ -503,4 +505,3 @@ void __exit i2o_exec_exit(void) EXPORT_SYMBOL(i2o_msg_post_wait_mem); EXPORT_SYMBOL(i2o_exec_lct_get); -EXPORT_SYMBOL(i2o_exec_lct_notify); diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index 22c38bb2b703..ab9cdcf7482d 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c @@ -51,7 +51,6 @@ extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int); static spinlock_t i2o_config_lock = SPIN_LOCK_UNLOCKED; -struct wait_queue *i2o_wait_queue; #define MODINC(x,y) ((x) = ((x) + 1) % (y)) @@ -79,7 +78,7 @@ static ulong i2o_cfg_info_id = 0; * multiplexed by the i2o_core code */ -struct i2o_driver i2o_config_driver = { +static struct i2o_driver i2o_config_driver = { .name = "Config-OSM" }; diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c index 25e9e3df3075..e02ea8f42d5d 100644 --- a/drivers/message/i2o/i2o_proc.c +++ b/drivers/message/i2o/i2o_proc.c @@ -290,7 +290,7 @@ static char *bus_strings[] = { "CARDBUS" }; -int i2o_seq_show_hrt(struct seq_file *seq, void *v) +static int i2o_seq_show_hrt(struct seq_file *seq, void *v) { struct i2o_controller *c = (struct i2o_controller *)seq->private; i2o_hrt *hrt = (i2o_hrt *) c->hrt.virt; @@ -391,7 +391,7 @@ int i2o_seq_show_hrt(struct seq_file *seq, void *v) return 0; } -int i2o_seq_show_lct(struct seq_file *seq, void *v) +static int i2o_seq_show_lct(struct seq_file *seq, void *v) { struct i2o_controller *c = (struct i2o_controller *)seq->private; i2o_lct *lct = (i2o_lct *) c->lct; @@ -521,7 +521,7 @@ int i2o_seq_show_lct(struct seq_file *seq, void *v) return 0; } -int i2o_seq_show_status(struct seq_file *seq, void *v) +static int i2o_seq_show_status(struct seq_file *seq, void *v) { struct i2o_controller *c = (struct i2o_controller *)seq->private; char prodstr[25]; @@ -718,7 +718,7 @@ int i2o_seq_show_status(struct seq_file *seq, void *v) return 0; } -int i2o_seq_show_hw(struct seq_file *seq, void *v) +static int i2o_seq_show_hw(struct seq_file *seq, void *v) { struct i2o_controller *c = (struct i2o_controller *)seq->private; static u32 work32[5]; @@ -775,7 +775,7 @@ int i2o_seq_show_hw(struct seq_file *seq, void *v) } /* Executive group 0003h - Executing DDM List (table) */ -int i2o_seq_show_ddm_table(struct seq_file *seq, void *v) +static int i2o_seq_show_ddm_table(struct seq_file *seq, void *v) { struct i2o_controller *c = (struct i2o_controller *)seq->private; int token; @@ -851,7 +851,7 @@ int i2o_seq_show_ddm_table(struct seq_file *seq, void *v) } /* Executive group 0004h - Driver Store (scalar) */ -int i2o_seq_show_driver_store(struct seq_file *seq, void *v) +static int i2o_seq_show_driver_store(struct seq_file *seq, void *v) { struct i2o_controller *c = (struct i2o_controller *)seq->private; u32 work32[8]; @@ -874,7 +874,7 @@ int i2o_seq_show_driver_store(struct seq_file *seq, void *v) } /* Executive group 0005h - Driver Store Table (table) */ -int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v) +static int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v) { typedef struct _i2o_driver_store { u16 stored_ddm_index; @@ -953,7 +953,7 @@ int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v) } /* Generic group F000h - Params Descriptor (table) */ -int i2o_seq_show_groups(struct seq_file *seq, void *v) +static int i2o_seq_show_groups(struct seq_file *seq, void *v) { struct i2o_device *d = (struct i2o_device *)seq->private; int token; @@ -1029,7 +1029,7 @@ int i2o_seq_show_groups(struct seq_file *seq, void *v) } /* Generic group F001h - Physical Device Table (table) */ -int i2o_seq_show_phys_device(struct seq_file *seq, void *v) +static int i2o_seq_show_phys_device(struct seq_file *seq, void *v) { struct i2o_device *d = (struct i2o_device *)seq->private; int token; @@ -1070,7 +1070,7 @@ int i2o_seq_show_phys_device(struct seq_file *seq, void *v) } /* Generic group F002h - Claimed Table (table) */ -int i2o_seq_show_claimed(struct seq_file *seq, void *v) +static int i2o_seq_show_claimed(struct seq_file *seq, void *v) { struct i2o_device *d = (struct i2o_device *)seq->private; int token; @@ -1110,7 +1110,7 @@ int i2o_seq_show_claimed(struct seq_file *seq, void *v) } /* Generic group F003h - User Table (table) */ -int i2o_seq_show_users(struct seq_file *seq, void *v) +static int i2o_seq_show_users(struct seq_file *seq, void *v) { struct i2o_device *d = (struct i2o_device *)seq->private; int token; @@ -1164,7 +1164,7 @@ int i2o_seq_show_users(struct seq_file *seq, void *v) } /* Generic group F005h - Private message extensions (table) (optional) */ -int i2o_seq_show_priv_msgs(struct seq_file *seq, void *v) +static int i2o_seq_show_priv_msgs(struct seq_file *seq, void *v) { struct i2o_device *d = (struct i2o_device *)seq->private; int token; @@ -1213,7 +1213,7 @@ int i2o_seq_show_priv_msgs(struct seq_file *seq, void *v) } /* Generic group F006h - Authorized User Table (table) */ -int i2o_seq_show_authorized_users(struct seq_file *seq, void *v) +static int i2o_seq_show_authorized_users(struct seq_file *seq, void *v) { struct i2o_device *d = (struct i2o_device *)seq->private; int token; @@ -1254,7 +1254,7 @@ int i2o_seq_show_authorized_users(struct seq_file *seq, void *v) } /* Generic group F100h - Device Identity (scalar) */ -int i2o_seq_show_dev_identity(struct seq_file *seq, void *v) +static int i2o_seq_show_dev_identity(struct seq_file *seq, void *v) { struct i2o_device *d = (struct i2o_device *)seq->private; static u32 work32[128]; // allow for "stuff" + up to 256 byte (max) serial number @@ -1292,7 +1292,7 @@ int i2o_seq_show_dev_identity(struct seq_file *seq, void *v) return 0; } -int i2o_seq_show_dev_name(struct seq_file *seq, void *v) +static int i2o_seq_show_dev_name(struct seq_file *seq, void *v) { struct i2o_device *d = (struct i2o_device *)seq->private; @@ -1302,7 +1302,7 @@ int i2o_seq_show_dev_name(struct seq_file *seq, void *v) } /* Generic group F101h - DDM Identity (scalar) */ -int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v) +static int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v) { struct i2o_device *d = (struct i2o_device *)seq->private; int token; @@ -1339,7 +1339,7 @@ int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v) } /* Generic group F102h - User Information (scalar) */ -int i2o_seq_show_uinfo(struct seq_file *seq, void *v) +static int i2o_seq_show_uinfo(struct seq_file *seq, void *v) { struct i2o_device *d = (struct i2o_device *)seq->private; int token; @@ -1371,7 +1371,7 @@ int i2o_seq_show_uinfo(struct seq_file *seq, void *v) } /* Generic group F103h - SGL Operating Limits (scalar) */ -int i2o_seq_show_sgl_limits(struct seq_file *seq, void *v) +static int i2o_seq_show_sgl_limits(struct seq_file *seq, void *v) { struct i2o_device *d = (struct i2o_device *)seq->private; static u32 work32[12]; @@ -1418,7 +1418,7 @@ int i2o_seq_show_sgl_limits(struct seq_file *seq, void *v) } /* Generic group F200h - Sensors (scalar) */ -int i2o_seq_show_sensors(struct seq_file *seq, void *v) +static int i2o_seq_show_sensors(struct seq_file *seq, void *v) { struct i2o_device *d = (struct i2o_device *)seq->private; int token; diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index 7186d004ec1d..cdffa12b3f20 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c @@ -460,7 +460,7 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m, * If a I2O controller is added, we catch the notification to add a * corresponding Scsi_Host. */ -void i2o_scsi_notify_controller_add(struct i2o_controller *c) +static void i2o_scsi_notify_controller_add(struct i2o_controller *c) { struct i2o_scsi_host *i2o_shost; int rc; @@ -492,7 +492,7 @@ void i2o_scsi_notify_controller_add(struct i2o_controller *c) * If a I2O controller is removed, we catch the notification to remove the * corresponding Scsi_Host. */ -void i2o_scsi_notify_controller_remove(struct i2o_controller *c) +static void i2o_scsi_notify_controller_remove(struct i2o_controller *c) { struct i2o_scsi_host *i2o_shost; i2o_shost = i2o_scsi_get_host(c); @@ -717,7 +717,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, * Returns 0 if the command is successfully aborted or negative error code * on failure. */ -int i2o_scsi_abort(struct scsi_cmnd *SCpnt) +static int i2o_scsi_abort(struct scsi_cmnd *SCpnt) { struct i2o_device *i2o_dev; struct i2o_controller *c; diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index e0ce5254f249..6232f5a92d77 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c @@ -38,6 +38,8 @@ LIST_HEAD(i2o_controllers); */ static struct i2o_dma i2o_systab; +static int i2o_hrt_get(struct i2o_controller *c); + /* Module internal functions from other sources */ extern struct i2o_driver i2o_exec_driver; extern int i2o_exec_lct_get(struct i2o_controller *); @@ -564,7 +566,7 @@ static int i2o_iop_reset(struct i2o_controller *c) * * Returns 0 on success or a negative errno code on failure. */ -int i2o_iop_init_outbound_queue(struct i2o_controller *c) +static int i2o_iop_init_outbound_queue(struct i2o_controller *c) { u8 *status = c->status.virt; u32 m; @@ -1050,7 +1052,7 @@ int i2o_status_get(struct i2o_controller *c) * * Returns 0 on success or negativer error code on failure. */ -int i2o_hrt_get(struct i2o_controller *c) +static int i2o_hrt_get(struct i2o_controller *c) { int rc; int i; @@ -1310,5 +1312,4 @@ EXPORT_SYMBOL(i2o_find_iop); EXPORT_SYMBOL(i2o_iop_find_device); EXPORT_SYMBOL(i2o_event_register); EXPORT_SYMBOL(i2o_status_get); -EXPORT_SYMBOL(i2o_hrt_get); EXPORT_SYMBOL(i2o_controllers); diff --git a/include/linux/i2o.h b/include/linux/i2o.h index a8ac18b36bea..b8fc7587498a 100644 --- a/include/linux/i2o.h +++ b/include/linux/i2o.h @@ -263,7 +263,6 @@ static inline void i2o_dma_unmap(struct device *, struct i2o_dma *); /* IOP functions */ extern int i2o_status_get(struct i2o_controller *); -extern int i2o_hrt_get(struct i2o_controller *); extern int i2o_event_register(struct i2o_device *, struct i2o_driver *, int, u32); @@ -385,7 +384,6 @@ extern int i2o_device_claim_release(struct i2o_device *); /* Exec OSM functions */ extern int i2o_exec_lct_get(struct i2o_controller *); -extern int i2o_exec_lct_notify(struct i2o_controller *, u32); /* device to i2o_device and driver to i2o_driver convertion functions */ #define to_i2o_driver(drv) container_of(drv,struct i2o_driver, driver) @@ -631,7 +629,6 @@ static inline void i2o_dma_unmap(struct device *dev, struct i2o_dma *addr) #define i2o_raw_writel(val, mem) __raw_writel(cpu_to_le32(val), mem) extern int i2o_parm_field_get(struct i2o_device *, int, int, void *, int); -extern int i2o_parm_field_set(struct i2o_device *, int, int, void *, int); extern int i2o_parm_table_get(struct i2o_device *, int, int, int, void *, int, void *, int); /* FIXME: remove -- cgit v1.2.3 From 43b56b35dd56357440bc27136f2e430071435d0c Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 16 Nov 2004 17:28:13 +0000 Subject: MTD: Fix detection of hardware partitions in Intel flash chips Determine it from the CFI query data instead of hard-coding it. Signed-off-by: Nicolas Pitre Signed-off-by: David Woodhouse --- drivers/mtd/chips/cfi_cmdset_0001.c | 131 +++++++++++++++++++++++++++++------- include/linux/mtd/cfi.h | 20 +++++- 2 files changed, 125 insertions(+), 26 deletions(-) (limited to 'include/linux') diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index ddf888624bf2..9028cacedd1b 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -6,6 +6,7 @@ * * $Id: cfi_cmdset_0001.c,v 1.160 2004/11/01 06:02:24 nico Exp $ * (+ suspend fix from v1.162) + * (+ partition detection fix from v1.163) * * 10/10/2000 Nicolas Pitre * - completely revamped method functions so they are aware and @@ -62,7 +63,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 mtd_info *); -static int cfi_intelext_partition_fixup(struct map_info *, struct cfi_private **); +static int cfi_intelext_partition_fixup(struct mtd_info *, struct cfi_private **); static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf); @@ -212,6 +213,66 @@ static struct cfi_fixup fixup_table[] = { { 0, 0, NULL, NULL } }; +static inline struct cfi_pri_intelext * +read_pri_intelext(struct map_info *map, __u16 adr) +{ + struct cfi_pri_intelext *extp; + unsigned int extp_size = sizeof(*extp); + + again: + extp = (struct cfi_pri_intelext *)cfi_read_pri(map, adr, extp_size, "Intel/Sharp"); + if (!extp) + return NULL; + + /* Do some byteswapping if necessary */ + extp->FeatureSupport = le32_to_cpu(extp->FeatureSupport); + extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask); + extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr); + + if (extp->MajorVersion == '1' && extp->MinorVersion == '3') { + unsigned int extra_size = 0; + int nb_parts, i; + + /* Protection Register info */ + extra_size += (extp->NumProtectionFields - 1) * (4 + 6); + + /* Burst Read info */ + extra_size += 6; + + /* Number of hardware-partitions */ + extra_size += 1; + if (extp_size < sizeof(*extp) + extra_size) + goto need_more; + nb_parts = extp->extra[extra_size - 1]; + + for (i = 0; i < nb_parts; i++) { + struct cfi_intelext_regioninfo *rinfo; + rinfo = (struct cfi_intelext_regioninfo *)&extp->extra[extra_size]; + extra_size += sizeof(*rinfo); + if (extp_size < sizeof(*extp) + extra_size) + goto need_more; + rinfo->NumIdentPartitions=le16_to_cpu(rinfo->NumIdentPartitions); + extra_size += (rinfo->NumBlockTypes - 1) + * sizeof(struct cfi_intelext_blockinfo); + } + + if (extp_size < sizeof(*extp) + extra_size) { + need_more: + extp_size = sizeof(*extp) + extra_size; + kfree(extp); + if (extp_size > 4096) { + printk(KERN_ERR + "%s: cfi_pri_intelext is too fat\n", + __FUNCTION__); + return NULL; + } + goto again; + } + } + + return extp; +} + /* This routine is made available to other mtd code via * inter_module_register. It must only be accessed through * inter_module_get which will bump the use count of this module. The @@ -255,22 +316,17 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR; struct cfi_pri_intelext *extp; - extp = (struct cfi_pri_intelext*)cfi_read_pri(map, adr, sizeof(*extp), "Intel/Sharp"); + extp = read_pri_intelext(map, adr); if (!extp) { kfree(mtd); return NULL; } - - /* Do some byteswapping if necessary */ - extp->FeatureSupport = le32_to_cpu(extp->FeatureSupport); - extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask); - extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr); /* Install our own private info structure */ cfi->cmdset_priv = extp; cfi_fixup(mtd, cfi_fixup_table); - + #ifdef DEBUG_CFI_FEATURES /* Tell the user about it in lots of lovely detail */ cfi_tell_features(extp); @@ -355,7 +411,7 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd) /* This function has the potential to distort the reality a bit and therefore should be called last. */ - if (cfi_intelext_partition_fixup(map, &cfi) != 0) + if (cfi_intelext_partition_fixup(mtd, &cfi) != 0) goto setup_err; __module_get(THIS_MODULE); @@ -371,20 +427,16 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd) return NULL; } -static int cfi_intelext_partition_fixup(struct map_info *map, +static int cfi_intelext_partition_fixup(struct mtd_info *mtd, struct cfi_private **pcfi) { + struct map_info *map = mtd->priv; struct cfi_private *cfi = *pcfi; struct cfi_pri_intelext *extp = cfi->cmdset_priv; /* * Probing of multi-partition flash ships. * - * This is extremely crude at the moment and should probably be - * extracted entirely from the Intel extended query data instead. - * Right now a L18 flash is assumed if multiple operations is - * detected. - * * To support multiple partitions when available, we simply arrange * for each of them to have their own flchip structure even if they * are on the same physical chip. This means completely recreating @@ -393,20 +445,49 @@ static int cfi_intelext_partition_fixup(struct map_info *map, * arrangement at this point. This can be rearranged in the future * if someone feels motivated enough. --nico */ - if (extp && extp->FeatureSupport & (1 << 9)) { + if (extp && extp->MajorVersion == '1' && extp->MinorVersion == '3' + && extp->FeatureSupport & (1 << 9)) { struct cfi_private *newcfi; struct flchip *chip; struct flchip_shared *shared; - int numparts, partshift, numvirtchips, i, j; + int offs, numregions, numparts, partshift, numvirtchips, i, j; + + /* Protection Register info */ + offs = (extp->NumProtectionFields - 1) * (4 + 6); + + /* Burst Read info */ + offs += 6; + + /* Number of partition regions */ + numregions = extp->extra[offs]; + offs += 1; + + /* Number of hardware partitions */ + numparts = 0; + for (i = 0; i < numregions; i++) { + struct cfi_intelext_regioninfo *rinfo; + rinfo = (struct cfi_intelext_regioninfo *)&extp->extra[offs]; + numparts += rinfo->NumIdentPartitions; + offs += sizeof(*rinfo) + + (rinfo->NumBlockTypes - 1) * + sizeof(struct cfi_intelext_blockinfo); + } /* - * The L18 flash memory array is divided - * into multiple 8-Mbit partitions. + * All functions below currently rely on all chips having + * the same geometry so we'll just assume that all hardware + * partitions are of the same size too. */ - numparts = 1 << (cfi->cfiq->DevSize - 20); - partshift = 20 + __ffs(cfi->interleave); - numvirtchips = cfi->numchips * numparts; + partshift = cfi->chipshift - __ffs(numparts); + if ((1 << partshift) < mtd->erasesize) { + printk( KERN_ERR + "%s: bad number of hw partitions (%d)\n", + __FUNCTION__, numparts); + return -EINVAL; + } + + numvirtchips = cfi->numchips * numparts; newcfi = kmalloc(sizeof(struct cfi_private) + numvirtchips * sizeof(struct flchip), GFP_KERNEL); if (!newcfi) return -ENOMEM; @@ -436,10 +517,10 @@ static int cfi_intelext_partition_fixup(struct map_info *map, } } - printk(KERN_DEBUG "%s: %d sets of %d interleaved chips " - "--> %d partitions of %#x bytes\n", + printk(KERN_DEBUG "%s: %d set(s) of %d interleaved chips " + "--> %d partitions of %d KiB\n", map->name, cfi->numchips, cfi->interleave, - newcfi->numchips, 1<chipshift); + newcfi->numchips, 1<<(newcfi->chipshift-10)); map->fldrv_priv = newcfi; *pcfi = newcfi; diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index 284f24851f1d..ba4b0d649661 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.48 2004/10/20 23:08:05 dwmw2 Exp $ + * $Id: cfi.h,v 1.49 2004/11/15 20:56:32 nico Exp $ */ #ifndef __MTD_CFI_H__ @@ -145,6 +145,24 @@ struct cfi_pri_intelext { uint16_t ProtRegAddr; uint8_t FactProtRegSize; uint8_t UserProtRegSize; + uint8_t extra[0]; +} __attribute__((packed)); + +struct cfi_intelext_blockinfo { + uint16_t NumIdentBlocks; + uint16_t BlockSize; + uint16_t MinBlockEraseCycles; + uint8_t BitsPerCell; + uint8_t BlockCap; +} __attribute__((packed)); + +struct cfi_intelext_regioninfo { + uint16_t NumIdentPartitions; + uint8_t NumOpAllowed; + uint8_t NumOpAllowedSimProgMode; + uint8_t NumOpAllowedSimEraMode; + uint8_t NumBlockTypes; + struct cfi_intelext_blockinfo BlockTypes[1]; } __attribute__((packed)); /* Vendor-Specific PRI for AMD/Fujitsu Extended Command Set (0x0002) */ -- cgit v1.2.3 From d8225be03c2605158f888c0b66643577b985e489 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 16 Nov 2004 17:45:47 +0000 Subject: JFFS2: jffs2_fs_i.h needs ... and should include it directly rather than hoping it's been done. Signed-off-by: David Woodhouse --- include/linux/jffs2_fs_i.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/jffs2_fs_i.h b/include/linux/jffs2_fs_i.h index 14743de6cf59..6dbb1cce6646 100644 --- a/include/linux/jffs2_fs_i.h +++ b/include/linux/jffs2_fs_i.h @@ -1,10 +1,11 @@ -/* $Id: jffs2_fs_i.h,v 1.16 2003/01/09 14:03:21 dwmw2 Exp $ */ +/* $Id: jffs2_fs_i.h,v 1.17 2004/11/11 23:51:27 dwmw2 Exp $ */ #ifndef _JFFS2_FS_I #define _JFFS2_FS_I #include #include +#include struct jffs2_inode_info { /* We need an internal semaphore similar to inode->i_sem. -- cgit v1.2.3 From e613797c6714a081efbad9a53c3bf841187bc17c Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 16 Nov 2004 18:36:59 +0000 Subject: MTD: some cleanups The patch below makes the following cleanups for code under drivers/mtd/ : - make some needlessly global code static Signed-off-by: Adrian Bunk Signed-off-by: David Woodhouse --- drivers/mtd/chips/cfi_cmdset_0002.c | 4 ++-- drivers/mtd/chips/cfi_cmdset_0020.c | 4 ++-- drivers/mtd/chips/chipreg.c | 4 ++-- drivers/mtd/chips/jedec_probe.c | 8 ++++---- drivers/mtd/chips/map_absent.c | 4 ++-- drivers/mtd/chips/map_ram.c | 4 ++-- drivers/mtd/chips/map_rom.c | 8 ++++---- drivers/mtd/cmdlinepart.c | 4 ++-- drivers/mtd/devices/blkmtd.c | 12 ++++++------ drivers/mtd/devices/doc2000.c | 4 ++-- drivers/mtd/devices/doc2001.c | 4 ++-- drivers/mtd/devices/doc2001plus.c | 4 ++-- drivers/mtd/devices/docprobe.c | 4 ++-- drivers/mtd/devices/mtdram.c | 8 ++++---- drivers/mtd/devices/phram.c | 14 +++++++------- drivers/mtd/devices/pmc551.c | 4 ++-- drivers/mtd/devices/slram.c | 32 ++++++++++++++++---------------- drivers/mtd/inftlcore.c | 10 +++++----- drivers/mtd/maps/amd76xrom.c | 4 ++-- drivers/mtd/maps/elan-104nc.c | 4 ++-- drivers/mtd/maps/ichxrom.c | 4 ++-- drivers/mtd/maps/l440gx.c | 6 +++--- drivers/mtd/maps/pnc2000.c | 6 +++--- drivers/mtd/maps/sbc_gxx.c | 4 ++-- drivers/mtd/maps/scb2_flash.c | 4 ++-- drivers/mtd/maps/scx200_docflash.c | 4 ++-- drivers/mtd/mtd_blkdevs.c | 10 +++++----- drivers/mtd/mtdblock.c | 6 +++--- drivers/mtd/mtdblock.h | 35 ----------------------------------- drivers/mtd/mtdblock_ro.c | 4 ++-- drivers/mtd/mtdcore.c | 4 ++-- drivers/mtd/mtdpart.c | 4 ++-- drivers/mtd/nand/diskonchip.c | 6 +++--- drivers/mtd/nftlcore.c | 10 +++++----- include/linux/mtd/partitions.h | 3 +-- 35 files changed, 109 insertions(+), 145 deletions(-) delete mode 100644 drivers/mtd/mtdblock.h (limited to 'include/linux') diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 1f9fe2ae780b..69a612659813 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.110 2004/09/24 04:26:04 eric Exp $ + * $Id: cfi_cmdset_0002.c,v 1.111 2004/11/16 18:29:00 dwmw2 Exp $ * */ @@ -1506,7 +1506,7 @@ static void cfi_amdstd_destroy(struct mtd_info *mtd) static char im_name[]="cfi_cmdset_0002"; -int __init cfi_amdstd_init(void) +static int __init cfi_amdstd_init(void) { inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0002); return 0; diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index 326eaf7a2bbb..e5957ceaa022 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c @@ -4,7 +4,7 @@ * * (C) 2000 Red Hat. GPL'd * - * $Id: cfi_cmdset_0020.c,v 1.15 2004/08/09 13:19:43 dwmw2 Exp $ + * $Id: cfi_cmdset_0020.c,v 1.16 2004/11/16 18:29:00 dwmw2 Exp $ * * 10/10/2000 Nicolas Pitre * - completely revamped method functions so they are aware and @@ -1401,7 +1401,7 @@ static void cfi_staa_destroy(struct mtd_info *mtd) static char im_name[]="cfi_cmdset_0020"; -int __init cfi_staa_init(void) +static int __init cfi_staa_init(void) { inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0020); return 0; diff --git a/drivers/mtd/chips/chipreg.c b/drivers/mtd/chips/chipreg.c index 1e45df074ee3..cd699cb3c7da 100644 --- a/drivers/mtd/chips/chipreg.c +++ b/drivers/mtd/chips/chipreg.c @@ -1,5 +1,5 @@ /* - * $Id: chipreg.c,v 1.16 2003/05/29 09:36:15 dwmw2 Exp $ + * $Id: chipreg.c,v 1.17 2004/11/16 18:29:00 dwmw2 Exp $ * * Registration for chip drivers * @@ -15,7 +15,7 @@ #include #include -spinlock_t chip_drvs_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t chip_drvs_lock = SPIN_LOCK_UNLOCKED; static LIST_HEAD(chip_drvs_list); void register_mtd_chip_driver(struct mtd_chip_driver *drv) diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index 250d038d2775..3e232fd0f7c5 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.57 2004/09/17 11:45:05 eric Exp $ + $Id: jedec_probe.c,v 1.58 2004/11/16 18:29:00 dwmw2 Exp $ See JEDEC (http://www.jedec.org/) standard JESD21C (section 3.5) for the standard this probe goes back to. @@ -1661,7 +1661,7 @@ static int cfi_jedec_setup(struct cfi_private *p_cfi, int index); static int jedec_probe_chip(struct map_info *map, __u32 base, unsigned long *chip_map, struct cfi_private *cfi); -struct mtd_info *jedec_probe(struct map_info *map); +static struct mtd_info *jedec_probe(struct map_info *map); static inline u32 jedec_read_mfr(struct map_info *map, __u32 base, struct cfi_private *cfi) @@ -2055,7 +2055,7 @@ static struct chip_probe jedec_chip_probe = { .probe_chip = jedec_probe_chip }; -struct mtd_info *jedec_probe(struct map_info *map) +static struct mtd_info *jedec_probe(struct map_info *map) { /* * Just use the generic probe stuff to call our CFI-specific @@ -2070,7 +2070,7 @@ static struct mtd_chip_driver jedec_chipdrv = { .module = THIS_MODULE }; -int __init jedec_probe_init(void) +static int __init jedec_probe_init(void) { register_mtd_chip_driver(&jedec_chipdrv); return 0; diff --git a/drivers/mtd/chips/map_absent.c b/drivers/mtd/chips/map_absent.c index f9ff6f02c79b..c6c83833cc32 100644 --- a/drivers/mtd/chips/map_absent.c +++ b/drivers/mtd/chips/map_absent.c @@ -1,7 +1,7 @@ /* * Common code to handle absent "placeholder" devices * Copyright 2001 Resilience Corporation - * $Id: map_absent.c,v 1.4 2003/05/28 12:51:49 dwmw2 Exp $ + * $Id: map_absent.c,v 1.5 2004/11/16 18:29:00 dwmw2 Exp $ * * This map driver is used to allocate "placeholder" MTD * devices on systems that have socketed/removable media. @@ -98,7 +98,7 @@ static void map_absent_destroy(struct mtd_info *mtd) /* nop */ } -int __init map_absent_init(void) +static int __init map_absent_init(void) { register_mtd_chip_driver(&map_absent_chipdrv); return 0; diff --git a/drivers/mtd/chips/map_ram.c b/drivers/mtd/chips/map_ram.c index 283be02dc311..c5e8f520c60d 100644 --- a/drivers/mtd/chips/map_ram.c +++ b/drivers/mtd/chips/map_ram.c @@ -1,7 +1,7 @@ /* * Common code to handle map devices which are simple RAM * (C) 2000 Red Hat. GPL'd. - * $Id: map_ram.c,v 1.20 2004/08/09 13:19:43 dwmw2 Exp $ + * $Id: map_ram.c,v 1.21 2004/11/16 18:29:00 dwmw2 Exp $ */ #include @@ -124,7 +124,7 @@ static void mapram_nop(struct mtd_info *mtd) /* Nothing to see here */ } -int __init map_ram_init(void) +static int __init map_ram_init(void) { register_mtd_chip_driver(&mapram_chipdrv); return 0; diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c index db2e2c6a1fcb..540f90348e4b 100644 --- a/drivers/mtd/chips/map_rom.c +++ b/drivers/mtd/chips/map_rom.c @@ -1,7 +1,7 @@ /* * Common code to handle map devices which are simple ROM * (C) 2000 Red Hat. GPL'd. - * $Id: map_rom.c,v 1.21 2004/07/12 14:06:01 dwmw2 Exp $ + * $Id: map_rom.c,v 1.22 2004/11/16 18:29:00 dwmw2 Exp $ */ #include @@ -19,7 +19,7 @@ static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); static void maprom_nop (struct mtd_info *); -struct mtd_info *map_rom_probe(struct map_info *map); +static struct mtd_info *map_rom_probe(struct map_info *map); static struct mtd_chip_driver maprom_chipdrv = { .probe = map_rom_probe, @@ -27,7 +27,7 @@ static struct mtd_chip_driver maprom_chipdrv = { .module = THIS_MODULE }; -struct mtd_info *map_rom_probe(struct map_info *map) +static struct mtd_info *map_rom_probe(struct map_info *map) { struct mtd_info *mtd; @@ -75,7 +75,7 @@ static int maprom_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *re return -EIO; } -int __init map_rom_init(void) +static int __init map_rom_init(void) { register_mtd_chip_driver(&maprom_chipdrv); return 0; diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index 1be353fb7aa3..d5ef1e75b1bc 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c @@ -1,5 +1,5 @@ /* - * $Id: cmdlinepart.c,v 1.15 2004/09/21 12:11:41 lavinen Exp $ + * $Id: cmdlinepart.c,v 1.16 2004/11/16 18:28:59 dwmw2 Exp $ * * Read flash partition table from command line * @@ -339,7 +339,7 @@ static int parse_cmdline_partitions(struct mtd_info *master, * main.c::checksetup(). Note that we can not yet kmalloc() anything, * so we only save the commandline for later processing. */ -int mtdpart_setup(char *s) +static int mtdpart_setup(char *s) { cmdline = s; return 1; diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c index a3eb97a9490f..80d3393ee817 100644 --- a/drivers/mtd/devices/blkmtd.c +++ b/drivers/mtd/devices/blkmtd.c @@ -1,5 +1,5 @@ /* - * $Id: blkmtd.c,v 1.23 2004/08/09 14:03:19 dwmw2 Exp $ + * $Id: blkmtd.c,v 1.24 2004/11/16 18:29:01 dwmw2 Exp $ * * blkmtd.c - use a block device as a fake MTD * @@ -39,7 +39,7 @@ /* Default erase size in K, always make it a multiple of PAGE_SIZE */ #define CONFIG_MTD_BLKDEV_ERASESIZE (128 << 10) /* 128KiB */ -#define VERSION "$Revision: 1.23 $" +#define VERSION "$Revision: 1.24 $" /* Info for the block device */ struct blkmtd_dev { @@ -59,10 +59,10 @@ static void blkmtd_sync(struct mtd_info *mtd); #define MAX_DEVICES 4 /* Module parameters passed by insmod/modprobe */ -char *device[MAX_DEVICES]; /* the block device to use */ -int erasesz[MAX_DEVICES]; /* optional default erase size */ -int ro[MAX_DEVICES]; /* optional read only flag */ -int sync; +static char *device[MAX_DEVICES]; /* the block device to use */ +static int erasesz[MAX_DEVICES]; /* optional default erase size */ +static int ro[MAX_DEVICES]; /* optional read only flag */ +static int sync; MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index 3a7826e00b18..bab10603328c 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c @@ -4,7 +4,7 @@ * (c) 1999 Machine Vision Holdings, Inc. * (c) 1999, 2000 David Woodhouse * - * $Id: doc2000.c,v 1.63 2004/09/16 23:51:56 gleixner Exp $ + * $Id: doc2000.c,v 1.64 2004/11/16 18:29:01 dwmw2 Exp $ */ #include @@ -1276,7 +1276,7 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr) * ****************************************************************************/ -int __init init_doc2000(void) +static int __init init_doc2000(void) { inter_module_register(im_name, THIS_MODULE, &DoC2k_init); return 0; diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c index 059e7f273363..8dc06062992c 100644 --- a/drivers/mtd/devices/doc2001.c +++ b/drivers/mtd/devices/doc2001.c @@ -4,7 +4,7 @@ * (c) 1999 Machine Vision Holdings, Inc. * (c) 1999, 2000 David Woodhouse * - * $Id: doc2001.c,v 1.45 2004/09/16 23:51:57 gleixner Exp $ + * $Id: doc2001.c,v 1.46 2004/11/16 18:29:01 dwmw2 Exp $ */ #include @@ -856,7 +856,7 @@ int doc_erase (struct mtd_info *mtd, struct erase_info *instr) * ****************************************************************************/ -int __init init_doc2001(void) +static int __init init_doc2001(void) { inter_module_register(im_name, THIS_MODULE, &DoCMil_init); return 0; diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c index 7963d924b81b..93087c5e8b9c 100644 --- a/drivers/mtd/devices/doc2001plus.c +++ b/drivers/mtd/devices/doc2001plus.c @@ -6,7 +6,7 @@ * (c) 1999 Machine Vision Holdings, Inc. * (c) 1999, 2000 David Woodhouse * - * $Id: doc2001plus.c,v 1.10 2004/09/16 23:51:57 gleixner Exp $ + * $Id: doc2001plus.c,v 1.11 2004/11/16 18:29:01 dwmw2 Exp $ * * Released under GPL */ @@ -1122,7 +1122,7 @@ int doc_erase(struct mtd_info *mtd, struct erase_info *instr) * ****************************************************************************/ -int __init init_doc2001plus(void) +static int __init init_doc2001plus(void) { inter_module_register(im_name, THIS_MODULE, &DoCMilPlus_init); return 0; diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c index 410e52c15125..12e71124f408 100644 --- a/drivers/mtd/devices/docprobe.c +++ b/drivers/mtd/devices/docprobe.c @@ -4,7 +4,7 @@ /* (C) 1999 Machine Vision Holdings, Inc. */ /* (C) 1999-2003 David Woodhouse */ -/* $Id: docprobe.c,v 1.42 2004/09/16 23:51:57 gleixner Exp $ */ +/* $Id: docprobe.c,v 1.43 2004/11/16 18:29:01 dwmw2 Exp $ */ @@ -328,7 +328,7 @@ static void __init DoC_Probe(unsigned long physadr) * ****************************************************************************/ -int __init init_doc(void) +static int __init init_doc(void) { int i; diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c index 5fe0a08655e2..aafe29b9d52f 100644 --- a/drivers/mtd/devices/mtdram.c +++ b/drivers/mtd/devices/mtdram.c @@ -1,6 +1,6 @@ /* * mtdram - a test mtd device - * $Id: mtdram.c,v 1.33 2004/08/09 13:19:44 dwmw2 Exp $ + * $Id: mtdram.c,v 1.34 2004/11/16 18:29:01 dwmw2 Exp $ * Author: Alexander Larsson * * Copyright (c) 1999 Alexander Larsson @@ -153,7 +153,7 @@ int mtdram_init_device(struct mtd_info *mtd, void *mapped_address, #if CONFIG_MTDRAM_TOTAL_SIZE > 0 #if CONFIG_MTDRAM_ABS_POS > 0 -int __init init_mtdram(void) +static int __init init_mtdram(void) { void *addr; int err; @@ -186,7 +186,7 @@ int __init init_mtdram(void) #else /* CONFIG_MTDRAM_ABS_POS > 0 */ -int __init init_mtdram(void) +static int __init init_mtdram(void) { void *addr; int err; @@ -220,7 +220,7 @@ int __init init_mtdram(void) #else /* CONFIG_MTDRAM_TOTAL_SIZE > 0 */ -int __init init_mtdram(void) +static int __init init_mtdram(void) { return 0; } diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index 03a955cdf17a..8aab73e6f26a 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c @@ -1,6 +1,6 @@ /** * - * $Id: phram.c,v 1.2 2004/08/09 13:19:44 dwmw2 Exp $ + * $Id: phram.c,v 1.3 2004/11/16 18:29:01 dwmw2 Exp $ * * Copyright (c) Jochen Schaeuble * 07/2003 rewritten by Joern Engel @@ -39,7 +39,7 @@ static LIST_HEAD(phram_list); -int phram_erase(struct mtd_info *mtd, struct erase_info *instr) +static int phram_erase(struct mtd_info *mtd, struct erase_info *instr) { u_char *start = (u_char *)mtd->priv; @@ -60,7 +60,7 @@ int phram_erase(struct mtd_info *mtd, struct erase_info *instr) return 0; } -int phram_point(struct mtd_info *mtd, loff_t from, size_t len, +static int phram_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf) { u_char *start = (u_char *)mtd->priv; @@ -73,11 +73,11 @@ int phram_point(struct mtd_info *mtd, loff_t from, size_t len, return 0; } -void phram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) +static void phram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) { } -int phram_read(struct mtd_info *mtd, loff_t from, size_t len, +static int phram_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { u_char *start = (u_char *)mtd->priv; @@ -91,7 +91,7 @@ int phram_read(struct mtd_info *mtd, loff_t from, size_t len, return 0; } -int phram_write(struct mtd_info *mtd, loff_t to, size_t len, +static int phram_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { u_char *start = (u_char *)mtd->priv; @@ -340,7 +340,7 @@ module_param_call(slram, slram_setup, NULL, NULL, 000); MODULE_PARM_DESC(slram, "List of memory regions to map. \"map=,\""); -int __init init_phram(void) +static int __init init_phram(void) { printk(KERN_ERR "phram loaded\n"); return 0; diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index c2c2a3c369b0..01c78f0dc772 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c @@ -1,5 +1,5 @@ /* - * $Id: pmc551.c,v 1.28 2004/08/09 13:19:44 dwmw2 Exp $ + * $Id: pmc551.c,v 1.29 2004/11/16 18:29:01 dwmw2 Exp $ * * PMC551 PCI Mezzanine Ram Device * @@ -648,7 +648,7 @@ static int asize=0; /* * PMC551 Card Initialization */ -int __init init_pmc551(void) +static int __init init_pmc551(void) { struct pci_dev *PCI_Device = NULL; struct mypriv *priv; diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c index fd579ae45dab..1caf00b8480b 100644 --- a/drivers/mtd/devices/slram.c +++ b/drivers/mtd/devices/slram.c @@ -1,6 +1,6 @@ /*====================================================================== - $Id: slram.c,v 1.31 2004/08/09 13:19:44 dwmw2 Exp $ + $Id: slram.c,v 1.32 2004/11/16 18:29:01 dwmw2 Exp $ This driver provides a method to access memory not used by the kernel itself (i.e. if the kernel commandline mem=xxx is used). To actually @@ -75,13 +75,13 @@ MODULE_PARM_DESC(map, "List of memory regions to map. \"map=, , priv; @@ -103,7 +103,7 @@ int slram_erase(struct mtd_info *mtd, struct erase_info *instr) return(0); } -int slram_point(struct mtd_info *mtd, loff_t from, size_t len, +static int slram_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf) { slram_priv_t *priv = (slram_priv_t *)mtd->priv; @@ -113,11 +113,11 @@ int slram_point(struct mtd_info *mtd, loff_t from, size_t len, return(0); } -void slram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) +static void slram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) { } -int slram_read(struct mtd_info *mtd, loff_t from, size_t len, +static int slram_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { slram_priv_t *priv = (slram_priv_t *)mtd->priv; @@ -128,7 +128,7 @@ int slram_read(struct mtd_info *mtd, loff_t from, size_t len, return(0); } -int slram_write(struct mtd_info *mtd, loff_t to, size_t len, +static int slram_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { slram_priv_t *priv = (slram_priv_t *)mtd->priv; @@ -141,7 +141,7 @@ int slram_write(struct mtd_info *mtd, loff_t to, size_t len, /*====================================================================*/ -int register_device(char *name, unsigned long start, unsigned long length) +static int register_device(char *name, unsigned long start, unsigned long length) { slram_mtd_list_t **curmtd; @@ -213,7 +213,7 @@ int register_device(char *name, unsigned long start, unsigned long length) return(0); } -void unregister_devices(void) +static void unregister_devices(void) { slram_mtd_list_t *nextitem; @@ -228,7 +228,7 @@ void unregister_devices(void) } } -unsigned long handle_unit(unsigned long value, char *unit) +static unsigned long handle_unit(unsigned long value, char *unit) { if ((*unit == 'M') || (*unit == 'm')) { return(value * 1024 * 1024); @@ -238,7 +238,7 @@ unsigned long handle_unit(unsigned long value, char *unit) return(value); } -int parse_cmdline(char *devname, char *szstart, char *szlength) +static int parse_cmdline(char *devname, char *szstart, char *szlength) { char *buffer; unsigned long devstart; @@ -285,7 +285,7 @@ __setup("slram=", mtd_slram_setup); #endif -int init_slram(void) +static int init_slram(void) { char *devname; int i; diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index ea32c03e670c..39eb53f6551f 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c @@ -7,7 +7,7 @@ * (c) 1999 Machine Vision Holdings, Inc. * Author: David Woodhouse * - * $Id: inftlcore.c,v 1.17 2004/08/09 13:56:48 dwmw2 Exp $ + * $Id: inftlcore.c,v 1.18 2004/11/16 18:28:59 dwmw2 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 @@ -352,7 +352,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned return targetEUN; } -u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock) +static u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock) { /* * This is the part that needs some cleverness applied. @@ -877,7 +877,7 @@ static int inftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) return 0; } -struct mtd_blktrans_ops inftl_tr = { +static struct mtd_blktrans_ops inftl_tr = { .name = "inftl", .major = INFTL_MAJOR, .part_bits = INFTL_PARTN_BITS, @@ -891,9 +891,9 @@ struct mtd_blktrans_ops inftl_tr = { extern char inftlmountrev[]; -int __init init_inftl(void) +static int __init init_inftl(void) { - printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.17 $, " + printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.18 $, " "inftlmount.c %s\n", inftlmountrev); return register_mtd_blktrans(&inftl_tr); diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c index cde413dbd846..5d732c4b21fa 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.17 2004/09/18 01:59:56 eric Exp $ + * $Id: amd76xrom.c,v 1.18 2004/11/16 18:29:02 dwmw2 Exp $ */ #include @@ -298,7 +298,7 @@ static struct pci_driver amd76xrom_driver = { }; #endif -int __init init_amd76xrom(void) +static int __init init_amd76xrom(void) { struct pci_dev *pdev; struct pci_device_id *id; diff --git a/drivers/mtd/maps/elan-104nc.c b/drivers/mtd/maps/elan-104nc.c index 52962155fb33..d77dfbdf440a 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.23 2004/11/04 13:24:14 gleixner Exp $ + $Id: elan-104nc.c,v 1.24 2004/11/16 18:29:02 dwmw2 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. @@ -185,7 +185,7 @@ static void cleanup_elan_104nc(void) iounmap((void *)iomapadr); } -int __init init_elan_104nc(void) +static 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. */ diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c index 03a5d772f56a..0e105f7720eb 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.14 2004/09/18 01:59:56 eric Exp $ + * $Id: ichxrom.c,v 1.15 2004/11/16 18:29:02 dwmw2 Exp $ */ #include @@ -349,7 +349,7 @@ static struct pci_driver ichxrom_driver = { }; #endif -int __init init_ichxrom(void) +static int __init init_ichxrom(void) { struct pci_dev *pdev; struct pci_device_id *id; diff --git a/drivers/mtd/maps/l440gx.c b/drivers/mtd/maps/l440gx.c index c87a38ae886b..b5b468a85797 100644 --- a/drivers/mtd/maps/l440gx.c +++ b/drivers/mtd/maps/l440gx.c @@ -1,5 +1,5 @@ /* - * $Id: l440gx.c,v 1.15 2004/11/04 13:24:15 gleixner Exp $ + * $Id: l440gx.c,v 1.16 2004/11/16 18:29:02 dwmw2 Exp $ * * BIOS Flash chip on Intel 440GX board. * @@ -30,7 +30,7 @@ static struct mtd_info *mymtd; /* Is this really the vpp port? */ -void l440gx_set_vpp(struct map_info *map, int vpp) +static void l440gx_set_vpp(struct map_info *map, int vpp) { unsigned long l; @@ -43,7 +43,7 @@ void l440gx_set_vpp(struct map_info *map, int vpp) outl(l, VPP_PORT); } -struct map_info l440gx_map = { +static struct map_info l440gx_map = { .name = "L440GX BIOS", .size = WINDOW_SIZE, .bankwidth = BUSWIDTH, diff --git a/drivers/mtd/maps/pnc2000.c b/drivers/mtd/maps/pnc2000.c index 3636d5a23c9a..a0f43dad8985 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.16 2004/09/16 23:27:13 gleixner Exp $ + * $Id: pnc2000.c,v 1.17 2004/11/16 18:29:02 dwmw2 Exp $ */ #include @@ -26,7 +26,7 @@ */ -struct map_info pnc_map = { +static struct map_info pnc_map = { .name = "PNC-2000", .size = WINDOW_SIZE, .bankwidth = 4, @@ -62,7 +62,7 @@ static struct mtd_partition pnc_partitions[3] = { */ static struct mtd_info *mymtd; -int __init init_pnc2000(void) +static int __init init_pnc2000(void) { printk(KERN_NOTICE "Photron PNC-2000 flash mapping: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); diff --git a/drivers/mtd/maps/sbc_gxx.c b/drivers/mtd/maps/sbc_gxx.c index f94d39dc7e86..e5b1c2066419 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.31 2004/11/04 13:24:15 gleixner Exp $ + $Id: sbc_gxx.c,v 1.32 2004/11/16 18:29:02 dwmw2 Exp $ The SBC-MediaGX / SBC-GXx has up to 16 MiB of Intel StrataFlash (28F320/28F640) in x8 mode. @@ -193,7 +193,7 @@ static void cleanup_sbc_gxx(void) release_region(PAGE_IO,PAGE_IO_SIZE); } -int __init init_sbc_gxx(void) +static int __init init_sbc_gxx(void) { iomapadr = ioremap(WINDOW_START, WINDOW_LENGTH); if (!iomapadr) { diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c index 288e4e19eb72..7231cafe7872 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.9 2004/09/16 23:27:14 gleixner Exp $ + * $Id: scb2_flash.c,v 1.10 2004/11/16 18:29:02 dwmw2 Exp $ * Copyright (C) 2002 Sun Microsystems, Inc. * Tim Hockin * @@ -64,7 +64,7 @@ static void *scb2_ioaddr; static struct mtd_info *scb2_mtd; -struct map_info scb2_map = { +static struct map_info scb2_map = { .name = "SCB2 BIOS Flash", .size = 0, .bankwidth = 1, diff --git a/drivers/mtd/maps/scx200_docflash.c b/drivers/mtd/maps/scx200_docflash.c index e165a516b9a1..9b106315905e 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.8 2004/11/04 13:24:15 gleixner Exp $ + $Id: scx200_docflash.c,v 1.9 2004/11/16 18:29:02 dwmw2 Exp $ National Semiconductor SCx200 flash mapped with DOCCS */ @@ -81,7 +81,7 @@ static struct map_info scx200_docflash_map = { .name = "NatSemi SCx200 DOCCS Flash", }; -int __init init_scx200_docflash(void) +static int __init init_scx200_docflash(void) { unsigned u; unsigned base; diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 2a417942f344..f8d2185819e7 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -1,5 +1,5 @@ /* - * $Id: mtd_blkdevs.c,v 1.23 2004/08/19 01:54:36 tpoynor Exp $ + * $Id: mtd_blkdevs.c,v 1.24 2004/11/16 18:28:59 dwmw2 Exp $ * * (C) 2003 David Woodhouse * @@ -143,7 +143,7 @@ static void mtd_blktrans_request(struct request_queue *rq) } -int blktrans_open(struct inode *i, struct file *f) +static int blktrans_open(struct inode *i, struct file *f) { struct mtd_blktrans_dev *dev; struct mtd_blktrans_ops *tr; @@ -174,7 +174,7 @@ int blktrans_open(struct inode *i, struct file *f) return ret; } -int blktrans_release(struct inode *i, struct file *f) +static int blktrans_release(struct inode *i, struct file *f) { struct mtd_blktrans_dev *dev; struct mtd_blktrans_ops *tr; @@ -326,7 +326,7 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) return 0; } -void blktrans_notify_remove(struct mtd_info *mtd) +static void blktrans_notify_remove(struct mtd_info *mtd) { struct list_head *this, *this2, *next; @@ -342,7 +342,7 @@ void blktrans_notify_remove(struct mtd_info *mtd) } } -void blktrans_notify_add(struct mtd_info *mtd) +static void blktrans_notify_add(struct mtd_info *mtd) { struct list_head *this; diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index c91d9701ef71..d6b9207863ff 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c @@ -1,7 +1,7 @@ /* * Direct MTD block device access * - * $Id: mtdblock.c,v 1.64 2003/10/04 17:14:14 dwmw2 Exp $ + * $Id: mtdblock.c,v 1.65 2004/11/16 18:28:59 dwmw2 Exp $ * * (C) 2000-2003 Nicolas Pitre * (C) 1999-2003 David Woodhouse @@ -361,7 +361,7 @@ static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev) kfree(dev); } -struct mtd_blktrans_ops mtdblock_tr = { +static struct mtd_blktrans_ops mtdblock_tr = { .name = "mtdblock", .major = 31, .part_bits = 0, @@ -375,7 +375,7 @@ struct mtd_blktrans_ops mtdblock_tr = { .owner = THIS_MODULE, }; -int __init init_mtdblock(void) +static int __init init_mtdblock(void) { return register_mtd_blktrans(&mtdblock_tr); } diff --git a/drivers/mtd/mtdblock.h b/drivers/mtd/mtdblock.h deleted file mode 100644 index f4c77fe41f92..000000000000 --- a/drivers/mtd/mtdblock.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * drivers/mtd/mtdblock.h - * - * common defines for mtdblock-core and mtdblock-2x - * - * $Id: mtdblock.h,v 1.1 2002/11/27 10:33:37 gleixner Exp $ - * - */ - -#ifndef __MTD_MTDBLOCK_H__ -#define __MTD_MTDBLOCK_H__ - -#define MAJOR_NR MTD_BLOCK_MAJOR -#define DEVICE_NAME "mtdblock" - -struct mtdblk_dev { - struct mtd_info *mtd; /* Locked */ - int count; - struct semaphore cache_sem; - unsigned char *cache_data; - unsigned long cache_offset; - unsigned int cache_size; - enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state; -}; - -extern int write_cached_data (struct mtdblk_dev *mtdblk); -extern int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, - int len, const char *buf); -extern int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, - int len, char *buf); - -extern void __exit cleanup_mtdblock(void); -extern int __init init_mtdblock(void); - -#endif diff --git a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c index cdd4ce1df205..0c830ba41ef0 100644 --- a/drivers/mtd/mtdblock_ro.c +++ b/drivers/mtd/mtdblock_ro.c @@ -1,5 +1,5 @@ /* - * $Id: mtdblock_ro.c,v 1.18 2003/06/23 12:00:08 dwmw2 Exp $ + * $Id: mtdblock_ro.c,v 1.19 2004/11/16 18:28:59 dwmw2 Exp $ * * (C) 2003 David Woodhouse * @@ -58,7 +58,7 @@ static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev) kfree(dev); } -struct mtd_blktrans_ops mtdblock_tr = { +static struct mtd_blktrans_ops mtdblock_tr = { .name = "mtdblock", .major = 31, .part_bits = 0, diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 842e7412fd5e..9c0315d1b1c4 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -1,5 +1,5 @@ /* - * $Id: mtdcore.c,v 1.43 2004/07/23 15:20:46 dwmw2 Exp $ + * $Id: mtdcore.c,v 1.44 2004/11/16 18:28:59 dwmw2 Exp $ * * Core registration and callback routines for MTD * drivers and users. @@ -382,7 +382,7 @@ done: /*====================================================================*/ /* Init code */ -int __init init_mtd(void) +static int __init init_mtd(void) { #ifdef CONFIG_PROC_FS if ((proc_mtd = create_proc_entry( "mtd", 0, NULL ))) diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index c3369e0aa5c3..d4547651dfe7 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -5,7 +5,7 @@ * * This code is GPL * - * $Id: mtdpart.c,v 1.50 2004/08/10 16:18:34 dwmw2 Exp $ + * $Id: mtdpart.c,v 1.51 2004/11/16 18:28:59 dwmw2 Exp $ * * 02-21-2002 Thomas Gleixner * added support for read_oob, write_oob @@ -526,7 +526,7 @@ EXPORT_SYMBOL(del_mtd_partitions); static spinlock_t part_parser_lock = SPIN_LOCK_UNLOCKED; static LIST_HEAD(part_parsers); -struct mtd_part_parser *get_partition_parser(const char *name) +static struct mtd_part_parser *get_partition_parser(const char *name) { struct list_head *this; void *ret = NULL; diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 7377015385d7..f2116fa8e919 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -16,7 +16,7 @@ * * Interface to generic NAND code for M-Systems DiskOnChip devices * - * $Id: diskonchip.c,v 1.41 2004/11/05 16:07:16 kalev Exp $ + * $Id: diskonchip.c,v 1.42 2004/11/16 18:29:03 dwmw2 Exp $ */ #include @@ -1720,7 +1720,7 @@ static void release_nanddoc(void) } } -int __init init_nanddoc(void) +static int __init init_nanddoc(void) { int i, ret = 0; @@ -1762,7 +1762,7 @@ outerr: return ret; } -void __exit cleanup_nanddoc(void) +static void __exit cleanup_nanddoc(void) { /* Cleanup the nand/DoC resources */ release_nanddoc(); diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index 4102a67978d6..b2014043634f 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c @@ -1,7 +1,7 @@ /* Linux driver for NAND Flash Translation Layer */ /* (c) 1999 Machine Vision Holdings, Inc. */ /* Author: David Woodhouse */ -/* $Id: nftlcore.c,v 1.96 2004/06/28 13:52:55 dbrown Exp $ */ +/* $Id: nftlcore.c,v 1.97 2004/11/16 18:28:59 dwmw2 Exp $ */ /* The contents of this file are distributed under the GNU General @@ -421,7 +421,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p return targetEUN; } -u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock) +static u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock) { /* This is the part that needs some cleverness applied. For now, I'm doing the minimum applicable to actually @@ -731,7 +731,7 @@ static int nftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) ****************************************************************************/ -struct mtd_blktrans_ops nftl_tr = { +static struct mtd_blktrans_ops nftl_tr = { .name = "nftl", .major = NFTL_MAJOR, .part_bits = NFTL_PARTN_BITS, @@ -747,9 +747,9 @@ struct mtd_blktrans_ops nftl_tr = { extern char nftlmountrev[]; -int __init init_nftl(void) +static int __init init_nftl(void) { - printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.96 $, nftlmount.c %s\n", nftlmountrev); + printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.97 $, nftlmount.c %s\n", nftlmountrev); return register_mtd_blktrans(&nftl_tr); } diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h index 100ea79de16d..50b2edfc8f11 100644 --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h @@ -5,7 +5,7 @@ * * This code is GPL * - * $Id: partitions.h,v 1.15 2003/07/09 11:15:43 dwmw2 Exp $ + * $Id: partitions.h,v 1.16 2004/11/16 18:34:40 dwmw2 Exp $ */ #ifndef MTD_PARTITIONS_H @@ -64,7 +64,6 @@ struct mtd_part_parser { int (*parse_fn)(struct mtd_info *, struct mtd_partition **, unsigned long); }; -extern struct mtd_part_parser *get_partition_parser(const char *name); extern int register_mtd_parser(struct mtd_part_parser *parser); extern int deregister_mtd_parser(struct mtd_part_parser *parser); extern int parse_mtd_partitions(struct mtd_info *master, const char **types, -- cgit v1.2.3 From ce1061cb7ebe9c32d1948c166e217a64093aeb9f Mon Sep 17 00:00:00 2001 From: Thomas Leibold Date: Thu, 18 Nov 2004 17:14:38 -0800 Subject: [PATCH] I2C: i2c-nforce2.c add support for nForce3 Pro 150 MCP This is the all new and improved version of the patch: - following the advise from Jean Delvare I removed the redundant definition of the PCI IDs from the driver and just add them to the pci_ids.h file. - the patch is now created against linux 2.6.10-RC2. Signed-off-by: Thomas Leibold Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/Kconfig | 1 + drivers/i2c/busses/i2c-nforce2.c | 9 ++++----- include/linux/pci_ids.h | 2 ++ 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 47a6c1c7d7bd..d0e7da45523a 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -218,6 +218,7 @@ config I2C_NFORCE2 help If you say yes to this option, support will be included for the Nvidia Nforce2 family of mainboard I2C interfaces. + This driver also supports the nForce3 Pro 150 MCP. This driver can also be built as a module. If so, the module will be called i2c-nforce2. diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index e5ebc4bf8c06..e9a64f979083 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c @@ -1,6 +1,7 @@ /* SMBus driver for nVidia nForce2 MCP + Added nForce3 Pro 150 Thomas Leibold , Ported to 2.5 Patrick Dreker , Copyright (c) 2003 Hans-Frieder Vogt , Based on @@ -25,6 +26,7 @@ /* SUPPORTED DEVICES PCI ID nForce2 MCP 0064 + nForce3 Pro150 MCP 00D4 This driver supports the 2 SMBuses that are included in the MCP2 of the nForce2 chipset. @@ -49,11 +51,6 @@ MODULE_AUTHOR ("Hans-Frieder Vogt "); MODULE_DESCRIPTION("nForce2 SMBus driver"); -#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS -#define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS 0x0064 -#endif - - struct nforce2_smbus { struct pci_dev *dev; struct i2c_adapter adapter; @@ -294,6 +291,8 @@ static u32 nforce2_func(struct i2c_adapter *adapter) static struct pci_device_id nforce2_ids[] = { { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0 } }; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index c53d4c6e5824..e820dfb66b31 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1082,6 +1082,7 @@ #define PCI_DEVICE_ID_NVIDIA_NVENET_8 0x0056 #define PCI_DEVICE_ID_NVIDIA_NVENET_9 0x0057 #define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO 0x0059 +#define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS 0x0064 #define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE 0x0065 #define PCI_DEVICE_ID_NVIDIA_NVENET_2 0x0066 #define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO 0x006a @@ -1093,6 +1094,7 @@ #define PCI_DEVICE_ID_NVIDIA_NFORCE3 0x00d1 #define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO 0x00da #define PCI_DEVICE_ID_NVIDIA_NFORCE3S 0x00e1 +#define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS 0x00d4 #define PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE 0x00d5 #define PCI_DEVICE_ID_NVIDIA_NVENET_3 0x00d6 #define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO 0x00da -- cgit v1.2.3 From 5b6c534999948ad1032adc44fab17a6e01d0a29f Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 18 Nov 2004 22:53:42 -0800 Subject: [PATCH] early uart console support This adds an early polled-mode "uart" console driver, based on Andi Kleen's early_printk work. The difference is that this locates the UART device directly by its MMIO or I/O port address, so we don't have to make assumptions about how ttyS devices will be named. After the normal serial driver starts, we try to locate the matching ttyS device and start a console there. Sample usage: console=uart,io,0x3f8 console=uart,mmio,0xff5e0000,115200n8 If the baud rate isn't specified, we peek at the UART to figure it out. Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/kernel-parameters.txt | 20 ++- drivers/serial/8250.c | 35 +++++ drivers/serial/8250_early.c | 255 ++++++++++++++++++++++++++++++++++++ drivers/serial/Makefile | 1 + include/linux/serial.h | 2 + kernel/printk.c | 2 +- 6 files changed, 312 insertions(+), 3 deletions(-) create mode 100644 drivers/serial/8250_early.c (limited to 'include/linux') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 0ef66ae82467..2b76f4eb732f 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -312,8 +312,24 @@ running once the system is up. condev= [HW,S390] console device conmode= - console= [KNL] Output console - Console device and comm spec (speed, control, parity). + console= [KNL] Output console device and options. + + tty Use the virtual console device . + + ttyS[,options] + Use the specified serial port. The options are of + the form "bbbbpn", where "bbbb" is the baud rate, + "p" is parity ("n", "o", or "e"), and "n" is bits. + Default is "9600n8". + + See also Documentation/serial-console.txt. + + uart,io,[,options] + uart,mmio,[,options] + Start an early, polled-mode console on the 8250/16550 + UART at the specified I/O port or MMIO address, + switching to the matching ttyS device later. The + options are the same as for ttyS, above. cpcihp_generic= [HW,PCI] Generic port I/O CompactPCI driver Format: ,,,[,] diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index b2555741a895..31dd922e28ef 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -2125,6 +2125,41 @@ static int __init serial8250_late_console_init(void) } late_initcall(serial8250_late_console_init); +static int __init find_port(struct uart_port *p) +{ + int line; + struct uart_port *port; + + for (line = 0; line < UART_NR; line++) { + port = &serial8250_ports[line].port; + if (p->iotype == port->iotype && + p->iobase == port->iobase && + p->membase == port->membase) + return line; + } + return -ENODEV; +} + +int __init serial8250_start_console(struct uart_port *port, char *options) +{ + int line; + + line = find_port(port); + if (line < 0) + return -ENODEV; + + add_preferred_console("ttyS", line, options); + printk("Adding console on ttyS%d at %s 0x%lx (options '%s')\n", + line, port->iotype == UPIO_MEM ? "MMIO" : "I/O port", + port->iotype == UPIO_MEM ? (unsigned long) port->mapbase : + (unsigned long) port->iobase, options); + if (!(serial8250_console.flags & CON_ENABLED)) { + serial8250_console.flags &= ~CON_PRINTBUFFER; + register_console(&serial8250_console); + } + return line; +} + #define SERIAL8250_CONSOLE &serial8250_console #else #define SERIAL8250_CONSOLE NULL diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c new file mode 100644 index 000000000000..b7a5dd710228 --- /dev/null +++ b/drivers/serial/8250_early.c @@ -0,0 +1,255 @@ +/* + * Early serial console for 8250/16550 devices + * + * (c) Copyright 2004 Hewlett-Packard Development Company, L.P. + * Bjorn Helgaas + * + * 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. + * + * Based on the 8250.c serial driver, Copyright (C) 2001 Russell King, + * and on early_printk.c by Andi Kleen. + * + * This is for use before the serial driver has initialized, in + * particular, before the UARTs have been discovered and named. + * Instead of specifying the console device as, e.g., "ttyS0", + * we locate the device directly by its MMIO or I/O port address. + * + * The user can specify the device directly, e.g., + * console=uart,io,0x3f8,9600n8 + * console=uart,mmio,0xff5e0000,115200n8 + * or platform code can call early_uart_console_init() to set + * the early UART device. + * + * After the normal serial driver starts, we try to locate the + * matching ttyS device and start a console there. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct early_uart_device { + struct uart_port port; + char options[16]; /* e.g., 115200n8 */ + unsigned int baud; +}; + +static struct early_uart_device early_device __initdata; +static int early_uart_registered __initdata; + +static unsigned int __init serial_in(struct uart_port *port, int offset) +{ + if (port->iotype == UPIO_MEM) + return readb(port->membase + offset); + else + return inb(port->iobase + offset); +} + +static void __init serial_out(struct uart_port *port, int offset, int value) +{ + if (port->iotype == UPIO_MEM) + writeb(value, port->membase + offset); + else + outb(value, port->iobase + offset); +} + +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + +static void __init wait_for_xmitr(struct uart_port *port) +{ + unsigned int status; + + for (;;) { + status = serial_in(port, UART_LSR); + if ((status & BOTH_EMPTY) == BOTH_EMPTY) + return; + cpu_relax(); + } +} + +static void __init putc(struct uart_port *port, unsigned char c) +{ + wait_for_xmitr(port); + serial_out(port, UART_TX, c); +} + +static void __init early_uart_write(struct console *console, const char *s, unsigned int count) +{ + struct uart_port *port = &early_device.port; + unsigned int ier; + + /* Save the IER and disable interrupts */ + ier = serial_in(port, UART_IER); + serial_out(port, UART_IER, 0); + + while (*s && count-- > 0) { + putc(port, *s); + if (*s == '\n') + putc(port, '\r'); + s++; + } + + /* Wait for transmitter to become empty and restore the IER */ + wait_for_xmitr(port); + serial_out(port, UART_IER, ier); +} + +static unsigned int __init probe_baud(struct uart_port *port) +{ + unsigned char lcr, dll, dlm; + unsigned int quot; + + lcr = serial_in(port, UART_LCR); + serial_out(port, UART_LCR, lcr | UART_LCR_DLAB); + dll = serial_in(port, UART_DLL); + dlm = serial_in(port, UART_DLM); + serial_out(port, UART_LCR, lcr); + + quot = (dlm << 8) | dll; + return (port->uartclk / 16) / quot; +} + +static void __init init_port(struct early_uart_device *device) +{ + struct uart_port *port = &device->port; + unsigned int divisor; + unsigned char c; + + serial_out(port, UART_LCR, 0x3); /* 8n1 */ + serial_out(port, UART_IER, 0); /* no interrupt */ + serial_out(port, UART_FCR, 0); /* no fifo */ + serial_out(port, UART_MCR, 0x3); /* DTR + RTS */ + + divisor = port->uartclk / (16 * device->baud); + c = serial_in(port, UART_LCR); + serial_out(port, UART_LCR, c | UART_LCR_DLAB); + serial_out(port, UART_DLL, divisor & 0xff); + serial_out(port, UART_DLM, (divisor >> 8) & 0xff); + serial_out(port, UART_LCR, c & ~UART_LCR_DLAB); +} + +static int __init parse_options(struct early_uart_device *device, char *options) +{ + struct uart_port *port = &device->port; + int mapsize = 64; + int mmio, length; + + if (!options) + return -ENODEV; + + port->uartclk = BASE_BAUD * 16; + if (!strncmp(options, "mmio,", 5)) { + port->iotype = UPIO_MEM; + port->mapbase = simple_strtoul(options + 5, &options, 0); + port->membase = ioremap(port->mapbase, mapsize); + if (!port->membase) { + printk(KERN_ERR "%s: Couldn't ioremap 0x%lx\n", + __FUNCTION__, port->mapbase); + return -ENOMEM; + } + mmio = 1; + } else if (!strncmp(options, "io,", 3)) { + port->iotype = UPIO_PORT; + port->iobase = simple_strtoul(options + 3, &options, 0); + mmio = 0; + } else + return -EINVAL; + + if ((options = strchr(options, ','))) { + options++; + device->baud = simple_strtoul(options, 0, 0); + length = min(strcspn(options, " "), sizeof(device->options)); + strncpy(device->options, options, length); + } else { + device->baud = probe_baud(port); + snprintf(device->options, sizeof(device->options), "%u", + device->baud); + } + + printk(KERN_INFO "Early serial console at %s 0x%lx (options '%s')\n", + mmio ? "MMIO" : "I/O port", + mmio ? port->mapbase : (unsigned long) port->iobase, + device->options); + return 0; +} + +static int __init early_uart_setup(struct console *console, char *options) +{ + struct early_uart_device *device = &early_device; + int err; + + if (device->port.membase || device->port.iobase) + return 0; + + if ((err = parse_options(device, options)) < 0) + return err; + + init_port(device); + return 0; +} + +static struct console early_uart_console __initdata = { + .name = "uart", + .write = early_uart_write, + .setup = early_uart_setup, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +static int __init early_uart_console_init(void) +{ + if (!early_uart_registered) { + register_console(&early_uart_console); + early_uart_registered = 1; + } + return 0; +} +console_initcall(early_uart_console_init); + +int __init early_serial_console_init(char *cmdline) +{ + char *options; + int err; + + options = strstr(cmdline, "console=uart,"); + if (!options) + return -ENODEV; + + options = strchr(cmdline, ',') + 1; + if ((err = early_uart_setup(NULL, options)) < 0) + return err; + return early_uart_console_init(); +} + +static int __init early_uart_console_switch(void) +{ + struct early_uart_device *device = &early_device; + struct uart_port *port = &device->port; + int mmio, line; + + if (!(early_uart_console.flags & CON_ENABLED)) + return 0; + + /* Try to start the normal driver on a matching line. */ + mmio = (port->iotype == UPIO_MEM); + line = serial8250_start_console(port, device->options); + if (line < 0) + printk("No ttyS device at %s 0x%lx for console\n", + mmio ? "MMIO" : "I/O port", + mmio ? port->mapbase : + (unsigned long) port->iobase); + + unregister_console(&early_uart_console); + if (mmio) + iounmap(port->membase); + + return 0; +} +late_initcall(early_uart_console_switch); diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 6732139d121b..ee8d8de3c141 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_SERIAL_21285) += 21285.o obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y) obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o +obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o diff --git a/include/linux/serial.h b/include/linux/serial.h index 9a07d00106f9..00145822fb74 100644 --- a/include/linux/serial.h +++ b/include/linux/serial.h @@ -181,6 +181,8 @@ extern void unregister_serial(int line); /* Allow architectures to override entries in serial8250_ports[] at run time: */ struct uart_port; /* forward declaration */ extern int early_serial_setup(struct uart_port *port); +extern int early_serial_console_init(char *options); +extern int serial8250_start_console(struct uart_port *port, char *options); #endif /* __KERNEL__ */ #endif /* _LINUX_SERIAL_H */ diff --git a/kernel/printk.c b/kernel/printk.c index 1b41c96f7151..4e9fd492f30e 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -142,7 +142,7 @@ static int __init console_setup(char *str) strcpy(name, "ttyS1"); #endif for(s = name; *s; s++) - if (*s >= '0' && *s <= '9') + if ((*s >= '0' && *s <= '9') || *s == ',') break; idx = simple_strtoul(s, NULL, 10); *s = 0; -- cgit v1.2.3 From 1af22f6d64f152e03d374b1eea2a7d2f9497c456 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 18 Nov 2004 22:53:56 -0800 Subject: [PATCH] move HCDP/PCDP to early uart console This changes the HCDP/PCDP support to use the early uart console rather than using early_serial_setup(). As a consequence, ia64 serial device names will now stay constant regardless of firmware console settings. (A serial device selected as an EFI console device on HP ia64 boxes used to automatically become ttyS0.) This also removes the ia64 early-boot kludge of assuming legacy COM ports at 0x3f8 and 0x2f8. For boxes that have legacy ports but no HCDP, "console=ttyS0" will still work, but the console won't start working until after the serial driver initializes and discovers the devices. WARNING: If you have an HP machine and you're using the MP serial console port (the connector labelled "console" on the 3-headed cable), this patch will break your console! HOW TO FIX IT: 1) The console device will change from /dev/ttyS0 to /dev/ttyS1, ttyS2, or ttyS3, so: 1a) Edit /etc/inittab to add a getty entry for /dev/ttyS1 (rx4640, rx5670, rx7620, rx8620, Superdome), /dev/ttyS2 (rx1600), or /dev/ttyS3 (rx2600). 1b) Edit /etc/securetty to add ttyS1, ttyS2, or ttyS3. 1c) Leave the existing ttyS0 entries in /etc/inittab and /etc/securetty so you can still boot old kernels. 2) Edit /etc/elilo.conf to remove any "console=" arguments (see [1]). 3) Run elilo to install the bootloader with new configuration. 4) Reboot and use the EFI boot option maintenance menu to select exactly one device for console output, input, and standard error. Then do a cold reset so the changes take effect. For the MP console, be careful to select the device with "Acpi(HWP0002,700)/Pci(...)/Uart" in the path (see [2]). DETAILS: - Prior to this patch, serial device names depended on the HCDP, which in turn depends on EFI console settings. After this patch, the naming always stays the same, regardless of firmware settings. For example, an rx1600 with a single built-in serial port plus an MP has these ports: Old Old MMIO (EFI console (EFI console address on builtin) on MP port) New ========== ========== ========== ====== builtin 0xff5e0000 ttyS0 ttyS1 ttyS0 MP UPS 0xf8031000 ttyS1 ttyS2 ttyS1 MP Console 0xf8030000 ttyS2 ttyS0 ttyS2 MP 2 0xf8030010 ttyS3 ttyS3 ttyS3 MP 3 0xf8030038 ttyS4 ttyS4 ttyS4 - If you want to have multiple devices in the EFI console path, you can, but Linux won't be able to deduce which console to use, so it will default to using VGA. You can use "console=hcdp" (the UART device from the EFI path) or "console=ttyS" to select the device directly. TROUBLESHOOTING: - No kernel output after "Uncompressing Linux... done": -> You're using an MP port as the console and specified "console=ttyS0". This port is now named something else. Remove the "console=" option. -> Multiple UARTs selected as EFI console devices, and you're looking at the wrong one. Make sure only one UART is selected (use the EFI Boot Manager "Boot option maintenance" menu). -> You're physically connected to the MP port but have a non-MP UART selected as EFI console device. Either move the console cable to the non-MP UART, or change the EFI console path to the MP UART (the MP UART is the one with "Acpi(HWP0002,700)/Pci(...)/Uart" in it.) - Long pause (60+ seconds) between "Uncompressing Linux... done" and start of kernel output: -> No early console, probably because you used "console=ttyS". Remove the "console=" option. - Kernel and init script output works fine, but no "login:" prompt: -> Add getty entry to /etc/inittab for console tty. Use the table in (1a) above or look for the "Adding console on ttyS" message that tells you which device is the console. - "login:" prompt, but can't login as root: -> Add entry to /etc/securetty for console tty. [1] When the EFI console path contains exactly one device (either serial or VGA), 2.6.6 and newer kernels default to that device automatically. So if you remove "console=" arguments, you can use the same elilo configuration to boot any 2.6.6 or newer kernel with or without this patch. If you need to boot kernels older than 2.6.6 (including RHEL3 and SLES9), keep an 'append="console=ttyS0"' line in those elilo.conf stanzas. Non-HP machines will still need "console=" for serial consoles because they don't supply the HCDP table. [2] The HP management card (MP) causes confusion because it is always active as an EFI console, even if it doesn't appear in the EFI console path. If your console path is set to a non-MP UART, and you happen to be attached to the MP UART, everything works in EFI, but the kernel will think the non-MP UART is the console, so you won't see any kernel output. Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/kernel/setup.c | 40 ++++---------- drivers/firmware/Kconfig | 6 ++- drivers/firmware/pcdp.c | 138 +++++++++++------------------------------------ include/linux/efi.h | 2 +- 4 files changed, 48 insertions(+), 138 deletions(-) (limited to 'include/linux') diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index da88d284e2ce..d54628de4970 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -258,25 +258,6 @@ io_port_init (void) num_io_spaces = 1; } -#ifdef CONFIG_SERIAL_8250_CONSOLE -static void __init -setup_serial_legacy (void) -{ - struct uart_port port; - unsigned int i, iobase[] = {0x3f8, 0x2f8}; - - printk(KERN_INFO "Registering legacy COM ports for serial console\n"); - memset(&port, 0, sizeof(port)); - port.iotype = SERIAL_IO_PORT; - port.uartclk = BASE_BAUD * 16; - for (i = 0; i < ARRAY_SIZE(iobase); i++) { - port.line = i; - port.iobase = iobase[i]; - early_serial_setup(&port); - } -} -#endif - /** * early_console_setup - setup debugging console * @@ -287,15 +268,23 @@ setup_serial_legacy (void) * Returns non-zero if a console couldn't be setup. */ static inline int __init -early_console_setup (void) +early_console_setup (char *cmdline) { #ifdef CONFIG_SERIAL_SGI_L1_CONSOLE { extern int sn_serial_console_early_setup(void); - if(!sn_serial_console_early_setup()) + if (!sn_serial_console_early_setup()) return 0; } #endif +#ifdef CONFIG_EFI_PCDP + if (!efi_setup_pcdp_console(cmdline)) + return 0; +#endif +#ifdef CONFIG_SERIAL_8250_CONSOLE + if (!early_serial_console_init(cmdline)) + return 0; +#endif return -1; } @@ -319,7 +308,7 @@ setup_arch (char **cmdline_p) #ifdef CONFIG_SMP /* If we register an early console, allow CPU 0 to printk */ - if (!early_console_setup()) + if (!early_console_setup(*cmdline_p)) cpu_set(smp_processor_id(), cpu_online_map); #endif @@ -349,13 +338,6 @@ setup_arch (char **cmdline_p) #ifdef CONFIG_ACPI_BOOT acpi_boot_init(); #endif -#ifdef CONFIG_EFI_PCDP - efi_setup_pcdp_console(*cmdline_p); -#endif -#ifdef CONFIG_SERIAL_8250_CONSOLE - if (!efi.hcdp) - setup_serial_legacy(); -#endif #ifdef CONFIG_VT if (!conswitchp) { diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 4607ddd4693e..019fa45d7b5d 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -48,7 +48,11 @@ config EFI_PCDP use the first serial port it describes as the Linux console, say Y here. If your EFI ConOut path contains only a UART device, it will become the console automatically. Otherwise, - you must specify the "console=ttyS0" kernel boot argument. + you must specify the "console=hcdp" kernel boot argument. + + Neither the PCDP nor the HCDP affects naming of serial devices, + so a serial console may be /dev/ttyS0, /dev/ttyS1, etc, depending + on how the driver discovers devices. You must also enable the appropriate drivers (serial, VGA, etc.) diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c index 375b7dc45090..ca751f573e7a 100644 --- a/drivers/firmware/pcdp.c +++ b/drivers/firmware/pcdp.c @@ -14,127 +14,45 @@ #include #include #include -#include #include -#include -#include -#include #include "pcdp.h" -static inline int -uart_irq_supported(int rev, struct pcdp_uart *uart) -{ - if (rev < 3) - return uart->pci_func & PCDP_UART_IRQ; - return uart->flags & PCDP_UART_IRQ; -} - -static inline int -uart_pci(int rev, struct pcdp_uart *uart) -{ - if (rev < 3) - return uart->pci_func & PCDP_UART_PCI; - return uart->flags & PCDP_UART_PCI; -} - -static inline int -uart_active_high_low(int rev, struct pcdp_uart *uart) -{ - if (uart_pci(rev, uart) || uart->flags & PCDP_UART_ACTIVE_LOW) - return ACPI_ACTIVE_LOW; - return ACPI_ACTIVE_HIGH; -} - -static inline int -uart_edge_level(int rev, struct pcdp_uart *uart) -{ - if (uart_pci(rev, uart)) - return ACPI_LEVEL_SENSITIVE; - if (rev < 3 || uart->flags & PCDP_UART_EDGE_SENSITIVE) - return ACPI_EDGE_SENSITIVE; - return ACPI_LEVEL_SENSITIVE; -} - -static void __init -setup_serial_console(int rev, struct pcdp_uart *uart) +static int __init +setup_serial_console(struct pcdp_uart *uart) { #ifdef CONFIG_SERIAL_8250_CONSOLE - struct uart_port port; - static char options[16]; - int mapsize = 64; - - memset(&port, 0, sizeof(port)); - port.uartclk = uart->clock_rate; - if (!port.uartclk) /* some FW doesn't supply this */ - port.uartclk = BASE_BAUD * 16; - - if (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { - port.mapbase = uart->addr.address; - port.membase = ioremap(port.mapbase, mapsize); - if (!port.membase) { - printk(KERN_ERR "%s: couldn't ioremap 0x%lx-0x%lx\n", - __FUNCTION__, port.mapbase, port.mapbase + mapsize); - return; - } - port.iotype = UPIO_MEM; - } else if (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) { - port.iobase = uart->addr.address; - port.iotype = UPIO_PORT; - } else - return; - - switch (uart->pci_prog_intfc) { - case 0x0: port.type = PORT_8250; break; - case 0x1: port.type = PORT_16450; break; - case 0x2: port.type = PORT_16550; break; - case 0x3: port.type = PORT_16650; break; - case 0x4: port.type = PORT_16750; break; - case 0x5: port.type = PORT_16850; break; - case 0x6: port.type = PORT_16C950; break; - default: port.type = PORT_UNKNOWN; break; - } - - port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; - - if (uart_irq_supported(rev, uart)) { - port.irq = acpi_register_gsi(uart->gsi, - uart_edge_level(rev, uart), - uart_active_high_low(rev, uart)); - port.flags |= UPF_AUTO_IRQ; /* some FW reported wrong GSI */ - if (uart_pci(rev, uart)) - port.flags |= UPF_SHARE_IRQ; - } - - if (early_serial_setup(&port) < 0) - return; + int mmio; + static char options[64]; - snprintf(options, sizeof(options), "%lun%d", uart->baud, + mmio = (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY); + snprintf(options, sizeof(options), "console=uart,%s,0x%lx,%lun%d", + mmio ? "mmio" : "io", uart->addr.address, uart->baud, uart->bits ? uart->bits : 8); - add_preferred_console("ttyS", port.line, options); - printk(KERN_INFO "PCDP: serial console at %s 0x%lx (ttyS%d, options %s)\n", - port.iotype == UPIO_MEM ? "MMIO" : "I/O", - uart->addr.address, port.line, options); + return early_serial_console_init(options); +#else + return -ENODEV; #endif } -static void __init +static int __init setup_vga_console(struct pcdp_vga *vga) { -#ifdef CONFIG_VT -#ifdef CONFIG_VGA_CONSOLE +#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) if (efi_mem_type(0xA0000) == EFI_CONVENTIONAL_MEMORY) { printk(KERN_ERR "PCDP: VGA selected, but frame buffer is not MMIO!\n"); - return; + return -ENODEV; } conswitchp = &vga_con; printk(KERN_INFO "PCDP: VGA console\n"); -#endif + return 0; +#else + return -ENODEV; #endif } -void __init +int __init efi_setup_pcdp_console(char *cmdline) { struct pcdp *pcdp; @@ -144,20 +62,25 @@ efi_setup_pcdp_console(char *cmdline) pcdp = efi.hcdp; if (!pcdp) - return; + return -ENODEV; - printk(KERN_INFO "PCDP: v%d at 0x%p\n", pcdp->rev, pcdp); + printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, __pa(pcdp)); - if (pcdp->rev < 3) { - if (strstr(cmdline, "console=ttyS0") || efi_uart_console_only()) + if (strstr(cmdline, "console=hcdp")) { + if (pcdp->rev < 3) serial = 1; + } else if (strstr(cmdline, "console=")) { + printk(KERN_INFO "Explicit \"console=\"; ignoring PCDP\n"); + return -ENODEV; } + if (pcdp->rev < 3 && efi_uart_console_only()) + serial = 1; + for (i = 0, uart = pcdp->uart; i < pcdp->num_uarts; i++, uart++) { if (uart->flags & PCDP_UART_PRIMARY_CONSOLE || serial) { if (uart->type == PCDP_CONSOLE_UART) { - setup_serial_console(pcdp->rev, uart); - return; + return setup_serial_console(uart); } } } @@ -168,11 +91,12 @@ efi_setup_pcdp_console(char *cmdline) dev = (struct pcdp_device *) ((u8 *) dev + dev->length)) { if (dev->flags & PCDP_PRIMARY_CONSOLE) { if (dev->type == PCDP_CONSOLE_VGA) { - setup_vga_console((struct pcdp_vga *) dev); - return; + return setup_vga_console((struct pcdp_vga *) dev); } } } + + return -ENODEV; } #ifdef CONFIG_IA64_EARLY_PRINTK_UART diff --git a/include/linux/efi.h b/include/linux/efi.h index 0c5c94ab1112..40c0cd72e925 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -306,7 +306,7 @@ extern int __init efi_set_rtc_mmss(unsigned long nowtime); extern struct efi_memory_map memmap; #ifdef CONFIG_EFI_PCDP -extern void __init efi_setup_pcdp_console(char *); +extern int __init efi_setup_pcdp_console(char *); #endif /* -- cgit v1.2.3 From c2234eee5c898eb2e2e8b11d4705ddb78eb2a751 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 18 Nov 2004 22:54:22 -0800 Subject: [PATCH] vmscan: ignore swap token when in trouble The token-based thrashing control patches introduced a problem: when a task which doesn't hold the token tries to run direct-reclaim, that task is told that pages which belong to the token-holding mm are referenced, even though they are not. This means that it is possible for a huge number of a non-token-holding mm's pages to be scanned to no effect. Eventually, we give up and go and oom-kill something. So the patch arranges for the thrashing control logic to be defeated if the caller has reached the highest level of scanning priority. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/rmap.h | 4 ++-- mm/rmap.c | 23 +++++++++++++---------- mm/vmscan.c | 4 ++-- 3 files changed, 17 insertions(+), 14 deletions(-) (limited to 'include/linux') diff --git a/include/linux/rmap.h b/include/linux/rmap.h index 9e6a26527047..11b484e37ac9 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -89,7 +89,7 @@ static inline void page_dup_rmap(struct page *page) /* * Called from mm/vmscan.c to handle paging out */ -int page_referenced(struct page *, int is_locked); +int page_referenced(struct page *, int is_locked, int ignore_token); int try_to_unmap(struct page *); /* @@ -103,7 +103,7 @@ unsigned long page_address_in_vma(struct page *, struct vm_area_struct *); #define anon_vma_prepare(vma) (0) #define anon_vma_link(vma) do {} while (0) -#define page_referenced(page,l) TestClearPageReferenced(page) +#define page_referenced(page,l,i) TestClearPageReferenced(page) #define try_to_unmap(page) SWAP_FAIL #endif /* CONFIG_MMU */ diff --git a/mm/rmap.c b/mm/rmap.c index b2f242f76cd7..83c86c2de4e5 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -254,7 +254,7 @@ unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma) * repeatedly from either page_referenced_anon or page_referenced_file. */ static int page_referenced_one(struct page *page, - struct vm_area_struct *vma, unsigned int *mapcount) + struct vm_area_struct *vma, unsigned int *mapcount, int ignore_token) { struct mm_struct *mm = vma->vm_mm; unsigned long address; @@ -289,7 +289,7 @@ static int page_referenced_one(struct page *page, if (ptep_clear_flush_young(vma, address, pte)) referenced++; - if (mm != current->mm && has_swap_token(mm)) + if (mm != current->mm && !ignore_token && has_swap_token(mm)) referenced++; (*mapcount)--; @@ -302,7 +302,7 @@ out: return referenced; } -static int page_referenced_anon(struct page *page) +static int page_referenced_anon(struct page *page, int ignore_token) { unsigned int mapcount; struct anon_vma *anon_vma; @@ -315,7 +315,8 @@ static int page_referenced_anon(struct page *page) mapcount = page_mapcount(page); list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { - referenced += page_referenced_one(page, vma, &mapcount); + referenced += page_referenced_one(page, vma, &mapcount, + ignore_token); if (!mapcount) break; } @@ -334,7 +335,7 @@ static int page_referenced_anon(struct page *page) * * This function is only called from page_referenced for object-based pages. */ -static int page_referenced_file(struct page *page) +static int page_referenced_file(struct page *page, int ignore_token) { unsigned int mapcount; struct address_space *mapping = page->mapping; @@ -372,7 +373,8 @@ static int page_referenced_file(struct page *page) referenced++; break; } - referenced += page_referenced_one(page, vma, &mapcount); + referenced += page_referenced_one(page, vma, &mapcount, + ignore_token); if (!mapcount) break; } @@ -389,7 +391,7 @@ static int page_referenced_file(struct page *page) * Quick test_and_clear_referenced for all mappings to a page, * returns the number of ptes which referenced the page. */ -int page_referenced(struct page *page, int is_locked) +int page_referenced(struct page *page, int is_locked, int ignore_token) { int referenced = 0; @@ -401,14 +403,15 @@ int page_referenced(struct page *page, int is_locked) if (page_mapped(page) && page->mapping) { if (PageAnon(page)) - referenced += page_referenced_anon(page); + referenced += page_referenced_anon(page, ignore_token); else if (is_locked) - referenced += page_referenced_file(page); + referenced += page_referenced_file(page, ignore_token); else if (TestSetPageLocked(page)) referenced++; else { if (page->mapping) - referenced += page_referenced_file(page); + referenced += page_referenced_file(page, + ignore_token); unlock_page(page); } } diff --git a/mm/vmscan.c b/mm/vmscan.c index 44dadf2d3778..585c0cff921b 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -377,7 +377,7 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc) if (page_mapped(page) || PageSwapCache(page)) sc->nr_scanned++; - referenced = page_referenced(page, 1); + referenced = page_referenced(page, 1, sc->priority <= 0); /* In active use or really unfreeable? Activate it. */ if (referenced && page_mapping_inuse(page)) goto activate_locked; @@ -715,7 +715,7 @@ refill_inactive_zone(struct zone *zone, struct scan_control *sc) if (page_mapped(page)) { if (!reclaim_mapped || (total_swap_pages == 0 && PageAnon(page)) || - page_referenced(page, 0)) { + page_referenced(page, 0, sc->priority <= 0)) { list_add(&page->lru, &l_active); continue; } -- cgit v1.2.3 From eaede9da09f586ea9d27a4a3fffd73db21924401 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 18 Nov 2004 22:59:55 -0800 Subject: [PATCH] allow NFS exports of EFS filesystems Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/efs/namei.c | 33 +++++++++++++++++++++++++++++++++ fs/efs/super.c | 5 +++++ include/linux/efs_fs.h | 1 + 3 files changed, 39 insertions(+) (limited to 'include/linux') diff --git a/fs/efs/namei.c b/fs/efs/namei.c index e6c7210f0a68..ed4a207fe22a 100644 --- a/fs/efs/namei.c +++ b/fs/efs/namei.c @@ -75,3 +75,36 @@ struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct namei return NULL; } +struct dentry *efs_get_parent(struct dentry *child) +{ + struct dentry *parent; + struct inode *inode; + efs_ino_t ino; + int error; + + lock_kernel(); + + error = -ENOENT; + ino = efs_find_entry(child->d_inode, "..", 2); + if (!ino) + goto fail; + + error = -EACCES; + inode = iget(child->d_inode->i_sb, ino); + if (!inode) + goto fail; + + error = -ENOMEM; + parent = d_alloc_anon(inode); + if (!parent) + goto fail_iput; + + unlock_kernel(); + return parent; + + fail_iput: + iput(inode); + fail: + unlock_kernel(); + return ERR_PTR(error); +} diff --git a/fs/efs/super.c b/fs/efs/super.c index 467e34b41f5c..af4d01e2730a 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c @@ -95,6 +95,10 @@ static struct super_operations efs_superblock_operations = { .remount_fs = efs_remount, }; +static struct export_operations efs_export_ops = { + .get_parent = efs_get_parent, +}; + static int __init init_efs_fs(void) { int err; printk("EFS: "EFS_VERSION" - http://aeschi.ch.eu.org/efs/\n"); @@ -278,6 +282,7 @@ static int efs_fill_super(struct super_block *s, void *d, int silent) s->s_flags |= MS_RDONLY; } s->s_op = &efs_superblock_operations; + s->s_export_op = &efs_export_ops; root = iget(s, EFS_ROOTINODE); s->s_root = d_alloc_root(root); diff --git a/include/linux/efs_fs.h b/include/linux/efs_fs.h index f7c8446239ac..28f368c526fb 100644 --- a/include/linux/efs_fs.h +++ b/include/linux/efs_fs.h @@ -45,6 +45,7 @@ extern efs_block_t efs_map_block(struct inode *, efs_block_t); extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int); extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *); +extern struct dentry *efs_get_parent(struct dentry *); extern int efs_bmap(struct inode *, int); #endif /* __EFS_FS_H__ */ -- cgit v1.2.3 From afc62cbf517c63aedd04037b92b7acd3dfa297d5 Mon Sep 17 00:00:00 2001 From: Stelian Pop Date: Thu, 18 Nov 2004 23:00:07 -0800 Subject: [PATCH] sonypi: return an error from sonypi_camera_command() if the camera isn't enabled The sonypi_camera_command() used to fail without returning an error code if the user fergot to enable the camera in the sonypi module (using the camera=1 module parameter). This caused the meye driver to apparently load correctly but miserably fail later, when trying to access the camera for getting some data out of it. This patch adds an error code to sonypi_camera_command() and makes the meye driver check for it in the PCI probe routine. If the function fails, a message is printed in the kernel logs reminding the user it should better RTFM. The patch also removes some sonypi_camera_command() commands (those supposed to return the current camera settings) which are unreliable. The meye driver does not use them anyway. Signed-off-by: Stelian Pop Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/sonypi.c | 47 +++++++++------------------------------------- drivers/char/sonypi.h | 2 +- drivers/media/video/meye.c | 8 +++++++- drivers/media/video/meye.h | 2 +- include/linux/sonypi.h | 24 +++++++++++------------ 5 files changed, 30 insertions(+), 53 deletions(-) (limited to 'include/linux') diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index a35e4aa77853..27eeed243f43 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -232,6 +232,8 @@ static u8 sonypi_call3(u8 dev, u8 fn, u8 v) return v1; } +#if 0 +/* Get brightness, hue etc. Unreliable... */ static u8 sonypi_read(u8 fn) { u8 v1, v2; @@ -245,6 +247,7 @@ static u8 sonypi_read(u8 fn) } return 0xff; } +#endif /* Set brightness, hue etc */ static void sonypi_set(u8 fn, u8 v) @@ -435,80 +438,48 @@ found: } /* External camera command (exported to the motion eye v4l driver) */ -u8 sonypi_camera_command(int command, u8 value) +int sonypi_camera_command(int command, u8 value) { - u8 ret = 0; - if (!camera) - return 0; + return -EIO; down(&sonypi_device.lock); switch (command) { - case SONYPI_COMMAND_GETCAMERA: - ret = sonypi_camera_ready(); - break; case SONYPI_COMMAND_SETCAMERA: if (value) sonypi_camera_on(); else sonypi_camera_off(); break; - case SONYPI_COMMAND_GETCAMERABRIGHTNESS: - ret = sonypi_read(SONYPI_CAMERA_BRIGHTNESS); - break; case SONYPI_COMMAND_SETCAMERABRIGHTNESS: sonypi_set(SONYPI_CAMERA_BRIGHTNESS, value); break; - case SONYPI_COMMAND_GETCAMERACONTRAST: - ret = sonypi_read(SONYPI_CAMERA_CONTRAST); - break; case SONYPI_COMMAND_SETCAMERACONTRAST: sonypi_set(SONYPI_CAMERA_CONTRAST, value); break; - case SONYPI_COMMAND_GETCAMERAHUE: - ret = sonypi_read(SONYPI_CAMERA_HUE); - break; case SONYPI_COMMAND_SETCAMERAHUE: sonypi_set(SONYPI_CAMERA_HUE, value); break; - case SONYPI_COMMAND_GETCAMERACOLOR: - ret = sonypi_read(SONYPI_CAMERA_COLOR); - break; case SONYPI_COMMAND_SETCAMERACOLOR: sonypi_set(SONYPI_CAMERA_COLOR, value); break; - case SONYPI_COMMAND_GETCAMERASHARPNESS: - ret = sonypi_read(SONYPI_CAMERA_SHARPNESS); - break; case SONYPI_COMMAND_SETCAMERASHARPNESS: sonypi_set(SONYPI_CAMERA_SHARPNESS, value); break; - case SONYPI_COMMAND_GETCAMERAPICTURE: - ret = sonypi_read(SONYPI_CAMERA_PICTURE); - break; case SONYPI_COMMAND_SETCAMERAPICTURE: sonypi_set(SONYPI_CAMERA_PICTURE, value); break; - case SONYPI_COMMAND_GETCAMERAAGC: - ret = sonypi_read(SONYPI_CAMERA_AGC); - break; case SONYPI_COMMAND_SETCAMERAAGC: sonypi_set(SONYPI_CAMERA_AGC, value); break; - case SONYPI_COMMAND_GETCAMERADIRECTION: - ret = sonypi_read(SONYPI_CAMERA_STATUS); - ret &= SONYPI_DIRECTION_BACKWARDS; - break; - case SONYPI_COMMAND_GETCAMERAROMVERSION: - ret = sonypi_read(SONYPI_CAMERA_ROMVERSION); - break; - case SONYPI_COMMAND_GETCAMERAREVISION: - ret = sonypi_read(SONYPI_CAMERA_REVISION); + default: + printk(KERN_ERR "sonypi: sonypi_camera_command invalid: %d\n", + command); break; } up(&sonypi_device.lock); - return ret; + return 0; } EXPORT_SYMBOL(sonypi_camera_command); diff --git a/drivers/char/sonypi.h b/drivers/char/sonypi.h index 003241a73d4e..b8f333684458 100644 --- a/drivers/char/sonypi.h +++ b/drivers/char/sonypi.h @@ -36,7 +36,7 @@ #ifdef __KERNEL__ -#define SONYPI_DRIVER_VERSION "1.24" +#define SONYPI_DRIVER_VERSION "1.25" #define SONYPI_DEVICE_MODEL_TYPE1 1 #define SONYPI_DEVICE_MODEL_TYPE2 2 diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 2a00c1ccf202..79bea86560db 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -1842,7 +1842,12 @@ static int __devinit meye_probe(struct pci_dev *pcidev, memcpy(meye.video_dev, &meye_template, sizeof(meye_template)); meye.video_dev->dev = &meye.mchip_dev->dev; - sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 1); + if ((ret = sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 1))) { + printk(KERN_ERR "meye: unable to power on the camera\n"); + printk(KERN_ERR "meye: did you enable the camera in " + "sonypi using the module options ?\n"); + goto outsonypienable; + } ret = -EIO; if ((ret = pci_enable_device(meye.mchip_dev))) { @@ -1943,6 +1948,7 @@ outregions: pci_disable_device(meye.mchip_dev); outenabledev: sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 0); +outsonypienable: kfifo_free(meye.doneq); outkfifoalloc2: kfifo_free(meye.grabq); diff --git a/drivers/media/video/meye.h b/drivers/media/video/meye.h index 102318086772..a1e95a5fe470 100644 --- a/drivers/media/video/meye.h +++ b/drivers/media/video/meye.h @@ -31,7 +31,7 @@ #define _MEYE_PRIV_H_ #define MEYE_DRIVER_MAJORVERSION 1 -#define MEYE_DRIVER_MINORVERSION 11 +#define MEYE_DRIVER_MINORVERSION 12 #define MEYE_DRIVER_VERSION __stringify(MEYE_DRIVER_MAJORVERSION) "." \ __stringify(MEYE_DRIVER_MINORVERSION) diff --git a/include/linux/sonypi.h b/include/linux/sonypi.h index fd8d3a931827..388d573e12a6 100644 --- a/include/linux/sonypi.h +++ b/include/linux/sonypi.h @@ -122,27 +122,27 @@ /* used only for communication between v4l and sonypi */ -#define SONYPI_COMMAND_GETCAMERA 1 +#define SONYPI_COMMAND_GETCAMERA 1 /* obsolete */ #define SONYPI_COMMAND_SETCAMERA 2 -#define SONYPI_COMMAND_GETCAMERABRIGHTNESS 3 +#define SONYPI_COMMAND_GETCAMERABRIGHTNESS 3 /* obsolete */ #define SONYPI_COMMAND_SETCAMERABRIGHTNESS 4 -#define SONYPI_COMMAND_GETCAMERACONTRAST 5 +#define SONYPI_COMMAND_GETCAMERACONTRAST 5 /* obsolete */ #define SONYPI_COMMAND_SETCAMERACONTRAST 6 -#define SONYPI_COMMAND_GETCAMERAHUE 7 +#define SONYPI_COMMAND_GETCAMERAHUE 7 /* obsolete */ #define SONYPI_COMMAND_SETCAMERAHUE 8 -#define SONYPI_COMMAND_GETCAMERACOLOR 9 +#define SONYPI_COMMAND_GETCAMERACOLOR 9 /* obsolete */ #define SONYPI_COMMAND_SETCAMERACOLOR 10 -#define SONYPI_COMMAND_GETCAMERASHARPNESS 11 +#define SONYPI_COMMAND_GETCAMERASHARPNESS 11 /* obsolete */ #define SONYPI_COMMAND_SETCAMERASHARPNESS 12 -#define SONYPI_COMMAND_GETCAMERAPICTURE 13 +#define SONYPI_COMMAND_GETCAMERAPICTURE 13 /* obsolete */ #define SONYPI_COMMAND_SETCAMERAPICTURE 14 -#define SONYPI_COMMAND_GETCAMERAAGC 15 +#define SONYPI_COMMAND_GETCAMERAAGC 15 /* obsolete */ #define SONYPI_COMMAND_SETCAMERAAGC 16 -#define SONYPI_COMMAND_GETCAMERADIRECTION 17 -#define SONYPI_COMMAND_GETCAMERAROMVERSION 18 -#define SONYPI_COMMAND_GETCAMERAREVISION 19 +#define SONYPI_COMMAND_GETCAMERADIRECTION 17 /* obsolete */ +#define SONYPI_COMMAND_GETCAMERAROMVERSION 18 /* obsolete */ +#define SONYPI_COMMAND_GETCAMERAREVISION 19 /* obsolete */ -u8 sonypi_camera_command(int command, u8 value); +int sonypi_camera_command(int command, u8 value); #endif /* __KERNEL__ */ -- cgit v1.2.3 From bbb0dbfc0300e2573b216753466293eaa3496489 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 18 Nov 2004 23:02:01 -0800 Subject: [PATCH] linux/mount.h: add atomic.h and spinlock.h #includes uses atomic_t and spinlock_t, but doesn't include either or , which means that any users of have to include them. This patch adds the necessary #includes to avoid this. Signed-off-by: Roland Dreier Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mount.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/mount.h b/include/linux/mount.h index 42e2c9460088..8b8d3b9beefd 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -13,6 +13,8 @@ #ifdef __KERNEL__ #include +#include +#include #define MNT_NOSUID 1 #define MNT_NODEV 2 -- cgit v1.2.3 From fc396d726fa5ddc5d593e2b13d525ae2eb4628fc Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Sat, 20 Nov 2004 21:13:07 -0800 Subject: [PATCH] i2o iomem annotations Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/message/i2o/device.c | 4 ++-- drivers/message/i2o/driver.c | 2 +- drivers/message/i2o/exec-osm.c | 12 ++++++------ drivers/message/i2o/i2o_block.c | 14 +++++++------- drivers/message/i2o/i2o_config.c | 12 ++++++------ drivers/message/i2o/i2o_scsi.c | 9 +++++---- drivers/message/i2o/iop.c | 24 ++++++++++++------------ include/linux/i2o.h | 14 +++++++------- 8 files changed, 46 insertions(+), 45 deletions(-) (limited to 'include/linux') diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c index 474d80615a1c..e4f9235882ed 100644 --- a/drivers/message/i2o/device.c +++ b/drivers/message/i2o/device.c @@ -35,7 +35,7 @@ extern struct bus_type i2o_bus_type; static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd, u32 type) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); @@ -446,7 +446,7 @@ static struct class_interface i2o_device_class_interface = { int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, int oplen, void *reslist, int reslen) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; u32 *res32 = (u32 *) reslist; u32 *restmp = (u32 *) reslist; diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c index ce5c49861834..388a44326620 100644 --- a/drivers/message/i2o/driver.c +++ b/drivers/message/i2o/driver.c @@ -175,7 +175,7 @@ void i2o_driver_unregister(struct i2o_driver *drv) * negative error code on failure (the message will be flushed too). */ int i2o_driver_dispatch(struct i2o_controller *c, u32 m, - struct i2o_message *msg) + struct i2o_message __iomem *msg) { struct i2o_driver *drv; u32 context = readl(&msg->u.s.icntxt); diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 60eac4efcc47..b25dc619c06e 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c @@ -48,7 +48,7 @@ struct i2o_exec_wait { u32 tcntxt; /* transaction context from reply */ int complete; /* 1 if reply received otherwise 0 */ u32 m; /* message id */ - struct i2o_message *msg; /* pointer to the reply message */ + struct i2o_message __iomem *msg; /* pointer to the reply message */ struct list_head list; /* node in global wait list */ }; @@ -114,7 +114,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long DECLARE_WAIT_QUEUE_HEAD(wq); struct i2o_exec_wait *wait; static u32 tcntxt = 0x80000000; - struct i2o_message *msg = c->in_queue.virt + m; + struct i2o_message __iomem *msg = c->in_queue.virt + m; int rc = 0; wait = i2o_exec_wait_alloc(); @@ -199,7 +199,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long * message must also be given back to the controller. */ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, - struct i2o_message *msg) + struct i2o_message __iomem *msg) { struct i2o_exec_wait *wait, *tmp; static spinlock_t lock; @@ -323,7 +323,7 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, struct i2o_message *msg) { if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) { // Fail bit is set - struct i2o_message *pmsg; /* preserved message */ + struct i2o_message __iomem *pmsg; /* preserved message */ u32 pm; pm = le32_to_cpu(msg->body[3]); @@ -395,7 +395,7 @@ static void i2o_exec_event(struct i2o_event *evt) */ int i2o_exec_lct_get(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; int i = 0; int rc = -EAGAIN; @@ -439,7 +439,7 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) { i2o_status_block *sb = c->status_block.virt; struct device *dev; - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; dev = &c->pdev->dev; diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index 04080c80ba37..21d87c9f6f62 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -126,7 +126,7 @@ static int i2o_block_remove(struct device *dev) */ static int i2o_block_device_flush(struct i2o_device *dev) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); @@ -154,7 +154,7 @@ static int i2o_block_device_flush(struct i2o_device *dev) */ static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); @@ -183,7 +183,7 @@ static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id) */ static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); @@ -211,7 +211,7 @@ static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id) */ static int i2o_block_device_unlock(struct i2o_device *dev, u32 media_id) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); @@ -240,7 +240,7 @@ static int i2o_block_device_power(struct i2o_block_device *dev, u8 op) { struct i2o_device *i2o_dev = dev->i2o_dev; struct i2o_controller *c = i2o_dev->iop; - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; int rc; @@ -777,8 +777,8 @@ static int i2o_block_transfer(struct request *req) struct i2o_block_device *dev = req->rq_disk->private_data; struct i2o_controller *c = dev->i2o_dev->iop; int tid = dev->i2o_dev->lct_data.tid; - struct i2o_message *msg; - void *mptr; + struct i2o_message __iomem *msg; + void __iomem *mptr; struct i2o_block_request *ireq = req->special; struct scatterlist *sg; int sgnum; diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index 1fa72cbbbc20..34451e8708c1 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c @@ -246,7 +246,7 @@ static int i2o_cfg_swdl(unsigned long arg) struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; unsigned char maxfrag = 0, curfrag = 1; struct i2o_dma buffer; - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; unsigned int status = 0, swlen = 0, fragsize = 8192; struct i2o_controller *c; @@ -320,7 +320,7 @@ static int i2o_cfg_swul(unsigned long arg) struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; unsigned char maxfrag = 0, curfrag = 1; struct i2o_dma buffer; - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; unsigned int status = 0, swlen = 0, fragsize = 8192; struct i2o_controller *c; @@ -400,7 +400,7 @@ static int i2o_cfg_swdel(unsigned long arg) struct i2o_controller *c; struct i2o_sw_xfer kxfer; struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; unsigned int swlen; int token; @@ -445,7 +445,7 @@ static int i2o_cfg_validate(unsigned long arg) { int token; int iop = (int)arg; - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; struct i2o_controller *c; @@ -476,7 +476,7 @@ static int i2o_cfg_validate(unsigned long arg) static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; struct i2o_evt_id __user *pdesc = (struct i2o_evt_id __user *)arg; struct i2o_evt_id kdesc; @@ -777,7 +777,7 @@ static int i2o_cfg_passthru(unsigned long arg) u32 i = 0; void *p = NULL; i2o_status_block *sb; - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; unsigned int iop; diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index cdffa12b3f20..69855ae299cf 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c @@ -299,7 +299,7 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m, cmd = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); if (msg->u.head[0] & (1 << 13)) { - struct i2o_message *pmsg; /* preserved message */ + struct i2o_message __iomem *pmsg; /* preserved message */ u32 pm; int err = DID_ERROR; @@ -541,10 +541,11 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, struct i2o_device *i2o_dev; struct device *dev; int tid; - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; u32 scsi_flags, sg_flags; - u32 *mptr, *lenptr; + u32 __iomem *mptr; + u32 __iomem *lenptr; u32 len, reqlen; int i; @@ -721,7 +722,7 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt) { struct i2o_device *i2o_dev; struct i2o_controller *c; - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; int tid; int status = FAILED; diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index fe0a5e61d1e3..ea6a8b371455 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c @@ -65,7 +65,7 @@ extern void i2o_device_exit(void); */ void i2o_msg_nop(struct i2o_controller *c, u32 m) { - struct i2o_message *msg = c->in_queue.virt + m; + struct i2o_message __iomem *msg = c->in_queue.virt + m; writel(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID, @@ -89,7 +89,7 @@ void i2o_msg_nop(struct i2o_controller *c, u32 m) * address from the read port (see the i2o spec). If no message is * available returns I2O_QUEUE_EMPTY and msg is leaved untouched. */ -u32 i2o_msg_get_wait(struct i2o_controller *c, struct i2o_message **msg, +u32 i2o_msg_get_wait(struct i2o_controller *c, struct i2o_message __iomem **msg, int wait) { unsigned long timeout = jiffies + wait * HZ; @@ -306,7 +306,7 @@ struct i2o_device *i2o_iop_find_device(struct i2o_controller *c, u16 tid) */ static int i2o_iop_quiesce(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; i2o_status_block *sb = c->status_block.virt; int rc; @@ -348,7 +348,7 @@ static int i2o_iop_quiesce(struct i2o_controller *c) */ static int i2o_iop_enable(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; i2o_status_block *sb = c->status_block.virt; int rc; @@ -420,7 +420,7 @@ static inline void i2o_iop_enable_all(void) */ static int i2o_iop_clear(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; int rc; @@ -461,7 +461,7 @@ static int i2o_iop_clear(struct i2o_controller *c) static int i2o_iop_reset(struct i2o_controller *c) { u8 *status = c->status.virt; - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; unsigned long timeout; i2o_status_block *sb = c->status_block.virt; @@ -570,7 +570,7 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c) { u8 *status = c->status.virt; u32 m; - struct i2o_message *msg; + struct i2o_message __iomem *msg; ulong timeout; int i; @@ -631,7 +631,7 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c) */ static int i2o_iop_send_nop(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m = i2o_msg_get_wait(c, &msg, HZ); if (m == I2O_QUEUE_EMPTY) return -ETIMEDOUT; @@ -734,7 +734,7 @@ static int i2o_iop_activate(struct i2o_controller *c) */ static int i2o_iop_systab_set(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; i2o_status_block *sb = c->status_block.virt; struct device *dev = &c->pdev->dev; @@ -997,7 +997,7 @@ static int i2o_parse_hrt(struct i2o_controller *c) */ int i2o_status_get(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; u8 *status_block; unsigned long timeout; @@ -1061,7 +1061,7 @@ static int i2o_hrt_get(struct i2o_controller *c) struct device *dev = &c->pdev->dev; for (i = 0; i < I2O_HRT_GET_TRIES; i++) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); @@ -1216,7 +1216,7 @@ int i2o_event_register(struct i2o_device *dev, struct i2o_driver *drv, int tcntxt, u32 evt_mask) { struct i2o_controller *c = dev->iop; - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); diff --git a/include/linux/i2o.h b/include/linux/i2o.h index b8fc7587498a..777a80f9f4a3 100644 --- a/include/linux/i2o.h +++ b/include/linux/i2o.h @@ -162,9 +162,9 @@ struct i2o_controller { struct notifier_block *event_notifer; /* Events */ atomic_t users; struct list_head list; /* Controller list */ - void *post_port; /* Inbout port address */ - void *reply_port; /* Outbound port address */ - void *irq_mask; /* Interrupt register address */ + void __iomem *post_port; /* Inbout port address */ + void __iomem *reply_port; /* Outbound port address */ + void __iomem *irq_mask; /* Interrupt register address */ /* Dynamic LCT related data */ @@ -241,8 +241,8 @@ struct i2o_sys_tbl { extern struct list_head i2o_controllers; /* Message functions */ -static inline u32 i2o_msg_get(struct i2o_controller *, struct i2o_message **); -extern u32 i2o_msg_get_wait(struct i2o_controller *, struct i2o_message **, +static inline u32 i2o_msg_get(struct i2o_controller *, struct i2o_message __iomem **); +extern u32 i2o_msg_get_wait(struct i2o_controller *, struct i2o_message __iomem **, int); static inline void i2o_msg_post(struct i2o_controller *, u32); static inline int i2o_msg_post_wait(struct i2o_controller *, u32, @@ -443,7 +443,7 @@ static inline void I2O_IRQ_WRITE32(struct i2o_controller *c, u32 val) * available returns I2O_QUEUE_EMPTY and msg is leaved untouched. */ static inline u32 i2o_msg_get(struct i2o_controller *c, - struct i2o_message **msg) + struct i2o_message __iomem **msg) { u32 m; @@ -530,7 +530,7 @@ static inline struct i2o_message *i2o_msg_out_to_virt(struct i2o_controller *c, * 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, +static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct i2o_controller *c, u32 m) { return c->in_queue.virt + m; -- cgit v1.2.3 From a81c67e199a64b45f8ad56fd2e74eb289d7f0b04 Mon Sep 17 00:00:00 2001 From: Antonino Daplas Date: Sun, 21 Nov 2004 01:22:42 -0800 Subject: [PATCH] fbdev: Add NV30 pci_id and cleanup of probe error returns From Guido Guenther this patch against 2.6.10-rc2 finally detects rivafb on NV30 based power books by adding the pciid. Wolfram Quester tested it and reported it working. It also cleans up the error code reported from the probe function. From Antonino Daplas - do not validate mode if monitor specifications are not available Signed-Off-By: Guido Guenther Signed-off-by: Antonino Daplas Signed-off-by: Linus Torvalds --- drivers/video/riva/fbdev.c | 73 +++++++++++++++++++++++++++------------------- include/linux/pci_ids.h | 1 + 2 files changed, 44 insertions(+), 30 deletions(-) (limited to 'include/linux') diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index 0caa909c80f4..cc24d1c780c1 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c @@ -192,6 +192,8 @@ static struct pci_device_id rivafb_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0, } /* terminate list */ }; MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl); @@ -1110,7 +1112,8 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) } if (!strictmode) { - if (!fb_validate_mode(var, info)) + if (!info->monspecs.vfmax || !info->monspecs.hfmax || + !info->monspecs.dclkmax || !fb_validate_mode(var, info)) mode_valid = 1; } @@ -1894,31 +1897,37 @@ static int __devinit rivafb_probe(struct pci_dev *pd, { struct riva_par *default_par; struct fb_info *info; + int ret; NVTRACE_ENTER(); assert(pd != NULL); info = framebuffer_alloc(sizeof(struct riva_par), &pd->dev); - - if (!info) - goto err_out; - + if (!info) { + printk (KERN_ERR PFX "could not allocate memory\n"); + ret = -ENOMEM; + goto err_ret; + } default_par = (struct riva_par *) info->par; default_par->pdev = pd; info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL); - if (info->pixmap.addr == NULL) - goto err_out_kfree; + if (info->pixmap.addr == NULL) { + ret = -ENOMEM; + goto err_framebuffer_release; + } memset(info->pixmap.addr, 0, 8 * 1024); - if (pci_enable_device(pd)) { + ret = pci_enable_device(pd); + if (ret < 0) { printk(KERN_ERR PFX "cannot enable PCI device\n"); - goto err_out_enable; + goto err_free_pixmap; } - if (pci_request_regions(pd, "rivafb")) { + ret = pci_request_regions(pd, "rivafb"); + if (ret < 0) { printk(KERN_ERR PFX "cannot request PCI regions\n"); - goto err_out_request; + goto err_disable_device; } default_par->riva.Architecture = riva_get_arch(pd); @@ -1932,7 +1941,8 @@ static int __devinit rivafb_probe(struct pci_dev *pd, if(default_par->riva.Architecture == 0) { printk(KERN_ERR PFX "unknown NV_ARCH\n"); - goto err_out_free_base0; + ret=-ENODEV; + goto err_release_region; } if(default_par->riva.Architecture == NV_ARCH_10 || default_par->riva.Architecture == NV_ARCH_20 || @@ -1966,11 +1976,10 @@ static int __devinit rivafb_probe(struct pci_dev *pd, rivafb_fix.mmio_len); if (!default_par->ctrl_base) { printk(KERN_ERR PFX "cannot ioremap MMIO base\n"); - goto err_out_free_base0; + ret = -EIO; + goto err_release_region; } - info->par = default_par; - switch (default_par->riva.Architecture) { case NV_ARCH_03: /* Riva128's PRAMIN is in the "framebuffer" space @@ -1980,7 +1989,8 @@ static int __devinit rivafb_probe(struct pci_dev *pd, default_par->riva.PRAMIN = ioremap(rivafb_fix.smem_start + 0x00C00000, 0x00008000); if (!default_par->riva.PRAMIN) { printk(KERN_ERR PFX "cannot ioremap PRAMIN region\n"); - goto err_out_free_nv3_pramin; + ret = -EIO; + goto err_iounmap_ctrl_base; } break; case NV_ARCH_04: @@ -2006,7 +2016,8 @@ static int __devinit rivafb_probe(struct pci_dev *pd, rivafb_fix.smem_len); if (!info->screen_base) { printk(KERN_ERR PFX "cannot ioremap FB base\n"); - goto err_out_free_base1; + ret = -EIO; + goto err_iounmap_pramin; } #ifdef CONFIG_MTRR @@ -2029,17 +2040,19 @@ static int __devinit rivafb_probe(struct pci_dev *pd, riva_get_EDID(info, pd); riva_get_edidinfo(info); - if (riva_set_fbinfo(info) < 0) { + ret=riva_set_fbinfo(info); + if (ret < 0) { printk(KERN_ERR PFX "error setting initial video mode\n"); - goto err_out_iounmap_fb; + goto err_iounmap_screen_base; } fb_destroy_modedb(info->monspecs.modedb); info->monspecs.modedb = NULL; - if (register_framebuffer(info) < 0) { + ret = register_framebuffer(info); + if (ret < 0) { printk(KERN_ERR PFX "error registering riva framebuffer\n"); - goto err_out_iounmap_fb; + goto err_iounmap_screen_base; } pci_set_drvdata(pd, info); @@ -2058,26 +2071,26 @@ static int __devinit rivafb_probe(struct pci_dev *pd, NVTRACE_LEAVE(); return 0; -err_out_iounmap_fb: +err_iounmap_screen_base: #ifdef CONFIG_FB_RIVA_I2C riva_delete_i2c_busses((struct riva_par *) info->par); #endif iounmap(info->screen_base); -err_out_free_base1: +err_iounmap_pramin: if (default_par->riva.Architecture == NV_ARCH_03) iounmap(default_par->riva.PRAMIN); -err_out_free_nv3_pramin: +err_iounmap_ctrl_base: iounmap(default_par->ctrl_base); -err_out_free_base0: +err_release_region: pci_release_regions(pd); -err_out_request: +err_disable_device: pci_disable_device(pd); -err_out_enable: +err_free_pixmap: kfree(info->pixmap.addr); -err_out_kfree: +err_framebuffer_release: framebuffer_release(info); -err_out: - return -ENODEV; +err_ret: + return ret; } static void __exit rivafb_remove(struct pci_dev *pd) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index e820dfb66b31..e1342df677ca 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1142,6 +1142,7 @@ #define PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL 0x0258 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL 0x0259 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL 0x025B +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200 0x0329 #define PCI_VENDOR_ID_IMS 0x10e0 #define PCI_DEVICE_ID_IMS_8849 0x8849 -- cgit v1.2.3 From be3e0da98d860f6d2d04ec35c8495aaa3b077782 Mon Sep 17 00:00:00 2001 From: "Tim T. Murphy" Date: Sun, 21 Nov 2004 16:43:12 -0800 Subject: [PATCH] serial: add support for Dell Remote Access Card 4. Here's a patch to include Dell's 4th generation Remote Access Controller ids. Acked-by: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/8250_pci.c | 7 +++++++ include/linux/pci_ids.h | 1 + 2 files changed, 8 insertions(+) (limited to 'include/linux') diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 0e56087742ee..11ed840476d7 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -2115,6 +2115,13 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_1_460800 }, + /* + * Dell Remote Access Card 4 - Tim_T_Murphy@Dell.com + */ + { PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RAC4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_1_1382400 }, + /* * Dell Remote Access Card III - Tim_T_Murphy@Dell.com */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index e1342df677ca..5cfcf8941445 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -523,6 +523,7 @@ #define PCI_VENDOR_ID_DELL 0x1028 #define PCI_DEVICE_ID_DELL_RACIII 0x0008 +#define PCI_DEVICE_ID_DELL_RAC4 0x0012 #define PCI_VENDOR_ID_MATROX 0x102B #define PCI_DEVICE_ID_MATROX_MGA_2 0x0518 -- cgit v1.2.3 From 4c089f74e9901c4b3fb85f6f461270e3dbecfed0 Mon Sep 17 00:00:00 2001 From: Michael Obster Date: Sun, 21 Nov 2004 16:44:01 -0800 Subject: [PATCH] mc146818rtc.h include fix Prevents user-space including spinlock.h which breaks the build. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mc146818rtc.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/mc146818rtc.h b/include/linux/mc146818rtc.h index cde7dbae375e..bbc93ae217e1 100644 --- a/include/linux/mc146818rtc.h +++ b/include/linux/mc146818rtc.h @@ -13,10 +13,12 @@ #include #include /* get the user-level API */ -#include /* spinlock_t */ #include /* register access macros */ +#ifdef __KERNEL__ +#include /* spinlock_t */ extern spinlock_t rtc_lock; /* serialize CMOS RAM access */ +#endif /********************************************************************** * register summary -- cgit v1.2.3 From 75a07ab9add5482ebc1c5a105e402cb646b9caaa Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 23 Nov 2004 07:58:26 -0800 Subject: [DIO]: Fix typo in dio_resource_len() Signed-off-by: Geert Uytterhoeven Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- include/linux/dio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/dio.h b/include/linux/dio.h index d42c86b9608d..fae9395fcf4f 100644 --- a/include/linux/dio.h +++ b/include/linux/dio.h @@ -254,7 +254,7 @@ static inline struct dio_driver *dio_dev_driver(const struct dio_dev *d) #define dio_resource_start(d) ((d)->resource.start) #define dio_resource_end(d) ((d)->resource.end) -#define dio_resource_len(d) ((d)->resource.end-(z)->resource.start+1) +#define dio_resource_len(d) ((d)->resource.end-(d)->resource.start+1) #define dio_resource_flags(d) ((d)->resource.flags) #define dio_request_device(d, name) \ -- cgit v1.2.3 From 0e0ae575da800ec86978bf86443144a5bda169e0 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 24 Nov 2004 23:58:26 -0800 Subject: [PATCH] dont deprecate MODULE_PARM Let's revert this for now so all those warnings do not soil our 2.6.10 release. We'll get Rusty's kernel-wide-sweep fixup patches in for 2.6.11, and then we can put this warning back. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/module.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/module.h b/include/linux/module.h index 59aebb15be2a..c8dd7b8495c6 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -559,7 +559,7 @@ struct obsolete_modparm { void *addr; }; -static inline void __deprecated MODULE_PARM_(void) { } +static inline void MODULE_PARM_(void) { } #ifdef MODULE /* DEPRECATED: Do not use. */ #define MODULE_PARM(var,type) \ -- cgit v1.2.3 From 3b5390826a85bad36012fe78c3052794ae418e54 Mon Sep 17 00:00:00 2001 From: Zou Nanhai Date: Thu, 25 Nov 2004 00:00:28 -0800 Subject: [PATCH] ia64/x86_64/s390 overlapping vma fix IA64 is also vulnerable to the huge-vma-in-executable bug in 64 bit elf support, it just insert a vma of zero page without checking overlap, so user can construct a elf with section begin from 0x0 to trigger this BUGON(). However, I think it's safe to check overlap before we actually insert a vma into vma list. And I also feel check vma overlap everywhere is unnecessary, because invert_vm_struct will check it again, so the check is duplicated. It's better to have invert_vm_struct return a value then let caller check if it successes. Here is a patch against 2.6.10.rc2-mm3 I have tested it on i386, x86_64 and ia64 machines. Signed-off-by: Tony Luck Signed-off-by: Zou Nan hai Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/ia32/binfmt_elf32.c | 26 +++++++++++++++++++++----- arch/ia64/mm/init.c | 16 ++++++++++++++-- arch/s390/kernel/compat_exec.c | 8 ++++++-- arch/x86_64/ia32/ia32_binfmt.c | 8 ++++++-- fs/exec.c | 9 +++------ include/linux/mm.h | 2 +- mm/mmap.c | 5 +++-- 7 files changed, 54 insertions(+), 20 deletions(-) (limited to 'include/linux') diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c index a4da6a93d604..ca468cd95d10 100644 --- a/arch/ia64/ia32/binfmt_elf32.c +++ b/arch/ia64/ia32/binfmt_elf32.c @@ -100,7 +100,11 @@ ia64_elf32_init (struct pt_regs *regs) vma->vm_ops = &ia32_shared_page_vm_ops; down_write(¤t->mm->mmap_sem); { - insert_vm_struct(current->mm, vma); + if (insert_vm_struct(current->mm, vma)) { + kmem_cache_free(vm_area_cachep, vma); + up_write(¤t->mm->mmap_sem); + return; + } } up_write(¤t->mm->mmap_sem); } @@ -123,7 +127,11 @@ ia64_elf32_init (struct pt_regs *regs) vma->vm_ops = &ia32_gate_page_vm_ops; down_write(¤t->mm->mmap_sem); { - insert_vm_struct(current->mm, vma); + if (insert_vm_struct(current->mm, vma)) { + kmem_cache_free(vm_area_cachep, vma); + up_write(¤t->mm->mmap_sem); + return; + } } up_write(¤t->mm->mmap_sem); } @@ -142,7 +150,11 @@ ia64_elf32_init (struct pt_regs *regs) vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE; down_write(¤t->mm->mmap_sem); { - insert_vm_struct(current->mm, vma); + if (insert_vm_struct(current->mm, vma)) { + kmem_cache_free(vm_area_cachep, vma); + up_write(¤t->mm->mmap_sem); + return; + } } up_write(¤t->mm->mmap_sem); } @@ -190,7 +202,7 @@ ia32_setup_arg_pages (struct linux_binprm *bprm, int executable_stack) unsigned long stack_base; struct vm_area_struct *mpnt; struct mm_struct *mm = current->mm; - int i; + int i, ret; stack_base = IA32_STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE; mm->arg_start = bprm->p + stack_base; @@ -225,7 +237,11 @@ ia32_setup_arg_pages (struct linux_binprm *bprm, int executable_stack) mpnt->vm_flags = VM_STACK_FLAGS; mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC)? PAGE_COPY_EXEC: PAGE_COPY; - insert_vm_struct(current->mm, mpnt); + if ((ret = insert_vm_struct(current->mm, mpnt))) { + up_write(¤t->mm->mmap_sem); + kmem_cache_free(vm_area_cachep, mpnt); + return ret; + } current->mm->stack_vm = current->mm->total_vm = vma_pages(mpnt); } diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index f7c6ddbf4ca3..a28351534325 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -131,7 +131,13 @@ ia64_init_addr_space (void) vma->vm_end = vma->vm_start + PAGE_SIZE; vma->vm_page_prot = protection_map[VM_DATA_DEFAULT_FLAGS & 0x7]; vma->vm_flags = VM_DATA_DEFAULT_FLAGS | VM_GROWSUP; - insert_vm_struct(current->mm, vma); + down_write(¤t->mm->mmap_sem); + if (insert_vm_struct(current->mm, vma)) { + up_write(¤t->mm->mmap_sem); + kmem_cache_free(vm_area_cachep, vma); + return; + } + up_write(¤t->mm->mmap_sem); } /* map NaT-page at address zero to speed up speculative dereferencing of NULL: */ @@ -143,7 +149,13 @@ ia64_init_addr_space (void) vma->vm_end = PAGE_SIZE; vma->vm_page_prot = __pgprot(pgprot_val(PAGE_READONLY) | _PAGE_MA_NAT); vma->vm_flags = VM_READ | VM_MAYREAD | VM_IO | VM_RESERVED; - insert_vm_struct(current->mm, vma); + down_write(¤t->mm->mmap_sem); + if (insert_vm_struct(current->mm, vma)) { + up_write(¤t->mm->mmap_sem); + kmem_cache_free(vm_area_cachep, vma); + return; + } + up_write(¤t->mm->mmap_sem); } } } diff --git a/arch/s390/kernel/compat_exec.c b/arch/s390/kernel/compat_exec.c index b4049a3dd396..51b294d33680 100644 --- a/arch/s390/kernel/compat_exec.c +++ b/arch/s390/kernel/compat_exec.c @@ -39,7 +39,7 @@ int setup_arg_pages32(struct linux_binprm *bprm, int executable_stack) unsigned long stack_base; struct vm_area_struct *mpnt; struct mm_struct *mm = current->mm; - int i; + int i, ret; stack_base = STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE; mm->arg_start = bprm->p + stack_base; @@ -68,7 +68,11 @@ int setup_arg_pages32(struct linux_binprm *bprm, int executable_stack) /* executable stack setting would be applied here */ mpnt->vm_page_prot = PAGE_COPY; mpnt->vm_flags = VM_STACK_FLAGS; - insert_vm_struct(mm, mpnt); + if ((ret = insert_vm_struct(mm, mpnt))) { + up_write(&mm->mmap_sem); + kmem_cache_free(vm_area_cachep, mpnt); + return ret; + } mm->stack_vm = mm->total_vm = vma_pages(mpnt); } diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c index b2ef6299812a..1abc95c54869 100644 --- a/arch/x86_64/ia32/ia32_binfmt.c +++ b/arch/x86_64/ia32/ia32_binfmt.c @@ -334,7 +334,7 @@ int setup_arg_pages(struct linux_binprm *bprm, int executable_stack) unsigned long stack_base; struct vm_area_struct *mpnt; struct mm_struct *mm = current->mm; - int i; + int i, ret; stack_base = IA32_STACK_TOP - MAX_ARG_PAGES * PAGE_SIZE; mm->arg_start = bprm->p + stack_base; @@ -368,7 +368,11 @@ int setup_arg_pages(struct linux_binprm *bprm, int executable_stack) mpnt->vm_flags = VM_STACK_FLAGS; mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC) ? PAGE_COPY_EXEC : PAGE_COPY; - insert_vm_struct(mm, mpnt); + if ((ret = insert_vm_struct(mm, mpnt))) { + up_write(&mm->mmap_sem); + kmem_cache_free(vm_area_cachep, mpnt); + return ret; + } mm->stack_vm = mm->total_vm = vma_pages(mpnt); } diff --git a/fs/exec.c b/fs/exec.c index 74d32c5a60e5..dd1c43b6f975 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -342,7 +342,7 @@ int setup_arg_pages(struct linux_binprm *bprm, int executable_stack) unsigned long stack_base; struct vm_area_struct *mpnt; struct mm_struct *mm = current->mm; - int i; + int i, ret; long arg_size; #ifdef CONFIG_STACK_GROWSUP @@ -413,7 +413,6 @@ int setup_arg_pages(struct linux_binprm *bprm, int executable_stack) down_write(&mm->mmap_sem); { - struct vm_area_struct *vma; mpnt->vm_mm = mm; #ifdef CONFIG_STACK_GROWSUP mpnt->vm_start = stack_base; @@ -434,13 +433,11 @@ int setup_arg_pages(struct linux_binprm *bprm, int executable_stack) mpnt->vm_flags = VM_STACK_FLAGS; mpnt->vm_flags |= mm->def_flags; mpnt->vm_page_prot = protection_map[mpnt->vm_flags & 0x7]; - vma = find_vma(mm, mpnt->vm_start); - if (vma) { + if ((ret = insert_vm_struct(mm, mpnt))) { up_write(&mm->mmap_sem); kmem_cache_free(vm_area_cachep, mpnt); - return -ENOMEM; + return ret; } - insert_vm_struct(mm, mpnt); mm->stack_vm = mm->total_vm = vma_pages(mpnt); } diff --git a/include/linux/mm.h b/include/linux/mm.h index 04fa8eea9268..ad76b8d51800 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -675,7 +675,7 @@ extern struct vm_area_struct *vma_merge(struct mm_struct *, extern struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *); extern int split_vma(struct mm_struct *, struct vm_area_struct *, unsigned long addr, int new_below); -extern void insert_vm_struct(struct mm_struct *, struct vm_area_struct *); +extern int insert_vm_struct(struct mm_struct *, struct vm_area_struct *); extern void __vma_link_rb(struct mm_struct *, struct vm_area_struct *, struct rb_node **, struct rb_node *); extern struct vm_area_struct *copy_vma(struct vm_area_struct **, diff --git a/mm/mmap.c b/mm/mmap.c index b55f5f534b65..54f6a2f9966f 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1871,7 +1871,7 @@ void exit_mmap(struct mm_struct *mm) * and into the inode's i_mmap tree. If vm_file is non-NULL * then i_mmap_lock is taken here. */ -void insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma) +int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma) { struct vm_area_struct * __vma, * prev; struct rb_node ** rb_link, * rb_parent; @@ -1894,8 +1894,9 @@ void insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma) } __vma = find_vma_prepare(mm,vma->vm_start,&prev,&rb_link,&rb_parent); if (__vma && __vma->vm_start < vma->vm_end) - BUG(); + return -ENOMEM; vma_link(mm, vma, prev, rb_link, rb_parent); + return 0; } /* -- cgit v1.2.3