aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/bus.c21
-rw-r--r--drivers/base/dd.c8
-rw-r--r--drivers/block/floppy.c6
-rw-r--r--drivers/char/agp/amd64-agp.c4
-rw-r--r--drivers/char/agp/backend.c2
-rw-r--r--drivers/char/agp/via-agp.c6
-rw-r--r--drivers/char/drm/drm_lock.c16
-rw-r--r--drivers/char/drm/drm_memory.c2
-rw-r--r--drivers/char/drm/drm_memory_debug.h2
-rw-r--r--drivers/char/drm/mga_drv.c2
-rw-r--r--drivers/char/drm/radeon_drv.h3
-rw-r--r--drivers/cpufreq/cpufreq.c14
-rw-r--r--drivers/firmware/Kconfig1
-rw-r--r--drivers/hwmon/hdaps.c2
-rw-r--r--drivers/hwmon/it87.c7
-rw-r--r--drivers/hwmon/lm78.c2
-rw-r--r--drivers/hwmon/w83627hf.c8
-rw-r--r--drivers/ieee1394/sbp2.c6
-rw-r--r--drivers/infiniband/core/mad.c4
-rw-r--r--drivers/input/gameport/gameport.c12
-rw-r--r--drivers/input/input.c63
-rw-r--r--drivers/input/keyboard/atkbd.c99
-rw-r--r--drivers/input/misc/Kconfig10
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/uinput.c325
-rw-r--r--drivers/input/misc/wistron_btns.c561
-rw-r--r--drivers/input/serio/serio.c12
-rw-r--r--drivers/md/dm-bio-list.h3
-rw-r--r--drivers/md/dm-ioctl.c3
-rw-r--r--drivers/md/dm-log.c4
-rw-r--r--drivers/md/dm-mpath.c13
-rw-r--r--drivers/md/dm-raid1.c20
-rw-r--r--drivers/md/md.c4
-rw-r--r--drivers/md/raid1.c8
-rw-r--r--drivers/md/raid10.c6
-rw-r--r--drivers/md/raid5.c2
-rw-r--r--drivers/md/raid6main.c27
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c2
-rw-r--r--drivers/media/video/Kconfig2
-rw-r--r--drivers/media/video/cx88/Kconfig20
-rw-r--r--drivers/media/video/cx88/Makefile27
-rw-r--r--drivers/media/video/ir-kbd-gpio.c5
-rw-r--r--drivers/media/video/saa7134/Kconfig12
-rw-r--r--drivers/media/video/saa7134/Makefile19
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c2
-rw-r--r--drivers/message/i2o/pci.c2
-rw-r--r--drivers/mmc/mmc.c2
-rw-r--r--drivers/net/dgrs.c2
-rw-r--r--drivers/pci/hotplug/pciehp.h1
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c15
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c10
-rw-r--r--drivers/pci/pci-acpi.c1
-rw-r--r--drivers/pcmcia/m32r_cfc.c3
-rw-r--r--drivers/sbus/char/aurora.c12
-rw-r--r--drivers/scsi/dpt_i2o.c9
-rw-r--r--drivers/scsi/libata-core.c20
-rw-r--r--drivers/scsi/scsi.c2
-rw-r--r--drivers/serial/8250.c2
-rw-r--r--drivers/serial/8250_pci.c2
-rw-r--r--drivers/serial/imx.c2
-rw-r--r--drivers/serial/serial_core.c2
-rw-r--r--drivers/serial/serial_cs.c6
-rw-r--r--drivers/usb/core/hcd-pci.c38
-rw-r--r--drivers/usb/core/hub.c1
-rw-r--r--drivers/usb/host/ehci-hcd.c160
-rw-r--r--drivers/usb/host/ehci-hub.c7
-rw-r--r--drivers/usb/host/ehci-pci.c359
-rw-r--r--drivers/usb/host/ohci-pci.c36
-rw-r--r--drivers/usb/media/sn9c102_core.c2
-rw-r--r--drivers/usb/serial/ftdi_sio.c2
-rw-r--r--drivers/usb/serial/ftdi_sio.h7
-rw-r--r--drivers/usb/serial/ipw.c1
-rw-r--r--drivers/usb/storage/unusual_devs.h9
-rw-r--r--drivers/video/console/fbcon_ccw.c2
-rw-r--r--drivers/video/console/fbcon_rotate.h17
-rw-r--r--drivers/video/console/vgacon.c1
-rw-r--r--drivers/video/fbmem.c6
77 files changed, 1407 insertions, 712 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 03204bfd17a..fa601b085eb 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -133,7 +133,7 @@ static struct kobj_type ktype_bus = {
decl_subsys(bus, &ktype_bus, NULL);
-/* Manually detach a device from it's associated driver. */
+/* Manually detach a device from its associated driver. */
static int driver_helper(struct device *dev, void *data)
{
const char *name = data;
@@ -151,14 +151,13 @@ static ssize_t driver_unbind(struct device_driver *drv,
int err = -ENODEV;
dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
- if ((dev) &&
- (dev->driver == drv)) {
+ if (dev && dev->driver == drv) {
device_release_driver(dev);
err = count;
}
- if (err)
- return err;
- return count;
+ put_device(dev);
+ put_bus(bus);
+ return err;
}
static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
@@ -175,16 +174,14 @@ static ssize_t driver_bind(struct device_driver *drv,
int err = -ENODEV;
dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
- if ((dev) &&
- (dev->driver == NULL)) {
+ if (dev && dev->driver == NULL) {
down(&dev->sem);
err = driver_probe_device(drv, dev);
up(&dev->sem);
- put_device(dev);
}
- if (err)
- return err;
- return count;
+ put_device(dev);
+ put_bus(bus);
+ return err;
}
static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 3565e979530..3b419c9a1e7 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -62,7 +62,6 @@ void device_bind_driver(struct device * dev)
* because we don't know the format of the ID structures, nor what
* is to be considered a match and what is not.
*
- *
* This function returns 1 if a match is found, an error if one
* occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.
*
@@ -158,7 +157,6 @@ static int __driver_attach(struct device * dev, void * data)
driver_probe_device(drv, dev);
up(&dev->sem);
-
return 0;
}
@@ -225,15 +223,15 @@ void driver_detach(struct device_driver * drv)
struct device * dev;
for (;;) {
- spin_lock_irq(&drv->klist_devices.k_lock);
+ spin_lock(&drv->klist_devices.k_lock);
if (list_empty(&drv->klist_devices.k_list)) {
- spin_unlock_irq(&drv->klist_devices.k_lock);
+ spin_unlock(&drv->klist_devices.k_lock);
break;
}
dev = list_entry(drv->klist_devices.k_list.prev,
struct device, knode_driver.n_node);
get_device(dev);
- spin_unlock_irq(&drv->klist_devices.k_lock);
+ spin_unlock(&drv->klist_devices.k_lock);
down(&dev->sem);
if (dev->driver == drv)
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 13b8a9bed66..f7e765a1d31 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3714,12 +3714,6 @@ static int floppy_open(struct inode *inode, struct file *filp)
USETF(FD_VERIFY);
}
- /* set underlying gendisk policy to reflect real ro/rw status */
- if (UTESTF(FD_DISK_WRITABLE))
- inode->i_bdev->bd_disk->policy = 0;
- else
- inode->i_bdev->bd_disk->policy = 1;
-
if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (filp->f_flags & O_EXCL)))
goto out2;
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 76589782adc..810679dcbbb 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -416,7 +416,7 @@ static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data
}
-static struct aper_size_info_32 uli_sizes[7] =
+static const struct aper_size_info_32 uli_sizes[7] =
{
{256, 65536, 6, 10},
{128, 32768, 5, 9},
@@ -470,7 +470,7 @@ static int __devinit uli_agp_init(struct pci_dev *pdev)
}
-static struct aper_size_info_32 nforce3_sizes[5] =
+static const struct aper_size_info_32 nforce3_sizes[5] =
{
{512, 131072, 7, 0x00000000 },
{256, 65536, 6, 0x00000008 },
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 27bca34b4a6..80ee17a8fc2 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -97,7 +97,7 @@ void agp_backend_release(struct agp_bridge_data *bridge)
EXPORT_SYMBOL(agp_backend_release);
-static struct { int mem, agp; } maxes_table[] = {
+static const struct { int mem, agp; } maxes_table[] = {
{0, 0},
{32, 4},
{64, 28},
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index c847df575cf..97b0a890ba7 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -371,6 +371,11 @@ static struct agp_device_ids via_agp_device_ids[] __devinitdata =
.device_id = PCI_DEVICE_ID_VIA_3296_0,
.chipset_name = "P4M800",
},
+ /* P4M800CE */
+ {
+ .device_id = PCI_DEVICE_ID_VIA_P4M800CE,
+ .chipset_name = "P4M800CE",
+ },
{ }, /* dummy final entry, always present */
};
@@ -511,6 +516,7 @@ static struct pci_device_id agp_via_pci_table[] = {
ID(PCI_DEVICE_ID_VIA_3269_0),
ID(PCI_DEVICE_ID_VIA_83_87XX_1),
ID(PCI_DEVICE_ID_VIA_3296_0),
+ ID(PCI_DEVICE_ID_VIA_P4M800CE),
{ }
};
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c
index b276ae8a663..b48a595d54e 100644
--- a/drivers/char/drm/drm_lock.c
+++ b/drivers/char/drm/drm_lock.c
@@ -104,6 +104,10 @@ int drm_lock(struct inode *inode, struct file *filp,
__set_current_state(TASK_RUNNING);
remove_wait_queue(&dev->lock.lock_queue, &entry);
+ DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
+ if (ret)
+ return ret;
+
sigemptyset(&dev->sigmask);
sigaddset(&dev->sigmask, SIGSTOP);
sigaddset(&dev->sigmask, SIGTSTP);
@@ -116,8 +120,12 @@ int drm_lock(struct inode *inode, struct file *filp,
if (dev->driver->dma_ready && (lock.flags & _DRM_LOCK_READY))
dev->driver->dma_ready(dev);
- if (dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT))
- return dev->driver->dma_quiescent(dev);
+ if (dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT)) {
+ if (dev->driver->dma_quiescent(dev)) {
+ DRM_DEBUG("%d waiting for DMA quiescent\n", lock.context);
+ return DRM_ERR(EBUSY);
+ }
+ }
/* dev->driver->kernel_context_switch isn't used by any of the x86
* drivers but is used by the Sparc driver.
@@ -128,9 +136,7 @@ int drm_lock(struct inode *inode, struct file *filp,
dev->driver->kernel_context_switch(dev, dev->last_context,
lock.context);
}
- DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
-
- return ret;
+ return 0;
}
/**
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
index 2c74155aa84..abef2acf99f 100644
--- a/drivers/char/drm/drm_memory.c
+++ b/drivers/char/drm/drm_memory.c
@@ -95,7 +95,7 @@ unsigned long drm_alloc_pages(int order, int area)
unsigned long addr;
unsigned int sz;
- address = __get_free_pages(GFP_KERNEL, order);
+ address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order);
if (!address)
return 0;
diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h
index 4542353195b..b370aca718d 100644
--- a/drivers/char/drm/drm_memory_debug.h
+++ b/drivers/char/drm/drm_memory_debug.h
@@ -221,7 +221,7 @@ unsigned long DRM(alloc_pages) (int order, int area) {
}
spin_unlock(&DRM(mem_lock));
- address = __get_free_pages(GFP_KERNEL, order);
+ address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order);
if (!address) {
spin_lock(&DRM(mem_lock));
++DRM(mem_stats)[area].fail_count;
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
index 0cc7c305a7f..1713451a5cc 100644
--- a/drivers/char/drm/mga_drv.c
+++ b/drivers/char/drm/mga_drv.c
@@ -161,7 +161,7 @@ static int mga_driver_device_is_agp(drm_device_t * dev)
* device.
*/
- if ((pdev->device == 0x0525)
+ if ((pdev->device == 0x0525) && pdev->bus->self
&& (pdev->bus->self->vendor == 0x3388)
&& (pdev->bus->self->device == 0x0021)) {
return 0;
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index 120ee5a8ebc..7bda7e33d2b 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -214,8 +214,6 @@ typedef struct drm_radeon_private {
int microcode_version;
- int is_pci;
-
struct {
u32 boxes;
int freelist_timeouts;
@@ -275,6 +273,7 @@ typedef struct drm_radeon_private {
/* starting from here on, data is preserved accross an open */
uint32_t flags; /* see radeon_chip_flags */
+ int is_pci;
} drm_radeon_private_t;
typedef struct drm_radeon_buf_priv {
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 23a63207d74..815902c2c85 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -693,8 +693,8 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
unsigned int cpu = sys_dev->id;
unsigned long flags;
struct cpufreq_policy *data;
- struct sys_device *cpu_sys_dev;
#ifdef CONFIG_SMP
+ struct sys_device *cpu_sys_dev;
unsigned int j;
#endif
@@ -1113,21 +1113,13 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
{
int retval = -EINVAL;
- /*
- * If we are already in context of hotplug thread, we dont need to
- * acquire the hotplug lock. Otherwise acquire cpucontrol to prevent
- * hotplug from removing this cpu that we are working on.
- */
- if (!current_in_cpu_hotplug())
- lock_cpu_hotplug();
-
+ lock_cpu_hotplug();
dprintk("target for CPU %u: %u kHz, relation %u\n", policy->cpu,
target_freq, relation);
if (cpu_online(policy->cpu) && cpufreq_driver->target)
retval = cpufreq_driver->target(policy, target_freq, relation);
- if (!current_in_cpu_hotplug())
- unlock_cpu_hotplug();
+ unlock_cpu_hotplug();
return retval;
}
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index b6815c6c29a..1e371a510dd 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -60,6 +60,7 @@ config EFI_PCDP
config DELL_RBU
tristate "BIOS update support for DELL systems via sysfs"
+ depends on X86
select FW_LOADER
help
Say m if you want to have the option of updating the BIOS for your
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index c81bd4bce1b..23a9e1ea8e3 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -570,7 +570,7 @@ static int __init hdaps_init(void)
hdaps_idev->evbit[0] = BIT(EV_ABS);
input_set_abs_params(hdaps_idev, ABS_X,
-256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT);
- input_set_abs_params(hdaps_idev, ABS_X,
+ input_set_abs_params(hdaps_idev, ABS_Y,
-256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT);
input_register_device(hdaps_idev);
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 6c41e25e670..a61f5d00f10 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -522,8 +522,15 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
+ u8 reg = it87_read_value(client, IT87_REG_FAN_DIV);
down(&data->update_lock);
+ switch (nr) {
+ case 0: data->fan_div[nr] = reg & 0x07; break;
+ case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break;
+ case 2: data->fan_div[nr] = (reg & 0x40) ? 3 : 1; break;
+ }
+
data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]);
up(&data->update_lock);
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index bde0cda9477..78cdd506439 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -451,7 +451,7 @@ static DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_3_div, NULL);
static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm78_data *data = lm78_update_device(dev);
- return sprintf(buf, "%d\n", vid_from_reg(82, data->vid));
+ return sprintf(buf, "%d\n", vid_from_reg(data->vid, 82));
}
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 4e9a04e1f08..bbb3dcde146 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -456,7 +456,9 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a
(w83627thf == data->type || w83637hf == data->type))
/* use VRM9 calculation */
- data->in_min[0] = (u8)(((val * 100) - 70000 + 244) / 488);
+ data->in_min[0] =
+ SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
+ 255);
else
/* use VRM8 (standard) calculation */
data->in_min[0] = IN_TO_REG(val);
@@ -481,7 +483,9 @@ static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *a
(w83627thf == data->type || w83637hf == data->type))
/* use VRM9 calculation */
- data->in_max[0] = (u8)(((val * 100) - 70000 + 244) / 488);
+ data->in_max[0] =
+ SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
+ 255);
else
/* use VRM8 (standard) calculation */
data->in_max[0] = IN_TO_REG(val);
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 12cec7c4a34..f7e18ccc5c0 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -2350,6 +2350,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
struct scsi_cmnd *SCpnt = NULL;
u32 scsi_status = SBP2_SCSI_STATUS_GOOD;
struct sbp2_command_info *command;
+ unsigned long flags;
SBP2_DEBUG("sbp2_handle_status_write");
@@ -2451,9 +2452,11 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
* null out last orb so that next time around we write directly to the orb pointer...
* Quick start saves one 1394 bus transaction.
*/
+ spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
if (list_empty(&scsi_id->sbp2_command_orb_inuse)) {
scsi_id->last_orb = NULL;
}
+ spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
} else {
@@ -2563,9 +2566,11 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id
struct sbp2scsi_host_info *hi = scsi_id->hi;
struct list_head *lh;
struct sbp2_command_info *command;
+ unsigned long flags;
SBP2_DEBUG("sbp2scsi_complete_all_commands");
+ spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
while (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
SBP2_DEBUG("Found pending command to complete");
lh = scsi_id->sbp2_command_orb_inuse.next;
@@ -2582,6 +2587,7 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id
command->Current_done(command->Current_SCpnt);
}
}
+ spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
return;
}
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 41d6b4017ac..d393b504bf2 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -355,9 +355,9 @@ error4:
spin_unlock_irqrestore(&port_priv->reg_lock, flags);
kfree(reg_req);
error3:
- kfree(mad_agent_priv);
-error2:
ib_dereg_mr(mad_agent_priv->agent.mr);
+error2:
+ kfree(mad_agent_priv);
error1:
return ret;
}
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 0506934244f..caac6d63d46 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -339,14 +339,20 @@ static struct gameport_event *gameport_get_event(void)
return event;
}
-static void gameport_handle_events(void)
+static void gameport_handle_event(void)
{
struct gameport_event *event;
struct gameport_driver *gameport_drv;
down(&gameport_sem);
- while ((event = gameport_get_event())) {
+ /*
+ * Note that we handle only one event here to give swsusp
+ * a chance to freeze kgameportd thread. Gameport events
+ * should be pretty rare so we are not concerned about
+ * taking performance hit.
+ */
+ if ((event = gameport_get_event())) {
switch (event->type) {
case GAMEPORT_REGISTER_PORT:
@@ -433,7 +439,7 @@ static struct gameport *gameport_get_pending_child(struct gameport *parent)
static int gameport_thread(void *nothing)
{
do {
- gameport_handle_events();
+ gameport_handle_event();
wait_event_interruptible(gameport_wait,
kthread_should_stop() || !list_empty(&gameport_event_list));
try_to_freeze();
diff --git a/drivers/input/input.c b/drivers/input/input.c
index c8ae2bb054e..bdd2a7fc268 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -536,7 +536,7 @@ static struct attribute *input_dev_attrs[] = {
NULL
};
-static struct attribute_group input_dev_group = {
+static struct attribute_group input_dev_attr_group = {
.attrs = input_dev_attrs,
};
@@ -717,35 +717,14 @@ struct input_dev *input_allocate_device(void)
return dev;
}
-static void input_register_classdevice(struct input_dev *dev)
-{
- static atomic_t input_no = ATOMIC_INIT(0);
- const char *path;
-
- __module_get(THIS_MODULE);
-
- dev->dev = dev->cdev.dev;
-
- snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
- "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
-
- path = kobject_get_path(&dev->cdev.class->subsys.kset.kobj, GFP_KERNEL);
- printk(KERN_INFO "input: %s as %s/%s\n",
- dev->name ? dev->name : "Unspecified device",
- path ? path : "", dev->cdev.class_id);
- kfree(path);
-
- class_device_add(&dev->cdev);
- sysfs_create_group(&dev->cdev.kobj, &input_dev_group);
- sysfs_create_group(&dev->cdev.kobj, &input_dev_id_attr_group);
- sysfs_create_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
-}
-
int input_register_device(struct input_dev *dev)
{
+ static atomic_t input_no = ATOMIC_INIT(0);
struct input_handle *handle;
struct input_handler *handler;
struct input_device_id *id;
+ const char *path;
+ int error;
if (!dev->dynalloc) {
printk(KERN_WARNING "input: device %s is statically allocated, will not register\n"
@@ -773,7 +752,32 @@ int input_register_device(struct input_dev *dev)
INIT_LIST_HEAD(&dev->h_list);
list_add_tail(&dev->node, &input_dev_list);
- input_register_classdevice(dev);
+ dev->cdev.class = &input_class;
+ snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
+ "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
+
+ error = class_device_add(&dev->cdev);
+ if (error)
+ return error;
+
+ error = sysfs_create_group(&dev->cdev.kobj, &input_dev_attr_group);
+ if (error)
+ goto fail1;
+
+ error = sysfs_create_group(&dev->cdev.kobj, &input_dev_id_attr_group);
+ if (error)
+ goto fail2;
+
+ error = sysfs_create_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
+ if (error)
+ goto fail3;
+
+ __module_get(THIS_MODULE);
+
+ path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+ printk(KERN_INFO "input: %s as %s\n",
+ dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
+ kfree(path);
list_for_each_entry(handler, &input_handler_list, node)
if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
@@ -784,6 +788,11 @@ int input_register_device(struct input_dev *dev)
input_wakeup_procfs_readers();
return 0;
+
+ fail3: sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
+ fail2: sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group);
+ fail1: class_device_del(&dev->cdev);
+ return error;
}
void input_unregister_device(struct input_dev *dev)
@@ -805,7 +814,7 @@ void input_unregister_device(struct input_dev *dev)
sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
- sysfs_remove_group(&dev->cdev.kobj, &input_dev_group);
+ sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group);
class_device_unregister(&dev->cdev);
input_wakeup_procfs_readers();
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 820c7fd9a60..a0256f8de8e 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -166,6 +166,9 @@ static unsigned char atkbd_unxlate_table[128] = {
#define ATKBD_SPECIAL 248
+#define ATKBD_LED_EVENT_BIT 0
+#define ATKBD_REP_EVENT_BIT 1
+
static struct {
unsigned char keycode;
unsigned char set2;
@@ -211,6 +214,10 @@ struct atkbd {
unsigned char err_xl;
unsigned int last;
unsigned long time;
+
+ struct work_struct event_work;
+ struct semaphore event_sem;
+ unsigned long event_mask;
};
static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
@@ -424,58 +431,86 @@ out:
}
/*
- * Event callback from the input module. Events that change the state of
- * the hardware are processed here.
+ * atkbd_event_work() is used to complete processing of events that
+ * can not be processed by input_event() which is often called from
+ * interrupt context.
*/
-static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+static void atkbd_event_work(void *data)
{
- struct atkbd *atkbd = dev->private;
const short period[32] =
{ 33, 37, 42, 46, 50, 54, 58, 63, 67, 75, 83, 92, 100, 109, 116, 125,
133, 149, 167, 182, 200, 217, 232, 250, 270, 303, 333, 370, 400, 435, 470, 500 };
const short delay[4] =
{ 250, 500, 750, 1000 };
+
+ struct atkbd *atkbd = data;
+ struct input_dev *dev = atkbd->dev;
unsigned char param[2];
int i, j;
+ down(&atkbd->event_sem);
+
+ if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) {
+ param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
+ | (test_bit(LED_NUML, dev->led) ? 2 : 0)
+ | (test_bit(LED_CAPSL, dev->led) ? 4 : 0);
+ ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS);
+
+ if (atkbd->extra) {
+ param[0] = 0;
+ param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0)
+ | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0)
+ | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0)
+ | (test_bit(LED_MISC, dev->led) ? 0x10 : 0)
+ | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0);
+ ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS);
+ }
+ }
+
+ if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask)) {
+ i = j = 0;
+ while (i < 31 && period[i] < dev->rep[REP_PERIOD])
+ i++;
+ while (j < 3 && delay[j] < dev->rep[REP_DELAY])
+ j++;
+ dev->rep[REP_PERIOD] = period[i];
+ dev->rep[REP_DELAY] = delay[j];
+ param[0] = i | (j << 5);
+ ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP);
+ }
+
+ up(&atkbd->event_sem);
+}
+
+/*
+ * Event callback from the input module. Events that change the state of
+ * the hardware are processed here. If action can not be performed in
+ * interrupt context it is offloaded to atkbd_event_work.
+ */
+
+static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+ struct atkbd *atkbd = dev->private;
+
if (!atkbd->write)
return -1;
switch (type) {
case EV_LED:
-
- param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
- | (test_bit(LED_NUML, dev->led) ? 2 : 0)
- | (test_bit(LED_CAPSL, dev->led) ? 4 : 0);
- ps2_schedule_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS);
-
- if (atkbd->extra) {
- param[0] = 0;
- param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0)
- | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0)
- | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0)
- | (test_bit(LED_MISC, dev->led) ? 0x10 : 0)
- | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0);
- ps2_schedule_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS);
- }
-
+ set_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask);
+ wmb();
+ schedule_work(&atkbd->event_work);
return 0;
case EV_REP:
- if (atkbd->softrepeat) return 0;
-
- i = j = 0;
- while (i < 31 && period[i] < dev->rep[REP_PERIOD])
- i++;
- while (j < 3 && delay[j] < dev->rep[REP_DELAY])
- j++;
- dev->rep[REP_PERIOD] = period[i];
- dev->rep[REP_DELAY] = delay[j];
- param[0] = i | (j << 5);
- ps2_schedule_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP);
+ if (!atkbd->softrepeat) {
+ set_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask);
+ wmb();
+ schedule_work(&atkbd->event_work);
+ }
return 0;
}
@@ -810,6 +845,8 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd->dev = dev;
ps2_init(&atkbd->ps2dev, serio);
+ INIT_WORK(&atkbd->event_work, atkbd_event_work, atkbd);
+ init_MUTEX(&atkbd->event_sem);
switch (serio->id.type) {
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index b3eaac1b35b..07813fc0523 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -40,6 +40,16 @@ config INPUT_M68K_BEEP
tristate "M68k Beeper support"
depends on M68K
+config INPUT_WISTRON_BTNS
+ tristate "x86 Wistron laptop button interface"
+ depends on X86 && !X86_64
+ help
+ Say Y here for support of Winstron laptop button interface, used on
+ laptops of various brands, including Acer and Fujitsu-Siemens.
+
+ To compile this driver as a module, choose M here: the module will
+ be called wistron_btns.
+
config INPUT_UINPUT
tristate "User level driver support"
help
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index f8d01c69f34..ce44cce0128 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -9,4 +9,5 @@ obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
obj-$(CONFIG_INPUT_98SPKR) += 98spkr.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
+obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 948c1cc01bc..546ed9b4901 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -92,24 +92,19 @@ static void uinput_request_done(struct uinput_device *udev, struct uinput_reques
{
/* Mark slot as available */
udev->requests[request->id] = NULL;
- wake_up_interruptible(&udev->requests_waitq);
+ wake_up(&udev->requests_waitq);
complete(&request->done);
}
static int uinput_request_submit(struct input_dev *dev, struct uinput_request *request)
{
- int retval;
-
/* Tell our userspace app about this new request by queueing an input event */
uinput_dev_event(dev, EV_UINPUT, request->code, request->id);
/* Wait for the request to complete */
- retval = wait_for_completion_interruptible(&request->done);
- if (!retval)
- retval = request->retval;
-
- return retval;
+ wait_for_completion(&request->done);
+ return request->retval;
}
static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect)
@@ -152,67 +147,62 @@ static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
return retval;
}
-static int uinput_create_device(struct uinput_device *udev)
+static void uinput_destroy_device(struct uinput_device *udev)
{
- if (!udev->dev->name) {
- printk(KERN_DEBUG "%s: write device info first\n", UINPUT_NAME);
- return -EINVAL;
+ const char *name, *phys;
+
+ if (udev->dev) {
+ name = udev->dev->name;
+ phys = udev->dev->phys;
+ if (udev->state == UIST_CREATED)
+ input_unregister_device(udev->dev);
+ else
+ input_free_device(udev->dev);
+ kfree(name);
+ kfree(phys);
+ udev->dev = NULL;
}
- udev->dev->event = uinput_dev_event;
- udev->dev->upload_effect = uinput_dev_upload_effect;
- udev->dev->erase_effect = uinput_dev_erase_effect;
- udev->dev->private = udev;
-
- init_waitqueue_head(&udev->waitq);
-
- input_register_device(udev->dev);
-
- set_bit(UIST_CREATED, &udev->state);
-
- return 0;
+ udev->state = UIST_NEW_DEVICE;
}
-static int uinput_destroy_device(struct uinput_device *udev)
+static int uinput_create_device(struct uinput_device *udev)
{
- if (!test_bit(UIST_CREATED, &udev->state)) {
- printk(KERN_WARNING "%s: create the device first\n", UINPUT_NAME);
+ int error;
+
+ if (udev->state != UIST_SETUP_COMPLETE) {
+ printk(KERN_DEBUG "%s: write device info first\n", UINPUT_NAME);
return -EINVAL;
}
- input_unregister_device(udev->dev);
+ error = input_register_device(udev->dev);
+ if (error) {
+ uinput_destroy_device(udev);
+ return error;
+ }
- clear_bit(UIST_CREATED, &udev->state);
+ udev->state = UIST_CREATED;
return 0;
}
static int uinput_open(struct inode *inode, struct file *file)
{
- struct uinput_device *newdev;
- struct input_dev *newinput;
+ struct uinput_device *newdev;
- newdev = kmalloc(sizeof(struct uinput_device), GFP_KERNEL);
+ newdev = kzalloc(sizeof(struct uinput_device), GFP_KERNEL);
if (!newdev)
- goto error;
- memset(newdev, 0, sizeof(struct uinput_device));
+ return -ENOMEM;
+
+ init_MUTEX(&newdev->sem);
spin_lock_init(&newdev->requests_lock);
init_waitqueue_head(&newdev->requests_waitq);
-
- newinput = kmalloc(sizeof(struct input_dev), GFP_KERNEL);
- if (!newinput)
- goto cleanup;
- memset(newinput, 0, sizeof(struct input_dev));
-
- newdev->dev = newinput;
+ init_waitqueue_head(&newdev->waitq);
+ newdev->state = UIST_NEW_DEVICE;
file->private_data = newdev;
return 0;
-cleanup:
- kfree(newdev);
-error:
- return -ENOMEM;
}
static int uinput_validate_absbits(struct input_dev *dev)
@@ -246,34 +236,55 @@ static int uinput_validate_absbits(struct input_dev *dev)
return retval;
}
-static int uinput_alloc_device(struct file *file, const char __user *buffer, size_t count)
+static int uinput_allocate_device(struct uinput_device *udev)
+{
+ udev->dev = input_allocate_device();
+ if (!udev->dev)
+ return -ENOMEM;
+
+ udev->dev->event = uinput_dev_event;
+ udev->dev->upload_effect = uinput_dev_upload_effect;
+ udev->dev->erase_effect = uinput_dev_erase_effect;
+ udev->dev->private = udev;
+
+ return 0;
+}
+
+static int uinput_setup_device(struct uinput_device *udev, const char __user *buffer, size_t count)
{
struct uinput_user_dev *user_dev;
struct input_dev *dev;
- struct uinput_device *udev;
char *name;
int size;
int retval;
- retval = count;
+ if (count != sizeof(struct uinput_user_dev))
+ return -EINVAL;
+
+ if (!udev->dev) {
+ retval = uinput_allocate_device(udev);
+ if (retval)
+ return retval;
+ }
- udev = file->private_data;
dev = udev->dev;
user_dev = kmalloc(sizeof(struct uinput_user_dev), GFP_KERNEL);
- if (!user_dev) {
- retval = -ENOMEM;
- goto exit;
- }
+ if (!user_dev)
+ return -ENOMEM;
if (copy_from_user(user_dev, buffer, sizeof(struct uinput_user_dev))) {
retval = -EFAULT;
goto exit;
}
- kfree(dev->name);
-
size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1;
+ if (!size) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ kfree(dev->name);
dev->name = name = kmalloc(size, GFP_KERNEL);
if (!name) {
retval = -ENOMEM;
@@ -296,32 +307,50 @@ static int uinput_alloc_device(struct file *file, const char __user *buffer, siz
/* check if absmin/absmax/absfuzz/absflat are filled as
* told in Documentation/input/input-programming.txt */
if (test_bit(EV_ABS, dev->evbit)) {
- int err = uinput_validate_absbits(dev);
- if (err < 0) {
- retval = err;
- kfree(dev->name);
- }
+ retval = uinput_validate_absbits(dev);
+ if (retval < 0)
+ goto exit;
}
-exit:
+ udev->state = UIST_SETUP_COMPLETE;
+ retval = count;
+
+ exit:
kfree(user_dev);
return retval;
}
+static inline ssize_t uinput_inject_event(struct uinput_device *udev, const char __user *buffer, size_t count)
+{
+ struct input_event ev;
+
+ if (count != sizeof(struct input_event))
+ return -EINVAL;
+
+ if (copy_from_user(&ev, buffer, sizeof(struct input_event)))
+ return -EFAULT;
+
+ input_event(udev->dev, ev.type, ev.code, ev.value);
+
+ return sizeof(struct input_event);
+}
+
static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
struct uinput_device *udev = file->private_data;
+ int retval;
+
+ retval = down_interruptible(&udev->sem);
+ if (retval)
+ return retval;
- if (test_bit(UIST_CREATED, &udev->state)) {
- struct input_event ev;
+ retval = udev->state == UIST_CREATED ?
+ uinput_inject_event(udev, buffer, count) :
+ uinput_setup_device(udev, buffer, count);
- if (copy_from_user(&ev, buffer, sizeof(struct input_event)))
- return -EFAULT;
- input_event(udev->dev, ev.type, ev.code, ev.value);
- } else
- count = uinput_alloc_device(file, buffer, count);
+ up(&udev->sem);
- return count;
+ return retval;
}
static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
@@ -329,28 +358,38 @@ static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count,
struct uinput_device *udev = file->private_data;
int retval = 0;
- if (!test_bit(UIST_CREATED, &udev->state))
+ if (udev->state != UIST_CREATED)
return -ENODEV;
if (udev->head == udev->tail && (file->f_flags & O_NONBLOCK))
return -EAGAIN;
retval = wait_event_interruptible(udev->waitq,
- udev->head != udev->tail || !test_bit(UIST_CREATED, &udev->state));
+ udev->head != udev->tail || udev->state != UIST_CREATED);
if (retval)
return retval;
- if (!test_bit(UIST_CREATED, &udev->state))
- return -ENODEV;
+ retval = down_interruptible(&udev->sem);
+ if (retval)
+ return retval;
- while ((udev->head != udev->tail) &&
- (retval + sizeof(struct input_event) <= count)) {
- if (copy_to_user(buffer + retval, &udev->buff[udev->tail], sizeof(struct input_event)))
- return -EFAULT;
+ if (udev->state != UIST_CREATED) {
+ retval = -ENODEV;
+ goto out;
+ }
+
+ while (udev->head != udev->tail && retval + sizeof(struct input_event) <= count) {
+ if (copy_to_user(buffer + retval, &udev->buff[udev->tail], sizeof(struct input_event))) {
+ retval = -EFAULT;
+ goto out;
+ }
udev->tail = (udev->tail + 1) % UINPUT_BUFFER_SIZE;
retval += sizeof(struct input_event);
}
+ out:
+ up(&udev->sem);
+
return retval;
}
@@ -366,28 +405,30 @@ static unsigned int uinput_poll(struct file *file, poll_table *wait)
return 0;
}
-static int uinput_burn_device(struct uinput_device *udev)
+static int uinput_release(struct inode *inode, struct file *file)
{
- if (test_bit(UIST_CREATED, &udev->state))
- uinput_destroy_device(udev);
+ struct uinput_device *udev = file->private_data;
- kfree(udev->dev->name);
- kfree(udev->dev->phys);
- kfree(udev->dev);
+ uinput_destroy_device(udev);
kfree(udev);
return 0;
}
-static int uinput_close(struct inode *inode, struct file *file)
+#define uinput_set_bit(_arg, _bit, _max) \
+({ \
+ int __ret = 0; \
+ if (udev->state == UIST_CREATED) \
+ __ret = -EINVAL; \
+ else if ((_arg) > (_max)) \
+ __ret = -EINVAL; \
+ else set_bit((_arg), udev->dev->_bit); \
+ __ret; \
+})
+
+static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- uinput_burn_device(file->private_data);
- return 0;
-}
-
-static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- int retval = 0;
+ int retval;
struct uinput_device *udev;
void __user *p = (void __user *)arg;
struct uinput_ff_upload ff_up;
@@ -398,19 +439,14 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
udev = file->private_data;
- /* device attributes can not be changed after the device is created */
- switch (cmd) {
- case UI_SET_EVBIT:
- case UI_SET_KEYBIT:
- case UI_SET_RELBIT:
- case UI_SET_ABSBIT:
- case UI_SET_MSCBIT:
- case UI_SET_LEDBIT:
- case UI_SET_SNDBIT:
- case UI_SET_FFBIT:
- case UI_SET_PHYS:
- if (test_bit(UIST_CREATED, &udev->state))
- return -EINVAL;
+ retval = down_interruptible(&udev->sem);
+ if (retval)
+ return retval;
+
+ if (!udev->dev) {
+ retval = uinput_allocate_device(udev);
+ if (retval)
+ goto out;
}
switch (cmd) {
@@ -419,74 +455,50 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
break;
case UI_DEV_DESTROY:
- retval = uinput_destroy_device(udev);
+ uinput_destroy_device(udev);
break;
case UI_SET_EVBIT:
- if (arg > EV_MAX) {
- retval = -EINVAL;
- break;
- }
- set_bit(arg, udev->dev->evbit);
+ retval = uinput_set_bit(arg, evbit, EV_MAX);
break;
case UI_SET_KEYBIT:
- if (arg > KEY_MAX) {
- retval = -EINVAL;
- break;
- }
- set_bit(arg, udev->dev->keybit);
+ retval = uinput_set_bit(arg, keybit, KEY_MAX);
break;
case UI_SET_RELBIT:
- if (arg > REL_MAX) {
- retval = -EINVAL;
- break;
- }
- set_bit(arg, udev->dev->relbit);
+ retval = uinput_set_bit(arg, relbit, REL_MAX);
break;
case UI_SET_ABSBIT:
- if (arg > ABS_MAX) {
- retval = -EINVAL;
- break;
- }
- set_bit(arg, udev->dev->absbit);
+ retval = uinput_set_bit(arg, absbit, ABS_MAX);
break;
case UI_SET_MSCBIT:
- if (arg > MSC_MAX) {
- retval = -EINVAL;
- break;
- }
- set_bit(arg, udev->dev->mscbit);
+ retval = uinput_set_bit(arg, mscbit, MSC_MAX);
break;
case UI_SET_LEDBIT:
- if (arg > LED_MAX) {
- retval = -EINVAL;
- break;
- }
- set_bit(arg, udev->dev->ledbit);
+ retval = uinput_set_bit(arg, ledbit, LED_MAX);
break;
case UI_SET_SNDBIT:
- if (arg > SND_MAX) {
- retval = -EINVAL;
- break;
- }
- set_bit(arg, udev->dev->sndbit);
+ retval = uinput_set_bit(arg, sndbit, SND_MAX);
break;
case UI_SET_FFBIT:
- if (arg > FF_MAX) {
- retval = -EINVAL;
- break;
- }
- set_bit(arg, udev->dev->ffbit);
+ retval = uinput_set_bit(arg, ffbit, FF_MAX);
+ break;
+
+ case UI_SET_SWBIT:
+ retval = uinput_set_bit(arg, swbit, SW_MAX);
break;
case UI_SET_PHYS:
+ if (udev->state == UIST_CREATED) {
+ retval = -EINVAL;
+ goto out;
+ }
length = strnlen_user(p, 1024);
if (length <= 0) {
retval = -EFAULT;
@@ -575,23 +587,26 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
default:
retval = -EINVAL;
}
+
+ out:
+ up(&udev->sem);
return retval;
}
static struct file_operations uinput_fops = {
- .owner = THIS_MODULE,
- .open = uinput_open,
- .release = uinput_close,
- .read = uinput_read,
- .write = uinput_write,
- .poll = uinput_poll,
- .ioctl = uinput_ioctl,
+ .owner = THIS_MODULE,
+ .open = uinput_open,
+ .release = uinput_release,
+ .read = uinput_read,
+ .write = uinput_write,
+ .poll = uinput_poll,
+ .unlocked_ioctl = uinput_ioctl,
};
static struct miscdevice uinput_misc = {
- .fops = &uinput_fops,
- .minor = UINPUT_MINOR,
- .name = UINPUT_NAME,
+ .fops = &uinput_fops,
+ .minor = UINPUT_MINOR,
+ .name = UINPUT_NAME,
};
static int __init uinput_init(void)
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
new file mode 100644
index 00000000000..49d0416a2a9
--- /dev/null
+++ b/drivers/input/misc/wistron_btns.c
@@ -0,0 +1,561 @@
+/*
+ * Wistron laptop button driver
+ * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
+ * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
+ * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
+ *
+ * You can redistribute and/or modify this program under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <asm/io.h>
+#include <linux/dmi.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mc146818rtc.h>
+#include <linux/module.h>
+#include <linux/preempt.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+
+/*
+ * Number of attempts to read data from queue per poll;
+ * the queue can hold up to 31 entries
+ */
+#define MAX_POLL_ITERATIONS 64
+
+#define POLL_FREQUENCY 10 /* Number of polls per second */
+
+#if POLL_FREQUENCY > HZ
+#error "POLL_FREQUENCY too high"
+#endif
+
+/* BIOS subsystem IDs */
+#define WIFI 0x35
+#define BLUETOOTH 0x34
+
+MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>");
+MODULE_DESCRIPTION("Wistron laptop button driver");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("0.1");
+
+static int force; /* = 0; */
+module_param(force, bool, 0);
+MODULE_PARM_DESC(force, "Load even if computer is not in database");
+
+static char *keymap_name; /* = NULL; */
+module_param_named(keymap, keymap_name, charp, 0);
+MODULE_PARM_DESC(keymap, "Keymap name, if it can't be autodetected");
+
+static struct platform_device *wistron_device;
+
+ /* BIOS interface implementation */
+
+static void __iomem *bios_entry_point; /* BIOS routine entry point */
+static void __iomem *bios_code_map_base;
+static void __iomem *bios_data_map_base;
+
+static u8 cmos_address;
+
+struct regs {
+ u32 eax, ebx, ecx;
+};
+
+static void call_bios(struct regs *regs)
+{
+ unsigned long flags;
+
+ preempt_disable();
+ local_irq_save(flags);
+ asm volatile ("pushl %%ebp;"
+ "movl %7, %%ebp;"
+ "call *%6;"
+ "popl %%ebp"
+ : "=a" (regs->eax), "=b" (regs->ebx), "=c" (regs->ecx)
+ : "0" (regs->eax), "1" (regs->ebx), "2" (regs->ecx),
+ "m" (bios_entry_point), "m" (bios_data_map_base)
+ : "edx", "edi", "esi", "memory");
+ local_irq_restore(flags);
+ preempt_enable();
+}
+
+static size_t __init locate_wistron_bios(void __iomem *base)
+{
+ static const unsigned char __initdata signature[] =
+ { 0x42, 0x21, 0x55, 0x30 };
+ size_t offset;
+
+ for (offset = 0; offset < 0x10000; offset += 0x10) {
+ if (check_signature(base + offset, signature,
+ sizeof(signature)) != 0)
+ return offset;
+ }
+ return -1;
+}
+
+static int __init map_bios(void)
+{
+ void __iomem *base;
+ size_t offset;
+ u32 entry_point;
+
+ base = ioremap(0xF0000, 0x10000); /* Can't fail */
+ offset = locate_wistron_bios(base);
+ if (offset < 0) {
+ printk(KERN_ERR "wistron_btns: BIOS entry point not found\n");
+ iounmap(base);
+ return -ENODEV;
+ }
+
+ entry_point = readl(base + offset + 5);
+ printk(KERN_DEBUG
+ "wistron_btns: BIOS signature found at %p, entry point %08X\n",
+ base + offset, entry_point);
+
+ if (entry_point >= 0xF0000) {
+ bios_code_map_base = base;
+ bios_entry_point = bios_code_map_base + (entry_point & 0xFFFF);
+ } else {
+ iounmap(base);
+ bios_code_map_base = ioremap(entry_point & ~0x3FFF, 0x4000);
+ if (bios_code_map_base == NULL) {
+ printk(KERN_ERR
+ "wistron_btns: Can't map BIOS code at %08X\n",
+ entry_point & ~0x3FFF);
+ goto err;
+ }
+ bios_entry_point = bios_code_map_base + (entry_point & 0x3FFF);
+ }
+ /* The Windows driver maps 0x10000 bytes, we keep only one page... */
+ bios_data_map_base = ioremap(0x400, 0xc00);
+ if (bios_data_map_base == NULL) {
+ printk(KERN_ERR "wistron_btns: Can't map BIOS data\n");
+ goto err_code;
+ }
+ return 0;
+
+err_code:
+ iounmap(bios_code_map_base);
+err:
+ return -ENOMEM;
+}
+
+static inline void unmap_bios(void)
+{
+ iounmap(bios_code_map_base);
+ iounmap(bios_data_map_base);
+}
+
+ /* BIOS calls */
+
+static u16 bios_pop_queue(void)
+{
+ struct regs regs;
+
+ memset(&regs, 0, sizeof (regs));
+ regs.eax = 0x9610;
+ regs.ebx = 0x061C;
+ regs.ecx = 0x0000;
+ call_bios(&regs);
+
+ return regs.eax;
+}
+
+static void __init bios_attach(void)
+{
+ struct regs regs;
+
+ memset(&regs, 0, sizeof (regs));
+ regs.eax = 0x9610;
+ regs.ebx = 0x012E;
+ call_bios(&regs);
+}
+
+static void bios_detach(void)
+{
+ struct regs regs;
+
+ memset(&regs, 0, sizeof (regs));
+ regs.eax = 0x9610;
+ regs.ebx = 0x002E;
+ call_bios(&regs);
+}
+
+static u8 __init bios_get_cmos_address(void)
+{
+ struct regs regs;
+
+ memset(&regs, 0, sizeof (regs));
+ regs.eax = 0x9610;
+ regs.ebx = 0x051C;
+ call_bios(&regs);
+
+ return regs.ecx;
+}
+
+static u16 __init bios_get_default_setting(u8 subsys)
+{
+ struct regs regs;
+
+ memset(&regs, 0, sizeof (regs));
+ regs.eax = 0x9610;
+ regs.ebx = 0x0200 | subsys;
+ call_bios(&regs);
+
+ return regs.eax;
+}
+
+static void bios_set_state(u8 subsys, int enable)
+{
+ struct regs regs;
+
+ memset(&regs, 0, sizeof (regs));
+ regs.eax = 0x9610;
+ regs.ebx = (enable ? 0x0100 : 0x0000) | subsys;
+ call_bios(&regs);
+}
+
+/* Hardware database */
+
+struct key_entry {
+ char type; /* See KE_* below */
+ u8 code;
+ unsigned keycode; /* For KE_KEY */
+};
+
+enum { KE_END, KE_KEY, KE_WIFI, KE_BLUETOOTH };
+
+static const struct key_entry *keymap; /* = NULL; Current key map */
+static int have_wifi;
+static int have_bluetooth;
+
+static int __init dmi_matched(struct dmi_system_id *dmi)
+{
+ const struct key_entry *key;
+
+ keymap = dmi->driver_data;
+ for (key = keymap; key->type != KE_END; key++) {
+ if (key->type == KE_WIFI) {
+ have_wifi = 1;
+ break;
+ } else if (key->type == KE_BLUETOOTH) {
+ have_bluetooth = 1;
+ break;
+ }
+ }
+ return 1;
+}
+
+static struct key_entry keymap_empty[] = {
+ { KE_END, 0 }
+};
+
+static struct key_entry keymap_fs_amilo_pro_v2000[] = {
+ { KE_KEY, 0x01, KEY_HELP },
+ { KE_KEY, 0x11, KEY_PROG1 },
+ { KE_KEY, 0x12, KEY_PROG2 },
+ { KE_WIFI, 0x30, 0 },
+ { KE_KEY, 0x31, KEY_MAIL },
+ { KE_KEY, 0x36, KEY_WWW },
+ { KE_END, 0 }
+};
+
+static struct key_entry keymap_wistron_ms2141[] = {
+ { KE_KEY, 0x11, KEY_PROG1 },
+ { KE_KEY, 0x12, KEY_PROG2 },
+ { KE_WIFI, 0x30, 0 },
+ { KE_KEY, 0x22, KEY_REWIND },
+ { KE_KEY, 0x23, KEY_FORWARD },
+ { KE_KEY, 0x24, KEY_PLAYPAUSE },
+ { KE_KEY, 0x25, KEY_STOPCD },
+ { KE_KEY, 0x31, KEY_MAIL },
+ { KE_KEY, 0x36, KEY_WWW },
+ { KE_END, 0 }
+};
+
+static struct key_entry keymap_acer_aspire_1500[] = {
+ { KE_KEY, 0x11, KEY_PROG1 },
+ { KE_KEY, 0x12, KEY_PROG2 },
+ { KE_WIFI, 0x30, 0 },
+ { KE_KEY, 0x31, KEY_MAIL },
+ { KE_KEY, 0x36, KEY_WWW },
+ { KE_BLUETOOTH, 0x44, 0 },
+ { KE_END, 0 }
+};
+
+/*
+ * If your machine is not here (which is currently rather likely), please send
+ * a list of buttons and their key codes (reported when loading this module
+ * with force=1) and the output of dmidecode to $MODULE_AUTHOR.
+ */
+static struct dmi_system_id dmi_ids[] = {
+ {
+ .callback = dmi_matched,
+ .ident = "Fujitsu-Siemens Amilo Pro V2000",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2000"),
+ },
+ .driver_data = keymap_fs_amilo_pro_v2000
+ },
+ {
+ .callback = dmi_matched,
+ .ident = "Acer Aspire 1500",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1500"),
+ },
+ .driver_data = keymap_acer_aspire_1500
+ },
+ { 0, }
+};
+
+static int __init select_keymap(void)
+{
+ if (keymap_name != NULL) {
+ if (strcmp (keymap_name, "1557/MS2141") == 0)
+ keymap = keymap_wistron_ms2141;
+ else {
+ printk(KERN_ERR "wistron_btns: Keymap unknown\n");
+ return -EINVAL;
+ }
+ }
+ dmi_check_system(dmi_ids);
+ if (keymap == NULL) {
+ if (!force) {
+ printk(KERN_ERR "wistron_btns: System unknown\n");
+ return -ENODEV;
+ }
+ keymap = keymap_empty;
+ }
+ return 0;
+}
+
+ /* Input layer interface */
+
+static struct input_dev *input_dev;
+
+static int __init setup_input_dev(void)
+{
+ const struct key_entry *key;
+ int error;
+
+ input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
+
+ input_dev->name = "Wistron laptop buttons";
+ input_dev->phys = "wistron/input0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->cdev.dev = &wistron_device->dev;
+
+ for (key = keymap; key->type != KE_END; key++) {
+ if (key->type == KE_KEY) {
+ input_dev->evbit[LONG(EV_KEY)] = BIT(EV_KEY);
+ set_bit(key->keycode, input_dev->keybit);
+ }
+ }
+
+ error = input_register_device(input_dev);
+ if (error) {
+ input_free_device(input_dev);
+ return error;
+ }
+
+ return 0;
+}
+
+static void report_key(unsigned keycode)
+{
+ input_report_key(input_dev, keycode, 1);
+ input_sync(input_dev);
+ input_report_key(input_dev, keycode, 0);
+ input_sync(input_dev);
+}
+
+ /* Driver core */
+
+static int wifi_enabled;
+static int bluetooth_enabled;
+
+static void poll_bios(unsigned long);
+
+static struct timer_list poll_timer = TIMER_INITIALIZER(poll_bios, 0, 0);
+
+static void handle_key(u8 code)
+{
+ const struct key_entry *key;
+
+ for (key = keymap; key->type != KE_END; key++) {
+ if (code == key->code) {
+ switch (key->type) {
+ case KE_KEY:
+ report_key(key->keycode);
+ break;
+
+ case KE_WIFI:
+ if (have_wifi) {
+ wifi_enabled = !wifi_enabled;
+ bios_set_state(WIFI, wifi_enabled);
+ }
+ break;
+
+ case KE_BLUETOOTH:
+ if (have_bluetooth) {
+ bluetooth_enabled = !bluetooth_enabled;
+ bios_set_state(BLUETOOTH, bluetooth_enabled);
+ }
+ break;
+
+ case KE_END:
+ default:
+ BUG();
+ }
+ return;
+ }
+ }
+ printk(KERN_NOTICE "wistron_btns: Unknown key code %02X\n", code);
+}
+
+static void poll_bios(unsigned long discard)
+{
+ u8 qlen;
+ u16 val;
+
+ for (;;) {
+ qlen = CMOS_READ(cmos_address);
+ if (qlen == 0)
+ break;
+ val = bios_pop_queue();
+ if (val != 0 && !discard)
+ handle_key((u8)val);
+ }
+
+ mod_timer(&poll_timer, jiffies + HZ / POLL_FREQUENCY);
+}
+
+static int wistron_suspend(struct platform_device *dev, pm_message_t state)
+{
+ del_timer_sync(&poll_timer);
+
+ if (have_wifi)
+ bios_set_state(WIFI, 0);
+
+ if (have_bluetooth)
+ bios_set_state(BLUETOOTH, 0);
+
+ return 0;
+}
+
+static int wistron_resume(struct platform_device *dev)
+{
+ if (have_wifi)
+ bios_set_state(WIFI, wifi_enabled);
+
+ if (have_bluetooth)
+ bios_set_state(BLUETOOTH, bluetooth_enabled);
+
+ poll_bios(1);
+
+ return 0;
+}
+
+static struct platform_driver wistron_driver = {
+ .suspend = wistron_suspend,
+ .resume = wistron_resume,
+ .driver = {
+ .name = "wistron-bios",
+ },
+};
+
+static int __init wb_module_init(void)
+{
+ int err;
+
+ err = select_keymap();
+ if (err)
+ return err;
+
+ err = map_bios();
+ if (err)
+ return err;
+
+ bios_attach();
+ cmos_address = bios_get_cmos_address();
+
+ err = platform_driver_register(&wistron_driver);
+ if (err)
+ goto err_detach_bios;
+
+ wistron_device = platform_device_register_simple("wistron-bios", -1, NULL, 0);
+ if (IS_ERR(wistron_device)) {
+ err = PTR_ERR(wistron_device);
+ goto err_unregister_driver;
+ }
+
+ if (have_wifi) {
+ u16 wifi = bios_get_default_setting(WIFI);
+ if (wifi & 1)
+ wifi_enabled = (wifi & 2) ? 1 : 0;
+ else
+ have_wifi = 0;
+
+ if (have_wifi)
+ bios_set_state(WIFI, wifi_enabled);
+ }
+
+ if (have_bluetooth) {
+ u16 bt = bios_get_default_setting(BLUETOOTH);
+ if (bt & 1)
+ bluetooth_enabled = (bt & 2) ? 1 : 0;
+ else
+ have_bluetooth = 0;
+
+ if (have_bluetooth)
+ bios_set_state(BLUETOOTH, bluetooth_enabled);
+ }
+
+ err = setup_input_dev();
+ if (err)
+ goto err_unregister_device;
+
+ poll_bios(1); /* Flush stale event queue and arm timer */
+
+ return 0;
+
+ err_unregister_device:
+ platform_device_unregister(wistron_device);
+ err_unregister_driver:
+ platform_driver_unregister(&wistron_driver);
+ err_detach_bios:
+ bios_detach();
+ unmap_bios();
+
+ return err;
+}
+
+static void __exit wb_module_exit(void)
+{
+ del_timer_sync(&poll_timer);
+ input_unregister_device(input_dev);
+ platform_device_unregister(wistron_device);
+ platform_driver_unregister(&wistron_driver);
+ bios_detach();
+ unmap_bios();
+}
+
+module_init(wb_module_init);
+module_exit(wb_module_exit);
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index edd15db1771..fbb69ef6a77 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -269,14 +269,20 @@ static struct serio_event *serio_get_event(void)
return event;
}
-static void serio_handle_events(void)
+static void serio_handle_event(void)
{
struct serio_event *event;
struct serio_driver *serio_drv;
down(&serio_sem);
- while ((event = serio_get_event())) {
+ /*
+ * Note that we handle only one event here to give swsusp
+ * a chance to freeze kseriod thread. Serio events should
+ * be pretty rare so we are not concerned about taking
+ * performance hit.
+ */
+ if ((event = serio_get_event())) {
switch (event->type) {
case SERIO_REGISTER_PORT:
@@ -368,7 +374,7 @@ static struct serio *serio_get_pending_child(struct serio *parent)
static int serio_thread(void *nothing)
{
do {
- serio_handle_events();
+ serio_handle_event();
wait_event_interruptible(serio_wait,
kthread_should_stop() || !list_empty(&serio_event_list));
try_to_freeze();
diff --git a/drivers/md/dm-bio-list.h b/drivers/md/dm-bio-list.h
index bc021e1fd4d..bbf4615f0e3 100644
--- a/drivers/md/dm-bio-list.h
+++ b/drivers/md/dm-bio-list.h
@@ -33,6 +33,9 @@ static inline void bio_list_add(struct bio_list *bl, struct bio *bio)
static inline void bio_list_merge(struct bio_list *bl, struct bio_list *bl2)
{
+ if (!bl2->head)
+ return;
+
if (bl->tail)
bl->tail->bi_next = bl2->head;
else
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 54ec737195e..07d44e19536 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -425,8 +425,8 @@ static void list_version_get_needed(struct target_type *tt, void *needed_param)
{
size_t *needed = needed_param;
+ *needed += sizeof(struct dm_target_versions);
*needed += strlen(tt->name);
- *needed += sizeof(tt->version);
*needed += ALIGN_MASK;
}
@@ -974,6 +974,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
if (!hc) {
DMWARN("device doesn't appear to be in the dev hash table.");
up_write(&_hash_lock);
+ dm_table_put(t);
return -ENXIO;
}
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index e110655eabd..a76349cb10a 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -333,10 +333,10 @@ static int core_ctr(struct dirty_log *log, struct dm_target *ti,
lc->sync = sync;
/*
- * Work out how many words we need to hold the bitset.
+ * Work out how many "unsigned long"s we need to hold the bitset.
*/
bitset_size = dm_round_up(region_count,
- sizeof(*lc->clean_bits) << BYTE_SHIFT);
+ sizeof(unsigned long) << BYTE_SHIFT);
bitset_size >>= BYTE_SHIFT;
lc->bitset_uint32_count = bitset_size / 4;
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index f9b7b32d5d5..f72a82fb943 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -1000,6 +1000,7 @@ static int do_end_io(struct multipath *m, struct bio *bio,
{
struct hw_handler *hwh = &m->hw_handler;
unsigned err_flags = MP_FAIL_PATH; /* Default behavior */
+ unsigned long flags;
if (!error)
return 0; /* I/O complete */
@@ -1010,17 +1011,17 @@ static int do_end_io(struct multipath *m, struct bio *bio,
if (error == -EOPNOTSUPP)
return error;
- spin_lock(&m->lock);
+ spin_lock_irqsave(&m->lock, flags);
if (!m->nr_valid_paths) {
if (!m->queue_if_no_path) {
- spin_unlock(&m->lock);
+ spin_unlock_irqrestore(&m->lock, flags);
return -EIO;
} else {
- spin_unlock(&m->lock);
+ spin_unlock_irqrestore(&m->lock, flags);
goto requeue;
}
}
- spin_unlock(&m->lock);
+ spin_unlock_irqrestore(&m->lock, flags);
if (hwh->type && hwh->type->error)
err_flags = hwh->type->error(hwh, bio);
@@ -1040,12 +1041,12 @@ static int do_end_io(struct multipath *m, struct bio *bio,
dm_bio_restore(&mpio->details, bio);
/* queue for the daemon to resubmit or fail */
- spin_lock(&m->lock);
+ spin_lock_irqsave(&m->lock, flags);
bio_list_add(&m->queued_ios, bio);
m->queue_size++;
if (!m->queue_io)
queue_work(kmultipathd, &m->process_queued_ios);
- spin_unlock(&m->lock);
+ spin_unlock_irqrestore(&m->lock, flags);
return 1; /* io not complete */
}
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 2375709a392..6b0fc167092 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -376,16 +376,18 @@ static void rh_inc(struct region_hash *rh, region_t region)
read_lock(&rh->hash_lock);
reg = __rh_find(rh, region);
+ spin_lock_irq(&rh->region_lock);
atomic_inc(&reg->pending);
- spin_lock_irq(&rh->region_lock);
if (reg->state == RH_CLEAN) {
- rh->log->type->mark_region(rh->log, reg->key);
-
reg->state = RH_DIRTY;
list_del_init(&reg->list); /* take off the clean list */
- }
- spin_unlock_irq(&rh->region_lock);
+ spin_unlock_irq(&rh->region_lock);
+
+ rh->log->type->mark_region(rh->log, reg->key);
+ } else
+ spin_unlock_irq(&rh->region_lock);
+
read_unlock(&rh->hash_lock);
}
@@ -408,21 +410,17 @@ static void rh_dec(struct region_hash *rh, region_t region)
reg = __rh_lookup(rh, region);
read_unlock(&rh->hash_lock);
+ spin_lock_irqsave(&rh->region_lock, flags);
if (atomic_dec_and_test(&reg->pending)) {
- spin_lock_irqsave(&rh->region_lock, flags);
- if (atomic_read(&reg->pending)) { /* check race */
- spin_unlock_irqrestore(&rh->region_lock, flags);
- return;
- }
if (reg->state == RH_RECOVERING) {
list_add_tail(&reg->list, &rh->quiesced_regions);
} else {
reg->state = RH_CLEAN;
list_add(&reg->list, &rh->clean_regions);
}
- spin_unlock_irqrestore(&rh->region_lock, flags);
should_wake = 1;
}
+ spin_unlock_irqrestore(&rh->region_lock, flags);
if (should_wake)
wake();
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 78c7418478d..cd12fca73b0 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1028,7 +1028,6 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
mddev->size = le64_to_cpu(sb->size)/2;
mddev->events = le64_to_cpu(sb->events);
mddev->bitmap_offset = 0;
- mddev->default_bitmap_offset = 0;
mddev->default_bitmap_offset = 1024;
mddev->recovery_cp = le64_to_cpu(sb->resync_offset);
@@ -2932,6 +2931,9 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
mddev->sb_dirty = 1;
+ mddev->default_bitmap_offset = MD_SB_BYTES >> 9;
+ mddev->bitmap_offset = 0;
+
/*
* Generate a 128 bit UUID
*/
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 2da9d3ba902..3066c587b53 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -953,9 +953,6 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
int mirror = 0;
mirror_info_t *p;
- if (rdev->saved_raid_disk >= 0 &&
- conf->mirrors[rdev->saved_raid_disk].rdev == NULL)
- mirror = rdev->saved_raid_disk;
for (mirror=0; mirror < mddev->raid_disks; mirror++)
if ( !(p=conf->mirrors+mirror)->rdev) {
@@ -972,7 +969,10 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
p->head_position = 0;
rdev->raid_disk = mirror;
found = 1;
- if (rdev->saved_raid_disk != mirror)
+ /* As all devices are equivalent, we don't need a full recovery
+ * if this was recently any drive of the array
+ */
+ if (rdev->saved_raid_disk < 0)
conf->fullsync = 1;
rcu_assign_pointer(p->rdev, rdev);
break;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 867f06ae33d..713dc9c2c73 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -552,7 +552,11 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio)
!test_bit(In_sync, &rdev->flags))
continue;
- if (!atomic_read(&rdev->nr_pending)) {
+ /* This optimisation is debatable, and completely destroys
+ * sequential read speed for 'far copies' arrays. So only
+ * keep it for 'near' arrays, and review those later.
+ */
+ if (conf->near_copies > 1 && !atomic_read(&rdev->nr_pending)) {
disk = ndisk;
slot = nslot;
break;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index e2a40283e32..36d5f8ac826 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1704,7 +1704,9 @@ static void raid5d (mddev_t *mddev)
if (conf->seq_flush - conf->seq_write > 0) {
int seq = conf->seq_flush;
+ spin_unlock_irq(&conf->device_lock);
bitmap_unplug(mddev->bitmap);
+ spin_lock_irq(&conf->device_lock);
conf->seq_write = seq;
activate_bit_delay(conf);
}
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index eae5a35629c..0000d162d19 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -1702,6 +1702,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
int data_disks = raid_disks - 2;
sector_t max_sector = mddev->size << 1;
int sync_blocks;
+ int still_degraded = 0;
+ int i;
if (sector_nr >= max_sector) {
/* just being told to finish up .. nothing much to do */
@@ -1710,7 +1712,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
if (mddev->curr_resync < max_sector) /* aborted */
bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
&sync_blocks, 1);
- else /* compelted sync */
+ else /* completed sync */
conf->fullsync = 0;
bitmap_close_sync(mddev->bitmap);
@@ -1748,7 +1750,16 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
*/
schedule_timeout_uninterruptible(1);
}
- bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 0);
+ /* Need to check if array will still be degraded after recovery/resync
+ * We don't need to check the 'failed' flag as when that gets set,
+ * recovery aborts.
+ */
+ for (i=0; i<mddev->raid_disks; i++)
+ if (conf->disks[i].rdev == NULL)
+ still_degraded = 1;
+
+ bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, still_degraded);
+
spin_lock(&sh->lock);
set_bit(STRIPE_SYNCING, &sh->state);
clear_bit(STRIPE_INSYNC, &sh->state);
@@ -1784,7 +1795,9 @@ static void raid6d (mddev_t *mddev)
if (conf->seq_flush - conf->seq_write > 0) {
int seq = conf->seq_flush;
+ spin_unlock_irq(&conf->device_lock);
bitmap_unplug(mddev->bitmap);
+ spin_lock_irq(&conf->device_lock);
conf->seq_write = seq;
activate_bit_delay(conf);
}
@@ -2145,9 +2158,15 @@ static int raid6_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
/* no point adding a device */
return 0;
/*
- * find the disk ...
+ * find the disk ... but prefer rdev->saved_raid_disk
+ * if possible.
*/
- for (disk=0; disk < mddev->raid_disks; disk++)
+ if (rdev->saved_raid_disk >= 0 &&
+ conf->disks[rdev->saved_raid_disk].rdev == NULL)
+ disk = rdev->saved_raid_disk;
+ else
+ disk = 0;
+ for ( ; disk < mddev->raid_disks; disk++)
if ((p=conf->disks + disk)->rdev == NULL) {
clear_bit(In_sync, &rdev->flags);
rdev->raid_disk = disk;
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index fb394a0d838..336fc284fa5 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -772,7 +772,7 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
input_dev->name = DRIVER_NAME " remote control";
input_dev->phys = cinergyt2->phys;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
- for (i = 0; ARRAY_SIZE(rc_keys); i += 3)
+ for (i = 0; i < ARRAY_SIZE(rc_keys); i += 3)
set_bit(rc_keys[i + 2], input_dev->keybit);
input_dev->keycodesize = 0;
input_dev->keycodemax = 0;
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 1a3b3c7e5e9..ecb9a31dd00 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -26,7 +26,7 @@ config VIDEO_BT848
module will be called bttv.
config VIDEO_BT848_DVB
- tristate "DVB/ATSC Support for bt878 based TV cards"
+ bool "DVB/ATSC Support for bt878 based TV cards"
depends on VIDEO_BT848 && DVB_CORE
select DVB_BT8XX
---help---
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index 41818b6205b..85ba4106dc7 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -46,8 +46,8 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS
If you are unsure, choose Y.
config VIDEO_CX88_DVB_MT352
- tristate "Zarlink MT352 DVB-T Support"
- default m
+ bool "Zarlink MT352 DVB-T Support"
+ default y
depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS
select DVB_MT352
---help---
@@ -55,8 +55,8 @@ config VIDEO_CX88_DVB_MT352
Connexant 2388x chip and the MT352 demodulator.
config VIDEO_CX88_DVB_OR51132
- tristate "OR51132 ATSC Support"
- default m
+ bool "OR51132 ATSC Support"
+ default y
depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS
select DVB_OR51132
---help---
@@ -64,8 +64,8 @@ config VIDEO_CX88_DVB_OR51132
Connexant 2388x chip and the OR51132 demodulator.
config VIDEO_CX88_DVB_CX22702
- tristate "Conexant CX22702 DVB-T Support"
- default m
+ bool "Conexant CX22702 DVB-T Support"
+ default y
depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS
select DVB_CX22702
---help---
@@ -73,8 +73,8 @@ config VIDEO_CX88_DVB_CX22702
Connexant 2388x chip and the CX22702 demodulator.
config VIDEO_CX88_DVB_LGDT330X
- tristate "LG Electronics DT3302/DT3303 ATSC Support"
- default m
+ bool "LG Electronics DT3302/DT3303 ATSC Support"
+ default y
depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS
select DVB_LGDT330X
---help---
@@ -82,8 +82,8 @@ config VIDEO_CX88_DVB_LGDT330X
Connexant 2388x chip and the LGDT3302/LGDT3303 demodulator.
config VIDEO_CX88_DVB_NXT200X
- tristate "NXT2002/NXT2004 ATSC Support"
- default m
+ bool "NXT2002/NXT2004 ATSC Support"
+ default y
depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS
select DVB_NXT200X
---help---
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
index 0df40b77345..54401b02b7c 100644
--- a/drivers/media/video/cx88/Makefile
+++ b/drivers/media/video/cx88/Makefile
@@ -9,21 +9,12 @@ obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
EXTRA_CFLAGS += -I$(src)/..
EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/frontends
-ifneq ($(CONFIG_VIDEO_BUF_DVB),n)
- EXTRA_CFLAGS += -DHAVE_VIDEO_BUF_DVB=1
-endif
-ifneq ($(CONFIG_DVB_CX22702),n)
- EXTRA_CFLAGS += -DHAVE_CX22702=1
-endif
-ifneq ($(CONFIG_DVB_OR51132),n)
- EXTRA_CFLAGS += -DHAVE_OR51132=1
-endif
-ifneq ($(CONFIG_DVB_LGDT330X),n)
- EXTRA_CFLAGS += -DHAVE_LGDT330X=1
-endif
-ifneq ($(CONFIG_DVB_MT352),n)
- EXTRA_CFLAGS += -DHAVE_MT352=1
-endif
-ifneq ($(CONFIG_DVB_NXT200X),n)
- EXTRA_CFLAGS += -DHAVE_NXT200X=1
-endif
+
+extra-cflags-$(CONFIG_VIDEO_BUF_DVB) += -DHAVE_VIDEO_BUF_DVB=1
+extra-cflags-$(CONFIG_DVB_CX22702) += -DHAVE_CX22702=1
+extra-cflags-$(CONFIG_DVB_OR51132) += -DHAVE_OR51132=1
+extra-cflags-$(CONFIG_DVB_LGDT330X) += -DHAVE_LGDT330X=1
+extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1
+extra-cflags-$(CONFIG_DVB_NXT200X) += -DHAVE_NXT200X=1
+
+EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c
index 5abfc0fbf6d..6345e29e495 100644
--- a/drivers/media/video/ir-kbd-gpio.c
+++ b/drivers/media/video/ir-kbd-gpio.c
@@ -673,7 +673,6 @@ static int ir_probe(struct device *dev)
snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
pci_name(sub->core->pci));
- ir->sub = sub;
ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
input_dev->name = ir->name;
input_dev->phys = ir->phys;
@@ -688,6 +687,9 @@ static int ir_probe(struct device *dev)
}
input_dev->cdev.dev = &sub->core->pci->dev;
+ ir->input = input_dev;
+ ir->sub = sub;
+
if (ir->polling) {
INIT_WORK(&ir->work, ir_work, ir);
init_timer(&ir->timer);
@@ -708,7 +710,6 @@ static int ir_probe(struct device *dev)
/* all done */
dev_set_drvdata(dev, ir);
input_register_device(ir->input);
- printk(DEVNAME ": %s detected at %s\n",ir->name,ir->phys);
/* the remote isn't as bouncy as a keyboard */
ir->input->rep[REP_DELAY] = repeat_delay;
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig
index 7bdeabe638c..c512c4411b3 100644
--- a/drivers/media/video/saa7134/Kconfig
+++ b/drivers/media/video/saa7134/Kconfig
@@ -42,8 +42,8 @@ config VIDEO_SAA7134_DVB_ALL_FRONTENDS
If you are unsure, choose Y.
config VIDEO_SAA7134_DVB_MT352
- tristate "Zarlink MT352 DVB-T Support"
- default m
+ bool "Zarlink MT352 DVB-T Support"
+ default y
depends on VIDEO_SAA7134_DVB && !VIDEO_SAA7134_DVB_ALL_FRONTENDS
select DVB_MT352
---help---
@@ -51,8 +51,8 @@ config VIDEO_SAA7134_DVB_MT352
Philips saa7134 chip and the MT352 demodulator.
config VIDEO_SAA7134_DVB_TDA1004X
- tristate "Phillips TDA10045H/TDA10046H DVB-T Support"
- default m
+ bool "Phillips TDA10045H/TDA10046H DVB-T Support"
+ default y
depends on VIDEO_SAA7134_DVB && !VIDEO_SAA7134_DVB_ALL_FRONTENDS
select DVB_TDA1004X
---help---
@@ -60,8 +60,8 @@ config VIDEO_SAA7134_DVB_TDA1004X
Philips saa7134 chip and the TDA10045H/TDA10046H demodulator.
config VIDEO_SAA7134_DVB_NXT200X
- tristate "NXT2002/NXT2004 ATSC Support"
- default m
+ bool "NXT2002/NXT2004 ATSC Support"
+ default y
depends on VIDEO_SAA7134_DVB && !VIDEO_SAA7134_DVB_ALL_FRONTENDS
select DVB_NXT200X
---help---
diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile
index 4226b61cc61..134f83a9621 100644
--- a/drivers/media/video/saa7134/Makefile
+++ b/drivers/media/video/saa7134/Makefile
@@ -11,15 +11,10 @@ obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
EXTRA_CFLAGS += -I$(src)/..
EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/frontends
-ifneq ($(CONFIG_VIDEO_BUF_DVB),n)
- EXTRA_CFLAGS += -DHAVE_VIDEO_BUF_DVB=1
-endif
-ifneq ($(CONFIG_DVB_MT352),n)
- EXTRA_CFLAGS += -DHAVE_MT352=1
-endif
-ifneq ($(CONFIG_DVB_TDA1004X),n)
- EXTRA_CFLAGS += -DHAVE_TDA1004X=1
-endif
-ifneq ($(CONFIG_DVB_NXT200X),n)
- EXTRA_CFLAGS += -DHAVE_NXT200X=1
-endif
+
+extra-cflags-$(CONFIG_VIDEO_BUF_DVB) += -DHAVE_VIDEO_BUF_DVB=1
+extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1
+extra-cflags-$(CONFIG_DVB_TDA1004X) += -DHAVE_TDA1004X=1
+extra-cflags-$(CONFIG_DVB_NXT200X) += -DHAVE_NXT200X=1
+
+EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index e648cc3bc96..ab75ca5ac35 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -713,6 +713,8 @@ int saa7134_input_init1(struct saa7134_dev *dev)
return -ENOMEM;
}
+ ir->dev = input_dev;
+
/* init hardware-specific stuff */
ir->mask_keycode = mask_keycode;
ir->mask_keydown = mask_keydown;
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index 66c03e88257..81ef306cb12 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -421,8 +421,8 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
i2o_pci_free(c);
free_controller:
- i2o_iop_free(c);
put_device(c->device.parent);
+ i2o_iop_free(c);
disable:
pci_disable_device(pdev);
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index da528390acf..d336a1d65dc 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -816,7 +816,7 @@ static void mmc_discover_cards(struct mmc_host *host)
cmd.opcode = SD_SEND_RELATIVE_ADDR;
cmd.arg = 0;
- cmd.flags = MMC_RSP_R1;
+ cmd.flags = MMC_RSP_R6;
err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
if (err != MMC_ERR_NONE)
diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c
index 2a290cc397a..70b47e4c4e9 100644
--- a/drivers/net/dgrs.c
+++ b/drivers/net/dgrs.c
@@ -1458,6 +1458,8 @@ static struct pci_driver dgrs_pci_driver = {
.probe = dgrs_pci_probe,
.remove = __devexit_p(dgrs_pci_remove),
};
+#else
+static struct pci_driver dgrs_pci_driver = {};
#endif
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index c42b68d3aa2..6a61b9f286e 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -59,7 +59,6 @@ struct slot {
struct slot *next;
u8 bus;
u8 device;
- u16 status;
u32 number;
u8 state;
struct timer_list task_event;
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 5e582eca21d..83c4b865718 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -207,7 +207,6 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
* power fault Cleared
*/
info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
- p_slot->status = 0x00;
taskInfo->event_type = INT_POWER_FAULT_CLEAR;
} else {
/*
@@ -215,8 +214,6 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
*/
info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
taskInfo->event_type = INT_POWER_FAULT;
- /* set power fault status for this board */
- p_slot->status = 0xFF;
info("power fault bit %x set\n", hp_slot);
}
if (rc)
@@ -317,13 +314,10 @@ static int board_added(struct slot *p_slot)
return rc;
}
- dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status);
-
/* Check for a power fault */
- if (p_slot->status == 0xFF) {
- /* power fault occurred, but it was benign */
+ if (p_slot->hpc_ops->query_power_fault(p_slot)) {
+ dbg("%s: power fault detected\n", __FUNCTION__);
rc = POWER_FAILURE;
- p_slot->status = 0;
goto err_exit;
}
@@ -334,8 +328,6 @@ static int board_added(struct slot *p_slot)
goto err_exit;
}
- p_slot->status = 0;
-
/*
* Some PCI Express root ports require fixup after hot-plug operation.
*/
@@ -382,9 +374,6 @@ static int remove_board(struct slot *p_slot)
dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
- /* Change status to shutdown */
- p_slot->status = 0x01;
-
/* 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 2387e75da0f..0b8b26beb16 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -750,7 +750,7 @@ static int hpc_power_on_slot(struct slot * slot)
{
struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
u16 slot_cmd;
- u16 slot_ctrl;
+ u16 slot_ctrl, slot_status;
int retval = 0;
@@ -767,6 +767,14 @@ static int hpc_power_on_slot(struct slot * slot)
return -1;
}
+ /* Clear sticky power-fault bit from previous power failures */
+ hp_register_read_word(php_ctlr->pci_dev,
+ SLOT_STATUS(slot->ctrl->cap_base), slot_status);
+ slot_status &= PWR_FAULT_DETECTED;
+ if (slot_status)
+ hp_register_write_word(php_ctlr->pci_dev,
+ SLOT_STATUS(slot->ctrl->cap_base), slot_status);
+
retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
if (retval) {
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index a9b00cc2d88..6917c6cb091 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -178,6 +178,7 @@ EXPORT_SYMBOL(pci_osc_support_set);
/**
* pci_osc_control_set - commit requested control to Firmware
+ * @handle: acpi_handle for the target ACPI object
* @flags: driver's requested control bits
*
* Attempt to take control from Firmware on requested control bits.
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 2c22b4b3619..078579ae635 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -355,9 +355,10 @@ static void add_pcc_socket(ulong base, int irq, ulong mapaddr, kio_addr_t ioaddr
#ifndef CONFIG_PLAT_USRV
/* insert interrupt */
request_irq(irq, pcc_interrupt, 0, "m32r_cfc", pcc_interrupt);
+#ifndef CONFIG_PLAT_MAPPI3
/* eject interrupt */
request_irq(irq+1, pcc_interrupt, 0, "m32r_cfc", pcc_interrupt);
-
+#endif
debug(3, "m32r_cfc: enable CFMSK, RDYSEL\n");
pcc_set(pcc_sockets, (unsigned int)PLD_CFIMASK, 0x01);
#endif /* CONFIG_PLAT_USRV */
diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c
index 672f9f2b216..92e6c5639dd 100644
--- a/drivers/sbus/char/aurora.c
+++ b/drivers/sbus/char/aurora.c
@@ -124,25 +124,25 @@ static inline int aurora_paranoia_check(struct Aurora_port const * port,
*/
/* Get board number from pointer */
-extern inline int board_No (struct Aurora_board const * bp)
+static inline int board_No (struct Aurora_board const * bp)
{
return bp - aurora_board;
}
/* Get port number from pointer */
-extern inline int port_No (struct Aurora_port const * port)
+static inline int port_No (struct Aurora_port const * port)
{
return AURORA_PORT(port - aurora_port);
}
/* Get pointer to board from pointer to port */
-extern inline struct Aurora_board * port_Board(struct Aurora_port const * port)
+static inline struct Aurora_board * port_Board(struct Aurora_port const * port)
{
return &aurora_board[AURORA_BOARD(port - aurora_port)];
}
/* Wait for Channel Command Register ready */
-extern inline void aurora_wait_CCR(struct aurora_reg128 * r)
+static inline void aurora_wait_CCR(struct aurora_reg128 * r)
{
unsigned long delay;
@@ -161,7 +161,7 @@ printk("aurora_wait_CCR\n");
*/
/* Must be called with enabled interrupts */
-extern inline void aurora_long_delay(unsigned long delay)
+static inline void aurora_long_delay(unsigned long delay)
{
unsigned long i;
@@ -420,7 +420,7 @@ static void aurora_release_io_range(struct Aurora_board *bp)
sbus_iounmap((unsigned long)bp->r3, 4);
}
-extern inline void aurora_mark_event(struct Aurora_port * port, int event)
+static inline void aurora_mark_event(struct Aurora_port * port, int event)
{
#ifdef AURORA_DEBUG
printk("aurora_mark_event: start\n");
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index c28e3aea1c3..418fc7b896a 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -816,7 +816,7 @@ static int adpt_hba_reset(adpt_hba* pHba)
static void adpt_i2o_sys_shutdown(void)
{
adpt_hba *pHba, *pNext;
- struct adpt_i2o_post_wait_data *p1, *p2;
+ struct adpt_i2o_post_wait_data *p1, *old;
printk(KERN_INFO"Shutting down Adaptec I2O controllers.\n");
printk(KERN_INFO" This could take a few minutes if there are many devices attached\n");
@@ -830,13 +830,14 @@ static void adpt_i2o_sys_shutdown(void)
}
/* Remove any timedout entries from the wait queue. */
- p2 = NULL;
// spin_lock_irqsave(&adpt_post_wait_lock, flags);
/* Nothing should be outstanding at this point so just
* free them
*/
- for(p1 = adpt_post_wait_queue; p1; p2 = p1, p1 = p2->next) {
- kfree(p1);
+ for(p1 = adpt_post_wait_queue; p1;) {
+ old = p1;
+ p1 = p1->next;
+ kfree(old);
}
// spin_unlock_irqrestore(&adpt_post_wait_lock, flags);
adpt_post_wait_queue = NULL;
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index aae3a331d75..f37cc01e8db 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1454,11 +1454,23 @@ void __sata_phy_reset(struct ata_port *ap)
} while (time_before(jiffies, timeout));
/* TODO: phy layer with polling, timeouts, etc. */
- if (sata_dev_present(ap))
+ sstatus = scr_read(ap, SCR_STATUS);
+ if (sata_dev_present(ap)) {
+ const char *speed;
+ u32 tmp;
+
+ tmp = (sstatus >> 4) & 0xf;
+ if (tmp & (1 << 0))
+ speed = "1.5";
+ else if (tmp & (1 << 1))
+ speed = "3.0";
+ else
+ speed = "<unknown>";
+ printk(KERN_INFO "ata%u: SATA link up %s Gbps (SStatus %X)\n",
+ ap->id, speed, sstatus);
ata_port_probe(ap);
- else {
- sstatus = scr_read(ap, SCR_STATUS);
- printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n",
+ } else {
+ printk(KERN_INFO "ata%u: SATA link down (SStatus %X)\n",
ap->id, sstatus);
ata_port_disable(ap);
}
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 0be60bba58d..180676d7115 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -265,10 +265,10 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask)
spin_lock_irqsave(&dev->list_lock, flags);
list_add_tail(&cmd->list, &dev->cmd_list);
spin_unlock_irqrestore(&dev->list_lock, flags);
+ cmd->jiffies_at_alloc = jiffies;
} else
put_device(&dev->sdev_gendev);
- cmd->jiffies_at_alloc = jiffies;
return cmd;
}
EXPORT_SYMBOL(scsi_get_command);
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index e08510d09ff..d2bcd1f87cd 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -102,7 +102,7 @@ static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
#define SERIAL_PORT_DFNS
#endif
-static struct old_serial_port old_serial_port[] = {
+static const struct old_serial_port old_serial_port[] = {
SERIAL_PORT_DFNS /* defined in asm/serial.h */
};
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 5c3c03932d6..8d92adfbb8b 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -468,7 +468,7 @@ static unsigned short timedia_eight_port[] = {
0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0
};
-static struct timedia_struct {
+static const struct timedia_struct {
int num;
unsigned short *ids;
} timedia_data[] = {
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 355cd93a8a8..83c4c121658 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -994,7 +994,7 @@ static int __init imx_serial_init(void)
static void __exit imx_serial_exit(void)
{
uart_unregister_driver(&imx_reg);
- driver_unregister(&serial_imx_driver);
+ platform_driver_unregister(&serial_imx_driver);
}
module_init(imx_serial_init);
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 2331296e1e1..c17d680e3f0 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1779,7 +1779,7 @@ struct baud_rates {
unsigned int cflag;
};
-static struct baud_rates baud_rates[] = {
+static const struct baud_rates baud_rates[] = {
{ 921600, B921600 },
{ 460800, B460800 },
{ 230400, B230400 },
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 2c7d3ef76e8..7ce0c7e66d3 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -85,7 +85,7 @@ struct multi_id {
int multi; /* 1 = multifunction, > 1 = # ports */
};
-static struct multi_id multi_id[] = {
+static const struct multi_id multi_id[] = {
{ MANFID_OMEGA, PRODID_OMEGA_QSP_100, 4 },
{ MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232, 2 },
{ MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232_D1, 2 },
@@ -354,8 +354,8 @@ next_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
static int simple_config(dev_link_t *link)
{
- static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
- static int size_table[2] = { 8, 16 };
+ static const kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+ static const int size_table[2] = { 8, 16 };
client_handle_t handle = link->handle;
struct serial_info *info = link->priv;
struct serial_cfg_mem *cfg_mem;
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 7feb829362d..5131d88e8c5 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -20,9 +20,17 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/usb.h>
+
#include <asm/io.h>
#include <asm/irq.h>
-#include <linux/usb.h>
+
+#ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/pci-bridge.h>
+#include <asm/prom.h>
+#endif
#include "usb.h"
#include "hcd.h"
@@ -277,8 +285,22 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
}
done:
- if (retval == 0)
+ if (retval == 0) {
dev->dev.power.power_state = PMSG_SUSPEND;
+
+#ifdef CONFIG_PPC_PMAC
+ /* Disable ASIC clocks for USB */
+ if (_machine == _MACH_Pmac) {
+ struct device_node *of_node;
+
+ of_node = pci_device_to_OF_node (dev);
+ if (of_node)
+ pmac_call_feature(PMAC_FTR_USB_ENABLE,
+ of_node, 0, 0);
+ }
+#endif
+ }
+
return retval;
}
EXPORT_SYMBOL (usb_hcd_pci_suspend);
@@ -301,6 +323,18 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
return 0;
}
+#ifdef CONFIG_PPC_PMAC
+ /* Reenable ASIC clocks for USB */
+ if (_machine == _MACH_Pmac) {
+ struct device_node *of_node;
+
+ of_node = pci_device_to_OF_node (dev);
+ if (of_node)
+ pmac_call_feature (PMAC_FTR_USB_ENABLE,
+ of_node, 0, 1);
+ }
+#endif
+
/* NOTE: chip docs cover clean "real suspend" cases (what Linux
* calls "standby", "suspend to RAM", and so on). There are also
* dirty cases when swsusp fakes a suspend in "shutdown" mode.
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 840727948d8..f78bd124d29 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1669,7 +1669,6 @@ int usb_suspend_device(struct usb_device *udev)
return 0;
#endif
}
-EXPORT_SYMBOL_GPL(usb_suspend_device);
/*
* If the USB "suspend" state is in use (rather than "global suspend"),
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index af3c05eb86f..29f52a44b92 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -411,50 +411,39 @@ static void ehci_stop (struct usb_hcd *hcd)
dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status));
}
-static int ehci_run (struct usb_hcd *hcd)
+/* one-time init, only for memory state */
+static int ehci_init(struct usb_hcd *hcd)
{
- struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
u32 temp;
int retval;
u32 hcc_params;
- int first;
-
- /* skip some things on restart paths */
- first = (ehci->watchdog.data == 0);
- if (first) {
- init_timer (&ehci->watchdog);
- ehci->watchdog.function = ehci_watchdog;
- ehci->watchdog.data = (unsigned long) ehci;
- }
+
+ spin_lock_init(&ehci->lock);
+
+ init_timer(&ehci->watchdog);
+ ehci->watchdog.function = ehci_watchdog;
+ ehci->watchdog.data = (unsigned long) ehci;
/*
* hw default: 1K periodic list heads, one per frame.
* periodic_size can shrink by USBCMD update if hcc_params allows.
*/
ehci->periodic_size = DEFAULT_I_TDPS;
- if (first && (retval = ehci_mem_init (ehci, GFP_KERNEL)) < 0)
+ if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0)
return retval;
/* controllers may cache some of the periodic schedule ... */
- hcc_params = readl (&ehci->caps->hcc_params);
- if (HCC_ISOC_CACHE (hcc_params)) // full frame cache
+ hcc_params = readl(&ehci->caps->hcc_params);
+ if (HCC_ISOC_CACHE(hcc_params)) // full frame cache
ehci->i_thresh = 8;
else // N microframes cached
- ehci->i_thresh = 2 + HCC_ISOC_THRES (hcc_params);
+ ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
ehci->reclaim = NULL;
ehci->reclaim_ready = 0;
ehci->next_uframe = -1;
- /* controller state: unknown --> reset */
-
- /* EHCI spec section 4.1 */
- if ((retval = ehci_reset (ehci)) != 0) {
- ehci_mem_cleanup (ehci);
- return retval;
- }
- writel (ehci->periodic_dma, &ehci->regs->frame_list);
-
/*
* dedicate a qh for the async ring head, since we couldn't unlink
* a 'real' qh without stopping the async schedule [4.8]. use it
@@ -462,37 +451,13 @@ static int ehci_run (struct usb_hcd *hcd)
* its dummy is used in hw_alt_next of many tds, to prevent the qh
* from automatically advancing to the next td after short reads.
*/
- if (first) {
- ehci->async->qh_next.qh = NULL;
- ehci->async->hw_next = QH_NEXT (ehci->async->qh_dma);
- ehci->async->hw_info1 = cpu_to_le32 (QH_HEAD);
- ehci->async->hw_token = cpu_to_le32 (QTD_STS_HALT);
- ehci->async->hw_qtd_next = EHCI_LIST_END;
- ehci->async->qh_state = QH_STATE_LINKED;
- ehci->async->hw_alt_next = QTD_NEXT (ehci->async->dummy->qtd_dma);
- }
- writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next);
-
- /*
- * hcc_params controls whether ehci->regs->segment must (!!!)
- * be used; it constrains QH/ITD/SITD and QTD locations.
- * pci_pool consistent memory always uses segment zero.
- * streaming mappings for I/O buffers, like pci_map_single(),
- * can return segments above 4GB, if the device allows.
- *
- * NOTE: the dma mask is visible through dma_supported(), so
- * drivers can pass this info along ... like NETIF_F_HIGHDMA,
- * Scsi_Host.highmem_io, and so forth. It's readonly to all
- * host side drivers though.
- */
- if (HCC_64BIT_ADDR (hcc_params)) {
- writel (0, &ehci->regs->segment);
-#if 0
-// this is deeply broken on almost all architectures
- if (!dma_set_mask (hcd->self.controller, DMA_64BIT_MASK))
- ehci_info (ehci, "enabled 64bit DMA\n");
-#endif
- }
+ ehci->async->qh_next.qh = NULL;
+ ehci->async->hw_next = QH_NEXT(ehci->async->qh_dma);
+ ehci->async->hw_info1 = cpu_to_le32(QH_HEAD);
+ ehci->async->hw_token = cpu_to_le32(QTD_STS_HALT);
+ ehci->async->hw_qtd_next = EHCI_LIST_END;
+ ehci->async->qh_state = QH_STATE_LINKED;
+ ehci->async->hw_alt_next = QTD_NEXT(ehci->async->dummy->qtd_dma);
/* clear interrupt enables, set irq latency */
if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
@@ -507,13 +472,13 @@ static int ehci_run (struct usb_hcd *hcd)
* make problems: throughput reduction (!), data errors...
*/
if (park) {
- park = min (park, (unsigned) 3);
+ park = min(park, (unsigned) 3);
temp |= CMD_PARK;
temp |= park << 8;
}
- ehci_info (ehci, "park %d\n", park);
+ ehci_dbg(ehci, "park %d\n", park);
}
- if (HCC_PGM_FRAMELISTLEN (hcc_params)) {
+ if (HCC_PGM_FRAMELISTLEN(hcc_params)) {
/* periodic schedule size can be smaller than default */
temp &= ~(3 << 2);
temp |= (EHCI_TUNE_FLS << 2);
@@ -521,16 +486,63 @@ static int ehci_run (struct usb_hcd *hcd)
case 0: ehci->periodic_size = 1024; break;
case 1: ehci->periodic_size = 512; break;
case 2: ehci->periodic_size = 256; break;
- default: BUG ();
+ default: BUG();
}
}
+ ehci->command = temp;
+
+ ehci->reboot_notifier.notifier_call = ehci_reboot;
+ register_reboot_notifier(&ehci->reboot_notifier);
+
+ return 0;
+}
+
+/* start HC running; it's halted, ehci_init() has been run (once) */
+static int ehci_run (struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ int retval;
+ u32 temp;
+ u32 hcc_params;
+
+ /* EHCI spec section 4.1 */
+ if ((retval = ehci_reset(ehci)) != 0) {
+ unregister_reboot_notifier(&ehci->reboot_notifier);
+ ehci_mem_cleanup(ehci);
+ return retval;
+ }
+ writel(ehci->periodic_dma, &ehci->regs->frame_list);
+ writel((u32)ehci->async->qh_dma, &ehci->regs->async_next);
+
+ /*
+ * hcc_params controls whether ehci->regs->segment must (!!!)
+ * be used; it constrains QH/ITD/SITD and QTD locations.
+ * pci_pool consistent memory always uses segment zero.
+ * streaming mappings for I/O buffers, like pci_map_single(),
+ * can return segments above 4GB, if the device allows.
+ *
+ * NOTE: the dma mask is visible through dma_supported(), so
+ * drivers can pass this info along ... like NETIF_F_HIGHDMA,
+ * Scsi_Host.highmem_io, and so forth. It's readonly to all
+ * host side drivers though.
+ */
+ hcc_params = readl(&ehci->caps->hcc_params);
+ if (HCC_64BIT_ADDR(hcc_params)) {
+ writel(0, &ehci->regs->segment);
+#if 0
+// this is deeply broken on almost all architectures
+ if (!dma_set_mask(hcd->self.controller, DMA_64BIT_MASK))
+ ehci_info(ehci, "enabled 64bit DMA\n");
+#endif
+ }
+
+
// Philips, Intel, and maybe others need CMD_RUN before the
// root hub will detect new devices (why?); NEC doesn't
- temp |= CMD_RUN;
- writel (temp, &ehci->regs->command);
- dbg_cmd (ehci, "init", temp);
-
- /* set async sleep time = 10 us ... ? */
+ ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
+ ehci->command |= CMD_RUN;
+ writel (ehci->command, &ehci->regs->command);
+ dbg_cmd (ehci, "init", ehci->command);
/*
* Start, enabling full USB 2.0 functionality ... usb 1.1 devices
@@ -538,26 +550,23 @@ static int ehci_run (struct usb_hcd *hcd)
* involved with the root hub. (Except where one is integrated,
* and there's no companion controller unless maybe for USB OTG.)
*/
- if (first) {
- ehci->reboot_notifier.notifier_call = ehci_reboot;
- register_reboot_notifier (&ehci->reboot_notifier);
- }
-
hcd->state = HC_STATE_RUNNING;
writel (FLAG_CF, &ehci->regs->configured_flag);
- readl (&ehci->regs->command); /* unblock posted write */
+ readl (&ehci->regs->command); /* unblock posted writes */
temp = HC_VERSION(readl (&ehci->caps->hc_capbase));
ehci_info (ehci,
- "USB %x.%x %s, EHCI %x.%02x, driver %s\n",
+ "USB %x.%x started, EHCI %x.%02x, driver %s\n",
((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
- first ? "initialized" : "restarted",
temp >> 8, temp & 0xff, DRIVER_VERSION);
writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */
- if (first)
- create_debug_files (ehci);
+ /* GRR this is run-once init(), being done every time the HC starts.
+ * So long as they're part of class devices, we can't do it init()
+ * since the class device isn't created that early.
+ */
+ create_debug_files(ehci);
return 0;
}
@@ -636,9 +645,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
* stop that signaling.
*/
ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
- mod_timer (&hcd->rh_timer,
- ehci->reset_done [i] + 1);
ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
+ usb_hcd_resume_root_hub(hcd);
}
}
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 88cb4ada686..82caf336e9b 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -94,6 +94,13 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
msleep(5);
spin_lock_irq (&ehci->lock);
+ /* Ideally and we've got a real resume here, and no port's power
+ * was lost. (For PCI, that means Vaux was maintained.) But we
+ * could instead be restoring a swsusp snapshot -- so that BIOS was
+ * the last user of the controller, not reset/pm hardware keeping
+ * state we gave to it.
+ */
+
/* re-init operational registers in case we lost power */
if (readl (&ehci->regs->intr_enable) == 0) {
/* at least some APM implementations will try to deliver
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index dfd9bd0b182..441c26064b4 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -27,7 +27,7 @@
/* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/...
* off the controller (maybe it can boot from highspeed USB disks).
*/
-static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
+static int bios_handoff(struct ehci_hcd *ehci, int where, u32 cap)
{
struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
@@ -48,7 +48,7 @@ static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
where, cap);
// some BIOS versions seem buggy...
// return 1;
- ehci_warn (ehci, "continuing after BIOS bug...\n");
+ ehci_warn(ehci, "continuing after BIOS bug...\n");
/* disable all SMIs, and clear "BIOS owns" flag */
pci_write_config_dword(pdev, where + 4, 0);
pci_write_config_byte(pdev, where + 2, 0);
@@ -58,96 +58,47 @@ static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
return 0;
}
-/* called by khubd or root hub init threads */
-static int ehci_pci_reset (struct usb_hcd *hcd)
+/* called after powerup, by probe or system-pm "wakeup" */
+static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
{
- struct ehci_hcd *ehci = hcd_to_ehci (hcd);
u32 temp;
+ int retval;
unsigned count = 256/4;
- spin_lock_init (&ehci->lock);
-
- ehci->caps = hcd->regs;
- ehci->regs = hcd->regs + HC_LENGTH (readl (&ehci->caps->hc_capbase));
- dbg_hcs_params (ehci, "reset");
- dbg_hcc_params (ehci, "reset");
-
- /* cache this readonly data; minimize chip reads */
- ehci->hcs_params = readl (&ehci->caps->hcs_params);
-
- if (hcd->self.controller->bus == &pci_bus_type) {
- struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
-
- switch (pdev->vendor) {
- case PCI_VENDOR_ID_TDI:
- if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
- ehci->is_tdi_rh_tt = 1;
- tdi_reset (ehci);
- }
- break;
- case PCI_VENDOR_ID_AMD:
- /* AMD8111 EHCI doesn't work, according to AMD errata */
- if (pdev->device == 0x7463) {
- ehci_info (ehci, "ignoring AMD8111 (errata)\n");
- return -EIO;
- }
- break;
- case PCI_VENDOR_ID_NVIDIA:
- /* NVidia reports that certain chips don't handle
- * QH, ITD, or SITD addresses above 2GB. (But TD,
- * data buffer, and periodic schedule are normal.)
- */
- switch (pdev->device) {
- case 0x003c: /* MCP04 */
- case 0x005b: /* CK804 */
- case 0x00d8: /* CK8 */
- case 0x00e8: /* CK8S */
- if (pci_set_consistent_dma_mask(pdev,
- DMA_31BIT_MASK) < 0)
- ehci_warn (ehci, "can't enable NVidia "
- "workaround for >2GB RAM\n");
- break;
- }
- break;
- }
-
- /* optional debug port, normally in the first BAR */
- temp = pci_find_capability (pdev, 0x0a);
- if (temp) {
- pci_read_config_dword(pdev, temp, &temp);
- temp >>= 16;
- if ((temp & (3 << 13)) == (1 << 13)) {
- temp &= 0x1fff;
- ehci->debug = hcd->regs + temp;
- temp = readl (&ehci->debug->control);
- ehci_info (ehci, "debug port %d%s\n",
- HCS_DEBUG_PORT(ehci->hcs_params),
- (temp & DBGP_ENABLED)
- ? " IN USE"
- : "");
- if (!(temp & DBGP_ENABLED))
- ehci->debug = NULL;
- }
+ /* optional debug port, normally in the first BAR */
+ temp = pci_find_capability(pdev, 0x0a);
+ if (temp) {
+ pci_read_config_dword(pdev, temp, &temp);
+ temp >>= 16;
+ if ((temp & (3 << 13)) == (1 << 13)) {
+ temp &= 0x1fff;
+ ehci->debug = ehci_to_hcd(ehci)->regs + temp;
+ temp = readl(&ehci->debug->control);
+ ehci_info(ehci, "debug port %d%s\n",
+ HCS_DEBUG_PORT(ehci->hcs_params),
+ (temp & DBGP_ENABLED)
+ ? " IN USE"
+ : "");
+ if (!(temp & DBGP_ENABLED))
+ ehci->debug = NULL;
}
+ }
- temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params));
- } else
- temp = 0;
+ temp = HCC_EXT_CAPS(readl(&ehci->caps->hcc_params));
/* EHCI 0.96 and later may have "extended capabilities" */
while (temp && count--) {
u32 cap;
- pci_read_config_dword (to_pci_dev(hcd->self.controller),
- temp, &cap);
- ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp);
+ pci_read_config_dword(pdev, temp, &cap);
+ ehci_dbg(ehci, "capability %04x at %02x\n", cap, temp);
switch (cap & 0xff) {
case 1: /* BIOS/SMM/... handoff */
- if (bios_handoff (ehci, temp, cap) != 0)
+ if (bios_handoff(ehci, temp, cap) != 0)
return -EOPNOTSUPP;
break;
case 0: /* illegal reserved capability */
- ehci_warn (ehci, "illegal capability!\n");
+ ehci_dbg(ehci, "illegal capability!\n");
cap = 0;
/* FALLTHROUGH */
default: /* unknown */
@@ -156,77 +107,109 @@ static int ehci_pci_reset (struct usb_hcd *hcd)
temp = (cap >> 8) & 0xff;
}
if (!count) {
- ehci_err (ehci, "bogus capabilities ... PCI problems!\n");
+ ehci_err(ehci, "bogus capabilities ... PCI problems!\n");
return -EIO;
}
- if (ehci_is_TDI(ehci))
- ehci_reset (ehci);
- ehci_port_power (ehci, 0);
+ /* PCI Memory-Write-Invalidate cycle support is optional (uncommon) */
+ retval = pci_set_mwi(pdev);
+ if (!retval)
+ ehci_dbg(ehci, "MWI active\n");
+
+ ehci_port_power(ehci, 0);
+
+ return 0;
+}
+
+/* called by khubd or root hub (re)init threads; leaves HC in halt state */
+static int ehci_pci_reset(struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+ u32 temp;
+ int retval;
+
+ ehci->caps = hcd->regs;
+ ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
+ dbg_hcs_params(ehci, "reset");
+ dbg_hcc_params(ehci, "reset");
+
+ /* cache this readonly data; minimize chip reads */
+ ehci->hcs_params = readl(&ehci->caps->hcs_params);
+
+ retval = ehci_halt(ehci);
+ if (retval)
+ return retval;
+
+ /* NOTE: only the parts below this line are PCI-specific */
+
+ switch (pdev->vendor) {
+ case PCI_VENDOR_ID_TDI:
+ if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
+ ehci->is_tdi_rh_tt = 1;
+ tdi_reset(ehci);
+ }
+ break;
+ case PCI_VENDOR_ID_AMD:
+ /* AMD8111 EHCI doesn't work, according to AMD errata */
+ if (pdev->device == 0x7463) {
+ ehci_info(ehci, "ignoring AMD8111 (errata)\n");
+ return -EIO;
+ }
+ break;
+ case PCI_VENDOR_ID_NVIDIA:
+ /* NVidia reports that certain chips don't handle
+ * QH, ITD, or SITD addresses above 2GB. (But TD,
+ * data buffer, and periodic schedule are normal.)
+ */
+ switch (pdev->device) {
+ case 0x003c: /* MCP04 */
+ case 0x005b: /* CK804 */
+ case 0x00d8: /* CK8 */
+ case 0x00e8: /* CK8S */
+ if (pci_set_consistent_dma_mask(pdev,
+ DMA_31BIT_MASK) < 0)
+ ehci_warn(ehci, "can't enable NVidia "
+ "workaround for >2GB RAM\n");
+ break;
+ }
+ break;
+ }
+
+ if (ehci_is_TDI(ehci))
+ ehci_reset(ehci);
/* at least the Genesys GL880S needs fixup here */
temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
temp &= 0x0f;
if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) {
- ehci_dbg (ehci, "bogus port configuration: "
+ ehci_dbg(ehci, "bogus port configuration: "
"cc=%d x pcc=%d < ports=%d\n",
HCS_N_CC(ehci->hcs_params),
HCS_N_PCC(ehci->hcs_params),
HCS_N_PORTS(ehci->hcs_params));
- if (hcd->self.controller->bus == &pci_bus_type) {
- struct pci_dev *pdev;
-
- pdev = to_pci_dev(hcd->self.controller);
- switch (pdev->vendor) {
- case 0x17a0: /* GENESYS */
- /* GL880S: should be PORTS=2 */
- temp |= (ehci->hcs_params & ~0xf);
- ehci->hcs_params = temp;
- break;
- case PCI_VENDOR_ID_NVIDIA:
- /* NF4: should be PCC=10 */
- break;
- }
+ switch (pdev->vendor) {
+ case 0x17a0: /* GENESYS */
+ /* GL880S: should be PORTS=2 */
+ temp |= (ehci->hcs_params & ~0xf);
+ ehci->hcs_params = temp;
+ break;
+ case PCI_VENDOR_ID_NVIDIA:
+ /* NF4: should be PCC=10 */
+ break;
}
}
- /* force HC to halt state */
- return ehci_halt (ehci);
-}
-
-static int ehci_pci_start (struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci (hcd);
- int result = 0;
-
- if (hcd->self.controller->bus == &pci_bus_type) {
- struct pci_dev *pdev;
- u16 port_wake;
-
- pdev = to_pci_dev(hcd->self.controller);
-
- /* Serial Bus Release Number is at PCI 0x60 offset */
- pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
-
- /* port wake capability, reported by boot firmware */
- pci_read_config_word(pdev, 0x62, &port_wake);
- hcd->can_wakeup = (port_wake & 1) != 0;
+ /* Serial Bus Release Number is at PCI 0x60 offset */
+ pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
- /* help hc dma work well with cachelines */
- result = pci_set_mwi(pdev);
- if (result)
- ehci_dbg(ehci, "unable to enable MWI - not fatal.\n");
- }
-
- return ehci_run (hcd);
-}
+ /* REVISIT: per-port wake capability (PCI 0x62) currently unused */
-/* always called by thread; normally rmmod */
+ retval = ehci_pci_reinit(ehci, pdev);
-static void ehci_pci_stop (struct usb_hcd *hcd)
-{
- ehci_stop (hcd);
+ /* finish init */
+ return ehci_init(hcd);
}
/*-------------------------------------------------------------------------*/
@@ -235,90 +218,88 @@ static void ehci_pci_stop (struct usb_hcd *hcd)
/* suspend/resume, section 4.3 */
-/* These routines rely on the bus (pci, platform, etc)
+/* These routines rely on the PCI bus glue
* to handle powerdown and wakeup, and currently also on
* transceivers that don't need any software attention to set up
* the right sort of wakeup.
+ * Also they depend on separate root hub suspend/resume.
*/
-static int ehci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
+static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
{
- struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- if (time_before (jiffies, ehci->next_statechange))
- msleep (100);
+ if (time_before(jiffies, ehci->next_statechange))
+ msleep(10);
-#ifdef CONFIG_USB_SUSPEND
- (void) usb_suspend_device (hcd->self.root_hub);
-#else
- usb_lock_device (hcd->self.root_hub);
- (void) ehci_bus_suspend (hcd);
- usb_unlock_device (hcd->self.root_hub);
-#endif
-
- // save (PCI) FLADJ in case of Vaux power loss
+ // could save FLADJ in case of Vaux power loss
// ... we'd only use it to handle clock skew
return 0;
}
-static int ehci_pci_resume (struct usb_hcd *hcd)
+static int ehci_pci_resume(struct usb_hcd *hcd)
{
- struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
unsigned port;
struct usb_device *root = hcd->self.root_hub;
+ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
int retval = -EINVAL;
- // maybe restore (PCI) FLADJ
+ // maybe restore FLADJ
- if (time_before (jiffies, ehci->next_statechange))
- msleep (100);
+ if (time_before(jiffies, ehci->next_statechange))
+ msleep(100);
+
+ /* If CF is clear, we lost PCI Vaux power and need to restart. */
+ if (readl(&ehci->regs->configured_flag) != FLAG_CF)
+ goto restart;
/* If any port is suspended (or owned by the companion),
* we know we can/must resume the HC (and mustn't reset it).
+ * We just defer that to the root hub code.
*/
- for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) {
+ for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) {
u32 status;
port--;
- status = readl (&ehci->regs->port_status [port]);
+ status = readl(&ehci->regs->port_status [port]);
if (!(status & PORT_POWER))
continue;
- if (status & (PORT_SUSPEND | PORT_OWNER)) {
- down (&hcd->self.root_hub->serialize);
- retval = ehci_bus_resume (hcd);
- up (&hcd->self.root_hub->serialize);
- break;
+ if (status & (PORT_SUSPEND | PORT_RESUME | PORT_OWNER)) {
+ usb_hcd_resume_root_hub(hcd);
+ return 0;
}
+ }
+
+restart:
+ ehci_dbg(ehci, "lost power, restarting\n");
+ for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) {
+ port--;
if (!root->children [port])
continue;
- dbg_port (ehci, __FUNCTION__, port + 1, status);
- usb_set_device_state (root->children[port],
+ usb_set_device_state(root->children[port],
USB_STATE_NOTATTACHED);
}
/* Else reset, to cope with power loss or flush-to-storage
- * style "resume" having activated BIOS during reboot.
+ * style "resume" having let BIOS kick in during reboot.
*/
- if (port == 0) {
- (void) ehci_halt (ehci);
- (void) ehci_reset (ehci);
- (void) ehci_pci_reset (hcd);
-
- /* emptying the schedule aborts any urbs */
- spin_lock_irq (&ehci->lock);
- if (ehci->reclaim)
- ehci->reclaim_ready = 1;
- ehci_work (ehci, NULL);
- spin_unlock_irq (&ehci->lock);
-
- /* restart; khubd will disconnect devices */
- retval = ehci_run (hcd);
-
- /* here we "know" root ports should always stay powered;
- * but some controllers may lose all power.
- */
- ehci_port_power (ehci, 1);
- }
+ (void) ehci_halt(ehci);
+ (void) ehci_reset(ehci);
+ (void) ehci_pci_reinit(ehci, pdev);
+
+ /* emptying the schedule aborts any urbs */
+ spin_lock_irq(&ehci->lock);
+ if (ehci->reclaim)
+ ehci->reclaim_ready = 1;
+ ehci_work(ehci, NULL);
+ spin_unlock_irq(&ehci->lock);
+
+ /* restart; khubd will disconnect devices */
+ retval = ehci_run(hcd);
+
+ /* here we "know" root ports should always stay powered */
+ ehci_port_power(ehci, 1);
return retval;
}
@@ -339,12 +320,12 @@ static const struct hc_driver ehci_pci_hc_driver = {
* basic lifecycle operations
*/
.reset = ehci_pci_reset,
- .start = ehci_pci_start,
+ .start = ehci_run,
#ifdef CONFIG_PM
.suspend = ehci_pci_suspend,
.resume = ehci_pci_resume,
#endif
- .stop = ehci_pci_stop,
+ .stop = ehci_stop,
/*
* managing i/o requests and associated device resources
@@ -377,7 +358,7 @@ static const struct pci_device_id pci_ids [] = { {
},
{ /* end: all zeroes */ }
};
-MODULE_DEVICE_TABLE (pci, pci_ids);
+MODULE_DEVICE_TABLE(pci, pci_ids);
/* pci driver glue; this is a "new style" PCI driver module */
static struct pci_driver ehci_pci_driver = {
@@ -393,22 +374,22 @@ static struct pci_driver ehci_pci_driver = {
#endif
};
-static int __init ehci_hcd_pci_init (void)
+static int __init ehci_hcd_pci_init(void)
{
if (usb_disabled())
return -ENODEV;
- pr_debug ("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
+ pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
hcd_name,
- sizeof (struct ehci_qh), sizeof (struct ehci_qtd),
- sizeof (struct ehci_itd), sizeof (struct ehci_sitd));
+ sizeof(struct ehci_qh), sizeof(struct ehci_qtd),
+ sizeof(struct ehci_itd), sizeof(struct ehci_sitd));
- return pci_register_driver (&ehci_pci_driver);
+ return pci_register_driver(&ehci_pci_driver);
}
-module_init (ehci_hcd_pci_init);
+module_init(ehci_hcd_pci_init);
-static void __exit ehci_hcd_pci_cleanup (void)
+static void __exit ehci_hcd_pci_cleanup(void)
{
- pci_unregister_driver (&ehci_pci_driver);
+ pci_unregister_driver(&ehci_pci_driver);
}
-module_exit (ehci_hcd_pci_cleanup);
+module_exit(ehci_hcd_pci_cleanup);
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index a59e536441e..5f22e6590cd 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -14,15 +14,6 @@
* This file is licenced under the GPL.
*/
-#include <linux/jiffies.h>
-
-#ifdef CONFIG_PPC_PMAC
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include <asm/pci-bridge.h>
-#include <asm/prom.h>
-#endif
-
#ifndef CONFIG_PCI
#error "This file is PCI bus glue. CONFIG_PCI must be defined."
#endif
@@ -115,39 +106,12 @@ ohci_pci_start (struct usb_hcd *hcd)
static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
{
/* root hub was already suspended */
-
- /* FIXME these PMAC things get called in the wrong places. ASIC
- * clocks should be turned off AFTER entering D3, and on BEFORE
- * trying to enter D0. Evidently the PCI layer doesn't currently
- * provide the right sort of platform hooks for this ...
- */
-#ifdef CONFIG_PPC_PMAC
- if (_machine == _MACH_Pmac) {
- struct device_node *of_node;
-
- /* Disable USB PAD & cell clock */
- of_node = pci_device_to_OF_node (to_pci_dev(hcd->self.controller));
- if (of_node)
- pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
- }
-#endif /* CONFIG_PPC_PMAC */
return 0;
}
static int ohci_pci_resume (struct usb_hcd *hcd)
{
-#ifdef CONFIG_PPC_PMAC
- if (_machine == _MACH_Pmac) {
- struct device_node *of_node;
-
- /* Re-enable USB PAD & cell clock */
- of_node = pci_device_to_OF_node (to_pci_dev(hcd->self.controller));
- if (of_node)
- pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1);
- }
-#endif /* CONFIG_PPC_PMAC */
-
usb_hcd_resume_root_hub(hcd);
return 0;
}
diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c
index cf8cfbabefd..b2e66e3b90a 100644
--- a/drivers/usb/media/sn9c102_core.c
+++ b/drivers/usb/media/sn9c102_core.c
@@ -199,7 +199,7 @@ static void sn9c102_release_buffers(struct sn9c102_device* cam)
{
if (cam->nbuffers) {
rvfree(cam->frame[0].bufmem,
- cam->nbuffers * cam->frame[0].buf.length);
+ cam->nbuffers * PAGE_ALIGN(cam->frame[0].buf.length));
cam->nbuffers = 0;
}
}
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 61204bf7cd7..06e04b442ff 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -475,6 +475,8 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) },
+ { USB_DEVICE(KOBIL_VID, KOBIL_CONV_B1_PID) },
+ { USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) },
{ }, /* Optional parameter entry */
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index ddb63df31ce..773ea3eca08 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -128,6 +128,13 @@
#define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */
/*
+ * The following are the values for two KOBIL chipcard terminals.
+ */
+#define KOBIL_VID 0x0d46 /* KOBIL Vendor ID */
+#define KOBIL_CONV_B1_PID 0x2020 /* KOBIL Konverter for B1 */
+#define KOBIL_CONV_KAAN_PID 0x2021 /* KOBIL_Konverter for KAAN */
+
+/*
* DSS-20 Sync Station for Sony Ericsson P800
*/
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index a02fada8536..7744b8148bc 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -46,7 +46,6 @@
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/usb.h>
-#include <linux/usb.h>
#include <asm/uaccess.h>
#include "usb-serial.h"
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 0a9858f69a9..f5f47a34b16 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1118,6 +1118,15 @@ UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_GO_SLOW ),
+/*
+ * David Härdeman <david@2gen.com>
+ * The key makes the SCSI stack print confusing (but harmless) messages
+ */
+UNUSUAL_DEV( 0x4146, 0xba01, 0x0100, 0x0100,
+ "Iomega",
+ "Micro Mini 1GB",
+ US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
+
#ifdef CONFIG_USB_STORAGE_SDDR55
UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999,
"Sandisk",
diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c
index 3afd1eeb1ad..4952b66ae20 100644
--- a/drivers/video/console/fbcon_ccw.c
+++ b/drivers/video/console/fbcon_ccw.c
@@ -34,7 +34,7 @@ static inline void ccw_update_attr(u8 *dst, u8 *src, int attribute,
msk <<= (8 - mod);
if (offset > mod)
- set_bit(FBCON_BIT(7), (void *)&msk1);
+ msk1 |= 0x01;
for (i = 0; i < vc->vc_font.width; i++) {
for (j = 0; j < width; j++) {
diff --git a/drivers/video/console/fbcon_rotate.h b/drivers/video/console/fbcon_rotate.h
index 90c672096c2..1b8f92fdc6a 100644
--- a/drivers/video/console/fbcon_rotate.h
+++ b/drivers/video/console/fbcon_rotate.h
@@ -21,21 +21,13 @@
(s == SCROLL_REDRAW || s == SCROLL_MOVE || !(i)->fix.xpanstep) ? \
(i)->var.xres : (i)->var.xres_virtual; })
-/*
- * The bitmap is always big endian
- */
-#if defined(__LITTLE_ENDIAN)
-#define FBCON_BIT(b) (7 - (b))
-#else
-#define FBCON_BIT(b) (b)
-#endif
static inline int pattern_test_bit(u32 x, u32 y, u32 pitch, const char *pat)
{
u32 tmp = (y * pitch) + x, index = tmp / 8, bit = tmp % 8;
pat +=index;
- return (test_bit(FBCON_BIT(bit), (void *)pat));
+ return (*pat) & (0x80 >> bit);
}
static inline void pattern_set_bit(u32 x, u32 y, u32 pitch, char *pat)
@@ -43,13 +35,14 @@ static inline void pattern_set_bit(u32 x, u32 y, u32 pitch, char *pat)
u32 tmp = (y * pitch) + x, index = tmp / 8, bit = tmp % 8;
pat += index;
- set_bit(FBCON_BIT(bit), (void *)pat);
+
+ (*pat) |= 0x80 >> bit;
}
static inline void rotate_ud(const char *in, char *out, u32 width, u32 height)
{
int i, j;
- int shift = width % 8;
+ int shift = (8 - (width % 8)) & 7;
width = (width + 7) & ~7;
@@ -85,7 +78,7 @@ static inline void rotate_cw(const char *in, char *out, u32 width, u32 height)
static inline void rotate_ccw(const char *in, char *out, u32 width, u32 height)
{
int i, j, h = height, w = width;
- int shift = width % 8;
+ int shift = (8 - (width % 8)) & 7;
width = (width + 7) & ~7;
height = (height + 7) & ~7;
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 274f90543e3..167de397e4b 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -966,6 +966,7 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
outb_p(0x12, vga_video_port_reg); /* Vertical display limit */
outb_p(vde, vga_video_port_val);
spin_unlock_irq(&vga_lock);
+ vga_video_font_height = fontheight;
for (i = 0; i < MAX_NR_CONSOLES; i++) {
struct vc_data *c = vc_cons[i].d;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 9f180096c89..6240aedb415 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -452,13 +452,17 @@ int fb_prepare_logo(struct fb_info *info, int rotate)
/* Return if no suitable logo was found */
fb_logo.logo = fb_find_logo(depth);
+
+ if (!fb_logo.logo) {
+ return 0;
+ }
if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD)
yres = info->var.yres;
else
yres = info->var.xres;
- if (fb_logo.logo && fb_logo.logo->height > yres) {
+ if (fb_logo.logo->height > yres) {
fb_logo.logo = NULL;
return 0;
}