aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acorn/block/fd1772.c3
-rw-r--r--drivers/acpi/Kconfig5
-rw-r--r--drivers/acpi/button.c206
-rw-r--r--drivers/acpi/dispatcher/dswload.c6
-rw-r--r--drivers/acpi/ec.c907
-rw-r--r--drivers/acpi/hotkey.c690
-rw-r--r--drivers/acpi/osl.c6
-rw-r--r--drivers/acpi/pci_irq.c85
-rw-r--r--drivers/acpi/pci_link.c127
-rw-r--r--drivers/acpi/processor_idle.c32
-rw-r--r--drivers/block/cfq-iosched.c1
-rw-r--r--drivers/block/ll_rw_blk.c18
-rw-r--r--drivers/bluetooth/bpa10x.c7
-rw-r--r--drivers/bluetooth/hci_bcsp.c2
-rw-r--r--drivers/bluetooth/hci_h4.c5
-rw-r--r--drivers/bluetooth/hci_ldisc.c2
-rw-r--r--drivers/bluetooth/hci_usb.c11
-rw-r--r--drivers/char/mem.c12
-rw-r--r--drivers/char/rtc.c7
-rw-r--r--drivers/char/tpm/Kconfig11
-rw-r--r--drivers/char/tpm/tpm_infineon.c146
-rw-r--r--drivers/char/watchdog/i8xx_tco.c41
-rw-r--r--drivers/char/watchdog/sa1100_wdt.c49
-rw-r--r--drivers/fc4/fc.c2
-rw-r--r--drivers/i2c/busses/i2c-mpc.c94
-rw-r--r--drivers/i2c/busses/i2c-sibyte.c4
-rw-r--r--drivers/ide/ide-disk.c2
-rw-r--r--drivers/ide/ide-probe.c7
-rw-r--r--drivers/ide/legacy/ide-cs.c2
-rw-r--r--drivers/infiniband/include/ib_cm.h3
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c5
-rw-r--r--drivers/input/gameport/ns558.c4
-rw-r--r--drivers/isdn/icn/icn.c5
-rw-r--r--drivers/md/bitmap.c75
-rw-r--r--drivers/md/dm-raid1.c2
-rw-r--r--drivers/md/md.c4
-rw-r--r--drivers/md/raid1.c29
-rw-r--r--drivers/md/raid5.c1
-rw-r--r--drivers/md/raid6main.c1
-rw-r--r--drivers/media/dvb/frontends/Kconfig2
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c16
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.h1
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.c514
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.h16
-rw-r--r--drivers/media/dvb/frontends/lgdt330x_priv.h8
-rw-r--r--drivers/media/video/bttv-cards.c8
-rw-r--r--drivers/media/video/bttv-driver.c33
-rw-r--r--drivers/media/video/bttv.h6
-rw-r--r--drivers/media/video/bttvp.h4
-rw-r--r--drivers/media/video/cx88/cx88-cards.c33
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c26
-rw-r--r--drivers/media/video/cx88/cx88-video.c4
-rw-r--r--drivers/media/video/cx88/cx88.h3
-rw-r--r--drivers/media/video/msp3400.c4
-rw-r--r--drivers/media/video/saa7134/saa7134-i2c.c4
-rw-r--r--drivers/media/video/saa7134/saa7134.h4
-rw-r--r--drivers/media/video/tea5767.c26
-rw-r--r--drivers/media/video/tuner-core.c29
-rw-r--r--drivers/media/video/tuner-simple.c8
-rw-r--r--drivers/media/video/tveeprom.c2
-rw-r--r--drivers/message/i2o/Kconfig3
-rw-r--r--drivers/message/i2o/config-osm.c494
-rw-r--r--drivers/message/i2o/pci.c10
-rw-r--r--drivers/mmc/wbsd.c2
-rw-r--r--drivers/net/cs89x0.c12
-rw-r--r--drivers/net/cs89x0.h1
-rw-r--r--drivers/net/e1000/e1000_main.c1
-rw-r--r--drivers/net/hamradio/6pack.c20
-rw-r--r--drivers/net/hamradio/Kconfig2
-rw-r--r--drivers/net/sk98lin/skge.c80
-rw-r--r--drivers/net/sk98lin/skgeinit.c2
-rw-r--r--drivers/net/sk98lin/skxmac2.c8
-rw-r--r--drivers/net/skge.c233
-rw-r--r--drivers/net/skge.h41
-rw-r--r--drivers/net/smc91x.h2
-rw-r--r--drivers/net/tg3.c16
-rw-r--r--drivers/pci/bus.c4
-rw-r--r--drivers/pci/quirks.c19
-rw-r--r--drivers/pci/setup-res.c7
-rw-r--r--drivers/pcmcia/ds.c2
-rw-r--r--drivers/pcmcia/yenta_socket.c27
-rw-r--r--drivers/s390/net/qeth_main.c24
-rw-r--r--drivers/s390/net/qeth_proc.c126
-rw-r--r--drivers/sbus/char/bbc_envctrl.c39
-rw-r--r--drivers/sbus/char/envctrl.c45
-rw-r--r--drivers/sbus/char/vfc.h2
-rw-r--r--drivers/sbus/char/vfc_dev.c1
-rw-r--r--drivers/sbus/char/vfc_i2c.c19
-rw-r--r--drivers/scsi/Kconfig2
-rw-r--r--drivers/scsi/aacraid/aacraid.h6
-rw-r--r--drivers/scsi/aacraid/linit.c3
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c24
-rw-r--r--drivers/scsi/aic7xxx/aicasm/aicasm.c4
-rw-r--r--drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h8
-rw-r--r--drivers/scsi/dc395x.c48
-rw-r--r--drivers/scsi/dpt_i2o.c9
-rw-r--r--drivers/scsi/ibmvscsi/srp.h2
-rw-r--r--drivers/scsi/ips.c8
-rw-r--r--drivers/scsi/ips.h39
-rw-r--r--drivers/scsi/libata-scsi.c1
-rw-r--r--drivers/scsi/sata_sx4.c2
-rw-r--r--drivers/scsi/scsi_scan.c16
-rw-r--r--drivers/scsi/scsi_transport_fc.c19
-rw-r--r--drivers/scsi/st.c8
-rw-r--r--drivers/serial/cpm_uart/cpm_uart.h10
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c132
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm1.c53
-rw-r--r--drivers/usb/host/ehci-dbg.c2
-rw-r--r--drivers/usb/host/ehci-q.c5
-rw-r--r--drivers/usb/host/ehci-sched.c13
-rw-r--r--drivers/usb/host/ehci.h5
-rw-r--r--drivers/usb/host/isp116x-hcd.c4
-rw-r--r--drivers/usb/mon/Kconfig9
-rw-r--r--drivers/usb/mon/Makefile1
-rw-r--r--drivers/video/fbsysfs.c8
-rw-r--r--drivers/video/modedb.c5
-rw-r--r--drivers/video/nvidia/nvidia.c7
-rw-r--r--drivers/video/pxafb.c8
-rw-r--r--drivers/video/sa1100fb.c2
-rw-r--r--drivers/video/tridentfb.c28
-rw-r--r--drivers/w1/w1.c2
121 files changed, 3026 insertions, 2079 deletions
diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
index 3cd2e968e96..c0a37d98b4f 100644
--- a/drivers/acorn/block/fd1772.c
+++ b/drivers/acorn/block/fd1772.c
@@ -1283,8 +1283,7 @@ static void do_fd_request(request_queue_t* q)
if (fdc_busy) return;
save_flags(flags);
cli();
- while (fdc_busy)
- sleep_on(&fdc_wait);
+ wait_event(fdc_wait, !fdc_busy);
fdc_busy = 1;
ENABLE_IRQ();
restore_flags(flags);
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 986410e7b48..ba13896cae4 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -133,9 +133,10 @@ config ACPI_HOTKEY
depends on ACPI_INTERPRETER
depends on EXPERIMENTAL
depends on !IA64_SGI_SN
- default m
+ default n
help
- ACPI generic hotkey
+ Experimental consolidated hotkey driver.
+ If you are unsure, say N.
config ACPI_FAN
tristate "Fan"
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 0f45d45f05a..8162fd0c21a 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -26,6 +26,9 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
@@ -33,6 +36,9 @@
#define ACPI_BUTTON_COMPONENT 0x00080000
#define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver"
#define ACPI_BUTTON_CLASS "button"
+#define ACPI_BUTTON_FILE_INFO "info"
+#define ACPI_BUTTON_FILE_STATE "state"
+#define ACPI_BUTTON_TYPE_UNKNOWN 0x00
#define ACPI_BUTTON_NOTIFY_STATUS 0x80
#define ACPI_BUTTON_SUBCLASS_POWER "power"
@@ -64,6 +70,8 @@ MODULE_LICENSE("GPL");
static int acpi_button_add (struct acpi_device *device);
static int acpi_button_remove (struct acpi_device *device, int type);
+static int acpi_button_info_open_fs(struct inode *inode, struct file *file);
+static int acpi_button_state_open_fs(struct inode *inode, struct file *file);
static struct acpi_driver acpi_button_driver = {
.name = ACPI_BUTTON_DRIVER_NAME,
@@ -82,6 +90,179 @@ struct acpi_button {
unsigned long pushed;
};
+static struct file_operations acpi_button_info_fops = {
+ .open = acpi_button_info_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static struct file_operations acpi_button_state_fops = {
+ .open = acpi_button_state_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+/* --------------------------------------------------------------------------
+ FS Interface (/proc)
+ -------------------------------------------------------------------------- */
+
+static struct proc_dir_entry *acpi_button_dir;
+
+static int acpi_button_info_seq_show(struct seq_file *seq, void *offset)
+{
+ struct acpi_button *button = (struct acpi_button *) seq->private;
+
+ ACPI_FUNCTION_TRACE("acpi_button_info_seq_show");
+
+ if (!button || !button->device)
+ return_VALUE(0);
+
+ seq_printf(seq, "type: %s\n",
+ acpi_device_name(button->device));
+
+ return_VALUE(0);
+}
+
+static int acpi_button_info_open_fs(struct inode *inode, struct file *file)
+{
+ return single_open(file, acpi_button_info_seq_show, PDE(inode)->data);
+}
+
+static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
+{
+ struct acpi_button *button = (struct acpi_button *) seq->private;
+ acpi_status status;
+ unsigned long state;
+
+ ACPI_FUNCTION_TRACE("acpi_button_state_seq_show");
+
+ if (!button || !button->device)
+ return_VALUE(0);
+
+ status = acpi_evaluate_integer(button->handle,"_LID",NULL,&state);
+ if (ACPI_FAILURE(status)) {
+ seq_printf(seq, "state: unsupported\n");
+ }
+ else{
+ seq_printf(seq, "state: %s\n", (state ? "open" : "closed"));
+ }
+
+ return_VALUE(0);
+}
+
+static int acpi_button_state_open_fs(struct inode *inode, struct file *file)
+{
+ return single_open(file, acpi_button_state_seq_show, PDE(inode)->data);
+}
+
+static struct proc_dir_entry *acpi_power_dir;
+static struct proc_dir_entry *acpi_sleep_dir;
+static struct proc_dir_entry *acpi_lid_dir;
+
+static int
+acpi_button_add_fs (
+ struct acpi_device *device)
+{
+ struct proc_dir_entry *entry = NULL;
+ struct acpi_button *button = NULL;
+
+ ACPI_FUNCTION_TRACE("acpi_button_add_fs");
+
+ if (!device || !acpi_driver_data(device))
+ return_VALUE(-EINVAL);
+
+ button = acpi_driver_data(device);
+
+ switch (button->type) {
+ case ACPI_BUTTON_TYPE_POWER:
+ case ACPI_BUTTON_TYPE_POWERF:
+ if (!acpi_power_dir)
+ acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER,
+ acpi_button_dir);
+ entry = acpi_power_dir;
+ break;
+ case ACPI_BUTTON_TYPE_SLEEP:
+ case ACPI_BUTTON_TYPE_SLEEPF:
+ if (!acpi_sleep_dir)
+ acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP,
+ acpi_button_dir);
+ entry = acpi_sleep_dir;
+ break;
+ case ACPI_BUTTON_TYPE_LID:
+ if (!acpi_lid_dir)
+ acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID,
+ acpi_button_dir);
+ entry = acpi_lid_dir;
+ break;
+ }
+
+ if (!entry)
+ return_VALUE(-ENODEV);
+ entry->owner = THIS_MODULE;
+
+ acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry);
+ if (!acpi_device_dir(device))
+ return_VALUE(-ENODEV);
+ acpi_device_dir(device)->owner = THIS_MODULE;
+
+ /* 'info' [R] */
+ entry = create_proc_entry(ACPI_BUTTON_FILE_INFO,
+ S_IRUGO, acpi_device_dir(device));
+ if (!entry)
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create '%s' fs entry\n",
+ ACPI_BUTTON_FILE_INFO));
+ else {
+ entry->proc_fops = &acpi_button_info_fops;
+ entry->data = acpi_driver_data(device);
+ entry->owner = THIS_MODULE;
+ }
+
+ /* show lid state [R] */
+ if (button->type == ACPI_BUTTON_TYPE_LID) {
+ entry = create_proc_entry(ACPI_BUTTON_FILE_STATE,
+ S_IRUGO, acpi_device_dir(device));
+ if (!entry)
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create '%s' fs entry\n",
+ ACPI_BUTTON_FILE_INFO));
+ else {
+ entry->proc_fops = &acpi_button_state_fops;
+ entry->data = acpi_driver_data(device);
+ entry->owner = THIS_MODULE;
+ }
+ }
+
+ return_VALUE(0);
+}
+
+
+static int
+acpi_button_remove_fs (
+ struct acpi_device *device)
+{
+ struct acpi_button *button = NULL;
+
+ ACPI_FUNCTION_TRACE("acpi_button_remove_fs");
+
+ button = acpi_driver_data(device);
+ if (acpi_device_dir(device)) {
+ if (button->type == ACPI_BUTTON_TYPE_LID)
+ remove_proc_entry(ACPI_BUTTON_FILE_STATE,
+ acpi_device_dir(device));
+ remove_proc_entry(ACPI_BUTTON_FILE_INFO,
+ acpi_device_dir(device));
+
+ remove_proc_entry(acpi_device_bid(device),
+ acpi_device_dir(device)->parent);
+ acpi_device_dir(device) = NULL;
+ }
+
+ return_VALUE(0);
+}
+
+
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
@@ -121,7 +302,8 @@ acpi_button_notify_fixed (
ACPI_FUNCTION_TRACE("acpi_button_notify_fixed");
- BUG_ON(!button);
+ if (!button)
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
acpi_button_notify(button->handle, ACPI_BUTTON_NOTIFY_STATUS, button);
@@ -197,6 +379,10 @@ acpi_button_add (
goto end;
}
+ result = acpi_button_add_fs(device);
+ if (result)
+ goto end;
+
switch (button->type) {
case ACPI_BUTTON_TYPE_POWERF:
status = acpi_install_fixed_event_handler (
@@ -240,6 +426,7 @@ acpi_button_add (
end:
if (result) {
+ acpi_button_remove_fs(device);
kfree(button);
}
@@ -280,6 +467,8 @@ acpi_button_remove (struct acpi_device *device, int type)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Error removing notify handler\n"));
+ acpi_button_remove_fs(device);
+
kfree(button);
return_VALUE(0);
@@ -293,14 +482,20 @@ acpi_button_init (void)
ACPI_FUNCTION_TRACE("acpi_button_init");
+ acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
+ if (!acpi_button_dir)
+ return_VALUE(-ENODEV);
+ acpi_button_dir->owner = THIS_MODULE;
result = acpi_bus_register_driver(&acpi_button_driver);
if (result < 0) {
+ remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
return_VALUE(-ENODEV);
}
return_VALUE(0);
}
+
static void __exit
acpi_button_exit (void)
{
@@ -308,8 +503,17 @@ acpi_button_exit (void)
acpi_bus_unregister_driver(&acpi_button_driver);
+ if (acpi_power_dir)
+ remove_proc_entry(ACPI_BUTTON_SUBCLASS_POWER, acpi_button_dir);
+ if (acpi_sleep_dir)
+ remove_proc_entry(ACPI_BUTTON_SUBCLASS_SLEEP, acpi_button_dir);
+ if (acpi_lid_dir)
+ remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
+ remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
+
return_VOID;
}
+
module_init(acpi_button_init);
module_exit(acpi_button_exit);
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c
index 1ac197ccfc8..d1162001842 100644
--- a/drivers/acpi/dispatcher/dswload.c
+++ b/drivers/acpi/dispatcher/dswload.c
@@ -491,12 +491,6 @@ acpi_ds_load2_begin_op (
if ((!(walk_state->op_info->flags & AML_NSOPCODE) &&
(walk_state->opcode != AML_INT_NAMEPATH_OP)) ||
(!(walk_state->op_info->flags & AML_NAMED))) {
- if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
- (walk_state->op_info->class == AML_CLASS_CONTROL)) {
- ACPI_REPORT_WARNING ((
- "Encountered executable code at module level, [%s]\n",
- acpi_ps_get_opcode_name (walk_state->opcode)));
- }
return_ACPI_STATUS (AE_OK);
}
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index fca4140a50a..1ac5731d45e 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -59,76 +59,186 @@ ACPI_MODULE_NAME ("acpi_ec")
#define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */
#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
+#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */
+#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */
+
#define ACPI_EC_COMMAND_READ 0x80
#define ACPI_EC_COMMAND_WRITE 0x81
#define ACPI_EC_BURST_ENABLE 0x82
#define ACPI_EC_BURST_DISABLE 0x83
#define ACPI_EC_COMMAND_QUERY 0x84
-static int acpi_ec_add (struct acpi_device *device);
+#define EC_POLLING 0xFF
+#define EC_BURST 0x00
+
+
static int acpi_ec_remove (struct acpi_device *device, int type);
static int acpi_ec_start (struct acpi_device *device);
static int acpi_ec_stop (struct acpi_device *device, int type);
+static int acpi_ec_burst_add ( struct acpi_device *device);
+static int acpi_ec_polling_add ( struct acpi_device *device);
static struct acpi_driver acpi_ec_driver = {
.name = ACPI_EC_DRIVER_NAME,
.class = ACPI_EC_CLASS,
.ids = ACPI_EC_HID,
.ops = {
- .add = acpi_ec_add,
+ .add = acpi_ec_polling_add,
.remove = acpi_ec_remove,
.start = acpi_ec_start,
.stop = acpi_ec_stop,
},
};
-
-struct acpi_ec {
- acpi_handle handle;
- unsigned long uid;
- unsigned long gpe_bit;
- struct acpi_generic_address status_addr;
- struct acpi_generic_address command_addr;
- struct acpi_generic_address data_addr;
- unsigned long global_lock;
- unsigned int expect_event;
- atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort*/
- atomic_t pending_gpe;
- struct semaphore sem;
- wait_queue_head_t wait;
+union acpi_ec {
+ struct {
+ u32 mode;
+ acpi_handle handle;
+ unsigned long uid;
+ unsigned long gpe_bit;
+ struct acpi_generic_address status_addr;
+ struct acpi_generic_address command_addr;
+ struct acpi_generic_address data_addr;
+ unsigned long global_lock;
+ } common;
+
+ struct {
+ u32 mode;
+ acpi_handle handle;
+ unsigned long uid;
+ unsigned long gpe_bit;
+ struct acpi_generic_address status_addr;
+ struct acpi_generic_address command_addr;
+ struct acpi_generic_address data_addr;
+ unsigned long global_lock;
+ unsigned int expect_event;
+ atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort*/
+ atomic_t pending_gpe;
+ struct semaphore sem;
+ wait_queue_head_t wait;
+ }burst;
+
+ struct {
+ u32 mode;
+ acpi_handle handle;
+ unsigned long uid;
+ unsigned long gpe_bit;
+ struct acpi_generic_address status_addr;
+ struct acpi_generic_address command_addr;
+ struct acpi_generic_address data_addr;
+ unsigned long global_lock;
+ spinlock_t lock;
+ }polling;
};
+static int acpi_ec_polling_wait ( union acpi_ec *ec, u8 event);
+static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event);
+static int acpi_ec_polling_read ( union acpi_ec *ec, u8 address, u32 *data);
+static int acpi_ec_burst_read( union acpi_ec *ec, u8 address, u32 *data);
+static int acpi_ec_polling_write ( union acpi_ec *ec, u8 address, u8 data);
+static int acpi_ec_burst_write ( union acpi_ec *ec, u8 address, u8 data);
+static int acpi_ec_polling_query ( union acpi_ec *ec, u32 *data);
+static int acpi_ec_burst_query ( union acpi_ec *ec, u32 *data);
+static void acpi_ec_gpe_polling_query ( void *ec_cxt);
+static void acpi_ec_gpe_burst_query ( void *ec_cxt);
+static u32 acpi_ec_gpe_polling_handler ( void *data);
+static u32 acpi_ec_gpe_burst_handler ( void *data);
+static acpi_status __init
+acpi_fake_ecdt_polling_callback (
+ acpi_handle handle,
+ u32 Level,
+ void *context,
+ void **retval);
+
+static acpi_status __init
+acpi_fake_ecdt_burst_callback (
+ acpi_handle handle,
+ u32 Level,
+ void *context,
+ void **retval);
+
+static int __init
+acpi_ec_polling_get_real_ecdt(void);
+static int __init
+acpi_ec_burst_get_real_ecdt(void);
/* If we find an EC via the ECDT, we need to keep a ptr to its context */
-static struct acpi_ec *ec_ecdt;
+static union acpi_ec *ec_ecdt;
/* External interfaces use first EC only, so remember */
static struct acpi_device *first_ec;
+static int acpi_ec_polling_mode = EC_POLLING;
/* --------------------------------------------------------------------------
Transaction Management
-------------------------------------------------------------------------- */
-static inline u32 acpi_ec_read_status(struct acpi_ec *ec)
+static inline u32 acpi_ec_read_status(union acpi_ec *ec)
{
u32 status = 0;
- acpi_hw_low_level_read(8, &status, &ec->status_addr);
+ acpi_hw_low_level_read(8, &status, &ec->common.status_addr);
return status;
}
-static int acpi_ec_wait(struct acpi_ec *ec, unsigned int event)
+static int
+acpi_ec_wait (
+ union acpi_ec *ec,
+ u8 event)
+{
+ if (acpi_ec_polling_mode)
+ return acpi_ec_polling_wait (ec, event);
+ else
+ return acpi_ec_burst_wait (ec, event);
+}
+
+static int
+acpi_ec_polling_wait (
+ union acpi_ec *ec,
+ u8 event)
+{
+ u32 acpi_ec_status = 0;
+ u32 i = ACPI_EC_UDELAY_COUNT;
+
+ if (!ec)
+ return -EINVAL;
+
+ /* Poll the EC status register waiting for the event to occur. */
+ switch (event) {
+ case ACPI_EC_EVENT_OBF:
+ do {
+ acpi_hw_low_level_read(8, &acpi_ec_status, &ec->common.status_addr);
+ if (acpi_ec_status & ACPI_EC_FLAG_OBF)
+ return 0;
+ udelay(ACPI_EC_UDELAY);
+ } while (--i>0);
+ break;
+ case ACPI_EC_EVENT_IBE:
+ do {
+ acpi_hw_low_level_read(8, &acpi_ec_status, &ec->common.status_addr);
+ if (!(acpi_ec_status & ACPI_EC_FLAG_IBF))
+ return 0;
+ udelay(ACPI_EC_UDELAY);
+ } while (--i>0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return -ETIME;
+}
+static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event)
{
int result = 0;
ACPI_FUNCTION_TRACE("acpi_ec_wait");
- ec->expect_event = event;
+ ec->burst.expect_event = event;
smp_mb();
- result = wait_event_interruptible_timeout(ec->wait,
- !ec->expect_event,
+ result = wait_event_interruptible_timeout(ec->burst.wait,
+ !ec->burst.expect_event,
msecs_to_jiffies(ACPI_EC_DELAY));
- ec->expect_event = 0;
+ ec->burst.expect_event = 0;
smp_mb();
if (result < 0){
@@ -160,7 +270,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, unsigned int event)
static int
acpi_ec_enter_burst_mode (
- struct acpi_ec *ec)
+ union acpi_ec *ec)
{
u32 tmp = 0;
int status = 0;
@@ -170,43 +280,43 @@ acpi_ec_enter_burst_mode (
status = acpi_ec_read_status(ec);
if (status != -EINVAL &&
!(status & ACPI_EC_FLAG_BURST)){
- acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->command_addr);
+ acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
if (status){
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
return_VALUE(-EINVAL);
}
- acpi_hw_low_level_read(8, &tmp, &ec->data_addr);
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr);
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
if(tmp != 0x90 ) {/* Burst ACK byte*/
return_VALUE(-EINVAL);
}
}
- atomic_set(&ec->leaving_burst , 0);
+ atomic_set(&ec->burst.leaving_burst , 0);
return_VALUE(0);
}
static int
acpi_ec_leave_burst_mode (
- struct acpi_ec *ec)
+ union acpi_ec *ec)
{
int status =0;
ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode");
- atomic_set(&ec->leaving_burst , 1);
+ atomic_set(&ec->burst.leaving_burst , 1);
status = acpi_ec_read_status(ec);
if (status != -EINVAL &&
(status & ACPI_EC_FLAG_BURST)){
- acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->command_addr);
+ acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF);
if (status){
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"------->wait fail\n"));
return_VALUE(-EINVAL);
}
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
status = acpi_ec_read_status(ec);
}
@@ -215,7 +325,131 @@ acpi_ec_leave_burst_mode (
static int
acpi_ec_read (
- struct acpi_ec *ec,
+ union acpi_ec *ec,
+ u8 address,
+ u32 *data)
+{
+ if (acpi_ec_polling_mode)
+ return acpi_ec_polling_read(ec, address, data);
+ else
+ return acpi_ec_burst_read(ec, address, data);
+}
+static int
+acpi_ec_write (
+ union acpi_ec *ec,
+ u8 address,
+ u8 data)
+{
+ if (acpi_ec_polling_mode)
+ return acpi_ec_polling_write(ec, address, data);
+ else
+ return acpi_ec_burst_write(ec, address, data);
+}
+static int
+acpi_ec_polling_read (
+ union acpi_ec *ec,
+ u8 address,
+ u32 *data)
+{
+ acpi_status status = AE_OK;
+ int result = 0;
+ unsigned long flags = 0;
+ u32 glk = 0;
+
+ ACPI_FUNCTION_TRACE("acpi_ec_read");
+
+ if (!ec || !data)
+ return_VALUE(-EINVAL);
+
+ *data = 0;
+
+ if (ec->common.global_lock) {
+ status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
+ if (ACPI_FAILURE(status))
+ return_VALUE(-ENODEV);
+ }
+
+ spin_lock_irqsave(&ec->polling.lock, flags);
+
+ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr);
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+ if (result)
+ goto end;
+
+ acpi_hw_low_level_write(8, address, &ec->common.data_addr);
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
+ if (result)
+ goto end;
+
+ acpi_hw_low_level_read(8, data, &ec->common.data_addr);
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n",
+ *data, address));
+
+end:
+ spin_unlock_irqrestore(&ec->polling.lock, flags);
+
+ if (ec->common.global_lock)
+ acpi_release_global_lock(glk);
+
+ return_VALUE(result);
+}
+
+
+static int
+acpi_ec_polling_write (
+ union acpi_ec *ec,
+ u8 address,
+ u8 data)
+{
+ int result = 0;
+ acpi_status status = AE_OK;
+ unsigned long flags = 0;
+ u32 glk = 0;
+
+ ACPI_FUNCTION_TRACE("acpi_ec_write");
+
+ if (!ec)
+ return_VALUE(-EINVAL);
+
+ if (ec->common.global_lock) {
+ status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
+ if (ACPI_FAILURE(status))
+ return_VALUE(-ENODEV);
+ }
+
+ spin_lock_irqsave(&ec->polling.lock, flags);
+
+ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr);
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+ if (result)
+ goto end;
+
+ acpi_hw_low_level_write(8, address, &ec->common.data_addr);
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+ if (result)
+ goto end;
+
+ acpi_hw_low_level_write(8, data, &ec->common.data_addr);
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+ if (result)
+ goto end;
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n",
+ data, address));
+
+end:
+ spin_unlock_irqrestore(&ec->polling.lock, flags);
+
+ if (ec->common.global_lock)
+ acpi_release_global_lock(glk);
+
+ return_VALUE(result);
+}
+
+static int
+acpi_ec_burst_read (
+ union acpi_ec *ec,
u8 address,
u32 *data)
{
@@ -230,51 +464,51 @@ acpi_ec_read (
retry:
*data = 0;
- if (ec->global_lock) {
+ if (ec->common.global_lock) {
status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
}
WARN_ON(in_interrupt());
- down(&ec->sem);
+ down(&ec->burst.sem);
if(acpi_ec_enter_burst_mode(ec))
goto end;
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->command_addr);
+ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
if (status) {
goto end;
}
- acpi_hw_low_level_write(8, address, &ec->data_addr);
+ acpi_hw_low_level_write(8, address, &ec->common.data_addr);
status= acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
if (status){
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
goto end;
}
- acpi_hw_low_level_read(8, data, &ec->data_addr);
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ acpi_hw_low_level_read(8, data, &ec->common.data_addr);
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n",
*data, address));
end:
acpi_ec_leave_burst_mode(ec);
- up(&ec->sem);
+ up(&ec->burst.sem);
- if (ec->global_lock)
+ if (ec->common.global_lock)
acpi_release_global_lock(glk);
- if(atomic_read(&ec->leaving_burst) == 2){
+ if(atomic_read(&ec->burst.leaving_burst) == 2){
ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n"));
- while(atomic_read(&ec->pending_gpe)){
+ while(atomic_read(&ec->burst.pending_gpe)){
msleep(1);
}
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
goto retry;
}
@@ -283,8 +517,8 @@ end:
static int
-acpi_ec_write (
- struct acpi_ec *ec,
+acpi_ec_burst_write (
+ union acpi_ec *ec,
u8 address,
u8 data)
{
@@ -297,14 +531,14 @@ acpi_ec_write (
if (!ec)
return_VALUE(-EINVAL);
retry:
- if (ec->global_lock) {
+ if (ec->common.global_lock) {
status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
}
WARN_ON(in_interrupt());
- down(&ec->sem);
+ down(&ec->burst.sem);
if(acpi_ec_enter_burst_mode(ec))
goto end;
@@ -312,33 +546,33 @@ retry:
status = acpi_ec_read_status(ec);
if (status != -EINVAL &&
!(status & ACPI_EC_FLAG_BURST)){
- acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->command_addr);
+ acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
if (status)
goto end;
- acpi_hw_low_level_read(8, &tmp, &ec->data_addr);
+ acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr);
if(tmp != 0x90 ) /* Burst ACK byte*/
goto end;
}
/*Now we are in burst mode*/
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->command_addr);
+ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
if (status){
goto end;
}
- acpi_hw_low_level_write(8, address, &ec->data_addr);
+ acpi_hw_low_level_write(8, address, &ec->common.data_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
if (status){
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
goto end;
}
- acpi_hw_low_level_write(8, data, &ec->data_addr);
+ acpi_hw_low_level_write(8, data, &ec->common.data_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
if (status)
goto end;
@@ -347,17 +581,17 @@ retry:
end:
acpi_ec_leave_burst_mode(ec);
- up(&ec->sem);
+ up(&ec->burst.sem);
- if (ec->global_lock)
+ if (ec->common.global_lock)
acpi_release_global_lock(glk);
- if(atomic_read(&ec->leaving_burst) == 2){
+ if(atomic_read(&ec->burst.leaving_burst) == 2){
ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n"));
- while(atomic_read(&ec->pending_gpe)){
+ while(atomic_read(&ec->burst.pending_gpe)){
msleep(1);
}
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
goto retry;
}
@@ -370,7 +604,7 @@ end:
int
ec_read(u8 addr, u8 *val)
{
- struct acpi_ec *ec;
+ union acpi_ec *ec;
int err;
u32 temp_data;
@@ -393,7 +627,7 @@ EXPORT_SYMBOL(ec_read);
int
ec_write(u8 addr, u8 val)
{
- struct acpi_ec *ec;
+ union acpi_ec *ec;
int err;
if (!first_ec)
@@ -407,10 +641,66 @@ ec_write(u8 addr, u8 val)
}
EXPORT_SYMBOL(ec_write);
-
static int
acpi_ec_query (
- struct acpi_ec *ec,
+ union acpi_ec *ec,
+ u32 *data)
+{
+ if (acpi_ec_polling_mode)
+ return acpi_ec_polling_query(ec, data);
+ else
+ return acpi_ec_burst_query(ec, data);
+}
+static int
+acpi_ec_polling_query (
+ union acpi_ec *ec,
+ u32 *data)
+{
+ int result = 0;
+ acpi_status status = AE_OK;
+ unsigned long flags = 0;
+ u32 glk = 0;
+
+ ACPI_FUNCTION_TRACE("acpi_ec_query");
+
+ if (!ec || !data)
+ return_VALUE(-EINVAL);
+
+ *data = 0;
+
+ if (ec->common.global_lock) {
+ status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
+ if (ACPI_FAILURE(status))
+ return_VALUE(-ENODEV);
+ }
+
+ /*
+ * Query the EC to find out which _Qxx method we need to evaluate.
+ * Note that successful completion of the query causes the ACPI_EC_SCI
+ * bit to be cleared (and thus clearing the interrupt source).
+ */
+ spin_lock_irqsave(&ec->polling.lock, flags);
+
+ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr);
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
+ if (result)
+ goto end;
+
+ acpi_hw_low_level_read(8, data, &ec->common.data_addr);
+ if (!*data)
+ result = -ENODATA;
+
+end:
+ spin_unlock_irqrestore(&ec->polling.lock, flags);
+
+ if (ec->common.global_lock)
+ acpi_release_global_lock(glk);
+
+ return_VALUE(result);
+}
+static int
+acpi_ec_burst_query (
+ union acpi_ec *ec,
u32 *data)
{
int status = 0;
@@ -422,13 +712,13 @@ acpi_ec_query (
return_VALUE(-EINVAL);
*data = 0;
- if (ec->global_lock) {
+ if (ec->common.global_lock) {
status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
}
- down(&ec->sem);
+ down(&ec->burst.sem);
if(acpi_ec_enter_burst_mode(ec))
goto end;
/*
@@ -436,28 +726,28 @@ acpi_ec_query (
* Note that successful completion of the query causes the ACPI_EC_SCI
* bit to be cleared (and thus clearing the interrupt source).
*/
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->command_addr);
+ acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
if (status){
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
goto end;
}
- acpi_hw_low_level_read(8, data, &ec->data_addr);
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ acpi_hw_low_level_read(8, data, &ec->common.data_addr);
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
if (!*data)
status = -ENODATA;
end:
acpi_ec_leave_burst_mode(ec);
- up(&ec->sem);
+ up(&ec->burst.sem);
- if (ec->global_lock)
+ if (ec->common.global_lock)
acpi_release_global_lock(glk);
- if(atomic_read(&ec->leaving_burst) == 2){
+ if(atomic_read(&ec->burst.leaving_burst) == 2){
ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n"));
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
status = -ENODATA;
}
return_VALUE(status);
@@ -468,7 +758,7 @@ end:
Event Management
-------------------------------------------------------------------------- */
-struct acpi_ec_query_data {
+union acpi_ec_query_data {
acpi_handle handle;
u8 data;
};
@@ -477,7 +767,59 @@ static void
acpi_ec_gpe_query (
void *ec_cxt)
{
- struct acpi_ec *ec = (struct acpi_ec *) ec_cxt;
+ if (acpi_ec_polling_mode)
+ acpi_ec_gpe_polling_query(ec_cxt);
+ else
+ acpi_ec_gpe_burst_query(ec_cxt);
+}
+
+static void
+acpi_ec_gpe_polling_query (
+ void *ec_cxt)
+{
+ union acpi_ec *ec = (union acpi_ec *) ec_cxt;
+ u32 value = 0;
+ unsigned long flags = 0;
+ static char object_name[5] = {'_','Q','0','0','\0'};
+ const char hex[] = {'0','1','2','3','4','5','6','7',
+ '8','9','A','B','C','D','E','F'};
+
+ ACPI_FUNCTION_TRACE("acpi_ec_gpe_query");
+
+ if (!ec_cxt)
+ goto end;
+
+ spin_lock_irqsave(&ec->polling.lock, flags);
+ acpi_hw_low_level_read(8, &value, &ec->common.command_addr);
+ spin_unlock_irqrestore(&ec->polling.lock, flags);
+
+ /* TBD: Implement asynch events!
+ * NOTE: All we care about are EC-SCI's. Other EC events are
+ * handled via polling (yuck!). This is because some systems
+ * treat EC-SCIs as level (versus EDGE!) triggered, preventing
+ * a purely interrupt-driven approach (grumble, grumble).
+ */
+ if (!(value & ACPI_EC_FLAG_SCI))
+ goto end;
+
+ if (acpi_ec_query(ec, &value))
+ goto end;
+
+ object_name[2] = hex[((value >> 4) & 0x0F)];
+ object_name[3] = hex[(value & 0x0F)];
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name));
+
+ acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL);
+
+end:
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
+}
+static void
+acpi_ec_gpe_burst_query (
+ void *ec_cxt)
+{
+ union acpi_ec *ec = (union acpi_ec *) ec_cxt;
u32 value;
int result = -ENODATA;
static char object_name[5] = {'_','Q','0','0','\0'};
@@ -497,9 +839,9 @@ acpi_ec_gpe_query (
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name));
- acpi_evaluate_object(ec->handle, object_name, NULL, NULL);
+ acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL);
end:
- atomic_dec(&ec->pending_gpe);
+ atomic_dec(&ec->burst.pending_gpe);
return;
}
@@ -507,48 +849,77 @@ static u32
acpi_ec_gpe_handler (
void *data)
{
+ if (acpi_ec_polling_mode)
+ return acpi_ec_gpe_polling_handler(data);
+ else
+ return acpi_ec_gpe_burst_handler(data);
+}
+static u32
+acpi_ec_gpe_polling_handler (
+ void *data)
+{
+ acpi_status status = AE_OK;
+ union acpi_ec *ec = (union acpi_ec *) data;
+
+ if (!ec)
+ return ACPI_INTERRUPT_NOT_HANDLED;
+
+ acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
+
+ status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
+ acpi_ec_gpe_query, ec);
+
+ if (status == AE_OK)
+ return ACPI_INTERRUPT_HANDLED;
+ else
+ return ACPI_INTERRUPT_NOT_HANDLED;
+}
+static u32
+acpi_ec_gpe_burst_handler (
+ void *data)
+{
acpi_status status = AE_OK;
u32 value;
- struct acpi_ec *ec = (struct acpi_ec *) data;
+ union acpi_ec *ec = (union acpi_ec *) data;
if (!ec)
return ACPI_INTERRUPT_NOT_HANDLED;
- acpi_disable_gpe(NULL, ec->gpe_bit, ACPI_ISR);
+ acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
value = acpi_ec_read_status(ec);
if((value & ACPI_EC_FLAG_IBF) &&
!(value & ACPI_EC_FLAG_BURST) &&
- (atomic_read(&ec->leaving_burst) == 0)) {
+ (atomic_read(&ec->burst.leaving_burst) == 0)) {
/*
* the embedded controller disables
* burst mode for any reason other
* than the burst disable command
* to process critical event.
*/
- atomic_set(&ec->leaving_burst , 2); /* block current pending transaction
+ atomic_set(&ec->burst.leaving_burst , 2); /* block current pending transaction
and retry */
- wake_up(&ec->wait);
+ wake_up(&ec->burst.wait);
}else {
- if ((ec->expect_event == ACPI_EC_EVENT_OBF &&
+ if ((ec->burst.expect_event == ACPI_EC_EVENT_OBF &&
(value & ACPI_EC_FLAG_OBF)) ||
- (ec->expect_event == ACPI_EC_EVENT_IBE &&
+ (ec->burst.expect_event == ACPI_EC_EVENT_IBE &&
!(value & ACPI_EC_FLAG_IBF))) {
- ec->expect_event = 0;
- wake_up(&ec->wait);
+ ec->burst.expect_event = 0;
+ wake_up(&ec->burst.wait);
return ACPI_INTERRUPT_HANDLED;
}
}
if (value & ACPI_EC_FLAG_SCI){
- atomic_add(1, &ec->pending_gpe) ;
+ atomic_add(1, &ec->burst.pending_gpe) ;
status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
acpi_ec_gpe_query, ec);
return status == AE_OK ?
ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
}
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_ISR);
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
return status == AE_OK ?
ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
}
@@ -585,7 +956,7 @@ acpi_ec_space_handler (
void *region_context)
{
int result = 0;
- struct acpi_ec *ec = NULL;
+ union acpi_ec *ec = NULL;
u64 temp = *value;
acpi_integer f_v = 0;
int i = 0;
@@ -600,7 +971,7 @@ acpi_ec_space_handler (
return_VALUE(AE_BAD_PARAMETER);
}
- ec = (struct acpi_ec *) handler_context;
+ ec = (union acpi_ec *) handler_context;
next_byte:
switch (function) {
@@ -661,7 +1032,7 @@ static struct proc_dir_entry *acpi_ec_dir;
static int
acpi_ec_read_info (struct seq_file *seq, void *offset)
{
- struct acpi_ec *ec = (struct acpi_ec *) seq->private;
+ union acpi_ec *ec = (union acpi_ec *) seq->private;
ACPI_FUNCTION_TRACE("acpi_ec_read_info");
@@ -669,12 +1040,12 @@ acpi_ec_read_info (struct seq_file *seq, void *offset)
goto end;
seq_printf(seq, "gpe bit: 0x%02x\n",
- (u32) ec->gpe_bit);
+ (u32) ec->common.gpe_bit);
seq_printf(seq, "ports: 0x%02x, 0x%02x\n",
- (u32) ec->status_addr.address, (u32) ec->data_addr.address);
+ (u32) ec->common.status_addr.address, (u32) ec->common.data_addr.address);
seq_printf(seq, "use global lock: %s\n",
- ec->global_lock?"yes":"no");
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ ec->common.global_lock?"yes":"no");
+ acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
end:
return_VALUE(0);
@@ -697,7 +1068,7 @@ static int
acpi_ec_add_fs (
struct acpi_device *device)
{
- struct proc_dir_entry *entry;
+ struct proc_dir_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_ec_add_fs");
@@ -744,13 +1115,14 @@ acpi_ec_remove_fs (
Driver Interface
-------------------------------------------------------------------------- */
+
static int
-acpi_ec_add (
+acpi_ec_polling_add (
struct acpi_device *device)
{
- int result;
- acpi_status status;
- struct acpi_ec *ec;
+ int result = 0;
+ acpi_status status = AE_OK;
+ union acpi_ec *ec = NULL;
unsigned long uid;
ACPI_FUNCTION_TRACE("acpi_ec_add");
@@ -758,39 +1130,107 @@ acpi_ec_add (
if (!device)
return_VALUE(-EINVAL);
- ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
+ ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
if (!ec)
return_VALUE(-ENOMEM);
- memset(ec, 0, sizeof(struct acpi_ec));
-
- ec->handle = device->handle;
- ec->uid = -1;
- atomic_set(&ec->pending_gpe, 0);
- atomic_set(&ec->leaving_burst , 1);
- init_MUTEX(&ec->sem);
- init_waitqueue_head(&ec->wait);
+ memset(ec, 0, sizeof(union acpi_ec));
+
+ ec->common.handle = device->handle;
+ ec->common.uid = -1;
+ spin_lock_init(&ec->polling.lock);
strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_EC_CLASS);
acpi_driver_data(device) = ec;
/* Use the global lock for all EC transactions? */
- acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock);
+ acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock);
/* If our UID matches the UID for the ECDT-enumerated EC,
we now have the *real* EC info, so kill the makeshift one.*/
- acpi_evaluate_integer(ec->handle, "_UID", NULL, &uid);
- if (ec_ecdt && ec_ecdt->uid == uid) {
+ acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid);
+ if (ec_ecdt && ec_ecdt->common.uid == uid) {
acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
+
+ acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler);
+
+ kfree(ec_ecdt);
+ }
+
+ /* Get GPE bit assignment (EC events). */
+ /* TODO: Add support for _GPE returning a package */
+ status = acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, &ec->common.gpe_bit);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error obtaining GPE bit assignment\n"));
+ result = -ENODEV;
+ goto end;
+ }
- acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, &acpi_ec_gpe_handler);
+ result = acpi_ec_add_fs(device);
+ if (result)
+ goto end;
+
+ printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n",
+ acpi_device_name(device), acpi_device_bid(device),
+ (u32) ec->common.gpe_bit);
+
+ if (!first_ec)
+ first_ec = device;
+
+end:
+ if (result)
+ kfree(ec);
+
+ return_VALUE(result);
+}
+static int
+acpi_ec_burst_add (
+ struct acpi_device *device)
+{
+ int result = 0;
+ acpi_status status = AE_OK;
+ union acpi_ec *ec = NULL;
+ unsigned long uid;
+
+ ACPI_FUNCTION_TRACE("acpi_ec_add");
+
+ if (!device)
+ return_VALUE(-EINVAL);
+
+ ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
+ if (!ec)
+ return_VALUE(-ENOMEM);
+ memset(ec, 0, sizeof(union acpi_ec));
+
+ ec->common.handle = device->handle;
+ ec->common.uid = -1;
+ atomic_set(&ec->burst.pending_gpe, 0);
+ atomic_set(&ec->burst.leaving_burst , 1);
+ init_MUTEX(&ec->burst.sem);
+ init_waitqueue_head(&ec->burst.wait);
+ strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
+ strcpy(acpi_device_class(device), ACPI_EC_CLASS);
+ acpi_driver_data(device) = ec;
+
+ /* Use the global lock for all EC transactions? */
+ acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock);
+
+ /* If our UID matches the UID for the ECDT-enumerated EC,
+ we now have the *real* EC info, so kill the makeshift one.*/
+ acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid);
+ if (ec_ecdt && ec_ecdt->common.uid == uid) {
+ acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
+ ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
+
+ acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler);
kfree(ec_ecdt);
}
/* Get GPE bit assignment (EC events). */
/* TODO: Add support for _GPE returning a package */
- status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe_bit);
+ status = acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, &ec->common.gpe_bit);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Error obtaining GPE bit assignment\n"));
@@ -804,7 +1244,7 @@ acpi_ec_add (
printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n",
acpi_device_name(device), acpi_device_bid(device),
- (u32) ec->gpe_bit);
+ (u32) ec->common.gpe_bit);
if (!first_ec)
first_ec = device;
@@ -822,7 +1262,7 @@ acpi_ec_remove (
struct acpi_device *device,
int type)
{
- struct acpi_ec *ec;
+ union acpi_ec *ec = NULL;
ACPI_FUNCTION_TRACE("acpi_ec_remove");
@@ -844,7 +1284,7 @@ acpi_ec_io_ports (
struct acpi_resource *resource,
void *context)
{
- struct acpi_ec *ec = (struct acpi_ec *) context;
+ union acpi_ec *ec = (union acpi_ec *) context;
struct acpi_generic_address *addr;
if (resource->id != ACPI_RSTYPE_IO) {
@@ -856,10 +1296,10 @@ acpi_ec_io_ports (
* the second address region returned is the status/command
* port.
*/
- if (ec->data_addr.register_bit_width == 0) {
- addr = &ec->data_addr;
- } else if (ec->command_addr.register_bit_width == 0) {
- addr = &ec->command_addr;
+ if (ec->common.data_addr.register_bit_width == 0) {
+ addr = &ec->common.data_addr;
+ } else if (ec->common.command_addr.register_bit_width == 0) {
+ addr = &ec->common.command_addr;
} else {
return AE_CTRL_TERMINATE;
}
@@ -877,8 +1317,8 @@ static int
acpi_ec_start (
struct acpi_device *device)
{
- acpi_status status;
- struct acpi_ec *ec;
+ acpi_status status = AE_OK;
+ union acpi_ec *ec = NULL;
ACPI_FUNCTION_TRACE("acpi_ec_start");
@@ -893,35 +1333,36 @@ acpi_ec_start (
/*
* Get I/O port addresses. Convert to GAS format.
*/
- status = acpi_walk_resources(ec->handle, METHOD_NAME__CRS,
+ status = acpi_walk_resources(ec->common.handle, METHOD_NAME__CRS,
acpi_ec_io_ports, ec);
- if (ACPI_FAILURE(status) || ec->command_addr.register_bit_width == 0) {
+ if (ACPI_FAILURE(status) || ec->common.command_addr.register_bit_width == 0) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error getting I/O port addresses"));
return_VALUE(-ENODEV);
}
- ec->status_addr = ec->command_addr;
+ ec->common.status_addr = ec->common.command_addr;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n",
- (u32) ec->gpe_bit, (u32) ec->command_addr.address,
- (u32) ec->data_addr.address));
+ (u32) ec->common.gpe_bit, (u32) ec->common.command_addr.address,
+ (u32) ec->common.data_addr.address));
+
/*
* Install GPE handler
*/
- status = acpi_install_gpe_handler(NULL, ec->gpe_bit,
+ status = acpi_install_gpe_handler(NULL, ec->common.gpe_bit,
ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec);
if (ACPI_FAILURE(status)) {
return_VALUE(-ENODEV);
}
- acpi_set_gpe_type (NULL, ec->gpe_bit, ACPI_GPE_TYPE_RUNTIME);
- acpi_enable_gpe (NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ acpi_set_gpe_type (NULL, ec->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME);
+ acpi_enable_gpe (NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
- status = acpi_install_address_space_handler (ec->handle,
+ status = acpi_install_address_space_handler (ec->common.handle,
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
&acpi_ec_space_setup, ec);
if (ACPI_FAILURE(status)) {
- acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler);
+ acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler);
return_VALUE(-ENODEV);
}
@@ -934,8 +1375,8 @@ acpi_ec_stop (
struct acpi_device *device,
int type)
{
- acpi_status status;
- struct acpi_ec *ec;
+ acpi_status status = AE_OK;
+ union acpi_ec *ec = NULL;
ACPI_FUNCTION_TRACE("acpi_ec_stop");
@@ -944,12 +1385,12 @@ acpi_ec_stop (
ec = acpi_driver_data(device);
- status = acpi_remove_address_space_handler(ec->handle,
+ status = acpi_remove_address_space_handler(ec->common.handle,
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
- status = acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler);
+ status = acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
@@ -963,26 +1404,76 @@ acpi_fake_ecdt_callback (
void *context,
void **retval)
{
+
+ if (acpi_ec_polling_mode)
+ return acpi_fake_ecdt_polling_callback(handle,
+ Level, context, retval);
+ else
+ return acpi_fake_ecdt_burst_callback(handle,
+ Level, context, retval);
+}
+
+static acpi_status __init
+acpi_fake_ecdt_polling_callback (
+ acpi_handle handle,
+ u32 Level,
+ void *context,
+ void **retval)
+{
acpi_status status;
status = acpi_walk_resources(handle, METHOD_NAME__CRS,
acpi_ec_io_ports, ec_ecdt);
if (ACPI_FAILURE(status))
return status;
- ec_ecdt->status_addr = ec_ecdt->command_addr;
+ ec_ecdt->common.status_addr = ec_ecdt->common.command_addr;
- ec_ecdt->uid = -1;
- acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid);
+ ec_ecdt->common.uid = -1;
+ acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid);
- status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->gpe_bit);
+ status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->common.gpe_bit);
if (ACPI_FAILURE(status))
return status;
- ec_ecdt->global_lock = TRUE;
- ec_ecdt->handle = handle;
+ spin_lock_init(&ec_ecdt->polling.lock);
+ ec_ecdt->common.global_lock = TRUE;
+ ec_ecdt->common.handle = handle;
printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n",
- (u32) ec_ecdt->gpe_bit, (u32) ec_ecdt->command_addr.address,
- (u32) ec_ecdt->data_addr.address);
+ (u32) ec_ecdt->common.gpe_bit, (u32) ec_ecdt->common.command_addr.address,
+ (u32) ec_ecdt->common.data_addr.address);
+
+ return AE_CTRL_TERMINATE;
+}
+
+static acpi_status __init
+acpi_fake_ecdt_burst_callback (
+ acpi_handle handle,
+ u32 Level,
+ void *context,
+ void **retval)
+{
+ acpi_status status;
+
+ init_MUTEX(&ec_ecdt->burst.sem);
+ init_waitqueue_head(&ec_ecdt->burst.wait);
+ status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+ acpi_ec_io_ports, ec_ecdt);
+ if (ACPI_FAILURE(status))
+ return status;
+ ec_ecdt->common.status_addr = ec_ecdt->common.command_addr;
+
+ ec_ecdt->common.uid = -1;
+ acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid);
+
+ status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->common.gpe_bit);
+ if (ACPI_FAILURE(status))
+ return status;
+ ec_ecdt->common.global_lock = TRUE;
+ ec_ecdt->common.handle = handle;
+
+ printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n",
+ (u32) ec_ecdt->common.gpe_bit, (u32) ec_ecdt->common.command_addr.address,
+ (u32) ec_ecdt->common.data_addr.address);
return AE_CTRL_TERMINATE;
}
@@ -1005,12 +1496,12 @@ acpi_ec_fake_ecdt(void)
printk(KERN_INFO PREFIX "Try to make an fake ECDT\n");
- ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
+ ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
if (!ec_ecdt) {
ret = -ENOMEM;
goto error;
}
- memset(ec_ecdt, 0, sizeof(struct acpi_ec));
+ memset(ec_ecdt, 0, sizeof(union acpi_ec));
status = acpi_get_devices (ACPI_EC_HID,
acpi_fake_ecdt_callback,
@@ -1031,6 +1522,60 @@ error:
static int __init
acpi_ec_get_real_ecdt(void)
{
+ if (acpi_ec_polling_mode)
+ return acpi_ec_polling_get_real_ecdt();
+ else
+ return acpi_ec_burst_get_real_ecdt();
+}
+
+static int __init
+acpi_ec_polling_get_real_ecdt(void)
+{
+ acpi_status status;
+ struct acpi_table_ecdt *ecdt_ptr;
+
+ status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING,
+ (struct acpi_table_header **) &ecdt_ptr);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ printk(KERN_INFO PREFIX "Found ECDT\n");
+
+ /*
+ * Generate a temporary ec context to use until the namespace is scanned
+ */
+ ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
+ if (!ec_ecdt)
+ return -ENOMEM;
+ memset(ec_ecdt, 0, sizeof(union acpi_ec));
+
+ ec_ecdt->common.command_addr = ecdt_ptr->ec_control;
+ ec_ecdt->common.status_addr = ecdt_ptr->ec_control;
+ ec_ecdt->common.data_addr = ecdt_ptr->ec_data;
+ ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit;
+ spin_lock_init(&ec_ecdt->polling.lock);
+ /* use the GL just to be safe */
+ ec_ecdt->common.global_lock = TRUE;
+ ec_ecdt->common.uid = ecdt_ptr->uid;
+
+ status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle);
+ if (ACPI_FAILURE(status)) {
+ goto error;
+ }
+
+ return 0;
+error:
+ printk(KERN_ERR PREFIX "Could not use ECDT\n");
+ kfree(ec_ecdt);
+ ec_ecdt = NULL;
+
+ return -ENODEV;
+}
+
+
+static int __init
+acpi_ec_burst_get_real_ecdt(void)
+{
acpi_status status;
struct acpi_table_ecdt *ecdt_ptr;
@@ -1044,22 +1589,22 @@ acpi_ec_get_real_ecdt(void)
/*
* Generate a temporary ec context to use until the namespace is scanned
*/
- ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
+ ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
if (!ec_ecdt)
return -ENOMEM;
- memset(ec_ecdt, 0, sizeof(struct acpi_ec));
-
- init_MUTEX(&ec_ecdt->sem);
- init_waitqueue_head(&ec_ecdt->wait);
- ec_ecdt->command_addr = ecdt_ptr->ec_control;
- ec_ecdt->status_addr = ecdt_ptr->ec_control;
- ec_ecdt->data_addr = ecdt_ptr->ec_data;
- ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit;
+ memset(ec_ecdt, 0, sizeof(union acpi_ec));
+
+ init_MUTEX(&ec_ecdt->burst.sem);
+ init_waitqueue_head(&ec_ecdt->burst.wait);
+ ec_ecdt->common.command_addr = ecdt_ptr->ec_control;
+ ec_ecdt->common.status_addr = ecdt_ptr->ec_control;
+ ec_ecdt->common.data_addr = ecdt_ptr->ec_data;
+ ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit;
/* use the GL just to be safe */
- ec_ecdt->global_lock = TRUE;
- ec_ecdt->uid = ecdt_ptr->uid;
+ ec_ecdt->common.global_lock = TRUE;
+ ec_ecdt->common.uid = ecdt_ptr->uid;
- status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle);
+ status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle);
if (ACPI_FAILURE(status)) {
goto error;
}
@@ -1092,20 +1637,20 @@ acpi_ec_ecdt_probe (void)
/*
* Install GPE handler
*/
- status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe_bit,
+ status = acpi_install_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler,
ec_ecdt);
if (ACPI_FAILURE(status)) {
goto error;
}
- acpi_set_gpe_type (NULL, ec_ecdt->gpe_bit, ACPI_GPE_TYPE_RUNTIME);
- acpi_enable_gpe (NULL, ec_ecdt->gpe_bit, ACPI_NOT_ISR);
+ acpi_set_gpe_type (NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME);
+ acpi_enable_gpe (NULL, ec_ecdt->common.gpe_bit, ACPI_NOT_ISR);
status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT,
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
&acpi_ec_space_setup, ec_ecdt);
if (ACPI_FAILURE(status)) {
- acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit,
+ acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
&acpi_ec_gpe_handler);
goto error;
}
@@ -1123,7 +1668,7 @@ error:
static int __init acpi_ec_init (void)
{
- int result;
+ int result = 0;
ACPI_FUNCTION_TRACE("acpi_ec_init");
@@ -1166,4 +1711,24 @@ static int __init acpi_fake_ecdt_setup(char *str)
acpi_fake_ecdt_enabled = 1;
return 0;
}
+
__setup("acpi_fake_ecdt", acpi_fake_ecdt_setup);
+static int __init acpi_ec_set_polling_mode(char *str)
+{
+ int burst;
+
+ if (!get_option(&str, &burst))
+ return 0;
+
+ if (burst) {
+ acpi_ec_polling_mode = EC_BURST;
+ acpi_ec_driver.ops.add = acpi_ec_burst_add;
+ } else {
+ acpi_ec_polling_mode = EC_POLLING;
+ acpi_ec_driver.ops.add = acpi_ec_polling_add;
+ }
+ printk(KERN_INFO PREFIX "EC %s mode.\n",
+ burst ? "burst": "polling");
+ return 0;
+}
+__setup("ec_burst=", acpi_ec_set_polling_mode);
diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c
index babdf762ead..1f76a40bade 100644
--- a/drivers/acpi/hotkey.c
+++ b/drivers/acpi/hotkey.c
@@ -1,5 +1,5 @@
-/*
- * hotkey.c - ACPI Hotkey Driver ($Revision:$)
+/*
+ * hotkey.c - ACPI Hotkey Driver ($Revision: 0.2 $)
*
* Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
*
@@ -51,17 +51,18 @@
#define ACPI_HOTKEY_POLLING 0x2
#define ACPI_UNDEFINED_EVENT 0xf
-#define MAX_CONFIG_RECORD_LEN 80
-#define MAX_NAME_PATH_LEN 80
-#define MAX_CALL_PARM 80
+#define RESULT_STR_LEN 80
-#define IS_EVENT(e) 0xff /* ((e) & 0x40000000) */
-#define IS_POLL(e) 0xff /* (~((e) & 0x40000000)) */
+#define ACTION_METHOD 0
+#define POLL_METHOD 1
+#define IS_EVENT(e) ((e) <= 10000 && (e) >0)
+#define IS_POLL(e) ((e) > 10000)
+#define IS_OTHERS(e) ((e)<=0 || (e)>=20000)
#define _COMPONENT ACPI_HOTKEY_COMPONENT
ACPI_MODULE_NAME("acpi_hotkey")
- MODULE_AUTHOR("luming.yu@intel.com");
+MODULE_AUTHOR("luming.yu@intel.com");
MODULE_DESCRIPTION(ACPI_HOTK_NAME);
MODULE_LICENSE("GPL");
@@ -114,7 +115,7 @@ struct acpi_event_hotkey {
char *action_method; /* action method */
};
-/*
+/*
* There are two ways to poll status
* 1. directy call read_xxx method, without any arguments passed in
* 2. call write_xxx method, with arguments passed in, you need
@@ -131,7 +132,7 @@ struct acpi_polling_hotkey {
char *poll_method; /* poll method */
acpi_handle action_handle; /* acpi handle attached action method */
char *action_method; /* action method */
- void *poll_result; /* polling_result */
+ union acpi_object *poll_result; /* polling_result */
struct proc_dir_entry *proc;
};
@@ -162,20 +163,25 @@ static struct acpi_driver hotkey_driver = {
},
};
+static void free_hotkey_device(union acpi_hotkey *key);
+static void free_hotkey_buffer(union acpi_hotkey *key);
+static void free_poll_hotkey_buffer(union acpi_hotkey *key);
static int hotkey_open_config(struct inode *inode, struct file *file);
+static int hotkey_poll_open_config(struct inode *inode, struct file *file);
static ssize_t hotkey_write_config(struct file *file,
const char __user * buffer,
size_t count, loff_t * data);
-static ssize_t hotkey_write_poll_config(struct file *file,
- const char __user * buffer,
- size_t count, loff_t * data);
static int hotkey_info_open_fs(struct inode *inode, struct file *file);
static int hotkey_action_open_fs(struct inode *inode, struct file *file);
static ssize_t hotkey_execute_aml_method(struct file *file,
const char __user * buffer,
size_t count, loff_t * data);
static int hotkey_config_seq_show(struct seq_file *seq, void *offset);
+static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset);
static int hotkey_polling_open_fs(struct inode *inode, struct file *file);
+static union acpi_hotkey *get_hotkey_by_event(struct
+ acpi_hotkey_list
+ *hotkey_list, int event);
/* event based config */
static struct file_operations hotkey_config_fops = {
@@ -188,9 +194,9 @@ static struct file_operations hotkey_config_fops = {
/* polling based config */
static struct file_operations hotkey_poll_config_fops = {
- .open = hotkey_open_config,
+ .open = hotkey_poll_open_config,
.read = seq_read,
- .write = hotkey_write_poll_config,
+ .write = hotkey_write_config,
.llseek = seq_lseek,
.release = single_release,
};
@@ -227,7 +233,7 @@ static int hotkey_info_seq_show(struct seq_file *seq, void *offset)
{
ACPI_FUNCTION_TRACE("hotkey_info_seq_show");
- seq_printf(seq, "Hotkey generic driver ver: %s", HOTKEY_ACPI_VERSION);
+ seq_printf(seq, "Hotkey generic driver ver: %s\n", HOTKEY_ACPI_VERSION);
return_VALUE(0);
}
@@ -239,27 +245,35 @@ static int hotkey_info_open_fs(struct inode *inode, struct file *file)
static char *format_result(union acpi_object *object)
{
- char *buf = (char *)kmalloc(sizeof(union acpi_object), GFP_KERNEL);
-
- memset(buf, 0, sizeof(union acpi_object));
+ char *buf = NULL;
+
+ buf = (char *)kmalloc(RESULT_STR_LEN, GFP_KERNEL);
+ if (buf)
+ memset(buf, 0, RESULT_STR_LEN);
+ else
+ goto do_fail;
/* Now, just support integer type */
if (object->type == ACPI_TYPE_INTEGER)
- sprintf(buf, "%d", (u32) object->integer.value);
-
- return buf;
+ sprintf(buf, "%d\n", (u32) object->integer.value);
+do_fail:
+ return (buf);
}
static int hotkey_polling_seq_show(struct seq_file *seq, void *offset)
{
struct acpi_polling_hotkey *poll_hotkey =
(struct acpi_polling_hotkey *)seq->private;
+ char *buf;
ACPI_FUNCTION_TRACE("hotkey_polling_seq_show");
- if (poll_hotkey->poll_result)
- seq_printf(seq, "%s", format_result(poll_hotkey->poll_result));
-
+ if (poll_hotkey->poll_result){
+ buf = format_result(poll_hotkey->poll_result);
+ if(buf)
+ seq_printf(seq, "%s", buf);
+ kfree(buf);
+ }
return_VALUE(0);
}
@@ -276,19 +290,19 @@ static int hotkey_action_open_fs(struct inode *inode, struct file *file)
/* Mapping external hotkey number to standardized hotkey event num */
static int hotkey_get_internal_event(int event, struct acpi_hotkey_list *list)
{
- struct list_head *entries, *next;
- int val = 0;
+ struct list_head *entries;
+ int val = -1;
ACPI_FUNCTION_TRACE("hotkey_get_internal_event");
- list_for_each_safe(entries, next, list->entries) {
+ list_for_each(entries, list->entries) {
union acpi_hotkey *key =
container_of(entries, union acpi_hotkey, entries);
if (key->link.hotkey_type == ACPI_HOTKEY_EVENT
- && key->event_hotkey.external_hotkey_num == event)
+ && key->event_hotkey.external_hotkey_num == event){
val = key->link.hotkey_standard_num;
- else
- val = -1;
+ break;
+ }
}
return_VALUE(val);
@@ -306,7 +320,7 @@ acpi_hotkey_notify_handler(acpi_handle handle, u32 event, void *data)
return_VOID;
internal_event = hotkey_get_internal_event(event, &global_hotkey_list);
- acpi_bus_generate_event(device, event, 0);
+ acpi_bus_generate_event(device, internal_event, 0);
return_VOID;
}
@@ -329,13 +343,17 @@ static int auto_hotkey_remove(struct acpi_device *device, int type)
static int create_polling_proc(union acpi_hotkey *device)
{
struct proc_dir_entry *proc;
+ char proc_name[80];
mode_t mode;
ACPI_FUNCTION_TRACE("create_polling_proc");
mode = S_IFREG | S_IRUGO | S_IWUGO;
- proc = create_proc_entry(device->poll_hotkey.action_method,
- mode, hotkey_proc_dir);
+ sprintf(proc_name, "%d", device->link.hotkey_standard_num);
+ /*
+ strcat(proc_name, device->poll_hotkey.poll_method);
+ */
+ proc = create_proc_entry(proc_name, mode, hotkey_proc_dir);
if (!proc) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
@@ -353,23 +371,6 @@ static int create_polling_proc(union acpi_hotkey *device)
return_VALUE(0);
}
-static int is_valid_acpi_path(const char *pathname)
-{
- acpi_handle handle;
- acpi_status status;
- ACPI_FUNCTION_TRACE("is_valid_acpi_path");
-
- status = acpi_get_handle(NULL, (char *)pathname, &handle);
- return_VALUE(!ACPI_FAILURE(status));
-}
-
-static int is_valid_hotkey(union acpi_hotkey *device)
-{
- ACPI_FUNCTION_TRACE("is_valid_hotkey");
- /* Implement valid check */
- return_VALUE(1);
-}
-
static int hotkey_add(union acpi_hotkey *device)
{
int status = 0;
@@ -378,15 +379,11 @@ static int hotkey_add(union acpi_hotkey *device)
ACPI_FUNCTION_TRACE("hotkey_add");
if (device->link.hotkey_type == ACPI_HOTKEY_EVENT) {
- status =
- acpi_bus_get_device(device->event_hotkey.bus_handle, &dev);
- if (status)
- return_VALUE(status);
-
+ acpi_bus_get_device(device->event_hotkey.bus_handle, &dev);
status = acpi_install_notify_handler(dev->handle,
- ACPI_SYSTEM_NOTIFY,
+ ACPI_DEVICE_NOTIFY,
acpi_hotkey_notify_handler,
- device);
+ dev);
} else /* Add polling hotkey */
create_polling_proc(device);
@@ -409,84 +406,143 @@ static int hotkey_remove(union acpi_hotkey *device)
if (key->link.hotkey_standard_num ==
device->link.hotkey_standard_num) {
list_del(&key->link.entries);
- remove_proc_entry(key->poll_hotkey.action_method,
- hotkey_proc_dir);
+ free_hotkey_device(key);
global_hotkey_list.count--;
break;
}
}
+ kfree(device);
return_VALUE(0);
}
-static void hotkey_update(union acpi_hotkey *key)
+static int hotkey_update(union acpi_hotkey *key)
{
- struct list_head *entries, *next;
+ struct list_head *entries;
ACPI_FUNCTION_TRACE("hotkey_update");
- list_for_each_safe(entries, next, global_hotkey_list.entries) {
- union acpi_hotkey *key =
+ list_for_each(entries, global_hotkey_list.entries) {
+ union acpi_hotkey *tmp=
container_of(entries, union acpi_hotkey, entries);
- if (key->link.hotkey_standard_num ==
+ if (tmp->link.hotkey_standard_num ==
key->link.hotkey_standard_num) {
- key->event_hotkey.bus_handle =
- key->event_hotkey.bus_handle;
- key->event_hotkey.external_hotkey_num =
- key->event_hotkey.external_hotkey_num;
- key->event_hotkey.action_handle =
- key->event_hotkey.action_handle;
- key->event_hotkey.action_method =
- key->event_hotkey.action_method;
+ if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) {
+ free_hotkey_buffer(tmp);
+ tmp->event_hotkey.bus_handle =
+ key->event_hotkey.bus_handle;
+ tmp->event_hotkey.external_hotkey_num =
+ key->event_hotkey.external_hotkey_num;
+ tmp->event_hotkey.action_handle =
+ key->event_hotkey.action_handle;
+ tmp->event_hotkey.action_method =
+ key->event_hotkey.action_method;
+ kfree(key);
+ } else {
+ /*
+ char proc_name[80];
+
+ sprintf(proc_name, "%d", tmp->link.hotkey_standard_num);
+ strcat(proc_name, tmp->poll_hotkey.poll_method);
+ remove_proc_entry(proc_name,hotkey_proc_dir);
+ */
+ free_poll_hotkey_buffer(tmp);
+ tmp->poll_hotkey.poll_handle =
+ key->poll_hotkey.poll_handle;
+ tmp->poll_hotkey.poll_method =
+ key->poll_hotkey.poll_method;
+ tmp->poll_hotkey.action_handle =
+ key->poll_hotkey.action_handle;
+ tmp->poll_hotkey.action_method =
+ key->poll_hotkey.action_method;
+ tmp->poll_hotkey.poll_result =
+ key->poll_hotkey.poll_result;
+ /*
+ create_polling_proc(tmp);
+ */
+ kfree(key);
+ }
+ return_VALUE(0);
break;
}
}
- return_VOID;
+ return_VALUE(-ENODEV);
}
static void free_hotkey_device(union acpi_hotkey *key)
{
struct acpi_device *dev;
- int status;
ACPI_FUNCTION_TRACE("free_hotkey_device");
if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) {
- status =
- acpi_bus_get_device(key->event_hotkey.bus_handle, &dev);
+ acpi_bus_get_device(key->event_hotkey.bus_handle, &dev);
if (dev->handle)
acpi_remove_notify_handler(dev->handle,
- ACPI_SYSTEM_NOTIFY,
+ ACPI_DEVICE_NOTIFY,
acpi_hotkey_notify_handler);
- } else
- remove_proc_entry(key->poll_hotkey.action_method,
- hotkey_proc_dir);
+ free_hotkey_buffer(key);
+ } else {
+ char proc_name[80];
+
+ sprintf(proc_name, "%d", key->link.hotkey_standard_num);
+ /*
+ strcat(proc_name, key->poll_hotkey.poll_method);
+ */
+ remove_proc_entry(proc_name,hotkey_proc_dir);
+ free_poll_hotkey_buffer(key);
+ }
kfree(key);
return_VOID;
}
+static void
+free_hotkey_buffer(union acpi_hotkey *key)
+{
+ kfree(key->event_hotkey.action_method);
+}
+
+static void
+free_poll_hotkey_buffer(union acpi_hotkey *key)
+{
+ kfree(key->poll_hotkey.action_method);
+ kfree(key->poll_hotkey.poll_method);
+ kfree(key->poll_hotkey.poll_result);
+}
static int
init_hotkey_device(union acpi_hotkey *key, char *bus_str, char *action_str,
char *method, int std_num, int external_num)
{
+ acpi_handle tmp_handle;
+ acpi_status status = AE_OK;
+
ACPI_FUNCTION_TRACE("init_hotkey_device");
+ if(std_num < 0 || IS_POLL(std_num) || !key )
+ goto do_fail;
+
+ if(!bus_str || !action_str || !method)
+ goto do_fail;
+
key->link.hotkey_type = ACPI_HOTKEY_EVENT;
key->link.hotkey_standard_num = std_num;
key->event_hotkey.flag = 0;
- if (is_valid_acpi_path(bus_str))
- acpi_get_handle((acpi_handle) 0,
- bus_str, &(key->event_hotkey.bus_handle));
- else
- return_VALUE(-ENODEV);
- key->event_hotkey.external_hotkey_num = external_num;
- if (is_valid_acpi_path(action_str))
- acpi_get_handle((acpi_handle) 0,
- action_str, &(key->event_hotkey.action_handle));
- key->event_hotkey.action_method = kmalloc(sizeof(method), GFP_KERNEL);
- strcpy(key->event_hotkey.action_method, method);
+ key->event_hotkey.action_method = method;
- return_VALUE(!is_valid_hotkey(key));
+ status = acpi_get_handle(NULL,bus_str, &(key->event_hotkey.bus_handle));
+ if(ACPI_FAILURE(status))
+ goto do_fail;
+ key->event_hotkey.external_hotkey_num = external_num;
+ status = acpi_get_handle(NULL,action_str, &(key->event_hotkey.action_handle));
+ if(ACPI_FAILURE(status))
+ goto do_fail;
+ status = acpi_get_handle(key->event_hotkey.action_handle,
+ method, &tmp_handle);
+ if (ACPI_FAILURE(status))
+ goto do_fail;
+ return_VALUE(AE_OK);
+do_fail:
+ return_VALUE(-ENODEV);
}
static int
@@ -495,34 +551,46 @@ init_poll_hotkey_device(union acpi_hotkey *key,
char *poll_method,
char *action_str, char *action_method, int std_num)
{
+ acpi_status status = AE_OK;
+ acpi_handle tmp_handle;
+
ACPI_FUNCTION_TRACE("init_poll_hotkey_device");
+ if(std_num < 0 || IS_EVENT(std_num) || !key)
+ goto do_fail;
+
+ if(!poll_str || !poll_method || !action_str || !action_method)
+ goto do_fail;
+
key->link.hotkey_type = ACPI_HOTKEY_POLLING;
key->link.hotkey_standard_num = std_num;
key->poll_hotkey.flag = 0;
- if (is_valid_acpi_path(poll_str))
- acpi_get_handle((acpi_handle) 0,
- poll_str, &(key->poll_hotkey.poll_handle));
- else
- return_VALUE(-ENODEV);
key->poll_hotkey.poll_method = poll_method;
- if (is_valid_acpi_path(action_str))
- acpi_get_handle((acpi_handle) 0,
- action_str, &(key->poll_hotkey.action_handle));
- key->poll_hotkey.action_method =
- kmalloc(sizeof(action_method), GFP_KERNEL);
- strcpy(key->poll_hotkey.action_method, action_method);
+ key->poll_hotkey.action_method = action_method;
+
+ status = acpi_get_handle(NULL,poll_str, &(key->poll_hotkey.poll_handle));
+ if(ACPI_FAILURE(status))
+ goto do_fail;
+ status = acpi_get_handle(key->poll_hotkey.poll_handle,
+ poll_method, &tmp_handle);
+ if (ACPI_FAILURE(status))
+ goto do_fail;
+ status = acpi_get_handle(NULL,action_str, &(key->poll_hotkey.action_handle));
+ if (ACPI_FAILURE(status))
+ goto do_fail;
+ status = acpi_get_handle(key->poll_hotkey.action_handle,
+ action_method, &tmp_handle);
+ if (ACPI_FAILURE(status))
+ goto do_fail;
key->poll_hotkey.poll_result =
(union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL);
- return_VALUE(is_valid_hotkey(key));
+ if(!key->poll_hotkey.poll_result)
+ goto do_fail;
+ return_VALUE(AE_OK);
+do_fail:
+ return_VALUE(-ENODEV);
}
-static int check_hotkey_valid(union acpi_hotkey *key,
- struct acpi_hotkey_list *list)
-{
- ACPI_FUNCTION_TRACE("check_hotkey_valid");
- return_VALUE(0);
-}
static int hotkey_open_config(struct inode *inode, struct file *file)
{
@@ -531,10 +599,17 @@ static int hotkey_open_config(struct inode *inode, struct file *file)
(file, hotkey_config_seq_show, PDE(inode)->data));
}
+static int hotkey_poll_open_config(struct inode *inode, struct file *file)
+{
+ ACPI_FUNCTION_TRACE("hotkey_poll_open_config");
+ return_VALUE(single_open
+ (file, hotkey_poll_config_seq_show, PDE(inode)->data));
+}
+
static int hotkey_config_seq_show(struct seq_file *seq, void *offset)
{
struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
- struct list_head *entries, *next;
+ struct list_head *entries;
char bus_name[ACPI_PATHNAME_MAX] = { 0 };
char action_name[ACPI_PATHNAME_MAX] = { 0 };
struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name };
@@ -542,10 +617,7 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset)
ACPI_FUNCTION_TRACE(("hotkey_config_seq_show"));
- if (!hotkey_list)
- goto end;
-
- list_for_each_safe(entries, next, hotkey_list->entries) {
+ list_for_each(entries, hotkey_list->entries) {
union acpi_hotkey *key =
container_of(entries, union acpi_hotkey, entries);
if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) {
@@ -553,18 +625,37 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset)
ACPI_NAME_TYPE_MAX, &bus);
acpi_get_name(key->event_hotkey.action_handle,
ACPI_NAME_TYPE_MAX, &act);
- seq_printf(seq, "%s:%s:%s:%d:%d", bus_name,
+ seq_printf(seq, "%s:%s:%s:%d:%d\n", bus_name,
action_name,
key->event_hotkey.action_method,
key->link.hotkey_standard_num,
key->event_hotkey.external_hotkey_num);
- } /* ACPI_HOTKEY_POLLING */
- else {
+ }
+ }
+ seq_puts(seq, "\n");
+ return_VALUE(0);
+}
+
+static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset)
+{
+ struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
+ struct list_head *entries;
+ char bus_name[ACPI_PATHNAME_MAX] = { 0 };
+ char action_name[ACPI_PATHNAME_MAX] = { 0 };
+ struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name };
+ struct acpi_buffer act = { ACPI_PATHNAME_MAX, action_name };
+
+ ACPI_FUNCTION_TRACE(("hotkey_config_seq_show"));
+
+ list_for_each(entries, hotkey_list->entries) {
+ union acpi_hotkey *key =
+ container_of(entries, union acpi_hotkey, entries);
+ if (key->link.hotkey_type == ACPI_HOTKEY_POLLING) {
acpi_get_name(key->poll_hotkey.poll_handle,
ACPI_NAME_TYPE_MAX, &bus);
acpi_get_name(key->poll_hotkey.action_handle,
ACPI_NAME_TYPE_MAX, &act);
- seq_printf(seq, "%s:%s:%s:%s:%d", bus_name,
+ seq_printf(seq, "%s:%s:%s:%s:%d\n", bus_name,
key->poll_hotkey.poll_method,
action_name,
key->poll_hotkey.action_method,
@@ -572,49 +663,83 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset)
}
}
seq_puts(seq, "\n");
- end:
return_VALUE(0);
}
static int
get_parms(char *config_record,
int *cmd,
- char *bus_handle,
- char *bus_method,
- char *action_handle,
- char *method, int *internal_event_num, int *external_event_num)
+ char **bus_handle,
+ char **bus_method,
+ char **action_handle,
+ char **method, int *internal_event_num, int *external_event_num)
{
- char *tmp, *tmp1;
+ char *tmp, *tmp1, count;
ACPI_FUNCTION_TRACE(("get_parms"));
sscanf(config_record, "%d", cmd);
+ if(*cmd == 1){
+ if(sscanf(config_record, "%d:%d", cmd, internal_event_num)!=2)
+ goto do_fail;
+ else
+ return (6);
+ }
tmp = strchr(config_record, ':');
+ if (!tmp)
+ goto do_fail;
tmp++;
tmp1 = strchr(tmp, ':');
- strncpy(bus_handle, tmp, tmp1 - tmp);
- bus_handle[tmp1 - tmp] = 0;
+ if (!tmp1)
+ goto do_fail;
+
+ count = tmp1 - tmp;
+ *bus_handle = (char *) kmalloc(count+1, GFP_KERNEL);
+ if(!*bus_handle)
+ goto do_fail;
+ strncpy(*bus_handle, tmp, count);
+ *(*bus_handle + count) = 0;
tmp = tmp1;
tmp++;
tmp1 = strchr(tmp, ':');
- strncpy(bus_method, tmp, tmp1 - tmp);
- bus_method[tmp1 - tmp] = 0;
+ if (!tmp1)
+ goto do_fail;
+ count = tmp1 - tmp;
+ *bus_method = (char *) kmalloc(count+1, GFP_KERNEL);
+ if(!*bus_method)
+ goto do_fail;
+ strncpy(*bus_method, tmp, count);
+ *(*bus_method + count) = 0;
tmp = tmp1;
tmp++;
tmp1 = strchr(tmp, ':');
- strncpy(action_handle, tmp, tmp1 - tmp);
- action_handle[tmp1 - tmp] = 0;
+ if (!tmp1)
+ goto do_fail;
+ count = tmp1 - tmp;
+ *action_handle = (char *) kmalloc(count+1, GFP_KERNEL);
+ strncpy(*action_handle, tmp, count);
+ *(*action_handle + count) = 0;
tmp = tmp1;
tmp++;
tmp1 = strchr(tmp, ':');
- strncpy(method, tmp, tmp1 - tmp);
- method[tmp1 - tmp] = 0;
+ if (!tmp1)
+ goto do_fail;
+ count = tmp1 - tmp;
+ *method = (char *) kmalloc(count+1, GFP_KERNEL);
+ if(!*method)
+ goto do_fail;
+ strncpy(*method, tmp, count);
+ *(*method + count) = 0;
+
+ if(sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num)<=0)
+ goto do_fail;
- sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num);
return_VALUE(6);
+do_fail:
+ return_VALUE(-1);
}
/* count is length for one input record */
@@ -622,135 +747,117 @@ static ssize_t hotkey_write_config(struct file *file,
const char __user * buffer,
size_t count, loff_t * data)
{
- struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
- char config_record[MAX_CONFIG_RECORD_LEN];
- char bus_handle[MAX_NAME_PATH_LEN];
- char bus_method[MAX_NAME_PATH_LEN];
- char action_handle[MAX_NAME_PATH_LEN];
- char method[20];
+ char *config_record = NULL;
+ char *bus_handle = NULL;
+ char *bus_method = NULL;
+ char *action_handle = NULL;
+ char *method = NULL;
int cmd, internal_event_num, external_event_num;
int ret = 0;
union acpi_hotkey *key = NULL;
ACPI_FUNCTION_TRACE(("hotkey_write_config"));
- if (!hotkey_list || count > MAX_CONFIG_RECORD_LEN) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid arguments\n"));
- return_VALUE(-EINVAL);
- }
+ config_record = (char *) kmalloc(count+1, GFP_KERNEL);
+ if(!config_record)
+ return_VALUE(-ENOMEM);
if (copy_from_user(config_record, buffer, count)) {
+ kfree(config_record);
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data \n"));
return_VALUE(-EINVAL);
}
- config_record[count] = '\0';
+ config_record[count] = 0;
ret = get_parms(config_record,
&cmd,
- bus_handle,
- bus_method,
- action_handle,
- method, &internal_event_num, &external_event_num);
+ &bus_handle,
+ &bus_method,
+ &action_handle,
+ &method, &internal_event_num, &external_event_num);
+
+ kfree(config_record);
+ if(IS_OTHERS(internal_event_num))
+ goto do_fail;
if (ret != 6) {
+do_fail:
+ kfree(bus_handle);
+ kfree(bus_method);
+ kfree(action_handle);
+ kfree(method);
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Invalid data format ret=%d\n", ret));
return_VALUE(-EINVAL);
}
key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL);
- ret = init_hotkey_device(key, bus_handle, action_handle, method,
+ if(!key)
+ goto do_fail;
+ memset(key, 0, sizeof(union acpi_hotkey));
+ if(cmd == 1) {
+ union acpi_hotkey *tmp = NULL;
+ tmp = get_hotkey_by_event(&global_hotkey_list,
+ internal_event_num);
+ if(!tmp)
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid key"));
+ else
+ memcpy(key, tmp, sizeof(union acpi_hotkey));
+ goto cont_cmd;
+ }
+ if (IS_EVENT(internal_event_num)) {
+ kfree(bus_method);
+ ret = init_hotkey_device(key, bus_handle, action_handle, method,
internal_event_num, external_event_num);
-
- if (ret || check_hotkey_valid(key, hotkey_list)) {
+ } else
+ ret = init_poll_hotkey_device(key, bus_handle, bus_method,
+ action_handle, method,
+ internal_event_num);
+ if (ret) {
+ kfree(bus_handle);
+ kfree(action_handle);
+ if(IS_EVENT(internal_event_num))
+ free_hotkey_buffer(key);
+ else
+ free_poll_hotkey_buffer(key);
kfree(key);
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid hotkey \n"));
return_VALUE(-EINVAL);
}
- switch (cmd) {
- case 0:
- hotkey_add(key);
- break;
- case 1:
- hotkey_remove(key);
- free_hotkey_device(key);
- break;
- case 2:
- hotkey_update(key);
- break;
- default:
- break;
- }
- return_VALUE(count);
-}
-
-/* count is length for one input record */
-static ssize_t hotkey_write_poll_config(struct file *file,
- const char __user * buffer,
- size_t count, loff_t * data)
-{
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_hotkey_list *hotkey_list =
- (struct acpi_hotkey_list *)m->private;
-
- char config_record[MAX_CONFIG_RECORD_LEN];
- char polling_handle[MAX_NAME_PATH_LEN];
- char action_handle[MAX_NAME_PATH_LEN];
- char poll_method[20], action_method[20];
- int ret, internal_event_num, cmd, external_event_num;
- union acpi_hotkey *key = NULL;
-
- ACPI_FUNCTION_TRACE("hotkey_write_poll_config");
-
- if (!hotkey_list || count > MAX_CONFIG_RECORD_LEN) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid arguments\n"));
- return_VALUE(-EINVAL);
- }
-
- if (copy_from_user(config_record, buffer, count)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data \n"));
- return_VALUE(-EINVAL);
- }
- config_record[count] = '\0';
- ret = get_parms(config_record,
- &cmd,
- polling_handle,
- poll_method,
- action_handle,
- action_method,
- &internal_event_num, &external_event_num);
-
- if (ret != 6) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n"));
- return_VALUE(-EINVAL);
- }
+cont_cmd:
+ kfree(bus_handle);
+ kfree(action_handle);
- key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL);
- ret = init_poll_hotkey_device(key, polling_handle, poll_method,
- action_handle, action_method,
- internal_event_num);
- if (ret || check_hotkey_valid(key, hotkey_list)) {
- kfree(key);
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid hotkey \n"));
- return_VALUE(-EINVAL);
- }
switch (cmd) {
case 0:
- hotkey_add(key);
+ if(get_hotkey_by_event(&global_hotkey_list,key->link.hotkey_standard_num))
+ goto fail_out;
+ else
+ hotkey_add(key);
break;
case 1:
hotkey_remove(key);
break;
case 2:
- hotkey_update(key);
+ if(hotkey_update(key))
+ goto fail_out;
break;
default:
+ goto fail_out;
break;
}
return_VALUE(count);
+fail_out:
+ if(IS_EVENT(internal_event_num))
+ free_hotkey_buffer(key);
+ else
+ free_poll_hotkey_buffer(key);
+ kfree(key);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "invalid key\n"));
+ return_VALUE(-EINVAL);
}
-/*
+/*
* This function evaluates an ACPI method, given an int as parameter, the
* method is searched within the scope of the handle, can be NULL. The output
* of the method is written is output, which can also be NULL
@@ -775,7 +882,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val,
return_VALUE(status == AE_OK);
}
-static int read_acpi_int(acpi_handle handle, const char *method, int *val)
+static int read_acpi_int(acpi_handle handle, const char *method, union acpi_object *val)
{
struct acpi_buffer output;
union acpi_object out_obj;
@@ -786,62 +893,32 @@ static int read_acpi_int(acpi_handle handle, const char *method, int *val)
output.pointer = &out_obj;
status = acpi_evaluate_object(handle, (char *)method, NULL, &output);
- *val = out_obj.integer.value;
+ if(val){
+ val->integer.value = out_obj.integer.value;
+ val->type = out_obj.type;
+ } else
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "null val pointer"));
return_VALUE((status == AE_OK)
&& (out_obj.type == ACPI_TYPE_INTEGER));
}
-static acpi_handle
-get_handle_from_hotkeylist(struct acpi_hotkey_list *hotkey_list, int event_num)
+static union acpi_hotkey *get_hotkey_by_event(struct
+ acpi_hotkey_list
+ *hotkey_list, int event)
{
- struct list_head *entries, *next;
-
- list_for_each_safe(entries, next, hotkey_list->entries) {
- union acpi_hotkey *key =
- container_of(entries, union acpi_hotkey, entries);
- if (key->link.hotkey_type == ACPI_HOTKEY_EVENT
- && key->link.hotkey_standard_num == event_num) {
- return (key->event_hotkey.action_handle);
- }
- }
- return (NULL);
-}
-
-static
-char *get_method_from_hotkeylist(struct acpi_hotkey_list *hotkey_list,
- int event_num)
-{
- struct list_head *entries, *next;
-
- list_for_each_safe(entries, next, hotkey_list->entries) {
- union acpi_hotkey *key =
- container_of(entries, union acpi_hotkey, entries);
-
- if (key->link.hotkey_type == ACPI_HOTKEY_EVENT &&
- key->link.hotkey_standard_num == event_num)
- return (key->event_hotkey.action_method);
- }
- return (NULL);
-}
-
-static struct acpi_polling_hotkey *get_hotkey_by_event(struct
- acpi_hotkey_list
- *hotkey_list, int event)
-{
- struct list_head *entries, *next;
+ struct list_head *entries;
- list_for_each_safe(entries, next, hotkey_list->entries) {
+ list_for_each(entries, hotkey_list->entries) {
union acpi_hotkey *key =
container_of(entries, union acpi_hotkey, entries);
- if (key->link.hotkey_type == ACPI_HOTKEY_POLLING
- && key->link.hotkey_standard_num == event) {
- return (&key->poll_hotkey);
+ if (key->link.hotkey_standard_num == event) {
+ return(key);
}
}
- return (NULL);
+ return(NULL);
}
-/*
+/*
* user call AML method interface:
* Call convention:
* echo "event_num: arg type : value"
@@ -854,48 +931,56 @@ static ssize_t hotkey_execute_aml_method(struct file *file,
size_t count, loff_t * data)
{
struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
- char arg[MAX_CALL_PARM];
- int event, type, value;
-
- char *method;
- acpi_handle handle;
+ char *arg;
+ int event,method_type,type, value;
+ union acpi_hotkey *key;
ACPI_FUNCTION_TRACE("hotkey_execte_aml_method");
- if (!hotkey_list || count > MAX_CALL_PARM) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 1"));
- return_VALUE(-EINVAL);
- }
+ arg = (char *) kmalloc(count+1, GFP_KERNEL);
+ if(!arg)
+ return_VALUE(-ENOMEM);
+ arg[count]=0;
if (copy_from_user(arg, buffer, count)) {
+ kfree(arg);
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 2"));
return_VALUE(-EINVAL);
}
- arg[count] = '\0';
-
- if (sscanf(arg, "%d:%d:%d", &event, &type, &value) != 3) {
+ if (sscanf(arg, "%d:%d:%d:%d", &event, &method_type, &type, &value) != 4) {
+ kfree(arg);
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 3"));
return_VALUE(-EINVAL);
}
-
+ kfree(arg);
if (type == ACPI_TYPE_INTEGER) {
- handle = get_handle_from_hotkeylist(hotkey_list, event);
- method = (char *)get_method_from_hotkeylist(hotkey_list, event);
+ key = get_hotkey_by_event(hotkey_list, event);
+ if(!key)
+ goto do_fail;
if (IS_EVENT(event))
- write_acpi_int(handle, method, value, NULL);
+ write_acpi_int(key->event_hotkey.action_handle,
+ key->event_hotkey.action_method, value, NULL);
else if (IS_POLL(event)) {
- struct acpi_polling_hotkey *key;
- key = (struct acpi_polling_hotkey *)
- get_hotkey_by_event(hotkey_list, event);
- read_acpi_int(handle, method, key->poll_result);
+ if ( method_type == POLL_METHOD )
+ read_acpi_int(key->poll_hotkey.poll_handle,
+ key->poll_hotkey.poll_method,
+ key->poll_hotkey.poll_result);
+ else if ( method_type == ACTION_METHOD )
+ write_acpi_int(key->poll_hotkey.action_handle,
+ key->poll_hotkey.action_method, value, NULL);
+ else
+ goto do_fail;
+
}
} else {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Not supported"));
return_VALUE(-EINVAL);
}
-
return_VALUE(count);
+do_fail:
+ return_VALUE(-EINVAL);
+
}
static int __init hotkey_init(void)
@@ -928,7 +1013,7 @@ static int __init hotkey_init(void)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Hotkey: Unable to create %s entry\n",
HOTKEY_EV_CONFIG));
- return (-ENODEV);
+ goto do_fail1;
} else {
hotkey_config->proc_fops = &hotkey_config_fops;
hotkey_config->data = &global_hotkey_list;
@@ -943,7 +1028,8 @@ static int __init hotkey_init(void)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Hotkey: Unable to create %s entry\n",
HOTKEY_EV_CONFIG));
- return (-ENODEV);
+
+ goto do_fail2;
} else {
hotkey_poll_config->proc_fops = &hotkey_poll_config_fops;
hotkey_poll_config->data = &global_hotkey_list;
@@ -957,7 +1043,7 @@ static int __init hotkey_init(void)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Hotkey: Unable to create %s entry\n",
HOTKEY_ACTION));
- return (-ENODEV);
+ goto do_fail3;
} else {
hotkey_action->proc_fops = &hotkey_action_fops;
hotkey_action->owner = THIS_MODULE;
@@ -970,7 +1056,7 @@ static int __init hotkey_init(void)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Hotkey: Unable to create %s entry\n",
HOTKEY_INFO));
- return (-ENODEV);
+ goto do_fail4;
} else {
hotkey_info->proc_fops = &hotkey_info_fops;
hotkey_info->owner = THIS_MODULE;
@@ -979,23 +1065,33 @@ static int __init hotkey_init(void)
}
result = acpi_bus_register_driver(&hotkey_driver);
- if (result < 0) {
- remove_proc_entry(HOTKEY_PROC, acpi_root_dir);
- return (-ENODEV);
- }
+ if (result < 0)
+ goto do_fail5;
global_hotkey_list.count = 0;
global_hotkey_list.entries = &hotkey_entries;
INIT_LIST_HEAD(&hotkey_entries);
return (0);
+
+do_fail5:
+ remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir);
+do_fail4:
+ remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir);
+do_fail3:
+ remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir);
+do_fail2:
+ remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir);
+do_fail1:
+ remove_proc_entry(HOTKEY_PROC, acpi_root_dir);
+ return (-ENODEV);
}
static void __exit hotkey_exit(void)
{
struct list_head *entries, *next;
- ACPI_FUNCTION_TRACE("hotkey_remove");
+ ACPI_FUNCTION_TRACE("hotkey_exit");
list_for_each_safe(entries, next, global_hotkey_list.entries) {
union acpi_hotkey *key =
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index bdd9f37f810..7289da3c4db 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -145,10 +145,14 @@ acpi_os_vprintf(const char *fmt, va_list args)
#endif
}
+extern int acpi_in_resume;
void *
acpi_os_allocate(acpi_size size)
{
- return kmalloc(size, GFP_KERNEL);
+ if (acpi_in_resume)
+ return kmalloc(size, GFP_ATOMIC);
+ else
+ return kmalloc(size, GFP_KERNEL);
}
void
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index d1f42b97282..bb973d2109a 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -269,7 +269,51 @@ acpi_pci_irq_del_prt (int segment, int bus)
/* --------------------------------------------------------------------------
PCI Interrupt Routing Support
-------------------------------------------------------------------------- */
+typedef int (*irq_lookup_func)(struct acpi_prt_entry *, int *, int *, char **);
+static int
+acpi_pci_allocate_irq(struct acpi_prt_entry *entry,
+ int *edge_level,
+ int *active_high_low,
+ char **link)
+{
+ int irq;
+
+ ACPI_FUNCTION_TRACE("acpi_pci_allocate_irq");
+
+ if (entry->link.handle) {
+ irq = acpi_pci_link_allocate_irq(entry->link.handle,
+ entry->link.index, edge_level, active_high_low, link);
+ if (irq < 0) {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n"));
+ return_VALUE(-1);
+ }
+ } else {
+ irq = entry->link.index;
+ *edge_level = ACPI_LEVEL_SENSITIVE;
+ *active_high_low = ACPI_ACTIVE_LOW;
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq));
+ return_VALUE(irq);
+}
+
+static int
+acpi_pci_free_irq(struct acpi_prt_entry *entry,
+ int *edge_level,
+ int *active_high_low,
+ char **link)
+{
+ int irq;
+
+ ACPI_FUNCTION_TRACE("acpi_pci_free_irq");
+ if (entry->link.handle) {
+ irq = acpi_pci_link_free_irq(entry->link.handle);
+ } else {
+ irq = entry->link.index;
+ }
+ return_VALUE(irq);
+}
/*
* acpi_pci_irq_lookup
* success: return IRQ >= 0
@@ -282,12 +326,13 @@ acpi_pci_irq_lookup (
int pin,
int *edge_level,
int *active_high_low,
- char **link)
+ char **link,
+ irq_lookup_func func)
{
struct acpi_prt_entry *entry = NULL;
int segment = pci_domain_nr(bus);
int bus_nr = bus->number;
- int irq;
+ int ret;
ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup");
@@ -301,22 +346,8 @@ acpi_pci_irq_lookup (
return_VALUE(-1);
}
- if (entry->link.handle) {
- irq = acpi_pci_link_get_irq(entry->link.handle,
- entry->link.index, edge_level, active_high_low, link);
- if (irq < 0) {
- ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n"));
- return_VALUE(-1);
- }
- } else {
- irq = entry->link.index;
- *edge_level = ACPI_LEVEL_SENSITIVE;
- *active_high_low = ACPI_ACTIVE_LOW;
- }
-
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq));
-
- return_VALUE(irq);
+ ret = func(entry, edge_level, active_high_low, link);
+ return_VALUE(ret);
}
/*
@@ -330,7 +361,8 @@ acpi_pci_irq_derive (
int pin,
int *edge_level,
int *active_high_low,
- char **link)
+ char **link,
+ irq_lookup_func func)
{
struct pci_dev *bridge = dev;
int irq = -1;
@@ -363,7 +395,7 @@ acpi_pci_irq_derive (
}
irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn),
- pin, edge_level, active_high_low, link);
+ pin, edge_level, active_high_low, link, func);
}
if (irq < 0) {
@@ -415,7 +447,7 @@ acpi_pci_irq_enable (
* values override any BIOS-assigned IRQs set during boot.
*/
irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
- &edge_level, &active_high_low, &link);
+ &edge_level, &active_high_low, &link, acpi_pci_allocate_irq);
/*
* If no PRT entry was found, we'll try to derive an IRQ from the
@@ -423,7 +455,7 @@ acpi_pci_irq_enable (
*/
if (irq < 0)
irq = acpi_pci_irq_derive(dev, pin, &edge_level,
- &active_high_low, &link);
+ &active_high_low, &link, acpi_pci_allocate_irq);
/*
* No IRQ known to the ACPI subsystem - maybe the BIOS /
@@ -462,7 +494,9 @@ acpi_pci_irq_enable (
EXPORT_SYMBOL(acpi_pci_irq_enable);
-#ifdef CONFIG_ACPI_DEALLOCATE_IRQ
+/* FIXME: implement x86/x86_64 version */
+void __attribute__((weak)) acpi_unregister_gsi(u32 i) {}
+
void
acpi_pci_irq_disable (
struct pci_dev *dev)
@@ -489,14 +523,14 @@ acpi_pci_irq_disable (
* First we check the PCI IRQ routing table (PRT) for an IRQ.
*/
gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
- &edge_level, &active_high_low, NULL);
+ &edge_level, &active_high_low, NULL, acpi_pci_free_irq);
/*
* If no PRT entry was found, we'll try to derive an IRQ from the
* device's parent bridge.
*/
if (gsi < 0)
gsi = acpi_pci_irq_derive(dev, pin,
- &edge_level, &active_high_low, NULL);
+ &edge_level, &active_high_low, NULL, acpi_pci_free_irq);
if (gsi < 0)
return_VOID;
@@ -512,4 +546,3 @@ acpi_pci_irq_disable (
return_VOID;
}
-#endif /* CONFIG_ACPI_DEALLOCATE_IRQ */
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 6ad0e77df9b..834c2ceff1a 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -68,6 +68,10 @@ static struct acpi_driver acpi_pci_link_driver = {
},
};
+/*
+ * If a link is initialized, we never change its active and initialized
+ * later even the link is disable. Instead, we just repick the active irq
+ */
struct acpi_pci_link_irq {
u8 active; /* Current IRQ */
u8 edge_level; /* All IRQs */
@@ -76,8 +80,7 @@ struct acpi_pci_link_irq {
u8 possible_count;
u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
u8 initialized:1;
- u8 suspend_resume:1;
- u8 reserved:6;
+ u8 reserved:7;
};
struct acpi_pci_link {
@@ -85,12 +88,14 @@ struct acpi_pci_link {
struct acpi_device *device;
acpi_handle handle;
struct acpi_pci_link_irq irq;
+ int refcnt;
};
static struct {
int count;
struct list_head entries;
} acpi_link;
+DECLARE_MUTEX(acpi_link_lock);
/* --------------------------------------------------------------------------
@@ -532,12 +537,12 @@ static int acpi_pci_link_allocate(
ACPI_FUNCTION_TRACE("acpi_pci_link_allocate");
- if (link->irq.suspend_resume) {
- acpi_pci_link_set(link, link->irq.active);
- link->irq.suspend_resume = 0;
- }
- if (link->irq.initialized)
+ if (link->irq.initialized) {
+ if (link->refcnt == 0)
+ /* This means the link is disabled but initialized */
+ acpi_pci_link_set(link, link->irq.active);
return_VALUE(0);
+ }
/*
* search for active IRQ in list of possible IRQs.
@@ -596,13 +601,13 @@ static int acpi_pci_link_allocate(
}
/*
- * acpi_pci_link_get_irq
+ * acpi_pci_link_allocate_irq
* success: return IRQ >= 0
* failure: return -1
*/
int
-acpi_pci_link_get_irq (
+acpi_pci_link_allocate_irq (
acpi_handle handle,
int index,
int *edge_level,
@@ -613,7 +618,7 @@ acpi_pci_link_get_irq (
struct acpi_device *device = NULL;
struct acpi_pci_link *link = NULL;
- ACPI_FUNCTION_TRACE("acpi_pci_link_get_irq");
+ ACPI_FUNCTION_TRACE("acpi_pci_link_allocate_irq");
result = acpi_bus_get_device(handle, &device);
if (result) {
@@ -633,21 +638,81 @@ acpi_pci_link_get_irq (
return_VALUE(-1);
}
- if (acpi_pci_link_allocate(link))
+ down(&acpi_link_lock);
+ if (acpi_pci_link_allocate(link)) {
+ up(&acpi_link_lock);
return_VALUE(-1);
+ }
if (!link->irq.active) {
+ up(&acpi_link_lock);
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n"));
return_VALUE(-1);
}
+ link->refcnt ++;
+ up(&acpi_link_lock);
if (edge_level) *edge_level = link->irq.edge_level;
if (active_high_low) *active_high_low = link->irq.active_high_low;
if (name) *name = acpi_device_bid(link->device);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Link %s is referenced\n", acpi_device_bid(link->device)));
return_VALUE(link->irq.active);
}
+/*
+ * We don't change link's irq information here. After it is reenabled, we
+ * continue use the info
+ */
+int
+acpi_pci_link_free_irq(acpi_handle handle)
+{
+ struct acpi_device *device = NULL;
+ struct acpi_pci_link *link = NULL;
+ acpi_status result;
+
+ ACPI_FUNCTION_TRACE("acpi_pci_link_free_irq");
+
+ result = acpi_bus_get_device(handle, &device);
+ if (result) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link device\n"));
+ return_VALUE(-1);
+ }
+
+ link = (struct acpi_pci_link *) acpi_driver_data(device);
+ if (!link) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
+ return_VALUE(-1);
+ }
+
+ down(&acpi_link_lock);
+ if (!link->irq.initialized) {
+ up(&acpi_link_lock);
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link isn't initialized\n"));
+ return_VALUE(-1);
+ }
+#ifdef FUTURE_USE
+ /*
+ * The Link reference count allows us to _DISable an unused link
+ * and suspend time, and set it again on resume.
+ * However, 2.6.12 still has irq_router.resume
+ * which blindly restores the link state.
+ * So we disable the reference count method
+ * to prevent duplicate acpi_pci_link_set()
+ * which would harm some systems
+ */
+ link->refcnt --;
+#endif
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Link %s is dereferenced\n", acpi_device_bid(link->device)));
+
+ if (link->refcnt == 0) {
+ acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL);
+ }
+ up(&acpi_link_lock);
+ return_VALUE(link->irq.active);
+}
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
@@ -677,6 +742,7 @@ acpi_pci_link_add (
strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS);
acpi_driver_data(device) = link;
+ down(&acpi_link_lock);
result = acpi_pci_link_get_possible(link);
if (result)
goto end;
@@ -712,6 +778,7 @@ acpi_pci_link_add (
end:
/* disable all links -- to be activated on use */
acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL);
+ up(&acpi_link_lock);
if (result)
kfree(link);
@@ -720,24 +787,42 @@ end:
}
static int
-irqrouter_suspend(
- struct sys_device *dev,
- u32 state)
+acpi_pci_link_resume(
+ struct acpi_pci_link *link)
+{
+ ACPI_FUNCTION_TRACE("acpi_pci_link_resume");
+
+ if (link->refcnt && link->irq.active && link->irq.initialized)
+ return_VALUE(acpi_pci_link_set(link, link->irq.active));
+ else
+ return_VALUE(0);
+}
+
+/*
+ * FIXME: this is a workaround to avoid nasty warning. It will be removed
+ * after every device calls pci_disable_device in .resume.
+ */
+int acpi_in_resume;
+static int
+irqrouter_resume(
+ struct sys_device *dev)
{
struct list_head *node = NULL;
struct acpi_pci_link *link = NULL;
- ACPI_FUNCTION_TRACE("irqrouter_suspend");
+ ACPI_FUNCTION_TRACE("irqrouter_resume");
+ acpi_in_resume = 1;
list_for_each(node, &acpi_link.entries) {
link = list_entry(node, struct acpi_pci_link, node);
if (!link) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Invalid link context\n"));
continue;
}
- if (link->irq.active && link->irq.initialized)
- link->irq.suspend_resume = 1;
+ acpi_pci_link_resume(link);
}
+ acpi_in_resume = 0;
return_VALUE(0);
}
@@ -756,8 +841,9 @@ acpi_pci_link_remove (
link = (struct acpi_pci_link *) acpi_driver_data(device);
- /* TBD: Acquire/release lock */
+ down(&acpi_link_lock);
list_del(&link->node);
+ up(&acpi_link_lock);
kfree(link);
@@ -849,9 +935,10 @@ int __init acpi_irq_balance_set(char *str)
__setup("acpi_irq_balance", acpi_irq_balance_set);
+/* FIXME: we will remove this interface after all drivers call pci_disable_device */
static struct sysdev_class irqrouter_sysdev_class = {
set_kset_name("irqrouter"),
- .suspend = irqrouter_suspend,
+ .resume = irqrouter_resume,
};
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 893b074e3d1..2c04740c654 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -81,30 +81,32 @@ module_param(bm_history, uint, 0644);
*
* To skip this limit, boot/load with a large max_cstate limit.
*/
-static int no_c2c3(struct dmi_system_id *id)
+static int set_max_cstate(struct dmi_system_id *id)
{
if (max_cstate > ACPI_PROCESSOR_MAX_POWER)
return 0;
- printk(KERN_NOTICE PREFIX "%s detected - C2,C3 disabled."
+ printk(KERN_NOTICE PREFIX "%s detected - limiting to C%ld max_cstate."
" Override with \"processor.max_cstate=%d\"\n", id->ident,
- ACPI_PROCESSOR_MAX_POWER + 1);
+ (long)id->driver_data, ACPI_PROCESSOR_MAX_POWER + 1);
- max_cstate = 1;
+ max_cstate = (long)id->driver_data;
return 0;
}
-
-
static struct dmi_system_id __initdata processor_power_dmi_table[] = {
- { no_c2c3, "IBM ThinkPad R40e", {
+ { set_max_cstate, "IBM ThinkPad R40e", {
DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
- DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }},
- { no_c2c3, "Medion 41700", {
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }, (void*)1},
+ { set_max_cstate, "Medion 41700", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
+ DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J") }, (void*)1},
+ { set_max_cstate, "Clevo 5600D", {
DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
- DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J") }},
+ DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307") },
+ (void*)2},
{},
};
@@ -549,7 +551,8 @@ static int acpi_processor_get_power_info_default_c1 (struct acpi_processor *pr)
ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_default_c1");
for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++)
- memset(pr->power.states, 0, sizeof(struct acpi_processor_cx));
+ memset(&(pr->power.states[i]), 0,
+ sizeof(struct acpi_processor_cx));
/* if info is obtained from pblk/fadt, type equals state */
pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1;
@@ -580,7 +583,8 @@ static int acpi_processor_get_power_info_cst (struct acpi_processor *pr)
pr->power.count = 0;
for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++)
- memset(pr->power.states, 0, sizeof(struct acpi_processor_cx));
+ memset(&(pr->power.states[i]), 0,
+ sizeof(struct acpi_processor_cx));
status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer);
if (ACPI_FAILURE(status)) {
@@ -763,7 +767,6 @@ static void acpi_processor_power_verify_c3(
}
if (pr->flags.bm_check) {
- printk("Disabling BM access before entering C3\n");
/* bus mastering control is necessary */
if (!pr->flags.bm_control) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -771,7 +774,6 @@ static void acpi_processor_power_verify_c3(
return_VOID;
}
} else {
- printk("Invalidating cache before entering C3\n");
/*
* WBINVD should be set in fadt, for C3 state to be
* supported on when bm_check is not required.
@@ -842,7 +844,7 @@ static int acpi_processor_get_power_info (
result = acpi_processor_get_power_info_cst(pr);
if ((result) || (acpi_processor_power_verify(pr) < 2)) {
result = acpi_processor_get_power_info_fadt(pr);
- if (result)
+ if ((result) || (acpi_processor_power_verify(pr) < 2))
result = acpi_processor_get_power_info_default_c1(pr);
}
diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c
index de5746e38af..2435a7c99b2 100644
--- a/drivers/block/cfq-iosched.c
+++ b/drivers/block/cfq-iosched.c
@@ -1281,6 +1281,7 @@ dispatch:
*/
if (!cfq_crq_in_driver(crq) &&
!cfq_cfqq_idle_window(cfqq) &&
+ !blk_barrier_rq(rq) &&
cfqd->rq_in_driver >= cfqd->cfq_max_depth)
return NULL;
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 692a5fced76..3c818544475 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -719,7 +719,7 @@ struct request *blk_queue_find_tag(request_queue_t *q, int tag)
{
struct blk_queue_tag *bqt = q->queue_tags;
- if (unlikely(bqt == NULL || tag >= bqt->max_depth))
+ if (unlikely(bqt == NULL || tag >= bqt->real_max_depth))
return NULL;
return bqt->tag_index[tag];
@@ -798,6 +798,7 @@ init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth)
memset(tag_index, 0, depth * sizeof(struct request *));
memset(tag_map, 0, nr_ulongs * sizeof(unsigned long));
+ tags->real_max_depth = depth;
tags->max_depth = depth;
tags->tag_index = tag_index;
tags->tag_map = tag_map;
@@ -872,11 +873,22 @@ int blk_queue_resize_tags(request_queue_t *q, int new_depth)
return -ENXIO;
/*
+ * if we already have large enough real_max_depth. just
+ * adjust max_depth. *NOTE* as requests with tag value
+ * between new_depth and real_max_depth can be in-flight, tag
+ * map can not be shrunk blindly here.
+ */
+ if (new_depth <= bqt->real_max_depth) {
+ bqt->max_depth = new_depth;
+ return 0;
+ }
+
+ /*
* save the old state info, so we can copy it back
*/
tag_index = bqt->tag_index;
tag_map = bqt->tag_map;
- max_depth = bqt->max_depth;
+ max_depth = bqt->real_max_depth;
if (init_tag_map(q, bqt, new_depth))
return -ENOMEM;
@@ -913,7 +925,7 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq)
BUG_ON(tag == -1);
- if (unlikely(tag >= bqt->max_depth))
+ if (unlikely(tag >= bqt->real_max_depth))
/*
* This can happen after tag depth has been reduced.
* FIXME: how about a warning or info message here?
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index 2771c861f18..f696da6f417 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -367,11 +367,8 @@ static inline void bpa10x_free_urb(struct urb *urb)
if (!urb)
return;
- if (urb->setup_packet)
- kfree(urb->setup_packet);
-
- if (urb->transfer_buffer)
- kfree(urb->transfer_buffer);
+ kfree(urb->setup_packet);
+ kfree(urb->transfer_buffer);
usb_free_urb(urb);
}
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index c0ed213fc85..858fddb046d 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -58,8 +58,6 @@
#ifndef CONFIG_BT_HCIUART_DEBUG
#undef BT_DBG
#define BT_DBG( A... )
-#undef BT_DMP
-#define BT_DMP( A... )
#endif
static int hciextn = 1;
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
index ade94a57bb1..533323b60e6 100644
--- a/drivers/bluetooth/hci_h4.c
+++ b/drivers/bluetooth/hci_h4.c
@@ -57,8 +57,6 @@
#ifndef CONFIG_BT_HCIUART_DEBUG
#undef BT_DBG
#define BT_DBG( A... )
-#undef BT_DMP
-#define BT_DMP( A... )
#endif
/* Initialize protocol */
@@ -125,7 +123,6 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
BT_DBG("len %d room %d", len, room);
if (!len) {
- BT_DMP(h4->rx_skb->data, h4->rx_skb->len);
hci_recv_frame(h4->rx_skb);
} else if (len > room) {
BT_ERR("Data length is too large");
@@ -169,8 +166,6 @@ static int h4_recv(struct hci_uart *hu, void *data, int count)
case H4_W4_DATA:
BT_DBG("Complete data");
- BT_DMP(h4->rx_skb->data, h4->rx_skb->len);
-
hci_recv_frame(h4->rx_skb);
h4->rx_state = H4_W4_PACKET_TYPE;
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index f766bc22c6b..90be2eae52e 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -57,8 +57,6 @@
#ifndef CONFIG_BT_HCIUART_DEBUG
#undef BT_DBG
#define BT_DBG( A... )
-#undef BT_DMP
-#define BT_DMP( A... )
#endif
static int reset = 0;
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index b120ecf7b8c..657719b8254 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -57,8 +57,6 @@
#ifndef CONFIG_BT_HCIUSB_DEBUG
#undef BT_DBG
#define BT_DBG(D...)
-#undef BT_DMP
-#define BT_DMP(D...)
#endif
#ifndef CONFIG_BT_HCIUSB_ZERO_PACKET
@@ -110,6 +108,9 @@ static struct usb_device_id blacklist_ids[] = {
/* Microsoft Wireless Transceiver for Bluetooth 2.0 */
{ USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET },
+ /* Kensington Bluetooth USB adapter */
+ { USB_DEVICE(0x047d, 0x105d), .driver_info = HCI_RESET },
+
/* ISSC Bluetooth Adapter v3.1 */
{ USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET },
@@ -387,10 +388,8 @@ static void hci_usb_unlink_urbs(struct hci_usb *husb)
urb = &_urb->urb;
BT_DBG("%s freeing _urb %p type %d urb %p",
husb->hdev->name, _urb, _urb->type, urb);
- if (urb->setup_packet)
- kfree(urb->setup_packet);
- if (urb->transfer_buffer)
- kfree(urb->transfer_buffer);
+ kfree(urb->setup_packet);
+ kfree(urb->transfer_buffer);
_urb_free(_urb);
}
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 42187381506..850a78c9c4b 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -261,7 +261,11 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
{
- unsigned long long val;
+ unsigned long pfn;
+
+ /* Turn a kernel-virtual address into a physical page frame */
+ pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT;
+
/*
* RED-PEN: on some architectures there is more mapped memory
* than available in mem_map which pfn_valid checks
@@ -269,10 +273,10 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
*
* RED-PEN: vmalloc is not supported right now.
*/
- if (!pfn_valid(vma->vm_pgoff))
+ if (!pfn_valid(pfn))
return -EIO;
- val = (u64)vma->vm_pgoff << PAGE_SHIFT;
- vma->vm_pgoff = __pa(val) >> PAGE_SHIFT;
+
+ vma->vm_pgoff = pfn;
return mmap_mem(file, vma);
}
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index d8f9e94ae47..cd4fe8b1709 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -1209,6 +1209,7 @@ static int rtc_proc_open(struct inode *inode, struct file *file)
void rtc_get_rtc_time(struct rtc_time *rtc_tm)
{
+ unsigned long uip_watchdog = jiffies;
unsigned char ctrl;
#ifdef CONFIG_MACH_DECSTATION
unsigned int real_year;
@@ -1224,8 +1225,10 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
* Once the read clears, read the RTC time (again via ioctl). Easy.
*/
- if (rtc_is_updating() != 0)
- msleep(20);
+ while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100) {
+ barrier();
+ cpu_relax();
+ }
/*
* Only the values that we read from the RTC are set. We leave
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 94a3b3e20bf..79e9832ef1f 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -17,6 +17,8 @@ config TCG_TPM
obtained at: <http://sourceforge.net/projects/trousers>. To
compile this driver as a module, choose M here; the module
will be called tpm. If unsure, say N.
+ Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI_BUS
+ and CONFIG_PNPACPI.
config TCG_NSC
tristate "National Semiconductor TPM Interface"
@@ -36,12 +38,13 @@ config TCG_ATMEL
as a module, choose M here; the module will be called tpm_atmel.
config TCG_INFINEON
- tristate "Infineon Technologies SLD 9630 TPM Interface"
- depends on TCG_TPM
+ tristate "Infineon Technologies TPM Interface"
+ depends on TCG_TPM && PNPACPI
---help---
If you have a TPM security chip from Infineon Technologies
- say Yes and it will be accessible from within Linux. To
- compile this driver as a module, choose M here; the module
+ (either SLD 9630 TT 1.1 or SLB 9635 TT 1.2) say Yes and it
+ will be accessible from within Linux.
+ To compile this driver as a module, choose M here; the module
will be called tpm_infineon.
Further information on this driver and the supported hardware
can be found at http://www.prosec.rub.de/tpm
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
index 0e3241645c1..dc8c540391f 100644
--- a/drivers/char/tpm/tpm_infineon.c
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -1,7 +1,7 @@
/*
* Description:
* Device Driver for the Infineon Technologies
- * SLD 9630 TT Trusted Platform Module
+ * SLD 9630 TT 1.1 and SLB 9635 TT 1.2 Trusted Platform Module
* Specifications at www.trustedcomputinggroup.org
*
* Copyright (C) 2005, Marcel Selhorst <selhorst@crypto.rub.de>
@@ -12,9 +12,10 @@
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
- *
*/
+#include <acpi/acpi_bus.h>
+#include <linux/pnp.h>
#include "tpm.h"
/* Infineon specific definitions */
@@ -26,8 +27,11 @@
#define TPM_MSLEEP_TIME 3
/* gives number of max. msleep()-calls before throwing timeout */
#define TPM_MAX_TRIES 5000
-#define TCPA_INFINEON_DEV_VEN_VALUE 0x15D1
-#define TPM_DATA (TPM_ADDR + 1) & 0xff
+#define TPM_INFINEON_DEV_VEN_VALUE 0x15D1
+
+/* These values will be filled after ACPI-call */
+static int TPM_INF_DATA = 0;
+static int TPM_INF_ADDR = 0;
/* TPM header definitions */
enum infineon_tpm_header {
@@ -305,9 +309,10 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
static void tpm_inf_cancel(struct tpm_chip *chip)
{
- /* Nothing yet!
- This has something to do with the internal functions
- of the TPM. Abort isn't really necessary...
+ /*
+ Since we are using the legacy mode to communicate
+ with the TPM, we have no cancel functions, but have
+ a workaround for interrupting the TPM through WTX.
*/
}
@@ -345,6 +350,32 @@ static struct tpm_vendor_specific tpm_inf = {
.miscdev = {.fops = &inf_ops,},
};
+static const struct pnp_device_id tpm_pnp_tbl[] = {
+ /* Infineon TPMs */
+ {"IFX0101", 0},
+ {"IFX0102", 0},
+ {"", 0}
+};
+
+static int __devinit tpm_inf_acpi_probe(struct pnp_dev *dev,
+ const struct pnp_device_id *dev_id)
+{
+ TPM_INF_ADDR = (pnp_port_start(dev, 0) & 0xff);
+ TPM_INF_DATA = ((TPM_INF_ADDR + 1) & 0xff);
+ tpm_inf.base = pnp_port_start(dev, 1);
+ dev_info(&dev->dev, "Found %s with ID %s\n",
+ dev->name, dev_id->id);
+ if (!((tpm_inf.base >> 8) & 0xff))
+ tpm_inf.base = 0;
+ return 0;
+}
+
+static struct pnp_driver tpm_inf_pnp = {
+ .name = "tpm_inf_pnp",
+ .id_table = tpm_pnp_tbl,
+ .probe = tpm_inf_acpi_probe,
+};
+
static int __devinit tpm_inf_probe(struct pci_dev *pci_dev,
const struct pci_device_id *pci_id)
{
@@ -353,64 +384,99 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev,
int vendorid[2];
int version[2];
int productid[2];
+ char chipname[20];
if (pci_enable_device(pci_dev))
return -EIO;
dev_info(&pci_dev->dev, "LPC-bus found at 0x%x\n", pci_id->device);
+ /* read IO-ports from ACPI */
+ pnp_register_driver(&tpm_inf_pnp);
+ pnp_unregister_driver(&tpm_inf_pnp);
+
+ /* Make sure, we have received valid config ports */
+ if (!TPM_INF_ADDR) {
+ pci_disable_device(pci_dev);
+ return -EIO;
+ }
+
/* query chip for its vendor, its version number a.s.o. */
- outb(ENABLE_REGISTER_PAIR, TPM_ADDR);
- outb(IDVENL, TPM_ADDR);
- vendorid[1] = inb(TPM_DATA);
- outb(IDVENH, TPM_ADDR);
- vendorid[0] = inb(TPM_DATA);
- outb(IDPDL, TPM_ADDR);
- productid[1] = inb(TPM_DATA);
- outb(IDPDH, TPM_ADDR);
- productid[0] = inb(TPM_DATA);
- outb(CHIP_ID1, TPM_ADDR);
- version[1] = inb(TPM_DATA);
- outb(CHIP_ID2, TPM_ADDR);
- version[0] = inb(TPM_DATA);
-
- if ((vendorid[0] << 8 | vendorid[1]) == (TCPA_INFINEON_DEV_VEN_VALUE)) {
-
- /* read IO-ports from TPM */
- outb(IOLIMH, TPM_ADDR);
- ioh = inb(TPM_DATA);
- outb(IOLIML, TPM_ADDR);
- iol = inb(TPM_DATA);
- tpm_inf.base = (ioh << 8) | iol;
+ outb(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
+ outb(IDVENL, TPM_INF_ADDR);
+ vendorid[1] = inb(TPM_INF_DATA);
+ outb(IDVENH, TPM_INF_ADDR);
+ vendorid[0] = inb(TPM_INF_DATA);
+ outb(IDPDL, TPM_INF_ADDR);
+ productid[1] = inb(TPM_INF_DATA);
+ outb(IDPDH, TPM_INF_ADDR);
+ productid[0] = inb(TPM_INF_DATA);
+ outb(CHIP_ID1, TPM_INF_ADDR);
+ version[1] = inb(TPM_INF_DATA);
+ outb(CHIP_ID2, TPM_INF_ADDR);
+ version[0] = inb(TPM_INF_DATA);
+
+ switch ((productid[0] << 8) | productid[1]) {
+ case 6:
+ sprintf(chipname, " (SLD 9630 TT 1.1)");
+ break;
+ case 11:
+ sprintf(chipname, " (SLB 9635 TT 1.2)");
+ break;
+ default:
+ sprintf(chipname, " (unknown chip)");
+ break;
+ }
+ chipname[19] = 0;
+
+ if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) {
if (tpm_inf.base == 0) {
- dev_err(&pci_dev->dev, "No IO-ports set!\n");
+ dev_err(&pci_dev->dev, "No IO-ports found!\n");
pci_disable_device(pci_dev);
- return -ENODEV;
+ return -EIO;
+ }
+ /* configure TPM with IO-ports */
+ outb(IOLIMH, TPM_INF_ADDR);
+ outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA);
+ outb(IOLIML, TPM_INF_ADDR);
+ outb((tpm_inf.base & 0xff), TPM_INF_DATA);
+
+ /* control if IO-ports are set correctly */
+ outb(IOLIMH, TPM_INF_ADDR);
+ ioh = inb(TPM_INF_DATA);
+ outb(IOLIML, TPM_INF_ADDR);
+ iol = inb(TPM_INF_DATA);
+
+ if ((ioh << 8 | iol) != tpm_inf.base) {
+ dev_err(&pci_dev->dev,
+ "Could not set IO-ports to %04x\n",
+ tpm_inf.base);
+ pci_disable_device(pci_dev);
+ return -EIO;
}
/* activate register */
- outb(TPM_DAR, TPM_ADDR);
- outb(0x01, TPM_DATA);
- outb(DISABLE_REGISTER_PAIR, TPM_ADDR);
+ outb(TPM_DAR, TPM_INF_ADDR);
+ outb(0x01, TPM_INF_DATA);
+ outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
/* disable RESET, LP and IRQC */
outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD);
/* Finally, we're done, print some infos */
dev_info(&pci_dev->dev, "TPM found: "
+ "config base 0x%x, "
"io base 0x%x, "
"chip version %02x%02x, "
"vendor id %x%x (Infineon), "
"product id %02x%02x"
"%s\n",
+ TPM_INF_ADDR,
tpm_inf.base,
version[0], version[1],
vendorid[0], vendorid[1],
- productid[0], productid[1], ((productid[0] == 0)
- && (productid[1] ==
- 6)) ?
- " (SLD 9630 TT 1.1)" : "");
+ productid[0], productid[1], chipname);
rc = tpm_register_hardware(pci_dev, &tpm_inf);
if (rc < 0) {
@@ -462,6 +528,6 @@ module_init(init_inf);
module_exit(cleanup_inf);
MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>");
-MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT");
-MODULE_VERSION("1.4");
+MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
+MODULE_VERSION("1.5");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c
index f975dab1ddf..a13395e2c37 100644
--- a/drivers/char/watchdog/i8xx_tco.c
+++ b/drivers/char/watchdog/i8xx_tco.c
@@ -1,5 +1,5 @@
/*
- * i8xx_tco 0.07: TCO timer driver for i8xx chipsets
+ * i8xx_tco: TCO timer driver for i8xx chipsets
*
* (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
* http://www.kernelconcepts.de
@@ -63,6 +63,9 @@
* 20050128 Wim Van Sebroeck <wim@iguana.be>
* 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW
* chipsets. Also added support for the "undocumented" ICH7 chipset.
+ * 20050807 Wim Van Sebroeck <wim@iguana.be>
+ * 0.08 Make sure that the watchdog is only "armed" when started.
+ * (Kernel Bug 4251)
*/
/*
@@ -87,7 +90,7 @@
#include "i8xx_tco.h"
/* Module and version information */
-#define TCO_VERSION "0.07"
+#define TCO_VERSION "0.08"
#define TCO_MODULE_NAME "i8xx TCO timer"
#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION
#define PFX TCO_MODULE_NAME ": "
@@ -125,10 +128,18 @@ static int tco_timer_start (void)
unsigned char val;
spin_lock(&tco_lock);
+
+ /* disable chipset's NO_REBOOT bit */
+ pci_read_config_byte (i8xx_tco_pci, 0xd4, &val);
+ val &= 0xfd;
+ pci_write_config_byte (i8xx_tco_pci, 0xd4, val);
+
+ /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */
val = inb (TCO1_CNT + 1);
val &= 0xf7;
outb (val, TCO1_CNT + 1);
val = inb (TCO1_CNT + 1);
+
spin_unlock(&tco_lock);
if (val & 0x08)
@@ -138,13 +149,20 @@ static int tco_timer_start (void)
static int tco_timer_stop (void)
{
- unsigned char val;
+ unsigned char val, val1;
spin_lock(&tco_lock);
+ /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
val = inb (TCO1_CNT + 1);
val |= 0x08;
outb (val, TCO1_CNT + 1);
val = inb (TCO1_CNT + 1);
+
+ /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
+ pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
+ val1 |= 0x02;
+ pci_write_config_byte (i8xx_tco_pci, 0xd4, val1);
+
spin_unlock(&tco_lock);
if ((val & 0x08) == 0)
@@ -155,6 +173,7 @@ static int tco_timer_stop (void)
static int tco_timer_keepalive (void)
{
spin_lock(&tco_lock);
+ /* Reload the timer by writing to the TCO Timer Reload register */
outb (0x01, TCO1_RLD);
spin_unlock(&tco_lock);
return 0;
@@ -417,9 +436,8 @@ static unsigned char __init i8xx_tco_getdevice (void)
printk (KERN_ERR PFX "failed to get TCOBASE address\n");
return 0;
}
- /*
- * Check chipset's NO_REBOOT bit
- */
+
+ /* Check chipset's NO_REBOOT bit */
pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
if (val1 & 0x02) {
val1 &= 0xfd;
@@ -430,6 +448,10 @@ static unsigned char __init i8xx_tco_getdevice (void)
return 0; /* Cannot reset NO_REBOOT bit */
}
}
+ /* Disable reboots untill the watchdog starts */
+ val1 |= 0x02;
+ pci_write_config_byte (i8xx_tco_pci, 0xd4, val1);
+
/* Set the TCO_EN bit in SMI_EN register */
if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) {
printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
@@ -505,17 +527,10 @@ out:
static void __exit watchdog_cleanup (void)
{
- u8 val;
-
/* Stop the timer before we leave */
if (!nowayout)
tco_timer_stop ();
- /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
- pci_read_config_byte (i8xx_tco_pci, 0xd4, &val);
- val |= 0x02;
- pci_write_config_byte (i8xx_tco_pci, 0xd4, val);
-
/* Deregister */
misc_deregister (&i8xx_tco_miscdev);
unregister_reboot_notifier(&i8xx_tco_notifier);
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c
index 1b2132617dc..fb88b4041dc 100644
--- a/drivers/char/watchdog/sa1100_wdt.c
+++ b/drivers/char/watchdog/sa1100_wdt.c
@@ -36,13 +36,10 @@
#include <asm/uaccess.h>
#define OSCR_FREQ CLOCK_TICK_RATE
-#define SA1100_CLOSE_MAGIC (0x5afc4453)
static unsigned long sa1100wdt_users;
-static int expect_close;
static int pre_margin;
static int boot_status;
-static int nowayout = WATCHDOG_NOWAYOUT;
/*
* Allow only one person to hold it open
@@ -62,55 +59,33 @@ static int sa1100dog_open(struct inode *inode, struct file *file)
}
/*
- * Shut off the timer.
- * Lock it in if it's a module and we defined ...NOWAYOUT
- * Oddly, the watchdog can only be enabled, but we can turn off
- * the interrupt, which appears to prevent the watchdog timing out.
+ * The watchdog cannot be disabled.
+ *
+ * Previous comments suggested that turning off the interrupt by
+ * clearing OIER[E3] would prevent the watchdog timing out but this
+ * does not appear to be true (at least on the PXA255).
*/
static int sa1100dog_release(struct inode *inode, struct file *file)
{
- OSMR3 = OSCR + pre_margin;
-
- if (expect_close == SA1100_CLOSE_MAGIC) {
- OIER &= ~OIER_E3;
- } else {
- printk(KERN_CRIT "WATCHDOG: WDT device closed unexpectedly. WDT will not stop!\n");
- }
+ printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n");
clear_bit(1, &sa1100wdt_users);
- expect_close = 0;
return 0;
}
static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
{
- if (len) {
- if (!nowayout) {
- size_t i;
-
- expect_close = 0;
-
- for (i = 0; i != len; i++) {
- char c;
-
- if (get_user(c, data + i))
- return -EFAULT;
- if (c == 'V')
- expect_close = SA1100_CLOSE_MAGIC;
- }
- }
+ if (len)
/* Refresh OSMR3 timer. */
OSMR3 = OSCR + pre_margin;
- }
return len;
}
static struct watchdog_info ident = {
- .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE |
- WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
- .identity = "SA1100 Watchdog",
+ .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+ .identity = "SA1100/PXA255 Watchdog",
};
static int sa1100dog_ioctl(struct inode *inode, struct file *file,
@@ -172,7 +147,7 @@ static struct file_operations sa1100dog_fops =
static struct miscdevice sa1100dog_miscdev =
{
.minor = WATCHDOG_MINOR,
- .name = "SA1100/PXA2xx watchdog",
+ .name = "watchdog",
.fops = &sa1100dog_fops,
};
@@ -194,7 +169,6 @@ static int __init sa1100dog_init(void)
if (ret == 0)
printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n",
margin);
-
return ret;
}
@@ -212,8 +186,5 @@ MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog");
module_param(margin, int, 0);
MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)");
-module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
-
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c
index 5d961f5e0ca..e4710d1d1f9 100644
--- a/drivers/fc4/fc.c
+++ b/drivers/fc4/fc.c
@@ -1004,8 +1004,8 @@ int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt)
return FAILED;
}
fc->rst_pkt->eh_state = SCSI_STATE_UNUSED;
- return SUCCESS;
#endif
+ return SUCCESS;
}
static int __fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 04adde62a00..9ad3e9262e8 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -382,100 +382,6 @@ static void __exit fsl_i2c_exit(void)
module_init(fsl_i2c_init);
module_exit(fsl_i2c_exit);
-static int fsl_i2c_probe(struct device *device)
-{
- int result = 0;
- struct mpc_i2c *i2c;
- struct platform_device *pdev = to_platform_device(device);
- struct fsl_i2c_platform_data *pdata;
- struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
-
- if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) {
- return -ENOMEM;
- }
- memset(i2c, 0, sizeof(*i2c));
-
- i2c->irq = platform_get_irq(pdev, 0);
- i2c->flags = pdata->device_flags;
- init_waitqueue_head(&i2c->queue);
-
- i2c->base = ioremap((phys_addr_t)r->start, MPC_I2C_REGION);
-
- if (!i2c->base) {
- printk(KERN_ERR "i2c-mpc - failed to map controller\n");
- result = -ENOMEM;
- goto fail_map;
- }
-
- if (i2c->irq != 0)
- if ((result = request_irq(i2c->irq, mpc_i2c_isr,
- SA_SHIRQ, "i2c-mpc", i2c)) < 0) {
- printk(KERN_ERR
- "i2c-mpc - failed to attach interrupt\n");
- goto fail_irq;
- }
-
- mpc_i2c_setclock(i2c);
- dev_set_drvdata(device, i2c);
-
- i2c->adap = mpc_ops;
- i2c_set_adapdata(&i2c->adap, i2c);
- i2c->adap.dev.parent = &pdev->dev;
- if ((result = i2c_add_adapter(&i2c->adap)) < 0) {
- printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
- goto fail_add;
- }
-
- return result;
-
- fail_add:
- if (i2c->irq != 0)
- free_irq(i2c->irq, NULL);
- fail_irq:
- iounmap(i2c->base);
- fail_map:
- kfree(i2c);
- return result;
-};
-
-static int fsl_i2c_remove(struct device *device)
-{
- struct mpc_i2c *i2c = dev_get_drvdata(device);
-
- i2c_del_adapter(&i2c->adap);
- dev_set_drvdata(device, NULL);
-
- if (i2c->irq != 0)
- free_irq(i2c->irq, i2c);
-
- iounmap(i2c->base);
- kfree(i2c);
- return 0;
-};
-
-/* Structure for a device driver */
-static struct device_driver fsl_i2c_driver = {
- .name = "fsl-i2c",
- .bus = &platform_bus_type,
- .probe = fsl_i2c_probe,
- .remove = fsl_i2c_remove,
-};
-
-static int __init fsl_i2c_init(void)
-{
- return driver_register(&fsl_i2c_driver);
-}
-
-static void __exit fsl_i2c_exit(void)
-{
- driver_unregister(&fsl_i2c_driver);
-}
-
-module_init(fsl_i2c_init);
-module_exit(fsl_i2c_exit);
-
MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>");
MODULE_DESCRIPTION
("I2C-Bus adapter for MPC107 bridge and MPC824x/85xx/52xx processors");
diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c
index 1c99536b673..fa503ed9f86 100644
--- a/drivers/i2c/busses/i2c-sibyte.c
+++ b/drivers/i2c/busses/i2c-sibyte.c
@@ -23,8 +23,8 @@
#include <asm/sibyte/sb1250_smbus.h>
static struct i2c_algo_sibyte_data sibyte_board_data[2] = {
- { NULL, 0, (void *) (KSEG1+A_SMB_BASE(0)) },
- { NULL, 1, (void *) (KSEG1+A_SMB_BASE(1)) }
+ { NULL, 0, (void *) (CKSEG1+A_SMB_BASE(0)) },
+ { NULL, 1, (void *) (CKSEG1+A_SMB_BASE(1)) }
};
static struct i2c_adapter sibyte_board_adapter[2] = {
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index f9c1acb4ed6..c9d3a00a3c0 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1220,7 +1220,7 @@ static int ide_disk_probe(struct device *dev)
goto failed;
g = alloc_disk_node(1 << PARTN_BITS,
- pcibus_to_node(drive->hwif->pci_dev->bus));
+ hwif_to_node(drive->hwif));
if (!g)
goto out_free_idkp;
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 7df85af7537..c1128ae5cd2 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -978,8 +978,7 @@ static int ide_init_queue(ide_drive_t *drive)
* do not.
*/
- q = blk_init_queue_node(do_ide_request, &ide_lock,
- pcibus_to_node(drive->hwif->pci_dev->bus));
+ q = blk_init_queue_node(do_ide_request, &ide_lock, hwif_to_node(hwif));
if (!q)
return 1;
@@ -1048,6 +1047,8 @@ static int init_irq (ide_hwif_t *hwif)
BUG_ON(in_interrupt());
BUG_ON(irqs_disabled());
+ BUG_ON(hwif == NULL);
+
down(&ide_cfg_sem);
hwif->hwgroup = NULL;
#if MAX_HWIFS > 1
@@ -1097,7 +1098,7 @@ static int init_irq (ide_hwif_t *hwif)
spin_unlock_irq(&ide_lock);
} else {
hwgroup = kmalloc_node(sizeof(ide_hwgroup_t), GFP_KERNEL,
- pcibus_to_node(hwif->drives[0].hwif->pci_dev->bus));
+ hwif_to_node(hwif->drives[0].hwif));
if (!hwgroup)
goto out_up;
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index 03747439ac9..f1d1ec4e967 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -508,5 +508,5 @@ static void __exit exit_ide_cs(void)
BUG_ON(dev_list != NULL);
}
-module_init(init_ide_cs);
+late_initcall(init_ide_cs);
module_exit(exit_ide_cs);
diff --git a/drivers/infiniband/include/ib_cm.h b/drivers/infiniband/include/ib_cm.h
index e5d74a730a7..da650115e79 100644
--- a/drivers/infiniband/include/ib_cm.h
+++ b/drivers/infiniband/include/ib_cm.h
@@ -169,7 +169,8 @@ enum ib_cm_rej_reason {
IB_CM_REJ_INVALID_ALT_TRAFFIC_CLASS = __constant_htons(21),
IB_CM_REJ_INVALID_ALT_HOP_LIMIT = __constant_htons(22),
IB_CM_REJ_INVALID_ALT_PACKET_RATE = __constant_htons(23),
- IB_CM_REJ_PORT_REDIRECT = __constant_htons(24),
+ IB_CM_REJ_PORT_CM_REDIRECT = __constant_htons(24),
+ IB_CM_REJ_PORT_REDIRECT = __constant_htons(25),
IB_CM_REJ_INVALID_MTU = __constant_htons(26),
IB_CM_REJ_INSUFFICIENT_RESP_RESOURCES = __constant_htons(27),
IB_CM_REJ_CONSUMER_DEFINED = __constant_htons(28),
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 6f60abbaebd..fa00816a3cf 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -600,9 +600,10 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
ipoib_mcast_send(dev, (union ib_gid *) (phdr->hwaddr + 4), skb);
} else {
- /* unicast GID -- should be ARP reply */
+ /* unicast GID -- should be ARP or RARP reply */
- if (be16_to_cpup((u16 *) skb->data) != ETH_P_ARP) {
+ if ((be16_to_cpup((__be16 *) skb->data) != ETH_P_ARP) &&
+ (be16_to_cpup((__be16 *) skb->data) != ETH_P_RARP)) {
ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x "
IPOIB_GID_FMT "\n",
skb->dst ? "neigh" : "dst",
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
index 1ab5f2dc8a2..70f051894a3 100644
--- a/drivers/input/gameport/ns558.c
+++ b/drivers/input/gameport/ns558.c
@@ -275,9 +275,9 @@ static int __init ns558_init(void)
static void __exit ns558_exit(void)
{
- struct ns558 *ns558;
+ struct ns558 *ns558, *safe;
- list_for_each_entry(ns558, &ns558_list, node) {
+ list_for_each_entry_safe(ns558, safe, &ns558_list, node) {
gameport_unregister_port(ns558->gameport);
release_region(ns558->io & ~(ns558->size - 1), ns558->size);
kfree(ns558);
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c
index e0d1b01cc74..386df71eee7 100644
--- a/drivers/isdn/icn/icn.c
+++ b/drivers/isdn/icn/icn.c
@@ -1650,7 +1650,7 @@ static void __exit icn_exit(void)
{
isdn_ctrl cmd;
icn_card *card = cards;
- icn_card *last;
+ icn_card *last, *tmpcard;
int i;
unsigned long flags;
@@ -1670,8 +1670,9 @@ static void __exit icn_exit(void)
for (i = 0; i < ICN_BCH; i++)
icn_free_queue(card, i);
}
- card = card->next;
+ tmpcard = card->next;
spin_unlock_irqrestore(&card->lock, flags);
+ card = tmpcard;
}
card = cards;
cards = NULL;
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 70bca955e0d..41df4cda66e 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -818,8 +818,7 @@ int bitmap_unplug(struct bitmap *bitmap)
return 0;
}
-static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
- unsigned long sectors, int in_sync);
+static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset);
/* * bitmap_init_from_disk -- called at bitmap_create time to initialize
* the in-memory bitmap from the on-disk bitmap -- also, sets up the
* memory mapping of the bitmap file
@@ -828,7 +827,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
* previously kicked from the array, we mark all the bits as
* 1's in order to cause a full resync.
*/
-static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
+static int bitmap_init_from_disk(struct bitmap *bitmap)
{
unsigned long i, chunks, index, oldindex, bit;
struct page *page = NULL, *oldpage = NULL;
@@ -929,8 +928,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
}
if (test_bit(bit, page_address(page))) {
/* if the disk bit is set, set the memory bit */
- bitmap_set_memory_bits(bitmap,
- i << CHUNK_BLOCK_SHIFT(bitmap), 1, in_sync);
+ bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap));
bit_cnt++;
}
}
@@ -1426,35 +1424,53 @@ void bitmap_close_sync(struct bitmap *bitmap)
}
}
-static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
- unsigned long sectors, int in_sync)
+static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset)
{
/* For each chunk covered by any of these sectors, set the
- * counter to 1 and set resync_needed unless in_sync. They should all
+ * counter to 1 and set resync_needed. They should all
* be 0 at this point
*/
- while (sectors) {
- int secs;
- bitmap_counter_t *bmc;
- spin_lock_irq(&bitmap->lock);
- bmc = bitmap_get_counter(bitmap, offset, &secs, 1);
- if (!bmc) {
- spin_unlock_irq(&bitmap->lock);
- return;
- }
- if (! *bmc) {
- struct page *page;
- *bmc = 1 | (in_sync? 0 : NEEDED_MASK);
- bitmap_count_page(bitmap, offset, 1);
- page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
- set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
- }
+
+ int secs;
+ bitmap_counter_t *bmc;
+ spin_lock_irq(&bitmap->lock);
+ bmc = bitmap_get_counter(bitmap, offset, &secs, 1);
+ if (!bmc) {
spin_unlock_irq(&bitmap->lock);
- if (sectors > secs)
- sectors -= secs;
- else
- sectors = 0;
+ return;
+ }
+ if (! *bmc) {
+ struct page *page;
+ *bmc = 1 | NEEDED_MASK;
+ bitmap_count_page(bitmap, offset, 1);
+ page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
+ set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
}
+ spin_unlock_irq(&bitmap->lock);
+
+}
+
+/*
+ * flush out any pending updates
+ */
+void bitmap_flush(mddev_t *mddev)
+{
+ struct bitmap *bitmap = mddev->bitmap;
+ int sleep;
+
+ if (!bitmap) /* there was no bitmap */
+ return;
+
+ /* run the daemon_work three time to ensure everything is flushed
+ * that can be
+ */
+ sleep = bitmap->daemon_sleep;
+ bitmap->daemon_sleep = 0;
+ bitmap_daemon_work(bitmap);
+ bitmap_daemon_work(bitmap);
+ bitmap_daemon_work(bitmap);
+ bitmap->daemon_sleep = sleep;
+ bitmap_update_sb(bitmap);
}
/*
@@ -1565,7 +1581,8 @@ int bitmap_create(mddev_t *mddev)
/* now that we have some pages available, initialize the in-memory
* bitmap from the on-disk bitmap */
- err = bitmap_init_from_disk(bitmap, mddev->recovery_cp == MaxSector);
+ err = bitmap_init_from_disk(bitmap);
+
if (err)
return err;
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 12031c9d3f1..b08df8b9b2c 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -1230,7 +1230,7 @@ static int __init dm_mirror_init(void)
if (r)
return r;
- _kmirrord_wq = create_workqueue("kmirrord");
+ _kmirrord_wq = create_singlethread_workqueue("kmirrord");
if (!_kmirrord_wq) {
DMERR("couldn't start kmirrord");
dm_dirty_log_exit();
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 6580e0fa4a4..480f658db6f 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1798,6 +1798,8 @@ static int do_md_stop(mddev_t * mddev, int ro)
goto out;
mddev->ro = 1;
} else {
+ bitmap_flush(mddev);
+ wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0);
if (mddev->ro)
set_disk_ro(disk, 0);
blk_queue_make_request(mddev->queue, md_fail_request);
@@ -3484,7 +3486,6 @@ static void md_do_sync(mddev_t *mddev)
goto skip;
}
ITERATE_MDDEV(mddev2,tmp) {
- printk(".");
if (mddev2 == mddev)
continue;
if (mddev2->curr_resync &&
@@ -4007,3 +4008,4 @@ EXPORT_SYMBOL(md_wakeup_thread);
EXPORT_SYMBOL(md_print_devices);
EXPORT_SYMBOL(md_check_recovery);
MODULE_LICENSE("GPL");
+MODULE_ALIAS("md");
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index d3a64a04a6d..51d9645ed09 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -893,7 +893,6 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
if (!uptodate) {
md_error(r1_bio->mddev,
conf->mirrors[r1_bio->read_disk].rdev);
- set_bit(R1BIO_Degraded, &r1_bio->state);
} else
set_bit(R1BIO_Uptodate, &r1_bio->state);
rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev);
@@ -918,10 +917,9 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error)
mirror = i;
break;
}
- if (!uptodate) {
+ if (!uptodate)
md_error(mddev, conf->mirrors[mirror].rdev);
- set_bit(R1BIO_Degraded, &r1_bio->state);
- }
+
update_head_pos(mirror, r1_bio);
if (atomic_dec_and_test(&r1_bio->remaining)) {
@@ -1109,6 +1107,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
int i;
int write_targets = 0;
int sync_blocks;
+ int still_degraded = 0;
if (!conf->r1buf_pool)
{
@@ -1137,7 +1136,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
return 0;
}
- if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, mddev->degraded) &&
+ /* before building a request, check if we can skip these blocks..
+ * This call the bitmap_start_sync doesn't actually record anything
+ */
+ if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
!conf->fullsync) {
/* We can skip this block, and probably several more */
*skipped = 1;
@@ -1203,24 +1205,23 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
if (i == disk) {
bio->bi_rw = READ;
bio->bi_end_io = end_sync_read;
- } else if (conf->mirrors[i].rdev &&
- !conf->mirrors[i].rdev->faulty &&
- (!conf->mirrors[i].rdev->in_sync ||
- sector_nr + RESYNC_SECTORS > mddev->recovery_cp)) {
+ } else if (conf->mirrors[i].rdev == NULL ||
+ conf->mirrors[i].rdev->faulty) {
+ still_degraded = 1;
+ continue;
+ } else if (!conf->mirrors[i].rdev->in_sync ||
+ sector_nr + RESYNC_SECTORS > mddev->recovery_cp) {
bio->bi_rw = WRITE;
bio->bi_end_io = end_sync_write;
write_targets ++;
} else
+ /* no need to read or write here */
continue;
bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset;
bio->bi_bdev = conf->mirrors[i].rdev->bdev;
bio->bi_private = r1_bio;
}
- if (write_targets + 1 < conf->raid_disks)
- /* array degraded, can't clear bitmap */
- set_bit(R1BIO_Degraded, &r1_bio->state);
-
if (write_targets == 0) {
/* There is nowhere to write, so all non-sync
* drives must be failed - so we are finished
@@ -1243,7 +1244,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
break;
if (sync_blocks == 0) {
if (!bitmap_start_sync(mddev->bitmap, sector_nr,
- &sync_blocks, mddev->degraded) &&
+ &sync_blocks, still_degraded) &&
!conf->fullsync)
break;
if (sync_blocks < (PAGE_SIZE>>9))
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 4698d5f7957..43f231a467d 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1653,6 +1653,7 @@ static int run (mddev_t *mddev)
/* device size must be a multiple of chunk size */
mddev->size &= ~(mddev->chunk_size/1024 -1);
+ mddev->resync_max_sectors = mddev->size << 1;
if (!conf->chunk_size || conf->chunk_size % 4) {
printk(KERN_ERR "raid5: invalid chunk size %d for %s\n",
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index f5ee1680511..495dee1d1e8 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -1813,6 +1813,7 @@ static int run (mddev_t *mddev)
/* device size must be a multiple of chunk size */
mddev->size &= ~(mddev->chunk_size/1024 -1);
+ mddev->resync_max_sectors = mddev->size << 1;
if (conf->raid_disks < 4) {
printk(KERN_ERR "raid6: not enough configured devices for %s (%d, minimum 4)\n",
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index e83256d0fd1..a50a41f6f79 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -188,7 +188,7 @@ config DVB_BCM3510
support this frontend.
config DVB_LGDT330X
- tristate "LGDT3302 or LGDT3303 based (DViCO FusionHDTV Gold)"
+ tristate "LG Electronics LGDT3302/LGDT3303 based"
depends on DVB_CORE
help
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index 5264310c070..536c35d969b 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -225,6 +225,22 @@ struct dvb_pll_desc dvb_pll_tua6034 = {
};
EXPORT_SYMBOL(dvb_pll_tua6034);
+/* Infineon TUA6034
+ * used in LG Innotek TDVS-H062F
+ */
+struct dvb_pll_desc dvb_pll_tdvs_tua6034 = {
+ .name = "LG/Infineon TUA6034",
+ .min = 54000000,
+ .max = 863000000,
+ .count = 3,
+ .entries = {
+ { 160000000, 44000000, 62500, 0xce, 0x01 },
+ { 455000000, 44000000, 62500, 0xce, 0x02 },
+ { 999999999, 44000000, 62500, 0xce, 0x04 },
+ },
+};
+EXPORT_SYMBOL(dvb_pll_tdvs_tua6034);
+
/* Philips FMD1216ME
* used in Medion Hybrid PCMCIA card and USB Box
*/
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
index cb794759d89..205b2d1a885 100644
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -31,6 +31,7 @@ extern struct dvb_pll_desc dvb_pll_unknown_1;
extern struct dvb_pll_desc dvb_pll_tua6010xs;
extern struct dvb_pll_desc dvb_pll_env57h1xd5;
extern struct dvb_pll_desc dvb_pll_tua6034;
+extern struct dvb_pll_desc dvb_pll_tdvs_tua6034;
extern struct dvb_pll_desc dvb_pll_tda665x;
extern struct dvb_pll_desc dvb_pll_fmd1216me;
extern struct dvb_pll_desc dvb_pll_tded4;
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
index e94dee50eec..1f1cd7a8d50 100644
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ b/drivers/media/dvb/frontends/lgdt330x.c
@@ -1,11 +1,8 @@
/*
- * Support for LGDT3302 & LGDT3303 (DViCO FusionHDTV Gold) - VSB/QAM
+ * Support for LGDT3302 and LGDT3303 - VSB/QAM
*
* Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net>
*
- * Based on code from Kirk Lapray <kirk_lapray@bigfoot.com>
- * Copyright (C) 2005
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -25,11 +22,13 @@
/*
* NOTES ABOUT THIS DRIVER
*
- * This driver supports DViCO FusionHDTV Gold under Linux.
+ * This Linux driver supports:
+ * DViCO FusionHDTV 3 Gold-Q
+ * DViCO FusionHDTV 3 Gold-T
+ * DViCO FusionHDTV 5 Gold
*
* TODO:
- * BER and signal strength always return 0.
- * Include support for LGDT3303
+ * signal strength always returns 0.
*
*/
@@ -41,7 +40,6 @@
#include <asm/byteorder.h>
#include "dvb_frontend.h"
-#include "dvb-pll.h"
#include "lgdt330x_priv.h"
#include "lgdt330x.h"
@@ -70,55 +68,37 @@ struct lgdt330x_state
u32 current_frequency;
};
-static int i2c_writebytes (struct lgdt330x_state* state,
- u8 addr, /* demod_address or pll_address */
+static int i2c_write_demod_bytes (struct lgdt330x_state* state,
u8 *buf, /* data bytes to send */
int len /* number of bytes to send */ )
{
- u8 tmp[] = { buf[0], buf[1] };
struct i2c_msg msg =
- { .addr = addr, .flags = 0, .buf = tmp, .len = 2 };
- int err;
+ { .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = buf,
+ .len = 2 };
int i;
+ int err;
- for (i=1; i<len; i++) {
- tmp[1] = buf[i];
+ for (i=0; i<len-1; i+=2){
if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
- printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err == %i)\n", __FUNCTION__, addr, buf[0], err);
+ printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err);
if (err < 0)
return err;
else
return -EREMOTEIO;
}
- tmp[0]++;
+ msg.buf += 2;
}
return 0;
}
-#if 0
-static int i2c_readbytes (struct lgdt330x_state* state,
- u8 addr, /* demod_address or pll_address */
- u8 *buf, /* holds data bytes read */
- int len /* number of bytes to read */ )
-{
- struct i2c_msg msg =
- { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len };
- int err;
-
- if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
- printk(KERN_WARNING "lgdt330x: %s error (addr %02x, err == %i)\n", __FUNCTION__, addr, err);
- return -EREMOTEIO;
- }
- return 0;
-}
-#endif
-
/*
* This routine writes the register (reg) to the demod bus
* then reads the data returned for (len) bytes.
*/
-static u8 i2c_selectreadbytes (struct lgdt330x_state* state,
+static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
enum I2C_REG reg, u8* buf, int len)
{
u8 wr [] = { reg };
@@ -139,7 +119,7 @@ static u8 i2c_selectreadbytes (struct lgdt330x_state* state,
}
/* Software reset */
-int lgdt330x_SwReset(struct lgdt330x_state* state)
+static int lgdt3302_SwReset(struct lgdt330x_state* state)
{
u8 ret;
u8 reset[] = {
@@ -148,23 +128,51 @@ int lgdt330x_SwReset(struct lgdt330x_state* state)
* bits 5-0 are 1 to mask interrupts */
};
- ret = i2c_writebytes(state,
- state->config->demod_address,
+ ret = i2c_write_demod_bytes(state,
+ reset, sizeof(reset));
+ if (ret == 0) {
+
+ /* force reset high (inactive) and unmask interrupts */
+ reset[1] = 0x7f;
+ ret = i2c_write_demod_bytes(state,
+ reset, sizeof(reset));
+ }
+ return ret;
+}
+
+static int lgdt3303_SwReset(struct lgdt330x_state* state)
+{
+ u8 ret;
+ u8 reset[] = {
+ 0x02,
+ 0x00 /* bit 0 is active low software reset */
+ };
+
+ ret = i2c_write_demod_bytes(state,
reset, sizeof(reset));
if (ret == 0) {
- /* spec says reset takes 100 ns why wait */
- /* mdelay(100); */ /* keep low for 100mS */
- reset[1] = 0x7f; /* force reset high (inactive)
- * and unmask interrupts */
- ret = i2c_writebytes(state,
- state->config->demod_address,
+
+ /* force reset high (inactive) */
+ reset[1] = 0x01;
+ ret = i2c_write_demod_bytes(state,
reset, sizeof(reset));
}
- /* Spec does not indicate a need for this either */
- /*mdelay(5); */ /* wait 5 msec before doing more */
return ret;
}
+static int lgdt330x_SwReset(struct lgdt330x_state* state)
+{
+ switch (state->config->demod_chip) {
+ case LGDT3302:
+ return lgdt3302_SwReset(state);
+ case LGDT3303:
+ return lgdt3303_SwReset(state);
+ default:
+ return -ENODEV;
+ }
+}
+
+
static int lgdt330x_init(struct dvb_frontend* fe)
{
/* Hardware reset is done using gpio[0] of cx23880x chip.
@@ -173,22 +181,98 @@ static int lgdt330x_init(struct dvb_frontend* fe)
* Maybe there needs to be a callable function in cx88-core or
* the caller of this function needs to do it. */
- dprintk("%s entered\n", __FUNCTION__);
- return lgdt330x_SwReset((struct lgdt330x_state*) fe->demodulator_priv);
+ /*
+ * Array of byte pairs <address, value>
+ * to initialize each different chip
+ */
+ static u8 lgdt3302_init_data[] = {
+ /* Use 50MHz parameter values from spec sheet since xtal is 50 */
+ /* Change the value of NCOCTFV[25:0] of carrier
+ recovery center frequency register */
+ VSB_CARRIER_FREQ0, 0x00,
+ VSB_CARRIER_FREQ1, 0x87,
+ VSB_CARRIER_FREQ2, 0x8e,
+ VSB_CARRIER_FREQ3, 0x01,
+ /* Change the TPCLK pin polarity
+ data is valid on falling clock */
+ DEMUX_CONTROL, 0xfb,
+ /* Change the value of IFBW[11:0] of
+ AGC IF/RF loop filter bandwidth register */
+ AGC_RF_BANDWIDTH0, 0x40,
+ AGC_RF_BANDWIDTH1, 0x93,
+ AGC_RF_BANDWIDTH2, 0x00,
+ /* Change the value of bit 6, 'nINAGCBY' and
+ 'NSSEL[1:0] of ACG function control register 2 */
+ AGC_FUNC_CTRL2, 0xc6,
+ /* Change the value of bit 6 'RFFIX'
+ of AGC function control register 3 */
+ AGC_FUNC_CTRL3, 0x40,
+ /* Set the value of 'INLVTHD' register 0x2a/0x2c
+ to 0x7fe */
+ AGC_DELAY0, 0x07,
+ AGC_DELAY2, 0xfe,
+ /* Change the value of IAGCBW[15:8]
+ of inner AGC loop filter bandwith */
+ AGC_LOOP_BANDWIDTH0, 0x08,
+ AGC_LOOP_BANDWIDTH1, 0x9a
+ };
+
+ static u8 lgdt3303_init_data[] = {
+ 0x4c, 0x14
+ };
+
+ struct lgdt330x_state* state = fe->demodulator_priv;
+ char *chip_name;
+ int err;
+
+ switch (state->config->demod_chip) {
+ case LGDT3302:
+ chip_name = "LGDT3302";
+ err = i2c_write_demod_bytes(state, lgdt3302_init_data,
+ sizeof(lgdt3302_init_data));
+ break;
+ case LGDT3303:
+ chip_name = "LGDT3303";
+ err = i2c_write_demod_bytes(state, lgdt3303_init_data,
+ sizeof(lgdt3303_init_data));
+ break;
+ default:
+ chip_name = "undefined";
+ printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
+ err = -ENODEV;
+ }
+ dprintk("%s entered as %s\n", __FUNCTION__, chip_name);
+ if (err < 0)
+ return err;
+ return lgdt330x_SwReset(state);
}
static int lgdt330x_read_ber(struct dvb_frontend* fe, u32* ber)
{
- *ber = 0; /* Dummy out for now */
+ *ber = 0; /* Not supplied by the demod chips */
return 0;
}
static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
- struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+ struct lgdt330x_state* state = fe->demodulator_priv;
+ int err;
u8 buf[2];
- i2c_selectreadbytes(state, PACKET_ERR_COUNTER1, buf, sizeof(buf));
+ switch (state->config->demod_chip) {
+ case LGDT3302:
+ err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
+ buf, sizeof(buf));
+ break;
+ case LGDT3303:
+ err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1,
+ buf, sizeof(buf));
+ break;
+ default:
+ printk(KERN_WARNING
+ "Only LGDT3302 and LGDT3303 are supported chips.\n");
+ err = -ENODEV;
+ }
*ucblocks = (buf[0] << 8) | buf[1];
return 0;
@@ -197,123 +281,113 @@ static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
static int lgdt330x_set_parameters(struct dvb_frontend* fe,
struct dvb_frontend_parameters *param)
{
- struct lgdt330x_state* state =
- (struct lgdt330x_state*) fe->demodulator_priv;
+ /*
+ * Array of byte pairs <address, value>
+ * to initialize 8VSB for lgdt3303 chip 50 MHz IF
+ */
+ static u8 lgdt3303_8vsb_44_data[] = {
+ 0x04, 0x00,
+ 0x0d, 0x40,
+ 0x0e, 0x87,
+ 0x0f, 0x8e,
+ 0x10, 0x01,
+ 0x47, 0x8b };
+
+ /*
+ * Array of byte pairs <address, value>
+ * to initialize QAM for lgdt3303 chip
+ */
+ static u8 lgdt3303_qam_data[] = {
+ 0x04, 0x00,
+ 0x0d, 0x00,
+ 0x0e, 0x00,
+ 0x0f, 0x00,
+ 0x10, 0x00,
+ 0x51, 0x63,
+ 0x47, 0x66,
+ 0x48, 0x66,
+ 0x4d, 0x1a,
+ 0x49, 0x08,
+ 0x4a, 0x9b };
+
+ struct lgdt330x_state* state = fe->demodulator_priv;
- /* Use 50MHz parameter values from spec sheet since xtal is 50 */
static u8 top_ctrl_cfg[] = { TOP_CONTROL, 0x03 };
- static u8 vsb_freq_cfg[] = { VSB_CARRIER_FREQ0, 0x00, 0x87, 0x8e, 0x01 };
- static u8 demux_ctrl_cfg[] = { DEMUX_CONTROL, 0xfb };
- static u8 agc_rf_cfg[] = { AGC_RF_BANDWIDTH0, 0x40, 0x93, 0x00 };
- static u8 agc_ctrl_cfg[] = { AGC_FUNC_CTRL2, 0xc6, 0x40 };
- static u8 agc_delay_cfg[] = { AGC_DELAY0, 0x07, 0x00, 0xfe };
- static u8 agc_loop_cfg[] = { AGC_LOOP_BANDWIDTH0, 0x08, 0x9a };
+ int err;
/* Change only if we are actually changing the modulation */
if (state->current_modulation != param->u.vsb.modulation) {
switch(param->u.vsb.modulation) {
case VSB_8:
dprintk("%s: VSB_8 MODE\n", __FUNCTION__);
- /* Select VSB mode and serial MPEG interface */
- top_ctrl_cfg[1] = 0x07;
+ /* Select VSB mode */
+ top_ctrl_cfg[1] = 0x03;
/* Select ANT connector if supported by card */
if (state->config->pll_rf_set)
state->config->pll_rf_set(fe, 1);
+
+ if (state->config->demod_chip == LGDT3303) {
+ err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data,
+ sizeof(lgdt3303_8vsb_44_data));
+ }
break;
case QAM_64:
dprintk("%s: QAM_64 MODE\n", __FUNCTION__);
- /* Select QAM_64 mode and serial MPEG interface */
- top_ctrl_cfg[1] = 0x04;
+ /* Select QAM_64 mode */
+ top_ctrl_cfg[1] = 0x00;
/* Select CABLE connector if supported by card */
if (state->config->pll_rf_set)
state->config->pll_rf_set(fe, 0);
+
+ if (state->config->demod_chip == LGDT3303) {
+ err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
+ sizeof(lgdt3303_qam_data));
+ }
break;
case QAM_256:
dprintk("%s: QAM_256 MODE\n", __FUNCTION__);
- /* Select QAM_256 mode and serial MPEG interface */
- top_ctrl_cfg[1] = 0x05;
+ /* Select QAM_256 mode */
+ top_ctrl_cfg[1] = 0x01;
/* Select CABLE connector if supported by card */
if (state->config->pll_rf_set)
state->config->pll_rf_set(fe, 0);
+
+ if (state->config->demod_chip == LGDT3303) {
+ err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
+ sizeof(lgdt3303_qam_data));
+ }
break;
default:
printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation);
return -1;
}
- /* Initializations common to all modes */
+ /*
+ * select serial or parallel MPEG harware interface
+ * Serial: 0x04 for LGDT3302 or 0x40 for LGDT3303
+ * Parallel: 0x00
+ */
+ top_ctrl_cfg[1] |= state->config->serial_mpeg;
/* Select the requested mode */
- i2c_writebytes(state, state->config->demod_address,
- top_ctrl_cfg, sizeof(top_ctrl_cfg));
-
- /* Change the value of IFBW[11:0]
- of AGC IF/RF loop filter bandwidth register */
- i2c_writebytes(state, state->config->demod_address,
- agc_rf_cfg, sizeof(agc_rf_cfg));
-
- /* Change the value of bit 6, 'nINAGCBY' and
- 'NSSEL[1:0] of ACG function control register 2 */
- /* Change the value of bit 6 'RFFIX'
- of AGC function control register 3 */
- i2c_writebytes(state, state->config->demod_address,
- agc_ctrl_cfg, sizeof(agc_ctrl_cfg));
-
- /* Change the TPCLK pin polarity
- data is valid on falling clock */
- i2c_writebytes(state, state->config->demod_address,
- demux_ctrl_cfg, sizeof(demux_ctrl_cfg));
-
- /* Change the value of NCOCTFV[25:0] of carrier
- recovery center frequency register */
- i2c_writebytes(state, state->config->demod_address,
- vsb_freq_cfg, sizeof(vsb_freq_cfg));
-
- /* Set the value of 'INLVTHD' register 0x2a/0x2c to 0x7fe */
- i2c_writebytes(state, state->config->demod_address,
- agc_delay_cfg, sizeof(agc_delay_cfg));
-
- /* Change the value of IAGCBW[15:8]
- of inner AGC loop filter bandwith */
- i2c_writebytes(state, state->config->demod_address,
- agc_loop_cfg, sizeof(agc_loop_cfg));
-
+ i2c_write_demod_bytes(state, top_ctrl_cfg,
+ sizeof(top_ctrl_cfg));
state->config->set_ts_params(fe, 0);
state->current_modulation = param->u.vsb.modulation;
}
/* Change only if we are actually changing the channel */
if (state->current_frequency != param->frequency) {
- u8 buf[5];
- struct i2c_msg msg = { .flags = 0, .buf = &buf[1], .len = 4 };
- int err;
-
- state->config->pll_set(fe, param, buf);
- msg.addr = buf[0];
-
- dprintk("%s: tuner at 0x%02x bytes: 0x%02x 0x%02x "
- "0x%02x 0x%02x\n", __FUNCTION__,
- buf[0],buf[1],buf[2],buf[3],buf[4]);
- if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
- printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, buf[0], buf[1], err);
- if (err < 0)
- return err;
- else
- return -EREMOTEIO;
- }
-#if 0
- /* Check the status of the tuner pll */
- i2c_readbytes(state, buf[0], &buf[1], 1);
- dprintk("%s: tuner status byte = 0x%02x\n", __FUNCTION__, buf[1]);
-#endif
- /* Update current frequency */
+ /* Tune to the new frequency */
+ state->config->pll_set(fe, param);
+ /* Keep track of the new frequency */
state->current_frequency = param->frequency;
}
lgdt330x_SwReset(state);
@@ -328,21 +402,15 @@ static int lgdt330x_get_frontend(struct dvb_frontend* fe,
return 0;
}
-static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+ struct lgdt330x_state* state = fe->demodulator_priv;
u8 buf[3];
*status = 0; /* Reset status result */
- /*
- * You must set the Mask bits to 1 in the IRQ_MASK in order
- * to see that status bit in the IRQ_STATUS register.
- * This is done in SwReset();
- */
-
/* AGC status register */
- i2c_selectreadbytes(state, AGC_STATUS, buf, 1);
+ i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
if ((buf[0] & 0x0c) == 0x8){
/* Test signal does not exist flag */
@@ -353,16 +421,15 @@ static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status)
return 0;
}
+ /*
+ * You must set the Mask bits to 1 in the IRQ_MASK in order
+ * to see that status bit in the IRQ_STATUS register.
+ * This is done in SwReset();
+ */
/* signal status */
- i2c_selectreadbytes(state, TOP_CONTROL, buf, sizeof(buf));
+ i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]);
-#if 0
- /* Alternative method to check for a signal */
- /* using the SNR good/bad interrupts. */
- if ((buf[2] & 0x30) == 0x10)
- *status |= FE_HAS_SIGNAL;
-#endif
/* sync status */
if ((buf[2] & 0x03) == 0x01) {
@@ -376,7 +443,7 @@ static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status)
}
/* Carrier Recovery Lock Status Register */
- i2c_selectreadbytes(state, CARRIER_LOCK, buf, 1);
+ i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
switch (state->current_modulation) {
case QAM_256:
@@ -396,13 +463,75 @@ static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status)
return 0;
}
+static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+ struct lgdt330x_state* state = fe->demodulator_priv;
+ int err;
+ u8 buf[3];
+
+ *status = 0; /* Reset status result */
+
+ /* lgdt3303 AGC status register */
+ err = i2c_read_demod_bytes(state, 0x58, buf, 1);
+ if (err < 0)
+ return err;
+
+ dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
+ if ((buf[0] & 0x21) == 0x01){
+ /* Test input signal does not exist flag */
+ /* as well as the AGC lock flag. */
+ *status |= FE_HAS_SIGNAL;
+ } else {
+ /* Without a signal all other status bits are meaningless */
+ return 0;
+ }
+
+ /* Carrier Recovery Lock Status Register */
+ i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
+ dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
+ switch (state->current_modulation) {
+ case QAM_256:
+ case QAM_64:
+ /* Need to undestand why there are 3 lock levels here */
+ if ((buf[0] & 0x07) == 0x07)
+ *status |= FE_HAS_CARRIER;
+ else
+ break;
+ i2c_read_demod_bytes(state, 0x8a, buf, 1);
+ if ((buf[0] & 0x04) == 0x04)
+ *status |= FE_HAS_SYNC;
+ if ((buf[0] & 0x01) == 0x01)
+ *status |= FE_HAS_LOCK;
+ if ((buf[0] & 0x08) == 0x08)
+ *status |= FE_HAS_VITERBI;
+ break;
+ case VSB_8:
+ if ((buf[0] & 0x80) == 0x80)
+ *status |= FE_HAS_CARRIER;
+ else
+ break;
+ i2c_read_demod_bytes(state, 0x38, buf, 1);
+ if ((buf[0] & 0x02) == 0x00)
+ *status |= FE_HAS_SYNC;
+ if ((buf[0] & 0x01) == 0x01) {
+ *status |= FE_HAS_LOCK;
+ *status |= FE_HAS_VITERBI;
+ }
+ break;
+ default:
+ printk("KERN_WARNING lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
+ }
+ return 0;
+}
+
static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
/* not directly available. */
+ *strength = 0;
return 0;
}
-static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr)
+static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
{
#ifdef SNR_IN_DB
/*
@@ -451,7 +580,7 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr)
91, 115, 144, 182, 229, 288, 362, 456, 574, 722,
909, 1144, 1440, 1813, 2282, 2873, 3617, 4553, 5732, 7216,
9084, 11436, 14396, 18124, 22817, 28724, 36161, 45524, 57312, 72151,
- 90833, 114351, 143960, 181235, 228161, 0x040000
+ 90833, 114351, 143960, 181235, 228161, 0x080000
};
static u8 buf[5];/* read data buffer */
@@ -459,8 +588,8 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr)
static u32 snr_db; /* index into SNR_EQ[] */
struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
- /* read both equalizer and pase tracker noise data */
- i2c_selectreadbytes(state, EQPH_ERR0, buf, sizeof(buf));
+ /* read both equalizer and phase tracker noise data */
+ i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
if (state->current_modulation == VSB_8) {
/* Equalizer Mean-Square Error Register for VSB */
@@ -496,19 +625,20 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr)
struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
/* read both equalizer and pase tracker noise data */
- i2c_selectreadbytes(state, EQPH_ERR0, buf, sizeof(buf));
+ i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
if (state->current_modulation == VSB_8) {
- /* Equalizer Mean-Square Error Register for VSB */
- noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
- } else {
- /* Phase Tracker Mean-Square Error Register for QAM */
+ /* Phase Tracker Mean-Square Error Register for VSB */
noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
+ } else {
+
+ /* Carrier Recovery Mean-Square Error for QAM */
+ i2c_read_demod_bytes(state, 0x1a, buf, 2);
+ noise = ((buf[0] & 3) << 8) | buf[1];
}
/* Small values for noise mean signal is better so invert noise */
- /* Noise is 19 bit value so discard 3 LSB*/
- *snr = ~noise>>3;
+ *snr = ~noise;
#endif
dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
@@ -516,6 +646,32 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr)
return 0;
}
+static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+ /* Return the raw noise value */
+ static u8 buf[5];/* read data buffer */
+ static u32 noise; /* noise value */
+ struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+
+ if (state->current_modulation == VSB_8) {
+
+ /* Phase Tracker Mean-Square Error Register for VSB */
+ noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
+ } else {
+
+ /* Carrier Recovery Mean-Square Error for QAM */
+ i2c_read_demod_bytes(state, 0x1a, buf, 2);
+ noise = (buf[0] << 8) | buf[1];
+ }
+
+ /* Small values for noise mean signal is better so invert noise */
+ *snr = ~noise;
+
+ dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
+
+ return 0;
+}
+
static int lgdt330x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
{
/* I have no idea about this - it may not be needed */
@@ -531,7 +687,8 @@ static void lgdt330x_release(struct dvb_frontend* fe)
kfree(state);
}
-static struct dvb_frontend_ops lgdt330x_ops;
+static struct dvb_frontend_ops lgdt3302_ops;
+static struct dvb_frontend_ops lgdt3303_ops;
struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
struct i2c_adapter* i2c)
@@ -548,9 +705,19 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
/* Setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &lgdt330x_ops, sizeof(struct dvb_frontend_ops));
+ switch (config->demod_chip) {
+ case LGDT3302:
+ memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
+ break;
+ case LGDT3303:
+ memcpy(&state->ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
+ break;
+ default:
+ goto error;
+ }
+
/* Verify communication with demod chip */
- if (i2c_selectreadbytes(state, 2, buf, 1))
+ if (i2c_read_demod_bytes(state, 2, buf, 1))
goto error;
state->current_frequency = -1;
@@ -568,9 +735,33 @@ error:
return NULL;
}
-static struct dvb_frontend_ops lgdt330x_ops = {
+static struct dvb_frontend_ops lgdt3302_ops = {
+ .info = {
+ .name= "LG Electronics LGDT3302 VSB/QAM Frontend",
+ .type = FE_ATSC,
+ .frequency_min= 54000000,
+ .frequency_max= 858000000,
+ .frequency_stepsize= 62500,
+ /* Symbol rate is for all VSB modes need to check QAM */
+ .symbol_rate_min = 10762000,
+ .symbol_rate_max = 10762000,
+ .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+ },
+ .init = lgdt330x_init,
+ .set_frontend = lgdt330x_set_parameters,
+ .get_frontend = lgdt330x_get_frontend,
+ .get_tune_settings = lgdt330x_get_tune_settings,
+ .read_status = lgdt3302_read_status,
+ .read_ber = lgdt330x_read_ber,
+ .read_signal_strength = lgdt330x_read_signal_strength,
+ .read_snr = lgdt3302_read_snr,
+ .read_ucblocks = lgdt330x_read_ucblocks,
+ .release = lgdt330x_release,
+};
+
+static struct dvb_frontend_ops lgdt3303_ops = {
.info = {
- .name= "LG Electronics lgdt330x VSB/QAM Frontend",
+ .name= "LG Electronics LGDT3303 VSB/QAM Frontend",
.type = FE_ATSC,
.frequency_min= 54000000,
.frequency_max= 858000000,
@@ -584,15 +775,15 @@ static struct dvb_frontend_ops lgdt330x_ops = {
.set_frontend = lgdt330x_set_parameters,
.get_frontend = lgdt330x_get_frontend,
.get_tune_settings = lgdt330x_get_tune_settings,
- .read_status = lgdt330x_read_status,
+ .read_status = lgdt3303_read_status,
.read_ber = lgdt330x_read_ber,
.read_signal_strength = lgdt330x_read_signal_strength,
- .read_snr = lgdt330x_read_snr,
+ .read_snr = lgdt3303_read_snr,
.read_ucblocks = lgdt330x_read_ucblocks,
.release = lgdt330x_release,
};
-MODULE_DESCRIPTION("lgdt330x [DViCO FusionHDTV 3 Gold] (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
+MODULE_DESCRIPTION("LGDT330X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
MODULE_AUTHOR("Wilson Michaels");
MODULE_LICENSE("GPL");
@@ -601,6 +792,5 @@ EXPORT_SYMBOL(lgdt330x_attach);
/*
* Local variables:
* c-basic-offset: 8
- * compile-command: "make DVB=1"
* End:
*/
diff --git a/drivers/media/dvb/frontends/lgdt330x.h b/drivers/media/dvb/frontends/lgdt330x.h
index 04986f8e756..e209ba1e47c 100644
--- a/drivers/media/dvb/frontends/lgdt330x.h
+++ b/drivers/media/dvb/frontends/lgdt330x.h
@@ -1,5 +1,5 @@
/*
- * Support for LGDT3302 & LGDT3303 (DViCO FustionHDTV Gold) - VSB/QAM
+ * Support for LGDT3302 and LGDT3303 - VSB/QAM
*
* Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net>
*
@@ -24,14 +24,26 @@
#include <linux/dvb/frontend.h>
+typedef enum lg_chip_t {
+ UNDEFINED,
+ LGDT3302,
+ LGDT3303
+}lg_chip_type;
+
struct lgdt330x_config
{
/* The demodulator's i2c address */
u8 demod_address;
+ /* LG demodulator chip LGDT3302 or LGDT3303 */
+ lg_chip_type demod_chip;
+
+ /* MPEG hardware interface - 0:parallel 1:serial */
+ int serial_mpeg;
+
/* PLL interface */
int (*pll_rf_set) (struct dvb_frontend* fe, int index);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pll_address);
+ int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
/* Need to set device param for start_dma */
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
diff --git a/drivers/media/dvb/frontends/lgdt330x_priv.h b/drivers/media/dvb/frontends/lgdt330x_priv.h
index 4143ce8f1a9..59b7c5b9012 100644
--- a/drivers/media/dvb/frontends/lgdt330x_priv.h
+++ b/drivers/media/dvb/frontends/lgdt330x_priv.h
@@ -1,5 +1,5 @@
/*
- * Support for LGDT3302 & LGDT3303 (DViCO FustionHDTV Gold) - VSB/QAM
+ * Support for LGDT3302 and LGDT3303 - VSB/QAM
*
* Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net>
*
@@ -57,8 +57,10 @@ enum I2C_REG {
PH_ERR1= 0x4a,
PH_ERR2= 0x4b,
DEMUX_CONTROL= 0x66,
- PACKET_ERR_COUNTER1= 0x6a,
- PACKET_ERR_COUNTER2= 0x6b,
+ LGDT3302_PACKET_ERR_COUNTER1= 0x6a,
+ LGDT3302_PACKET_ERR_COUNTER2= 0x6b,
+ LGDT3303_PACKET_ERR_COUNTER1= 0x8b,
+ LGDT3303_PACKET_ERR_COUNTER2= 0x8c,
};
#endif /* _LGDT330X_PRIV_ */
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
index 6c52fd0bb7d..a97b9b958ed 100644
--- a/drivers/media/video/bttv-cards.c
+++ b/drivers/media/video/bttv-cards.c
@@ -95,7 +95,7 @@ static int __devinit pvr_boot(struct bttv *btv);
static unsigned int triton1=0;
static unsigned int vsfx=0;
static unsigned int latency = UNSET;
-static unsigned int no_overlay=-1;
+int no_overlay=-1;
static unsigned int card[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
static unsigned int pll[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
@@ -4296,9 +4296,11 @@ void __devinit bttv_check_chipset(void)
printk(KERN_INFO "bttv: Host bridge needs VSFX enabled.\n");
if (pcipci_fail) {
printk(KERN_WARNING "bttv: BT848 and your chipset may not work together.\n");
- if (UNSET == no_overlay) {
- printk(KERN_WARNING "bttv: going to disable overlay.\n");
+ if (!no_overlay) {
+ printk(KERN_WARNING "bttv: overlay will be disabled.\n");
no_overlay = 1;
+ } else {
+ printk(KERN_WARNING "bttv: overlay forced. Use this option at your own risk.\n");
}
}
if (UNSET != latency)
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index 51a0f6d68e7..eee9322ce21 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -1,5 +1,5 @@
/*
- $Id: bttv-driver.c,v 1.42 2005/07/05 17:37:35 nsh Exp $
+ $Id: bttv-driver.c,v 1.52 2005/08/04 00:55:16 mchehab Exp $
bttv - Bt848 frame grabber driver
@@ -80,6 +80,7 @@ static unsigned int irq_iswitch = 0;
static unsigned int uv_ratio = 50;
static unsigned int full_luma_range = 0;
static unsigned int coring = 0;
+extern int no_overlay;
/* API features (turn on/off stuff for testing) */
static unsigned int v4l2 = 1;
@@ -2151,6 +2152,10 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv,
return 0;
}
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ if (no_overlay > 0) {
+ printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+ return -EINVAL;
+ }
return setup_window(fh, btv, &f->fmt.win, 1);
case V4L2_BUF_TYPE_VBI_CAPTURE:
retval = bttv_switch_type(fh,f->type);
@@ -2224,9 +2229,11 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
/* others */
cap->type = VID_TYPE_CAPTURE|
VID_TYPE_TUNER|
- VID_TYPE_OVERLAY|
VID_TYPE_CLIPPING|
VID_TYPE_SCALES;
+ if (no_overlay <= 0)
+ cap->type |= VID_TYPE_OVERLAY;
+
cap->maxwidth = bttv_tvnorms[btv->tvnorm].swidth;
cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight;
cap->minwidth = 48;
@@ -2302,6 +2309,11 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
struct video_window *win = arg;
struct v4l2_window w2;
+ if (no_overlay > 0) {
+ printk ("VIDIOCSWIN: no_overlay\n");
+ return -EINVAL;
+ }
+
w2.field = V4L2_FIELD_ANY;
w2.w.left = win->x;
w2.w.top = win->y;
@@ -2577,10 +2589,12 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
cap->version = BTTV_VERSION_CODE;
cap->capabilities =
V4L2_CAP_VIDEO_CAPTURE |
- V4L2_CAP_VIDEO_OVERLAY |
V4L2_CAP_VBI_CAPTURE |
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING;
+ if (no_overlay <= 0)
+ cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
+
if (bttv_tvcards[btv->c.type].tuner != UNSET &&
bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT)
cap->capabilities |= V4L2_CAP_TUNER;
@@ -3076,7 +3090,7 @@ static struct file_operations bttv_fops =
static struct video_device bttv_video_template =
{
.name = "UNSET",
- .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY|
+ .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|
VID_TYPE_CLIPPING|VID_TYPE_SCALES,
.hardware = VID_HARDWARE_BT848,
.fops = &bttv_fops,
@@ -3756,6 +3770,12 @@ static void bttv_unregister_video(struct bttv *btv)
/* register video4linux devices */
static int __devinit bttv_register_video(struct bttv *btv)
{
+ if (no_overlay <= 0) {
+ bttv_video_template.type |= VID_TYPE_OVERLAY;
+ } else {
+ printk("bttv: Overlay support disabled.\n");
+ }
+
/* video */
btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
if (NULL == btv->video_dev)
@@ -3869,11 +3889,6 @@ static int __devinit bttv_probe(struct pci_dev *dev,
pci_set_master(dev);
pci_set_command(dev);
pci_set_drvdata(dev,btv);
- if (!pci_dma_supported(dev,0xffffffff)) {
- printk("bttv%d: Oops: no 32bit PCI DMA ???\n", btv->c.nr);
- result = -EIO;
- goto fail1;
- }
pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision);
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h
index 191eaf1714b..f2af9e1454f 100644
--- a/drivers/media/video/bttv.h
+++ b/drivers/media/video/bttv.h
@@ -1,5 +1,5 @@
/*
- * $Id: bttv.h,v 1.18 2005/05/24 23:41:42 nsh Exp $
+ * $Id: bttv.h,v 1.22 2005/07/28 18:41:21 mchehab Exp $
*
* bttv - Bt848 frame grabber driver
*
@@ -135,7 +135,9 @@
#define BTTV_DVICO_DVBT_LITE 0x80
#define BTTV_TIBET_CS16 0x83
#define BTTV_KODICOM_4400R 0x84
-#define BTTV_ADLINK_RTV24 0x85
+#define BTTV_ADLINK_RTV24 0x86
+#define BTTV_DVICO_FUSIONHDTV_5_LITE 0x87
+#define BTTV_ACORP_Y878F 0x88
/* i2c address list */
#define I2C_TSA5522 0xc2
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
index f3293e4a15a..aab094bc243 100644
--- a/drivers/media/video/bttvp.h
+++ b/drivers/media/video/bttvp.h
@@ -1,5 +1,5 @@
/*
- $Id: bttvp.h,v 1.19 2005/06/16 21:38:45 nsh Exp $
+ $Id: bttvp.h,v 1.21 2005/07/15 21:44:14 mchehab Exp $
bttv - Bt848 frame grabber driver
@@ -27,7 +27,7 @@
#define _BTTVP_H_
#include <linux/version.h>
-#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,15)
+#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,16)
#include <linux/types.h>
#include <linux/wait.h>
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index 3d0c784b376..ebf02a7f81e 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-cards.c,v 1.86 2005/07/14 03:06:43 mchehab Exp $
+ * $Id: cx88-cards.c,v 1.90 2005/07/28 02:47:42 mkrufky Exp $
*
* device driver for Conexant 2388x based TV cards
* card-specific stuff.
@@ -90,6 +90,9 @@ struct cx88_board cx88_boards[] = {
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
}},
},
[CX88_BOARD_PIXELVIEW] = {
@@ -496,6 +499,9 @@ struct cx88_board cx88_boards[] = {
.input = {{
.type = CX88_VMUX_DVB,
.vmux = 0,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
}},
.dvb = 1,
},
@@ -753,6 +759,27 @@ struct cx88_board cx88_boards[] = {
}},
.dvb = 1,
},
+ [CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD] = {
+ .name = "DViCO FusionHDTV 5 Gold",
+ .tuner_type = TUNER_LG_TDVS_H062F,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ /* See DViCO FusionHDTV 3 Gold-Q for GPIO documentation. */
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0x0f0d,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x0f00,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x0f00,
+ }},
+ },
};
const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
@@ -880,6 +907,10 @@ struct cx88_subid cx88_subids[] = {
.subvendor = 0x153b,
.subdevice = 0x1166,
.card = CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1,
+ },{
+ .subvendor = 0x18ac,
+ .subdevice = 0xd500,
+ .card = CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD,
},
};
const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index ef0e9a85c35..78d223257a6 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-dvb.c,v 1.54 2005/07/25 05:13:50 mkrufky Exp $
+ * $Id: cx88-dvb.c,v 1.58 2005/08/07 09:24:08 mkrufky Exp $
*
* device driver for Conexant 2388x based TV cards
* MPEG Transport Stream (DVB) routines
@@ -208,14 +208,26 @@ static struct or51132_config pchdtv_hd3000 = {
#ifdef HAVE_LGDT330X
static int lgdt330x_pll_set(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params,
- u8* pllbuf)
+ struct dvb_frontend_parameters* params)
{
struct cx8802_dev *dev= fe->dvb->priv;
+ u8 buf[4];
+ struct i2c_msg msg =
+ { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 };
+ int err;
- pllbuf[0] = dev->core->pll_addr;
- dvb_pll_configure(dev->core->pll_desc, &pllbuf[1],
- params->frequency, 0);
+ dvb_pll_configure(dev->core->pll_desc, buf, params->frequency, 0);
+ dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
+ __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
+ if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
+ printk(KERN_WARNING "cx88-dvb: %s error "
+ "(addr %02x <- %02x, err = %i)\n",
+ __FUNCTION__, buf[0], buf[1], err);
+ if (err < 0)
+ return err;
+ else
+ return -EREMOTEIO;
+ }
return 0;
}
@@ -244,6 +256,8 @@ static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
static struct lgdt330x_config fusionhdtv_3_gold = {
.demod_address = 0x0e,
+ .demod_chip = LGDT3302,
+ .serial_mpeg = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */
.pll_set = lgdt330x_pll_set,
.set_ts_params = lgdt330x_set_ts_param,
};
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 5588a3aeecb..5f58c103198 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-video.c,v 1.80 2005/07/13 08:49:08 mchehab Exp $
+ * $Id: cx88-video.c,v 1.82 2005/07/22 05:13:34 mkrufky Exp $
*
* device driver for Conexant 2388x based TV cards
* video4linux video interface
@@ -758,10 +758,10 @@ static int video_open(struct inode *inode, struct file *file)
struct cx88_core *core = dev->core;
int board = core->board;
dprintk(1,"video_open: setting radio device\n");
+ cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3);
cx_write(MO_GP0_IO, cx88_boards[board].radio.gpio0);
cx_write(MO_GP1_IO, cx88_boards[board].radio.gpio1);
cx_write(MO_GP2_IO, cx88_boards[board].radio.gpio2);
- cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3);
dev->core->tvaudio = WW_FM;
cx88_set_tvaudio(core);
cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index b008f7db6df..da65dc92787 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -1,5 +1,5 @@
/*
- * $Id: cx88.h,v 1.69 2005/07/13 17:25:25 mchehab Exp $
+ * $Id: cx88.h,v 1.70 2005/07/24 17:44:09 mkrufky Exp $
*
* v4l2 device driver for cx2388x based TV cards
*
@@ -171,6 +171,7 @@ extern struct sram_channel cx88_sram_channels[];
#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T 28
#define CX88_BOARD_ADSTECH_DVB_T_PCI 29
#define CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1 30
+#define CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD 31
enum cx88_itype {
CX88_VMUX_COMPOSITE1 = 1,
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
index 6239254db27..62f1b8ddb98 100644
--- a/drivers/media/video/msp3400.c
+++ b/drivers/media/video/msp3400.c
@@ -741,11 +741,9 @@ static int msp34xx_sleep(struct msp3400c *msp, int timeout)
schedule_timeout(msecs_to_jiffies(timeout));
}
}
- if (current->flags & PF_FREEZE) {
- refrigerator ();
- }
remove_wait_queue(&msp->wq, &wait);
+ try_to_freeze();
return msp->restart;
}
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index 93dd6197854..1203b93a572 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-i2c.c,v 1.19 2005/07/07 01:49:30 mkrufky Exp $
+ * $Id: saa7134-i2c.c,v 1.22 2005/07/22 04:09:41 mkrufky Exp $
*
* device driver for philips saa7134 based TV cards
* i2c interface support
@@ -300,6 +300,8 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
status = i2c_get_status(dev);
if (i2c_is_error(status))
goto err;
+ /* ensure that the bus is idle for at least one bit slot */
+ msleep(1);
d1printk("\n");
return num;
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 6836c07794f..2af0cb2a731 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134.h,v 1.48 2005/07/01 08:22:24 nsh Exp $
+ * $Id: saa7134.h,v 1.49 2005/07/13 17:25:25 mchehab Exp $
*
* v4l2 device driver for philips saa7134 based TV cards
*
@@ -21,7 +21,7 @@
*/
#include <linux/version.h>
-#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,13)
+#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,14)
#include <linux/pci.h>
#include <linux/i2c.h>
diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c
index 4d27ac1b7fb..cebcc1fa68d 100644
--- a/drivers/media/video/tea5767.c
+++ b/drivers/media/video/tea5767.c
@@ -2,7 +2,7 @@
* For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview
* I2C address is allways 0xC0.
*
- * $Id: tea5767.c,v 1.21 2005/07/14 03:06:43 mchehab Exp $
+ * $Id: tea5767.c,v 1.27 2005/07/31 12:10:56 mchehab Exp $
*
* Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br)
* This code is placed under the terms of the GNU General Public License
@@ -15,7 +15,6 @@
#include <linux/videodev.h>
#include <linux/delay.h>
#include <media/tuner.h>
-#include <media/tuner.h>
#define PREFIX "TEA5767 "
@@ -293,16 +292,16 @@ static int tea5767_stereo(struct i2c_client *c)
int tea5767_autodetection(struct i2c_client *c)
{
- unsigned char buffer[5] = { 0xff, 0xff, 0xff, 0xff, 0xff };
+ unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
int rc;
struct tuner *t = i2c_get_clientdata(c);
- if (5 != (rc = i2c_master_recv(c, buffer, 5))) {
+ if (7 != (rc = i2c_master_recv(c, buffer, 7))) {
tuner_warn("It is not a TEA5767. Received %i bytes.\n", rc);
return EINVAL;
}
- /* If all bytes are the same then it's a TV tuner and not a tea5767 chip. */
+ /* If all bytes are the same then it's a TV tuner and not a tea5767 */
if (buffer[0] == buffer[1] && buffer[0] == buffer[2] &&
buffer[0] == buffer[3] && buffer[0] == buffer[4]) {
tuner_warn("All bytes are equal. It is not a TEA5767\n");
@@ -318,6 +317,17 @@ int tea5767_autodetection(struct i2c_client *c)
tuner_warn("Chip ID is not zero. It is not a TEA5767\n");
return EINVAL;
}
+ /* It seems that tea5767 returns 0xff after the 5th byte */
+ if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
+ tuner_warn("Returned more than 5 bytes. It is not a TEA5767\n");
+ return EINVAL;
+ }
+
+ /* It seems that tea5767 returns 0xff after the 5th byte */
+ if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
+ tuner_warn("Returned more than 5 bytes. It is not a TEA5767\n");
+ return EINVAL;
+ }
tuner_warn("TEA5767 detected.\n");
return 0;
@@ -327,10 +337,8 @@ int tea5767_tuner_init(struct i2c_client *c)
{
struct tuner *t = i2c_get_clientdata(c);
- if (tea5767_autodetection(c) == EINVAL)
- return EINVAL;
-
- tuner_info("type set to %d (%s)\n", t->type, "Philips TEA5767HN FM Radio");
+ tuner_info("type set to %d (%s)\n", t->type,
+ "Philips TEA5767HN FM Radio");
strlcpy(c->name, "tea5767", sizeof(c->name));
t->tv_freq = set_tv_freq;
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index b25a9c08ac0..f0a579827a2 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -1,5 +1,5 @@
/*
- * $Id: tuner-core.c,v 1.58 2005/07/14 03:06:43 mchehab Exp $
+ * $Id: tuner-core.c,v 1.63 2005/07/28 18:19:55 mchehab Exp $
*
* i2c tv tuner chip device driver
* core core, i.e. kernel interfaces, registering and so on
@@ -23,6 +23,8 @@
#include <media/tuner.h>
#include <media/audiochip.h>
+#include "msp3400.h"
+
#define UNSET (-1U)
/* standard i2c insmod options */
@@ -42,6 +44,9 @@ module_param(addr, int, 0444);
static unsigned int no_autodetect = 0;
module_param(no_autodetect, int, 0444);
+static unsigned int show_i2c = 0;
+module_param(show_i2c, int, 0444);
+
/* insmod options used at runtime => read/write */
unsigned int tuner_debug = 0;
module_param(tuner_debug, int, 0644);
@@ -320,6 +325,17 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name);
+ if (show_i2c) {
+ unsigned char buffer[16];
+ int i,rc;
+
+ memset(buffer, 0, sizeof(buffer));
+ rc = i2c_master_recv(&t->i2c, buffer, sizeof(buffer));
+ printk("tuner-%04x I2C RECV = ",addr);
+ for (i=0;i<rc;i++)
+ printk("%02x ",buffer[i]);
+ printk("\n");
+ }
/* TEA5767 autodetection code - only for addr = 0xc0 */
if (!no_autodetect) {
if (addr == 0x60) {
@@ -451,6 +467,17 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
break;
}
break;
+ case VIDIOCSAUDIO:
+ if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
+ return 0;
+ if (check_v4l2(t) == EINVAL)
+ return 0;
+
+ /* Should be implemented, since bttv calls it */
+ tuner_dbg("VIDIOCSAUDIO not implemented.\n");
+
+ break;
+ case MSP_SET_MATRIX:
case TDA9887_SET_CONFIG:
break;
/* --- v4l ioctls --- */
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
index a3f8e83f531..de0c93aeb75 100644
--- a/drivers/media/video/tuner-simple.c
+++ b/drivers/media/video/tuner-simple.c
@@ -1,5 +1,5 @@
/*
- * $Id: tuner-simple.c,v 1.39 2005/07/07 01:49:30 mkrufky Exp $
+ * $Id: tuner-simple.c,v 1.43 2005/07/28 18:41:21 mchehab Exp $
*
* i2c tv tuner chip device driver
* controls all those simple 4-control-bytes style tuners.
@@ -245,6 +245,12 @@ static struct tunertype tuners[] = {
/* see tea5767.c for details */},
{ "Philips FMD1216ME MK3 Hybrid Tuner", Philips, PAL,
16*160.00,16*442.00,0x51,0x52,0x54,0x86,623 },
+
+ { "LG TDVS-H062F/TUA6034", LGINNOTEK, NTSC,
+ 16*160.00,16*455.00,0x01,0x02,0x04,0x8e,732},
+
+ { "Ymec TVF66T5-B/DFF", Philips, PAL,
+ 16*160.25,16*464.25,0x01,0x02,0x08,0x8e,623},
};
unsigned const int tuner_count = ARRAY_SIZE(tuners);
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index 62b03ef091e..127ec38ebd6 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -189,7 +189,7 @@ hauppauge_tuner[] =
{ TUNER_ABSENT, "Philips FQ1236 MK3"},
{ TUNER_ABSENT, "Samsung TCPN 2121P30A"},
{ TUNER_ABSENT, "Samsung TCPE 4121P30A"},
- { TUNER_ABSENT, "TCL MFPE05 2"},
+ { TUNER_PHILIPS_FM1216ME_MK3, "TCL MFPE05 2"},
/* 90-99 */
{ TUNER_ABSENT, "LG TALN H202T"},
{ TUNER_PHILIPS_FQ1216AME_MK4, "Philips FQ1216AME MK4"},
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig
index 06e8eb19a05..43a942a29c2 100644
--- a/drivers/message/i2o/Kconfig
+++ b/drivers/message/i2o/Kconfig
@@ -53,6 +53,9 @@ config I2O_CONFIG
To compile this support as a module, choose M here: the
module will be called i2o_config.
+ Note: If you want to use the new API you have to download the
+ i2o_config patch from http://i2o.shadowconnect.com/
+
config I2O_CONFIG_OLD_IOCTL
bool "Enable ioctls (OBSOLETE)"
depends on I2O_CONFIG
diff --git a/drivers/message/i2o/config-osm.c b/drivers/message/i2o/config-osm.c
index fe2e7afc9ea..af32ab4e90c 100644
--- a/drivers/message/i2o/config-osm.c
+++ b/drivers/message/i2o/config-osm.c
@@ -30,503 +30,9 @@
static struct i2o_driver i2o_config_driver;
-/* Special file operations for sysfs */
-struct fops_attribute {
- struct bin_attribute bin;
- struct file_operations fops;
-};
-
-/**
- * sysfs_read_dummy
- */
-static ssize_t sysfs_read_dummy(struct kobject *kobj, char *buf, loff_t offset,
- size_t count)
-{
- return 0;
-};
-
-/**
- * sysfs_write_dummy
- */
-static ssize_t sysfs_write_dummy(struct kobject *kobj, char *buf, loff_t offset,
- size_t count)
-{
- return 0;
-};
-
-/**
- * sysfs_create_fops_file - Creates attribute with special file operations
- * @kobj: kobject which should contains the attribute
- * @attr: attributes which should be used to create file
- *
- * First creates attribute @attr in kobject @kobj. If it is the first time
- * this function is called, merge old fops from sysfs with new one and
- * write it back. Afterwords the new fops will be set for the created
- * attribute.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int sysfs_create_fops_file(struct kobject *kobj,
- struct fops_attribute *attr)
-{
- struct file_operations tmp, *fops;
- struct dentry *d;
- struct qstr qstr;
- int rc;
-
- fops = &attr->fops;
-
- if (fops->read)
- attr->bin.read = sysfs_read_dummy;
-
- if (fops->write)
- attr->bin.write = sysfs_write_dummy;
-
- if ((rc = sysfs_create_bin_file(kobj, &attr->bin)))
- return rc;
-
- qstr.name = attr->bin.attr.name;
- qstr.len = strlen(qstr.name);
- qstr.hash = full_name_hash(qstr.name, qstr.len);
-
- if ((d = lookup_hash(&qstr, kobj->dentry))) {
- if (!fops->owner) {
- memcpy(&tmp, d->d_inode->i_fop, sizeof(tmp));
- if (fops->read)
- tmp.read = fops->read;
- if (fops->write)
- tmp.write = fops->write;
- memcpy(fops, &tmp, sizeof(tmp));
- }
-
- d->d_inode->i_fop = fops;
- } else
- sysfs_remove_bin_file(kobj, &attr->bin);
-
- return -ENOENT;
-};
-
-/**
- * sysfs_remove_fops_file - Remove attribute with special file operations
- * @kobj: kobject which contains the attribute
- * @attr: attributes which are used to create file
- *
- * Only wrapper arround sysfs_remove_bin_file()
- *
- * Returns 0 on success or negative error code on failure.
- */
-static inline int sysfs_remove_fops_file(struct kobject *kobj,
- struct fops_attribute *attr)
-{
- return sysfs_remove_bin_file(kobj, &attr->bin);
-};
-
-/**
- * i2o_config_read_hrt - Returns the HRT of the controller
- * @kob: kernel object handle
- * @buf: buffer into which the HRT should be copied
- * @off: file offset
- * @count: number of bytes to read
- *
- * Put @count bytes starting at @off into @buf from the HRT of the I2O
- * controller corresponding to @kobj.
- *
- * Returns number of bytes copied into buffer.
- */
-static ssize_t i2o_config_read_hrt(struct kobject *kobj, char *buf,
- loff_t offset, size_t count)
-{
- struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
- i2o_hrt *hrt = c->hrt.virt;
-
- u32 size = (hrt->num_entries * hrt->entry_len + 2) * 4;
-
- if (offset > size)
- return 0;
-
- if (offset + count > size)
- count = size - offset;
-
- memcpy(buf, (u8 *) hrt + offset, count);
-
- return count;
-};
-
-/**
- * i2o_config_read_lct - Returns the LCT of the controller
- * @kob: kernel object handle
- * @buf: buffer into which the LCT should be copied
- * @off: file offset
- * @count: number of bytes to read
- *
- * Put @count bytes starting at @off into @buf from the LCT of the I2O
- * controller corresponding to @kobj.
- *
- * Returns number of bytes copied into buffer.
- */
-static ssize_t i2o_config_read_lct(struct kobject *kobj, char *buf,
- loff_t offset, size_t count)
-{
- struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
- u32 size = c->lct->table_size * 4;
-
- if (offset > size)
- return 0;
-
- if (offset + count > size)
- count = size - offset;
-
- memcpy(buf, (u8 *) c->lct + offset, count);
-
- return count;
-};
-
-#define I2O_CONFIG_SW_ATTR(_name,_mode,_type,_swid) \
-static ssize_t i2o_config_##_name##_read(struct file *file, char __user *buf, size_t count, loff_t * offset) { \
- return i2o_config_sw_read(file, buf, count, offset, _type, _swid); \
-};\
-\
-static ssize_t i2o_config_##_name##_write(struct file *file, const char __user *buf, size_t count, loff_t * offset) { \
- return i2o_config_sw_write(file, buf, count, offset, _type, _swid); \
-}; \
-\
-static struct fops_attribute i2o_config_attr_##_name = { \
- .bin = { .attr = { .name = __stringify(_name), .mode = _mode, \
- .owner = THIS_MODULE }, \
- .size = 0, }, \
- .fops = { .write = i2o_config_##_name##_write, \
- .read = i2o_config_##_name##_read} \
-};
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-
-/**
- * i2o_config_dpt_reagion - Converts type and id to flash region
- * @swtype: type of software module reading
- * @swid: id of software which should be read
- *
- * Converts type and id from I2O spec to the matching region for DPT /
- * Adaptec controllers.
- *
- * Returns region which match type and id or -1 on error.
- */
-static u32 i2o_config_dpt_region(u8 swtype, u8 swid)
-{
- switch (swtype) {
- case I2O_SOFTWARE_MODULE_IRTOS:
- /*
- * content: operation firmware
- * region size:
- * 0xbc000 for 2554, 3754, 2564, 3757
- * 0x170000 for 2865
- * 0x17c000 for 3966
- */
- if (!swid)
- return 0;
-
- break;
-
- case I2O_SOFTWARE_MODULE_IOP_PRIVATE:
- /*
- * content: BIOS and SMOR
- * BIOS size: first 0x8000 bytes
- * region size:
- * 0x40000 for 2554, 3754, 2564, 3757
- * 0x80000 for 2865, 3966
- */
- if (!swid)
- return 1;
-
- break;
-
- case I2O_SOFTWARE_MODULE_IOP_CONFIG:
- switch (swid) {
- case 0:
- /*
- * content: NVRAM defaults
- * region size: 0x2000 bytes
- */
- return 2;
- case 1:
- /*
- * content: serial number
- * region size: 0x2000 bytes
- */
- return 3;
- }
- break;
- }
-
- return -1;
-};
-
-#endif
-
-/**
- * i2o_config_sw_read - Read a software module from controller
- * @file: file pointer
- * @buf: buffer into which the data should be copied
- * @count: number of bytes to read
- * @off: file offset
- * @swtype: type of software module reading
- * @swid: id of software which should be read
- *
- * Transfers @count bytes at offset @offset from IOP into buffer using
- * type @swtype and id @swid as described in I2O spec.
- *
- * Returns number of bytes copied into buffer or error code on failure.
- */
-static ssize_t i2o_config_sw_read(struct file *file, char __user * buf,
- size_t count, loff_t * offset, u8 swtype,
- u32 swid)
-{
- struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata;
- struct kobject *kobj = sd->s_element;
- struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
- u32 m, function = I2O_CMD_SW_UPLOAD;
- struct i2o_dma buffer;
- struct i2o_message __iomem *msg;
- u32 __iomem *mptr;
- int rc, status;
-
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
-
- mptr = &msg->body[3];
-
- if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) {
- i2o_msg_nop(c, m);
- return rc;
- }
-#ifdef CONFIG_I2O_EXT_ADAPTEC
- if (c->adaptec) {
- mptr = &msg->body[4];
- function = I2O_CMD_PRIVATE;
-
- writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]);
-
- writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_READ,
- &msg->body[0]);
- writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]);
- writel(*offset, &msg->body[2]);
- writel(count, &msg->body[3]);
- } else
-#endif
- writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
-
- writel(0xD0000000 | count, mptr++);
- writel(buffer.phys, mptr);
-
- writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(0, &msg->u.head[3]);
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
- if (!c->adaptec)
-#endif
- {
- writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]);
- writel(0, &msg->body[1]);
- writel(swid, &msg->body[2]);
- }
-
- status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
-
- if (status == I2O_POST_WAIT_OK) {
- if (!(rc = copy_to_user(buf, buffer.virt, count))) {
- rc = count;
- *offset += count;
- }
- } else
- rc = -EIO;
-
- if (status != -ETIMEDOUT)
- i2o_dma_free(&c->pdev->dev, &buffer);
-
- return rc;
-};
-
-/**
- * i2o_config_sw_write - Write a software module to controller
- * @file: file pointer
- * @buf: buffer into which the data should be copied
- * @count: number of bytes to read
- * @off: file offset
- * @swtype: type of software module writing
- * @swid: id of software which should be written
- *
- * Transfers @count bytes at offset @offset from buffer to IOP using
- * type @swtype and id @swid as described in I2O spec.
- *
- * Returns number of bytes copied from buffer or error code on failure.
- */
-static ssize_t i2o_config_sw_write(struct file *file, const char __user * buf,
- size_t count, loff_t * offset, u8 swtype,
- u32 swid)
-{
- struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata;
- struct kobject *kobj = sd->s_element;
- struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
- u32 m, function = I2O_CMD_SW_DOWNLOAD;
- struct i2o_dma buffer;
- struct i2o_message __iomem *msg;
- u32 __iomem *mptr;
- int rc, status;
-
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
-
- mptr = &msg->body[3];
-
- if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL)))
- goto nop_msg;
-
- if ((rc = copy_from_user(buffer.virt, buf, count)))
- goto free_buffer;
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
- if (c->adaptec) {
- mptr = &msg->body[4];
- function = I2O_CMD_PRIVATE;
-
- writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]);
-
- writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_WRITE,
- &msg->body[0]);
- writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]);
- writel(*offset, &msg->body[2]);
- writel(count, &msg->body[3]);
- } else
-#endif
- writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
-
- writel(0xD4000000 | count, mptr++);
- writel(buffer.phys, mptr);
-
- writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(0, &msg->u.head[3]);
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
- if (!c->adaptec)
-#endif
- {
- writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]);
- writel(0, &msg->body[1]);
- writel(swid, &msg->body[2]);
- }
-
- status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
-
- if (status != -ETIMEDOUT)
- i2o_dma_free(&c->pdev->dev, &buffer);
-
- if (status != I2O_POST_WAIT_OK)
- return -EIO;
-
- *offset += count;
-
- return count;
-
- free_buffer:
- i2o_dma_free(&c->pdev->dev, &buffer);
-
- nop_msg:
- i2o_msg_nop(c, m);
-
- return rc;
-};
-
-/* attribute for HRT in sysfs */
-static struct bin_attribute i2o_config_hrt_attr = {
- .attr = {
- .name = "hrt",
- .mode = S_IRUGO,
- .owner = THIS_MODULE},
- .size = 0,
- .read = i2o_config_read_hrt
-};
-
-/* attribute for LCT in sysfs */
-static struct bin_attribute i2o_config_lct_attr = {
- .attr = {
- .name = "lct",
- .mode = S_IRUGO,
- .owner = THIS_MODULE},
- .size = 0,
- .read = i2o_config_read_lct
-};
-
-/* IRTOS firmware access */
-I2O_CONFIG_SW_ATTR(irtos, S_IWRSR, I2O_SOFTWARE_MODULE_IRTOS, 0);
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-
-/*
- * attribute for BIOS / SMOR, nvram and serial number access on DPT / Adaptec
- * controllers
- */
-I2O_CONFIG_SW_ATTR(bios, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_PRIVATE, 0);
-I2O_CONFIG_SW_ATTR(nvram, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 0);
-I2O_CONFIG_SW_ATTR(serial, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 1);
-
-#endif
-
-/**
- * i2o_config_notify_controller_add - Notify of added controller
- * @c: the controller which was added
- *
- * If a I2O controller is added, we catch the notification to add sysfs
- * entries.
- */
-static void i2o_config_notify_controller_add(struct i2o_controller *c)
-{
- struct kobject *kobj = &c->exec->device.kobj;
-
- sysfs_create_bin_file(kobj, &i2o_config_hrt_attr);
- sysfs_create_bin_file(kobj, &i2o_config_lct_attr);
-
- sysfs_create_fops_file(kobj, &i2o_config_attr_irtos);
-#ifdef CONFIG_I2O_EXT_ADAPTEC
- if (c->adaptec) {
- sysfs_create_fops_file(kobj, &i2o_config_attr_bios);
- sysfs_create_fops_file(kobj, &i2o_config_attr_nvram);
- sysfs_create_fops_file(kobj, &i2o_config_attr_serial);
- }
-#endif
-};
-
-/**
- * i2o_config_notify_controller_remove - Notify of removed controller
- * @c: the controller which was removed
- *
- * If a I2O controller is removed, we catch the notification to remove the
- * sysfs entries.
- */
-static void i2o_config_notify_controller_remove(struct i2o_controller *c)
-{
- struct kobject *kobj = &c->exec->device.kobj;
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
- if (c->adaptec) {
- sysfs_remove_fops_file(kobj, &i2o_config_attr_serial);
- sysfs_remove_fops_file(kobj, &i2o_config_attr_nvram);
- sysfs_remove_fops_file(kobj, &i2o_config_attr_bios);
- }
-#endif
- sysfs_remove_fops_file(kobj, &i2o_config_attr_irtos);
-
- sysfs_remove_bin_file(kobj, &i2o_config_lct_attr);
- sysfs_remove_bin_file(kobj, &i2o_config_hrt_attr);
-};
-
/* Config OSM driver struct */
static struct i2o_driver i2o_config_driver = {
.name = OSM_NAME,
- .notify_controller_add = i2o_config_notify_controller_add,
- .notify_controller_remove = i2o_config_notify_controller_remove
};
#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index 7a60fd7be8a..66c03e88257 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -32,6 +32,8 @@
#include <linux/i2o.h>
#include "core.h"
+#define OSM_DESCRIPTION "I2O-subsystem"
+
/* PCI device id table for all I2O controllers */
static struct pci_device_id __devinitdata i2o_pci_ids[] = {
{PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)},
@@ -66,6 +68,8 @@ static void i2o_pci_free(struct i2o_controller *c)
if (c->base.virt)
iounmap(c->base.virt);
+
+ pci_release_regions(c->pdev);
}
/**
@@ -84,6 +88,11 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
struct device *dev = &pdev->dev;
int i;
+ if (pci_request_regions(pdev, OSM_DESCRIPTION)) {
+ printk(KERN_ERR "%s: device already claimed\n", c->name);
+ return -ENODEV;
+ }
+
for (i = 0; i < 6; i++) {
/* Skip I/O spaces */
if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
@@ -138,6 +147,7 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
c->base.virt = ioremap_nocache(c->base.phys, c->base.len);
if (!c->base.virt) {
printk(KERN_ERR "%s: Unable to map controller.\n", c->name);
+ i2o_pci_free(c);
return -ENOMEM;
}
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index 8b487ed1069..974f2f36bdb 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -42,7 +42,7 @@
#include "wbsd.h"
#define DRIVER_NAME "wbsd"
-#define DRIVER_VERSION "1.2"
+#define DRIVER_VERSION "1.3"
#ifdef CONFIG_MMC_DEBUG
#define DBG(x...) \
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index 2c6dc24c372..b780307093e 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -417,6 +417,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
struct net_local *lp = netdev_priv(dev);
static unsigned version_printed;
int i;
+ int tmp;
unsigned rev_type = 0;
int eeprom_buff[CHKSUM_LEN];
int retval;
@@ -492,14 +493,17 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
goto out2;
}
}
-printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
+ printk(KERN_DEBUG "PP_addr at %x: 0x%x\n",
+ ioaddr + ADD_PORT, inw(ioaddr + ADD_PORT));
ioaddr &= ~3;
outw(PP_ChipID, ioaddr + ADD_PORT);
- if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) {
- printk(KERN_ERR "%s: incorrect signature 0x%x\n",
- dev->name, inw(ioaddr + DATA_PORT));
+ tmp = inw(ioaddr + DATA_PORT);
+ if (tmp != CHIP_EISA_ID_SIG) {
+ printk(KERN_DEBUG "%s: incorrect signature at %x: 0x%x!="
+ CHIP_EISA_ID_SIG_STR "\n",
+ dev->name, ioaddr + DATA_PORT, tmp);
retval = -ENODEV;
goto out2;
}
diff --git a/drivers/net/cs89x0.h b/drivers/net/cs89x0.h
index bd3ad8e6cce..decea264f12 100644
--- a/drivers/net/cs89x0.h
+++ b/drivers/net/cs89x0.h
@@ -93,6 +93,7 @@
#endif
#define CHIP_EISA_ID_SIG 0x630E /* Product ID Code for Crystal Chip (CS8900 spec 4.3) */
+#define CHIP_EISA_ID_SIG_STR "0x630E"
#ifdef IBMEIPKT
#define EISA_ID_SIG 0x4D24 /* IBM */
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 5e5d2c3c7ce..b82fd15d089 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -3789,6 +3789,7 @@ e1000_netpoll(struct net_device *netdev)
struct e1000_adapter *adapter = netdev_priv(netdev);
disable_irq(adapter->pdev->irq);
e1000_intr(adapter->pdev->irq, netdev, NULL);
+ e1000_clean_tx_irq(adapter);
enable_irq(adapter->pdev->irq);
}
#endif
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index e44f8e9055e..f9e3be96963 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -130,12 +130,11 @@ struct sixpack {
#define AX25_6PACK_HEADER_LEN 0
-static void sp_start_tx_timer(struct sixpack *);
static void sixpack_decode(struct sixpack *, unsigned char[], int);
static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
/*
- * perform the persistence/slottime algorithm for CSMA access. If the
+ * Perform the persistence/slottime algorithm for CSMA access. If the
* persistence check was successful, write the data to the serial driver.
* Note that in case of DAMA operation, the data is not sent here.
*/
@@ -143,7 +142,7 @@ static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
static void sp_xmit_on_air(unsigned long channel)
{
struct sixpack *sp = (struct sixpack *) channel;
- int actual;
+ int actual, when = sp->slottime;
static unsigned char random;
random = random * 17 + 41;
@@ -159,20 +158,10 @@ static void sp_xmit_on_air(unsigned long channel)
sp->tty->driver->write(sp->tty, &sp->led_state, 1);
sp->status2 = 0;
} else
- sp_start_tx_timer(sp);
+ mod_timer(&sp->tx_t, jiffies + ((when + 1) * HZ) / 100);
}
/* ----> 6pack timer interrupt handler and friends. <---- */
-static void sp_start_tx_timer(struct sixpack *sp)
-{
- int when = sp->slottime;
-
- del_timer(&sp->tx_t);
- sp->tx_t.data = (unsigned long) sp;
- sp->tx_t.function = sp_xmit_on_air;
- sp->tx_t.expires = jiffies + ((when + 1) * HZ) / 100;
- add_timer(&sp->tx_t);
-}
/* Encapsulate one AX.25 frame and stuff into a TTY queue. */
static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
@@ -243,8 +232,7 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
sp->xleft = count;
sp->xhead = sp->xbuff;
sp->status2 = count;
- if (sp->duplex == 0)
- sp_start_tx_timer(sp);
+ sp_xmit_on_air((unsigned long)sp);
}
return;
diff --git a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig
index 7cdebe1a0b6..0cd54306e63 100644
--- a/drivers/net/hamradio/Kconfig
+++ b/drivers/net/hamradio/Kconfig
@@ -17,7 +17,7 @@ config MKISS
config 6PACK
tristate "Serial port 6PACK driver"
- depends on AX25 && BROKEN_ON_SMP
+ depends on AX25
---help---
6pack is a transmission protocol for the data exchange between your
PC and your TNC (the Terminal Node Controller acts as a kind of
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index 82570ec44d8..6ee4771addf 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -5133,6 +5133,84 @@ static void __devexit skge_remove_one(struct pci_dev *pdev)
kfree(pAC);
}
+#ifdef CONFIG_PM
+static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ DEV_NET *pNet = netdev_priv(dev);
+ SK_AC *pAC = pNet->pAC;
+ struct net_device *otherdev = pAC->dev[1];
+
+ if (netif_running(dev)) {
+ netif_carrier_off(dev);
+ DoPrintInterfaceChange = SK_FALSE;
+ SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */
+ netif_device_detach(dev);
+ }
+ if (otherdev != dev) {
+ if (netif_running(otherdev)) {
+ netif_carrier_off(otherdev);
+ DoPrintInterfaceChange = SK_FALSE;
+ SkDrvDeInitAdapter(pAC, 1); /* performs SkGeClose */
+ netif_device_detach(otherdev);
+ }
+ }
+
+ pci_save_state(pdev);
+ pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+ if (pAC->AllocFlag & SK_ALLOC_IRQ) {
+ free_irq(dev->irq, dev);
+ }
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+}
+
+static int skge_resume(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ DEV_NET *pNet = netdev_priv(dev);
+ SK_AC *pAC = pNet->pAC;
+ struct net_device *otherdev = pAC->dev[1];
+ int ret;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ pci_enable_device(pdev);
+ pci_set_master(pdev);
+ if (pAC->GIni.GIMacsFound == 2)
+ ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev);
+ else
+ ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, pAC->Name, dev);
+ if (ret) {
+ printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq);
+ pAC->AllocFlag &= ~SK_ALLOC_IRQ;
+ dev->irq = 0;
+ pci_disable_device(pdev);
+ return -EBUSY;
+ }
+
+ netif_device_attach(dev);
+ if (netif_running(dev)) {
+ DoPrintInterfaceChange = SK_FALSE;
+ SkDrvInitAdapter(pAC, 0); /* first device */
+ }
+ if (otherdev != dev) {
+ netif_device_attach(otherdev);
+ if (netif_running(otherdev)) {
+ DoPrintInterfaceChange = SK_FALSE;
+ SkDrvInitAdapter(pAC, 1); /* second device */
+ }
+ }
+
+ return 0;
+}
+#else
+#define skge_suspend NULL
+#define skge_resume NULL
+#endif
+
static struct pci_device_id skge_pci_tbl[] = {
{ PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
@@ -5158,6 +5236,8 @@ static struct pci_driver skge_driver = {
.id_table = skge_pci_tbl,
.probe = skge_probe_one,
.remove = __devexit_p(skge_remove_one),
+ .suspend = skge_suspend,
+ .resume = skge_resume,
};
static int __init skge_init(void)
diff --git a/drivers/net/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c
index df4483429a7..6cb49dd0225 100644
--- a/drivers/net/sk98lin/skgeinit.c
+++ b/drivers/net/sk98lin/skgeinit.c
@@ -2016,7 +2016,7 @@ SK_IOC IoC) /* IO context */
* we set the PHY to coma mode and switch to D3 power state.
*/
if (pAC->GIni.GIYukonLite &&
- pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
+ pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
/* for all ports switch PHY to coma mode */
for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
diff --git a/drivers/net/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c
index 94a09deecb3..42d2d963150 100644
--- a/drivers/net/sk98lin/skxmac2.c
+++ b/drivers/net/sk98lin/skxmac2.c
@@ -1065,7 +1065,7 @@ int Port) /* Port Index (MAC_1 + n) */
/* WA code for COMA mode */
if (pAC->GIni.GIYukonLite &&
- pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
+ pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
SK_IN32(IoC, B2_GP_IO, &DWord);
@@ -1110,7 +1110,7 @@ int Port) /* Port Index (MAC_1 + n) */
/* WA code for COMA mode */
if (pAC->GIni.GIYukonLite &&
- pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
+ pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
SK_IN32(IoC, B2_GP_IO, &DWord);
@@ -2126,7 +2126,7 @@ SK_U8 Mode) /* low power mode */
int Ret = 0;
if (pAC->GIni.GIYukonLite &&
- pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
+ pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
/* save current power mode */
LastMode = pAC->GIni.GP[Port].PPhyPowerState;
@@ -2253,7 +2253,7 @@ int Port) /* Port Index (e.g. MAC_1) */
int Ret = 0;
if (pAC->GIni.GIYukonLite &&
- pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
+ pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
/* save current power mode */
LastMode = pAC->GIni.GP[Port].PPhyPowerState;
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 5cacc7ad9e7..f15739481d6 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -42,7 +42,7 @@
#include "skge.h"
#define DRV_NAME "skge"
-#define DRV_VERSION "0.7"
+#define DRV_VERSION "0.8"
#define PFX DRV_NAME " "
#define DEFAULT_TX_RING_SIZE 128
@@ -55,7 +55,7 @@
#define ETH_JUMBO_MTU 9000
#define TX_WATCHDOG (5 * HZ)
#define NAPI_WEIGHT 64
-#define BLINK_HZ (HZ/4)
+#define BLINK_MS 250
MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
@@ -75,7 +75,6 @@ static const struct pci_device_id skge_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B) },
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) },
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) },
- { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */
@@ -249,7 +248,7 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
} else {
u32 setting;
- switch(ecmd->speed) {
+ switch (ecmd->speed) {
case SPEED_1000:
if (ecmd->duplex == DUPLEX_FULL)
setting = SUPPORTED_1000baseT_Full;
@@ -620,84 +619,98 @@ static int skge_set_coalesce(struct net_device *dev,
return 0;
}
-static void skge_led_on(struct skge_hw *hw, int port)
+enum led_mode { LED_MODE_OFF, LED_MODE_ON, LED_MODE_TST };
+static void skge_led(struct skge_port *skge, enum led_mode mode)
{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+
+ spin_lock_bh(&hw->phy_lock);
if (hw->chip_id == CHIP_ID_GENESIS) {
- skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON);
- skge_write8(hw, B0_LED, LED_STAT_ON);
+ switch (mode) {
+ case LED_MODE_OFF:
+ xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
+ skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
+ skge_write32(hw, SK_REG(port, RX_LED_VAL), 0);
+ skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF);
+ break;
- skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON);
- skge_write32(hw, SK_REG(port, RX_LED_VAL), 100);
- skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
+ case LED_MODE_ON:
+ skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON);
+ skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON);
- /* For Broadcom Phy only */
- xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
- } else {
- gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
- gm_phy_write(hw, port, PHY_MARV_LED_OVER,
- PHY_M_LED_MO_DUP(MO_LED_ON) |
- PHY_M_LED_MO_10(MO_LED_ON) |
- PHY_M_LED_MO_100(MO_LED_ON) |
- PHY_M_LED_MO_1000(MO_LED_ON) |
- PHY_M_LED_MO_RX(MO_LED_ON));
- }
-}
+ skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
+ skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START);
-static void skge_led_off(struct skge_hw *hw, int port)
-{
- if (hw->chip_id == CHIP_ID_GENESIS) {
- skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
- skge_write8(hw, B0_LED, LED_STAT_OFF);
+ break;
- skge_write32(hw, SK_REG(port, RX_LED_VAL), 0);
- skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF);
+ case LED_MODE_TST:
+ skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON);
+ skge_write32(hw, SK_REG(port, RX_LED_VAL), 100);
+ skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
- /* Broadcom only */
- xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
+ xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
+ break;
+ }
} else {
- gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
- gm_phy_write(hw, port, PHY_MARV_LED_OVER,
- PHY_M_LED_MO_DUP(MO_LED_OFF) |
- PHY_M_LED_MO_10(MO_LED_OFF) |
- PHY_M_LED_MO_100(MO_LED_OFF) |
- PHY_M_LED_MO_1000(MO_LED_OFF) |
- PHY_M_LED_MO_RX(MO_LED_OFF));
+ switch (mode) {
+ case LED_MODE_OFF:
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+ PHY_M_LED_MO_DUP(MO_LED_OFF) |
+ PHY_M_LED_MO_10(MO_LED_OFF) |
+ PHY_M_LED_MO_100(MO_LED_OFF) |
+ PHY_M_LED_MO_1000(MO_LED_OFF) |
+ PHY_M_LED_MO_RX(MO_LED_OFF));
+ break;
+ case LED_MODE_ON:
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL,
+ PHY_M_LED_PULS_DUR(PULS_170MS) |
+ PHY_M_LED_BLINK_RT(BLINK_84MS) |
+ PHY_M_LEDC_TX_CTRL |
+ PHY_M_LEDC_DP_CTRL);
+
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+ PHY_M_LED_MO_RX(MO_LED_OFF) |
+ (skge->speed == SPEED_100 ?
+ PHY_M_LED_MO_100(MO_LED_ON) : 0));
+ break;
+ case LED_MODE_TST:
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+ PHY_M_LED_MO_DUP(MO_LED_ON) |
+ PHY_M_LED_MO_10(MO_LED_ON) |
+ PHY_M_LED_MO_100(MO_LED_ON) |
+ PHY_M_LED_MO_1000(MO_LED_ON) |
+ PHY_M_LED_MO_RX(MO_LED_ON));
+ }
}
-}
-
-static void skge_blink_timer(unsigned long data)
-{
- struct skge_port *skge = (struct skge_port *) data;
- struct skge_hw *hw = skge->hw;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->phy_lock, flags);
- if (skge->blink_on)
- skge_led_on(hw, skge->port);
- else
- skge_led_off(hw, skge->port);
- spin_unlock_irqrestore(&hw->phy_lock, flags);
-
- skge->blink_on = !skge->blink_on;
- mod_timer(&skge->led_blink, jiffies + BLINK_HZ);
+ spin_unlock_bh(&hw->phy_lock);
}
/* blink LED's for finding board */
static int skge_phys_id(struct net_device *dev, u32 data)
{
struct skge_port *skge = netdev_priv(dev);
+ unsigned long ms;
+ enum led_mode mode = LED_MODE_TST;
if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
- data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
+ ms = jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT / HZ) * 1000;
+ else
+ ms = data * 1000;
- /* start blinking */
- skge->blink_on = 1;
- mod_timer(&skge->led_blink, jiffies+1);
+ while (ms > 0) {
+ skge_led(skge, mode);
+ mode ^= LED_MODE_TST;
- msleep_interruptible(data * 1000);
- del_timer_sync(&skge->led_blink);
+ if (msleep_interruptible(BLINK_MS))
+ break;
+ ms -= BLINK_MS;
+ }
- skge_led_off(skge->hw, skge->port);
+ /* back to regular LED state */
+ skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF);
return 0;
}
@@ -1028,7 +1041,7 @@ static void bcom_check_link(struct skge_hw *hw, int port)
}
/* Check Duplex mismatch */
- switch(aux & PHY_B_AS_AN_RES_MSK) {
+ switch (aux & PHY_B_AS_AN_RES_MSK) {
case PHY_B_RES_1000FD:
skge->duplex = DUPLEX_FULL;
break;
@@ -1099,7 +1112,7 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo)
r |= XM_MMU_NO_PRE;
xm_write16(hw, port, XM_MMU_CMD,r);
- switch(id1) {
+ switch (id1) {
case PHY_BCOM_ID1_C0:
/*
* Workaround BCOM Errata for the C0 type.
@@ -1194,13 +1207,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
xm_write16(hw, port, XM_STAT_CMD,
XM_SC_CLR_RXC | XM_SC_CLR_TXC);
- /* initialize Rx, Tx and Link LED */
- skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON);
- skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON);
-
- skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
- skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START);
-
/* Unreset the XMAC. */
skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
@@ -1209,7 +1215,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
* namely for the 1000baseTX cards that use the XMAC's
* GMII mode.
*/
- spin_lock_bh(&hw->phy_lock);
/* Take external Phy out of reset */
r = skge_read32(hw, B2_GP_IO);
if (port == 0)
@@ -1219,7 +1224,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
skge_write32(hw, B2_GP_IO, r);
skge_read32(hw, B2_GP_IO);
- spin_unlock_bh(&hw->phy_lock);
/* Enable GMII interfac */
xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
@@ -1569,7 +1573,6 @@ static void yukon_init(struct skge_hw *hw, int port)
{
struct skge_port *skge = netdev_priv(hw->dev[port]);
u16 ctrl, ct1000, adv;
- u16 ledctrl, ledover;
pr_debug("yukon_init\n");
if (skge->autoneg == AUTONEG_ENABLE) {
@@ -1641,32 +1644,11 @@ static void yukon_init(struct skge_hw *hw, int port)
gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv);
gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
- /* Setup Phy LED's */
- ledctrl = PHY_M_LED_PULS_DUR(PULS_170MS);
- ledover = 0;
-
- ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL;
-
- /* turn off the Rx LED (LED_RX) */
- ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
-
- /* disable blink mode (LED_DUPLEX) on collisions */
- ctrl |= PHY_M_LEDC_DP_CTRL;
- gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
-
- if (skge->autoneg == AUTONEG_DISABLE || skge->speed == SPEED_100) {
- /* turn on 100 Mbps LED (LED_LINK100) */
- ledover |= PHY_M_LED_MO_100(MO_LED_ON);
- }
-
- if (ledover)
- gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
-
/* Enable phy interrupt on autonegotiation complete (or link up) */
if (skge->autoneg == AUTONEG_ENABLE)
- gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL);
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_MSK);
else
- gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK);
}
static void yukon_reset(struct skge_hw *hw, int port)
@@ -1691,7 +1673,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
/* WA code for COMA mode -- set PHY reset */
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev == CHIP_REV_YU_LITE_A3)
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3)
skge_write32(hw, B2_GP_IO,
(skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9));
@@ -1701,7 +1683,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
/* WA code for COMA mode -- clear PHY reset */
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev == CHIP_REV_YU_LITE_A3)
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3)
skge_write32(hw, B2_GP_IO,
(skge_read32(hw, B2_GP_IO) | GP_DIR_9)
& ~GP_IO_9);
@@ -1745,9 +1727,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
gma_write16(hw, port, GM_GP_CTRL, reg);
skge_read16(hw, GMAC_IRQ_SRC);
- spin_lock_bh(&hw->phy_lock);
yukon_init(hw, port);
- spin_unlock_bh(&hw->phy_lock);
/* MIB clear */
reg = gma_read16(hw, port, GM_PHY_ADDR);
@@ -1796,7 +1776,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK);
reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev == CHIP_REV_YU_LITE_A3)
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3)
reg &= ~GMF_RX_F_FL_ON;
skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg);
@@ -1813,19 +1793,19 @@ static void yukon_stop(struct skge_port *skge)
int port = skge->port;
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev == CHIP_REV_YU_LITE_A3) {
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
skge_write32(hw, B2_GP_IO,
skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9);
}
gma_write16(hw, port, GM_GP_CTRL,
gma_read16(hw, port, GM_GP_CTRL)
- & ~(GM_GPCR_RX_ENA|GM_GPCR_RX_ENA));
+ & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA));
gma_read16(hw, port, GM_GP_CTRL);
/* set GPHY Control reset */
- gma_write32(hw, port, GPHY_CTRL, GPC_RST_SET);
- gma_write32(hw, port, GMAC_CTRL, GMC_RST_SET);
+ skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+ skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
}
static void yukon_get_stats(struct skge_port *skge, u64 *data)
@@ -1856,11 +1836,12 @@ static void yukon_mac_intr(struct skge_hw *hw, int port)
if (status & GM_IS_RX_FF_OR) {
++skge->net_stats.rx_fifo_errors;
- gma_write8(hw, port, RX_GMF_CTRL_T, GMF_CLI_RX_FO);
+ skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO);
}
+
if (status & GM_IS_TX_FF_UR) {
++skge->net_stats.tx_fifo_errors;
- gma_write8(hw, port, TX_GMF_CTRL_T, GMF_CLI_TX_FU);
+ skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU);
}
}
@@ -1896,7 +1877,7 @@ static void yukon_link_up(struct skge_port *skge)
reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
gma_write16(hw, port, GM_GP_CTRL, reg);
- gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK);
skge_link_up(skge);
}
@@ -1904,12 +1885,14 @@ static void yukon_link_down(struct skge_port *skge)
{
struct skge_hw *hw = skge->hw;
int port = skge->port;
+ u16 ctrl;
pr_debug("yukon_link_down\n");
gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
- gm_phy_write(hw, port, GM_GP_CTRL,
- gm_phy_read(hw, port, GM_GP_CTRL)
- & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA));
+
+ ctrl = gma_read16(hw, port, GM_GP_CTRL);
+ ctrl &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
+ gma_write16(hw, port, GM_GP_CTRL, ctrl);
if (skge->flow_control == FLOW_MODE_REM_SEND) {
/* restore Asymmetric Pause bit */
@@ -2097,10 +2080,12 @@ static int skge_up(struct net_device *dev)
skge_write32(hw, B0_IMSK, hw->intr_mask);
/* Initialze MAC */
+ spin_lock_bh(&hw->phy_lock);
if (hw->chip_id == CHIP_ID_GENESIS)
genesis_mac_init(hw, port);
else
yukon_mac_init(hw, port);
+ spin_unlock_bh(&hw->phy_lock);
/* Configure RAMbuffers */
chunk = hw->ram_size / ((hw->ports + 1)*2);
@@ -2116,6 +2101,7 @@ static int skge_up(struct net_device *dev)
/* Start receiver BMU */
wmb();
skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
+ skge_led(skge, LED_MODE_ON);
pr_debug("skge_up completed\n");
return 0;
@@ -2140,8 +2126,6 @@ static int skge_down(struct net_device *dev)
netif_stop_queue(dev);
- del_timer_sync(&skge->led_blink);
-
/* Stop transmitter */
skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
@@ -2175,15 +2159,12 @@ static int skge_down(struct net_device *dev)
if (hw->chip_id == CHIP_ID_GENESIS) {
skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET);
skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_SET);
- skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_STOP);
- skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_STOP);
} else {
skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
}
- /* turn off led's */
- skge_write16(hw, B0_LED, LED_STAT_OFF);
+ skge_led(skge, LED_MODE_OFF);
skge_tx_clean(skge);
skge_rx_clean(skge);
@@ -2633,11 +2614,17 @@ static inline void skge_tx_intr(struct net_device *dev)
spin_unlock(&skge->tx_lock);
}
+/* Parity errors seem to happen when Genesis is connected to a switch
+ * with no other ports present. Heartbeat error??
+ */
static void skge_mac_parity(struct skge_hw *hw, int port)
{
- printk(KERN_ERR PFX "%s: mac data parity error\n",
- hw->dev[port] ? hw->dev[port]->name
- : (port == 0 ? "(port A)": "(port B"));
+ struct net_device *dev = hw->dev[port];
+
+ if (dev) {
+ struct skge_port *skge = netdev_priv(dev);
+ ++skge->net_stats.tx_heartbeat_errors;
+ }
if (hw->chip_id == CHIP_ID_GENESIS)
skge_write16(hw, SK_REG(port, TX_MFF_CTRL1),
@@ -3083,10 +3070,6 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
spin_lock_init(&skge->tx_lock);
- init_timer(&skge->led_blink);
- skge->led_blink.function = skge_blink_timer;
- skge->led_blink.data = (unsigned long) skge;
-
if (hw->chip_id != CHIP_ID_GENESIS) {
dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
skge->rx_csum = 1;
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index fced3d2bc07..b432f1bb816 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -1449,10 +1449,12 @@ enum {
PHY_M_IS_DTE_CHANGE = 1<<2, /* DTE Power Det. Status Changed */
PHY_M_IS_POL_CHANGE = 1<<1, /* Polarity Changed */
PHY_M_IS_JABBER = 1<<0, /* Jabber */
-};
-#define PHY_M_DEF_MSK ( PHY_M_IS_AN_ERROR | PHY_M_IS_LSP_CHANGE | \
- PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR)
+ PHY_M_IS_DEF_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_LSP_CHANGE |
+ PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR,
+
+ PHY_M_IS_AN_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_AN_COMPL,
+};
/***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/
enum {
@@ -1509,7 +1511,7 @@ enum {
PHY_M_LEDC_TX_C_MSB = 1<<0, /* Tx Control (MSB, 88E1111 only) */
};
-#define PHY_M_LED_PULS_DUR(x) ( ((x)<<12) & PHY_M_LEDC_PULS_MSK)
+#define PHY_M_LED_PULS_DUR(x) (((x)<<12) & PHY_M_LEDC_PULS_MSK)
enum {
PULS_NO_STR = 0,/* no pulse stretching */
@@ -1522,7 +1524,7 @@ enum {
PULS_1300MS = 7,/* 1.3 s to 2.7 s */
};
-#define PHY_M_LED_BLINK_RT(x) ( ((x)<<8) & PHY_M_LEDC_BL_R_MSK)
+#define PHY_M_LED_BLINK_RT(x) (((x)<<8) & PHY_M_LEDC_BL_R_MSK)
enum {
BLINK_42MS = 0,/* 42 ms */
@@ -1602,9 +1604,9 @@ enum {
PHY_M_FELP_LED0_MSK = 0xf, /* Bit 3.. 0: LED0 Mask (SPEED) */
};
-#define PHY_M_FELP_LED2_CTRL(x) ( ((x)<<8) & PHY_M_FELP_LED2_MSK)
-#define PHY_M_FELP_LED1_CTRL(x) ( ((x)<<4) & PHY_M_FELP_LED1_MSK)
-#define PHY_M_FELP_LED0_CTRL(x) ( ((x)<<0) & PHY_M_FELP_LED0_MSK)
+#define PHY_M_FELP_LED2_CTRL(x) (((x)<<8) & PHY_M_FELP_LED2_MSK)
+#define PHY_M_FELP_LED1_CTRL(x) (((x)<<4) & PHY_M_FELP_LED1_MSK)
+#define PHY_M_FELP_LED0_CTRL(x) (((x)<<0) & PHY_M_FELP_LED0_MSK)
enum {
LED_PAR_CTRL_COLX = 0x00,
@@ -1640,7 +1642,7 @@ enum {
PHY_M_MAC_MD_COPPER = 5,/* Copper only */
PHY_M_MAC_MD_1000BX = 7,/* 1000Base-X only */
};
-#define PHY_M_MAC_MODE_SEL(x) ( ((x)<<7) & PHY_M_MAC_MD_MSK)
+#define PHY_M_MAC_MODE_SEL(x) (((x)<<7) & PHY_M_MAC_MD_MSK)
/***** PHY_MARV_PHY_CTRL (page 3) 16 bit r/w LED Control Reg. *****/
enum {
@@ -1650,10 +1652,10 @@ enum {
PHY_M_LEDC_STA0_MSK = 0xf, /* Bit 3.. 0: STAT0 LED Ctrl. Mask */
};
-#define PHY_M_LEDC_LOS_CTRL(x) ( ((x)<<12) & PHY_M_LEDC_LOS_MSK)
-#define PHY_M_LEDC_INIT_CTRL(x) ( ((x)<<8) & PHY_M_LEDC_INIT_MSK)
-#define PHY_M_LEDC_STA1_CTRL(x) ( ((x)<<4) & PHY_M_LEDC_STA1_MSK)
-#define PHY_M_LEDC_STA0_CTRL(x) ( ((x)<<0) & PHY_M_LEDC_STA0_MSK)
+#define PHY_M_LEDC_LOS_CTRL(x) (((x)<<12) & PHY_M_LEDC_LOS_MSK)
+#define PHY_M_LEDC_INIT_CTRL(x) (((x)<<8) & PHY_M_LEDC_INIT_MSK)
+#define PHY_M_LEDC_STA1_CTRL(x) (((x)<<4) & PHY_M_LEDC_STA1_MSK)
+#define PHY_M_LEDC_STA0_CTRL(x) (((x)<<0) & PHY_M_LEDC_STA0_MSK)
/* GMAC registers */
/* Port Registers */
@@ -2505,8 +2507,6 @@ struct skge_port {
dma_addr_t dma;
unsigned long mem_size;
unsigned int rx_buf_size;
-
- struct timer_list led_blink;
};
@@ -2606,17 +2606,6 @@ static inline void gma_write16(const struct skge_hw *hw, int port, int r, u16 v)
skge_write16(hw, SK_GMAC_REG(port,r), v);
}
-static inline void gma_write32(const struct skge_hw *hw, int port, int r, u32 v)
-{
- skge_write16(hw, SK_GMAC_REG(port, r), (u16) v);
- skge_write32(hw, SK_GMAC_REG(port, r+4), (u16)(v >> 16));
-}
-
-static inline void gma_write8(const struct skge_hw *hw, int port, int r, u8 v)
-{
- skge_write8(hw, SK_GMAC_REG(port,r), v);
-}
-
static inline void gma_set_addr(struct skge_hw *hw, int port, int reg,
const u8 *addr)
{
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 7089d86e857..a9b06b8d8e3 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -188,7 +188,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define SMC_IRQ_TRIGGER_TYPE (( \
machine_is_omap_h2() \
|| machine_is_omap_h3() \
- || (machine_is_omap_innovator() && !cpu_is_omap150()) \
+ || (machine_is_omap_innovator() && !cpu_is_omap1510()) \
) ? IRQT_FALLING : IRQT_RISING)
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 201a550f0bc..368b8fb1402 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -66,8 +66,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.34"
-#define DRV_MODULE_RELDATE "July 25, 2005"
+#define DRV_MODULE_VERSION "3.35"
+#define DRV_MODULE_RELDATE "August 6, 2005"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -10421,6 +10421,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
tg3_init_coal(tp);
+ /* Now that we have fully setup the chip, save away a snapshot
+ * of the PCI config space. We need to restore this after
+ * GRC_MISC_CFG core clock resets and some resume events.
+ */
+ pci_save_state(tp->pdev);
+
err = register_netdev(dev);
if (err) {
printk(KERN_ERR PFX "Cannot register net device, "
@@ -10430,12 +10436,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
pci_set_drvdata(pdev, dev);
- /* Now that we have fully setup the chip, save away a snapshot
- * of the PCI config space. We need to restore this after
- * GRC_MISC_CFG core clock resets and some resume events.
- */
- pci_save_state(tp->pdev);
-
printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT Ethernet ",
dev->name,
tp->board_part_number,
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index fedae89d8f7..fb9a11243d2 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -60,7 +60,9 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
continue;
/* Ok, try it out.. */
- ret = allocate_resource(r, res, size, min, -1, align,
+ ret = allocate_resource(r, res, size,
+ r->start ? : min,
+ -1, align,
alignf, alignf_data);
if (ret == 0)
break;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 8d0968bd527..a9160ad1658 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -373,6 +373,25 @@ static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi );
+/*
+ * VIA VT8235 ISA Bridge: Two IO regions pointed to by words at
+ * 0x88 (128 bytes of power management registers)
+ * 0xd0 (16 bytes of SMB registers)
+ */
+static void __devinit quirk_vt8235_acpi(struct pci_dev *dev)
+{
+ u16 pm, smb;
+
+ pci_read_config_word(dev, 0x88, &pm);
+ pm &= PCI_BASE_ADDRESS_IO_MASK;
+ quirk_io_region(dev, pm, 128, PCI_BRIDGE_RESOURCES);
+
+ pci_read_config_word(dev, 0xd0, &smb);
+ smb &= PCI_BASE_ADDRESS_IO_MASK;
+ quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 1);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, quirk_vt8235_acpi);
+
#ifdef CONFIG_X86_IO_APIC
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 1ca21d2ba11..84eedc96568 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -33,6 +33,11 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
u32 new, check, mask;
int reg;
+ /* Ignore resources for unimplemented BARs and unused resource slots
+ for 64 bit BARs. */
+ if (!res->flags)
+ return;
+
pcibios_resource_to_bus(dev, &region, res);
pr_debug(" got res [%lx:%lx] bus [%lx:%lx] flags %lx for "
@@ -67,7 +72,7 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
if ((new & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
(PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) {
- new = 0; /* currently everyone zeros the high address */
+ new = region.start >> 16 >> 16;
pci_write_config_dword(dev, reg + 4, new);
pci_read_config_dword(dev, reg + 4, &check);
if (check != new) {
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index d63f22a5bf7..43da2e92d50 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -589,8 +589,8 @@ static void pcmcia_delayed_add_pseudo_device(void *data)
static inline void pcmcia_add_pseudo_device(struct pcmcia_socket *s)
{
if (!s->pcmcia_state.device_add_pending) {
- schedule_work(&s->device_add);
s->pcmcia_state.device_add_pending = 1;
+ schedule_work(&s->device_add);
}
return;
}
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 744e469a9ed..62fd705203f 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -605,9 +605,8 @@ static int yenta_search_res(struct yenta_socket *socket, struct resource *res,
static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end)
{
- struct pci_bus *bus;
struct resource *root, *res;
- u32 start, end;
+ struct pci_bus_region region;
unsigned mask;
res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr;
@@ -620,15 +619,13 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
if (type & IORESOURCE_IO)
mask = ~3;
- bus = socket->dev->subordinate;
- res->name = bus->name;
+ res->name = socket->dev->subordinate->name;
res->flags = type;
- start = config_readl(socket, addr_start) & mask;
- end = config_readl(socket, addr_end) | ~mask;
- if (start && end > start && !override_bios) {
- res->start = start;
- res->end = end;
+ region.start = config_readl(socket, addr_start) & mask;
+ region.end = config_readl(socket, addr_end) | ~mask;
+ if (region.start && region.end > region.start && !override_bios) {
+ pcibios_bus_to_resource(socket->dev, res, &region);
root = pci_find_parent_resource(socket->dev, res);
if (root && (request_resource(root, res) == 0))
return;
@@ -642,6 +639,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
(yenta_search_res(socket, res, BRIDGE_IO_MIN))) {
config_writel(socket, addr_start, res->start);
config_writel(socket, addr_end, res->end);
+ return;
}
} else {
if (type & IORESOURCE_PREFETCH) {
@@ -650,6 +648,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
(yenta_search_res(socket, res, BRIDGE_MEM_MIN))) {
config_writel(socket, addr_start, res->start);
config_writel(socket, addr_end, res->end);
+ return;
}
/* Approximating prefetchable by non-prefetchable */
res->flags = IORESOURCE_MEM;
@@ -659,6 +658,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
(yenta_search_res(socket, res, BRIDGE_MEM_MIN))) {
config_writel(socket, addr_start, res->start);
config_writel(socket, addr_end, res->end);
+ return;
}
}
@@ -1107,8 +1107,6 @@ static int yenta_dev_suspend (struct pci_dev *dev, pm_message_t state)
pci_read_config_dword(dev, 17*4, &socket->saved_state[1]);
pci_disable_device(dev);
- free_irq(dev->irq, socket);
-
/*
* Some laptops (IBM T22) do not like us putting the Cardbus
* bridge into D3. At a guess, some other laptop will
@@ -1134,13 +1132,6 @@ static int yenta_dev_resume (struct pci_dev *dev)
pci_enable_device(dev);
pci_set_master(dev);
- if (socket->cb_irq)
- if (request_irq(socket->cb_irq, yenta_interrupt,
- SA_SHIRQ, "yenta", socket)) {
- printk(KERN_WARNING "Yenta: request_irq() failed on resume!\n");
- socket->cb_irq = 0;
- }
-
if (socket->type && socket->type->restore_state)
socket->type->restore_state(socket);
}
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 8f4d2999af8..79c74f3a11f 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -8120,20 +8120,22 @@ static struct notifier_block qeth_ip6_notifier = {
#endif
static int
-qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
+__qeth_reboot_event_card(struct device *dev, void *data)
{
-
- struct device *entry;
struct qeth_card *card;
- down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
- list_for_each_entry(entry, &qeth_ccwgroup_driver.driver.devices,
- driver_list) {
- card = (struct qeth_card *) entry->driver_data;
- qeth_clear_ip_list(card, 0, 0);
- qeth_qdio_clear_card(card, 0);
- }
- up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
+ card = (struct qeth_card *) dev->driver_data;
+ qeth_clear_ip_list(card, 0, 0);
+ qeth_qdio_clear_card(card, 0);
+ return 0;
+}
+
+static int
+qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+
+ driver_for_each_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
+ __qeth_reboot_event_card);
return NOTIFY_DONE;
}
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c
index 04719196fd2..f2ccfea8fdb 100644
--- a/drivers/s390/net/qeth_proc.c
+++ b/drivers/s390/net/qeth_proc.c
@@ -27,23 +27,33 @@ const char *VERSION_QETH_PROC_C = "$Revision: 1.13 $";
#define QETH_PROCFILE_NAME "qeth"
static struct proc_dir_entry *qeth_procfile;
+static int
+qeth_procfile_seq_match(struct device *dev, void *data)
+{
+ return 1;
+}
+
static void *
qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)
{
- struct list_head *next_card = NULL;
- int i = 0;
+ struct device *dev;
+ loff_t nr;
down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
- if (*offset == 0)
+ nr = *offset;
+ if (nr == 0)
return SEQ_START_TOKEN;
- /* get card at pos *offset */
- list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices)
- if (++i == *offset)
- return next_card;
+ dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL,
+ NULL, qeth_procfile_seq_match);
- return NULL;
+ /* get card at pos *offset */
+ nr = *offset;
+ while (nr-- > 1 && dev)
+ dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev,
+ NULL, qeth_procfile_seq_match);
+ return (void *) dev;
}
static void
@@ -55,23 +65,21 @@ qeth_procfile_seq_stop(struct seq_file *s, void* it)
static void *
qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
{
- struct list_head *next_card = NULL;
- struct list_head *current_card;
+ struct device *prev, *next;
if (it == SEQ_START_TOKEN) {
- next_card = qeth_ccwgroup_driver.driver.devices.next;
- if (next_card->next == next_card) /* list empty */
- return NULL;
- (*offset)++;
- } else {
- current_card = (struct list_head *)it;
- if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
- return NULL; /* end of list reached */
- next_card = current_card->next;
- (*offset)++;
+ next = driver_find_device(&qeth_ccwgroup_driver.driver,
+ NULL, NULL, qeth_procfile_seq_match);
+ if (next)
+ (*offset)++;
+ return (void *) next;
}
-
- return next_card;
+ prev = (struct device *) it;
+ next = driver_find_device(&qeth_ccwgroup_driver.driver,
+ prev, NULL, qeth_procfile_seq_match);
+ if (next)
+ (*offset)++;
+ return (void *) next;
}
static inline const char *
@@ -126,7 +134,7 @@ qeth_procfile_seq_show(struct seq_file *s, void *it)
"-------------- ---- ------ ---------- ---- "
"---- ----- -----\n");
} else {
- device = list_entry(it, struct device, driver_list);
+ device = (struct device *) it;
card = device->driver_data;
seq_printf(s, "%s/%s/%s x%02X %-10s %-14s %-4i ",
CARD_RDEV_ID(card),
@@ -180,17 +188,20 @@ static struct proc_dir_entry *qeth_perf_procfile;
static void *
qeth_perf_procfile_seq_start(struct seq_file *s, loff_t *offset)
{
- struct list_head *next_card = NULL;
- int i = 0;
+ struct device *dev = NULL;
+ int nr;
down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
/* get card at pos *offset */
- list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){
- if (i == *offset)
- return next_card;
- i++;
- }
- return NULL;
+ dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
+ qeth_procfile_seq_match);
+
+ /* get card at pos *offset */
+ nr = *offset;
+ while (nr-- > 1 && dev)
+ dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev,
+ NULL, qeth_procfile_seq_match);
+ return (void *) dev;
}
static void
@@ -202,12 +213,14 @@ qeth_perf_procfile_seq_stop(struct seq_file *s, void* it)
static void *
qeth_perf_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
{
- struct list_head *current_card = (struct list_head *)it;
+ struct device *prev, *next;
- if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
- return NULL; /* end of list reached */
- (*offset)++;
- return current_card->next;
+ prev = (struct device *) it;
+ next = driver_find_device(&qeth_ccwgroup_driver.driver, prev,
+ NULL, qeth_procfile_seq_match);
+ if (next)
+ (*offset)++;
+ return (void *) next;
}
static int
@@ -216,7 +229,7 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
struct device *device;
struct qeth_card *card;
- device = list_entry(it, struct device, driver_list);
+ device = (struct device *) it;
card = device->driver_data;
seq_printf(s, "For card with devnos %s/%s/%s (%s):\n",
CARD_RDEV_ID(card),
@@ -318,8 +331,8 @@ static struct proc_dir_entry *qeth_ipato_procfile;
static void *
qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset)
{
- struct list_head *next_card = NULL;
- int i = 0;
+ struct device *dev;
+ loff_t nr;
down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
/* TODO: finish this */
@@ -328,13 +341,16 @@ qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset)
* output driver settings then;
* else output setting for respective card
*/
+
+ dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
+ qeth_procfile_seq_match);
+
/* get card at pos *offset */
- list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){
- if (i == *offset)
- return next_card;
- i++;
- }
- return NULL;
+ nr = *offset;
+ while (nr-- > 1 && dev)
+ dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev,
+ NULL, qeth_procfile_seq_match);
+ return (void *) dev;
}
static void
@@ -346,18 +362,14 @@ qeth_ipato_procfile_seq_stop(struct seq_file *s, void* it)
static void *
qeth_ipato_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
{
- struct list_head *current_card = (struct list_head *)it;
+ struct device *prev, *next;
- /* TODO: finish this */
- /*
- * maybe SEQ_SATRT_TOKEN can be returned for offset 0
- * output driver settings then;
- * else output setting for respective card
- */
- if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
- return NULL; /* end of list reached */
- (*offset)++;
- return current_card->next;
+ prev = (struct device *) it;
+ next = driver_find_device(&qeth_ccwgroup_driver.driver, prev,
+ NULL, qeth_procfile_seq_match);
+ if (next)
+ (*offset)++;
+ return (void *) next;
}
static int
@@ -372,7 +384,7 @@ qeth_ipato_procfile_seq_show(struct seq_file *s, void *it)
* output driver settings then;
* else output setting for respective card
*/
- device = list_entry(it, struct device, driver_list);
+ device = (struct device *) it;
card = device->driver_data;
return 0;
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c
index b8a2c7353b0..d44205d52bf 100644
--- a/drivers/sbus/char/bbc_envctrl.c
+++ b/drivers/sbus/char/bbc_envctrl.c
@@ -7,6 +7,7 @@
#define __KERNEL_SYSCALLS__
#include <linux/kernel.h>
+#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/delay.h>
@@ -459,10 +460,6 @@ static struct task_struct *kenvctrld_task;
static int kenvctrld(void *__unused)
{
- daemonize("kenvctrld");
- allow_signal(SIGKILL);
- kenvctrld_task = current;
-
printk(KERN_INFO "bbc_envctrl: kenvctrld starting...\n");
last_warning_jiffies = jiffies - WARN_INTERVAL;
for (;;) {
@@ -470,7 +467,7 @@ static int kenvctrld(void *__unused)
struct bbc_fan_control *fp;
msleep_interruptible(POLL_INTERVAL);
- if (signal_pending(current))
+ if (kthread_should_stop())
break;
for (tp = all_bbc_temps; tp; tp = tp->next) {
@@ -577,7 +574,6 @@ int bbc_envctrl_init(void)
int temp_index = 0;
int fan_index = 0;
int devidx = 0;
- int err = 0;
while ((echild = bbc_i2c_getdev(devidx++)) != NULL) {
if (!strcmp(echild->prom_name, "temperature"))
@@ -585,9 +581,13 @@ int bbc_envctrl_init(void)
if (!strcmp(echild->prom_name, "fan-control"))
attach_one_fan(echild, fan_index++);
}
- if (temp_index != 0 && fan_index != 0)
- err = kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES);
- return err;
+ if (temp_index != 0 && fan_index != 0) {
+ kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld");
+ if (IS_ERR(kenvctrld_task))
+ return PTR_ERR(kenvctrld_task);
+ }
+
+ return 0;
}
static void destroy_one_temp(struct bbc_cpu_temperature *tp)
@@ -607,26 +607,7 @@ void bbc_envctrl_cleanup(void)
struct bbc_cpu_temperature *tp;
struct bbc_fan_control *fp;
- if (kenvctrld_task != NULL) {
- force_sig(SIGKILL, kenvctrld_task);
- for (;;) {
- struct task_struct *p;
- int found = 0;
-
- read_lock(&tasklist_lock);
- for_each_process(p) {
- if (p == kenvctrld_task) {
- found = 1;
- break;
- }
- }
- read_unlock(&tasklist_lock);
- if (!found)
- break;
- msleep(1000);
- }
- kenvctrld_task = NULL;
- }
+ kthread_stop(kenvctrld_task);
tp = all_bbc_temps;
while (tp != NULL) {
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index 9a8c572554f..d765cc1bf06 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -24,6 +24,7 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/sched.h>
+#include <linux/kthread.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/ioport.h>
@@ -1010,16 +1011,13 @@ static int kenvctrld(void *__unused)
poll_interval = 5000; /* TODO env_mon_interval */
- daemonize("kenvctrld");
- allow_signal(SIGKILL);
-
- kenvctrld_task = current;
-
printk(KERN_INFO "envctrl: %s starting...\n", current->comm);
for (;;) {
- if(msleep_interruptible(poll_interval))
- break;
+ msleep_interruptible(poll_interval);
+ if (kthread_should_stop())
+ break;
+
for (whichcpu = 0; whichcpu < ENVCTRL_MAX_CPU; ++whichcpu) {
if (0 < envctrl_read_cpu_info(whichcpu, cputemp,
ENVCTRL_CPUTEMP_MON,
@@ -1041,7 +1039,6 @@ static int kenvctrld(void *__unused)
static int __init envctrl_init(void)
{
-#ifdef CONFIG_PCI
struct linux_ebus *ebus = NULL;
struct linux_ebus_device *edev = NULL;
struct linux_ebus_child *edev_child = NULL;
@@ -1118,9 +1115,11 @@ done:
i2c_childlist[i].addr, (0 == i) ? ("\n") : (" "));
}
- err = kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES);
- if (err < 0)
+ kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld");
+ if (IS_ERR(kenvctrld_task)) {
+ err = PTR_ERR(kenvctrld_task);
goto out_deregister;
+ }
return 0;
@@ -1133,37 +1132,13 @@ out_iounmap:
kfree(i2c_childlist[i].tables);
}
return err;
-#else
- return -ENODEV;
-#endif
}
static void __exit envctrl_cleanup(void)
{
int i;
- if (NULL != kenvctrld_task) {
- force_sig(SIGKILL, kenvctrld_task);
- for (;;) {
- struct task_struct *p;
- int found = 0;
-
- read_lock(&tasklist_lock);
- for_each_process(p) {
- if (p == kenvctrld_task) {
- found = 1;
- break;
- }
- }
- read_unlock(&tasklist_lock);
-
- if (!found)
- break;
-
- msleep(1000);
- }
- kenvctrld_task = NULL;
- }
+ kthread_stop(kenvctrld_task);
iounmap(i2c);
misc_deregister(&envctrl_dev);
diff --git a/drivers/sbus/char/vfc.h b/drivers/sbus/char/vfc.h
index e56a43af0f6..a7782e7da42 100644
--- a/drivers/sbus/char/vfc.h
+++ b/drivers/sbus/char/vfc.h
@@ -129,8 +129,6 @@ struct vfc_dev {
struct vfc_regs *phys_regs;
unsigned int control_reg;
struct semaphore device_lock_sem;
- struct timer_list poll_timer;
- wait_queue_head_t poll_wait;
int instance;
int busy;
unsigned long which_io;
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
index 86ce5413095..7a103698fa3 100644
--- a/drivers/sbus/char/vfc_dev.c
+++ b/drivers/sbus/char/vfc_dev.c
@@ -137,7 +137,6 @@ int init_vfc_devstruct(struct vfc_dev *dev, int instance)
dev->instance=instance;
init_MUTEX(&dev->device_lock_sem);
dev->control_reg=0;
- init_waitqueue_head(&dev->poll_wait);
dev->busy=0;
return 0;
}
diff --git a/drivers/sbus/char/vfc_i2c.c b/drivers/sbus/char/vfc_i2c.c
index 1faf1e75f71..739cad9b19a 100644
--- a/drivers/sbus/char/vfc_i2c.c
+++ b/drivers/sbus/char/vfc_i2c.c
@@ -79,25 +79,10 @@ int vfc_pcf8584_init(struct vfc_dev *dev)
return 0;
}
-void vfc_i2c_delay_wakeup(struct vfc_dev *dev)
-{
- /* Used to profile code and eliminate too many delays */
- VFC_I2C_DEBUG_PRINTK(("vfc%d: Delaying\n", dev->instance));
- wake_up(&dev->poll_wait);
-}
-
void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs)
{
- DEFINE_WAIT(wait);
- init_timer(&dev->poll_timer);
- dev->poll_timer.expires = jiffies + usecs_to_jiffies(usecs);
- dev->poll_timer.data=(unsigned long)dev;
- dev->poll_timer.function=(void *)(unsigned long)vfc_i2c_delay_wakeup;
- add_timer(&dev->poll_timer);
- prepare_to_wait(&dev->poll_wait, &wait, TASK_UNINTERRUPTIBLE);
- schedule();
- del_timer(&dev->poll_timer);
- finish_wait(&dev->poll_wait, &wait);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(usecs_to_jiffies(usecs));
}
void inline vfc_i2c_delay(struct vfc_dev *dev)
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 96df148ed96..f1e8c4223ed 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -424,7 +424,7 @@ config SCSI_IN2000
source "drivers/scsi/megaraid/Kconfig.megaraid"
config SCSI_SATA
- bool "Serial ATA (SATA) support"
+ tristate "Serial ATA (SATA) support"
depends on SCSI
help
This driver family supports Serial ATA host controllers
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 3a11a536c0d..4ab07861b45 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -15,11 +15,7 @@
#define AAC_MAX_LUN (8)
#define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff)
-/*
- * max_sectors is an unsigned short, otherwise limit is 0x100000000 / 512
- * Linux has starvation problems if we permit larger than 4MB I/O ...
- */
-#define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)8192)
+#define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)512)
/*
* These macros convert from physical channels to virtual channels
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index c1a4f978fcb..562da90480a 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -374,7 +374,8 @@ static int aac_slave_configure(struct scsi_device *sdev)
else
scsi_adjust_queue_depth(sdev, 0, 1);
- if (host->max_sectors < AAC_MAX_32BIT_SGBCOUNT)
+ if (!(((struct aac_dev *)host->hostdata)->adapter_info.options
+ & AAC_OPT_NEW_COMM))
blk_queue_max_segment_size(sdev->request_queue, 65536);
return 0;
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 116d0f51ca2..687f19e9cf0 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -1264,14 +1264,12 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
}
switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) {
case AHC_DEV_Q_BASIC:
- scsi_adjust_queue_depth(sdev,
- MSG_SIMPLE_TASK,
- dev->openings + dev->active);
+ scsi_set_tag_type(sdev, MSG_SIMPLE_TAG);
+ scsi_activate_tcq(sdev, dev->openings + dev->active);
break;
case AHC_DEV_Q_TAGGED:
- scsi_adjust_queue_depth(sdev,
- MSG_ORDERED_TASK,
- dev->openings + dev->active);
+ scsi_set_tag_type(sdev, MSG_ORDERED_TAG);
+ scsi_activate_tcq(sdev, dev->openings + dev->active);
break;
default:
/*
@@ -1280,9 +1278,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
* serially on the controller/device. This should
* remove some latency.
*/
- scsi_adjust_queue_depth(sdev,
- /*NON-TAGGED*/0,
- /*queue depth*/2);
+ scsi_deactivate_tcq(sdev, 2);
break;
}
}
@@ -1635,9 +1631,9 @@ ahc_send_async(struct ahc_softc *ahc, char channel,
spi_period(starget) = tinfo->curr.period;
spi_width(starget) = tinfo->curr.width;
spi_offset(starget) = tinfo->curr.offset;
- spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ;
- spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ;
- spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ;
+ spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ ? 1 : 0;
+ spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ ? 1 : 0;
+ spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ ? 1 : 0;
spi_display_xfer_agreement(starget);
break;
}
@@ -2429,12 +2425,14 @@ static void ahc_linux_set_dt(struct scsi_target *starget, int dt)
unsigned int ppr_options = tinfo->goal.ppr_options
& ~MSG_EXT_PPR_DT_REQ;
unsigned int period = tinfo->goal.period;
+ unsigned int width = tinfo->goal.width;
unsigned long flags;
struct ahc_syncrate *syncrate;
if (dt) {
- period = 9; /* 12.5ns is the only period valid for DT */
ppr_options |= MSG_EXT_PPR_DT_REQ;
+ if (!width)
+ ahc_linux_set_width(starget, 1);
} else if (period == 9)
period = 10; /* if resetting DT, period must be >= 25ns */
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm.c b/drivers/scsi/aic7xxx/aicasm/aicasm.c
index c3463948190..f936b691232 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm.c
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm.c
@@ -369,7 +369,7 @@ output_code()
fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x",
cur_instr == STAILQ_FIRST(&seq_program) ? "" : ",\n",
-#if BYTE_ORDER == LITTLE_ENDIAN
+#ifdef __LITTLE_ENDIAN
cur_instr->format.bytes[0],
cur_instr->format.bytes[1],
cur_instr->format.bytes[2],
@@ -613,7 +613,7 @@ output_listing(char *ifilename)
line++;
}
fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr,
-#if BYTE_ORDER == LITTLE_ENDIAN
+#ifdef __LITTLE_ENDIAN
cur_instr->format.bytes[0],
cur_instr->format.bytes[1],
cur_instr->format.bytes[2],
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h b/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h
index 3e80f07df49..e64f802bbaa 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h
@@ -42,8 +42,10 @@
* $FreeBSD$
*/
+#include <asm/byteorder.h>
+
struct ins_format1 {
-#if BYTE_ORDER == LITTLE_ENDIAN
+#ifdef __LITTLE_ENDIAN
uint32_t immediate : 8,
source : 9,
destination : 9,
@@ -61,7 +63,7 @@ struct ins_format1 {
};
struct ins_format2 {
-#if BYTE_ORDER == LITTLE_ENDIAN
+#ifdef __LITTLE_ENDIAN
uint32_t shift_control : 8,
source : 9,
destination : 9,
@@ -79,7 +81,7 @@ struct ins_format2 {
};
struct ins_format3 {
-#if BYTE_ORDER == LITTLE_ENDIAN
+#ifdef __LITTLE_ENDIAN
uint32_t immediate : 8,
source : 9,
address : 10,
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 929170dcd3c..600ba120286 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -183,7 +183,7 @@
* cross a page boundy.
*/
#define SEGMENTX_LEN (sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY)
-#define VIRTX_LEN (sizeof(void *) * DC395x_MAX_SG_LISTENTRY)
+
struct SGentry {
u32 address; /* bus! address */
@@ -235,7 +235,6 @@ struct ScsiReqBlk {
u8 sg_count; /* No of HW sg entries for this request */
u8 sg_index; /* Index of HW sg entry for this request */
u32 total_xfer_length; /* Total number of bytes remaining to be transfered */
- void **virt_map;
unsigned char *virt_addr; /* Virtual address of current transfer position */
/*
@@ -1022,14 +1021,14 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
reqlen, cmd->request_buffer, cmd->use_sg,
srb->sg_count);
+ srb->virt_addr = page_address(sl->page);
for (i = 0; i < srb->sg_count; i++) {
- u32 seglen = (u32)sg_dma_len(sl + i);
- sgp[i].address = (u32)sg_dma_address(sl + i);
+ u32 busaddr = (u32)sg_dma_address(&sl[i]);
+ u32 seglen = (u32)sl[i].length;
+ sgp[i].address = busaddr;
sgp[i].length = seglen;
srb->total_xfer_length += seglen;
- srb->virt_map[i] = kmap(sl[i].page);
}
- srb->virt_addr = srb->virt_map[0];
sgp += srb->sg_count - 1;
/*
@@ -1976,7 +1975,6 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
int segment = cmd->use_sg;
u32 xferred = srb->total_xfer_length - left; /* bytes transfered */
struct SGentry *psge = srb->segment_x + srb->sg_index;
- void **virt = srb->virt_map;
dprintkdbg(DBG_0,
"sg_update_list: Transfered %i of %i bytes, %i remain\n",
@@ -2016,16 +2014,16 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
/* We have to walk the scatterlist to find it */
sg = (struct scatterlist *)cmd->request_buffer;
- idx = 0;
while (segment--) {
unsigned long mask =
~((unsigned long)sg->length - 1) & PAGE_MASK;
if ((sg_dma_address(sg) & mask) == (psge->address & mask)) {
- srb->virt_addr = virt[idx] + (psge->address & ~PAGE_MASK);
+ srb->virt_addr = (page_address(sg->page)
+ + psge->address -
+ (psge->address & PAGE_MASK));
return;
}
++sg;
- ++idx;
}
dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n");
@@ -2151,7 +2149,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
DC395x_read32(acb, TRM_S1040_DMA_CXCNT));
}
/*
- * calculate all the residue data that not yet transfered
+ * calculate all the residue data that not yet tranfered
* SCSI transfer counter + left in SCSI FIFO data
*
* .....TRM_S1040_SCSI_COUNTER (24bits)
@@ -3269,7 +3267,6 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
struct scsi_cmnd *cmd = srb->cmd;
enum dma_data_direction dir = cmd->sc_data_direction;
if (cmd->use_sg && dir != PCI_DMA_NONE) {
- int i;
/* unmap DC395x SG list */
dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n",
srb->sg_bus_addr, SEGMENTX_LEN);
@@ -3279,8 +3276,6 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n",
cmd->use_sg, cmd->request_buffer);
/* unmap the sg segments */
- for (i = 0; i < srb->sg_count; i++)
- kunmap(virt_to_page(srb->virt_map[i]));
pci_unmap_sg(acb->dev,
(struct scatterlist *)cmd->request_buffer,
cmd->use_sg, dir);
@@ -3327,7 +3322,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
if (cmd->use_sg) {
struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer;
- ptr = (struct ScsiInqData *)(srb->virt_map[0] + sg->offset);
+ ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset);
} else {
ptr = (struct ScsiInqData *)(cmd->request_buffer);
}
@@ -4262,9 +4257,8 @@ static void adapter_sg_tables_free(struct AdapterCtlBlk *acb)
const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN;
for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page)
- kfree(acb->srb_array[i].segment_x);
-
- vfree(acb->srb_array[0].virt_map);
+ if (acb->srb_array[i].segment_x)
+ kfree(acb->srb_array[i].segment_x);
}
@@ -4280,12 +4274,9 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
int srb_idx = 0;
unsigned i = 0;
struct SGentry *ptr;
- void **virt_array;
- for (i = 0; i < DC395x_MAX_SRB_CNT; i++) {
+ for (i = 0; i < DC395x_MAX_SRB_CNT; i++)
acb->srb_array[i].segment_x = NULL;
- acb->srb_array[i].virt_map = NULL;
- }
dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages);
while (pages--) {
@@ -4306,19 +4297,6 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
ptr + (i * DC395x_MAX_SG_LISTENTRY);
else
dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n");
-
- virt_array = vmalloc((DC395x_MAX_SRB_CNT + 1) * DC395x_MAX_SG_LISTENTRY * sizeof(void*));
-
- if (!virt_array) {
- adapter_sg_tables_free(acb);
- return 1;
- }
-
- for (i = 0; i < DC395x_MAX_SRB_CNT + 1; i++) {
- acb->srb_array[i].virt_map = virt_array;
- virt_array += DC395x_MAX_SG_LISTENTRY;
- }
-
return 0;
}
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index e2370529c63..7235f94f119 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -907,9 +907,13 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
raptorFlag = TRUE;
}
-
+ if (pci_request_regions(pDev, "dpt_i2o")) {
+ PERROR("dpti: adpt_config_hba: pci request region failed\n");
+ return -EINVAL;
+ }
base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size);
if (!base_addr_virt) {
+ pci_release_regions(pDev);
PERROR("dpti: adpt_config_hba: io remap failed\n");
return -EINVAL;
}
@@ -919,6 +923,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
if (!msg_addr_virt) {
PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n");
iounmap(base_addr_virt);
+ pci_release_regions(pDev);
return -EINVAL;
}
} else {
@@ -932,6 +937,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
iounmap(msg_addr_virt);
}
iounmap(base_addr_virt);
+ pci_release_regions(pDev);
return -ENOMEM;
}
memset(pHba, 0, sizeof(adpt_hba));
@@ -1027,6 +1033,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba)
up(&adpt_configuration_lock);
iounmap(pHba->base_addr_virt);
+ pci_release_regions(pHba->pDev);
if(pHba->msg_addr_virt != pHba->base_addr_virt){
iounmap(pHba->msg_addr_virt);
}
diff --git a/drivers/scsi/ibmvscsi/srp.h b/drivers/scsi/ibmvscsi/srp.h
index 2ae5154fd89..7d8e4c4accb 100644
--- a/drivers/scsi/ibmvscsi/srp.h
+++ b/drivers/scsi/ibmvscsi/srp.h
@@ -35,7 +35,7 @@
enum srp_types {
SRP_LOGIN_REQ_TYPE = 0x00,
SRP_LOGIN_RSP_TYPE = 0xC0,
- SRP_LOGIN_REJ_TYPE = 0x80,
+ SRP_LOGIN_REJ_TYPE = 0xC2,
SRP_I_LOGOUT_TYPE = 0x03,
SRP_T_LOGOUT_TYPE = 0x80,
SRP_TSK_MGMT_TYPE = 0x01,
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 6dfcb4fbccd..4cdd891781b 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -133,10 +133,12 @@
/* 6.10.00 - Remove 1G Addressing Limitations */
/* 6.11.xx - Get VersionInfo buffer off the stack ! DDTS 60401 */
/* 6.11.xx - Make Logical Drive Info structure safe for DMA DDTS 60639 */
-/* 7.10.xx - Add highmem_io flag in SCSI Templete for 2.4 kernels */
+/* 7.10.18 - Add highmem_io flag in SCSI Templete for 2.4 kernels */
/* - Fix path/name for scsi_hosts.h include for 2.6 kernels */
/* - Fix sort order of 7k */
/* - Remove 3 unused "inline" functions */
+/* 7.12.xx - Use STATIC functions whereever possible */
+/* - Clean up deprecated MODULE_PARM calls */
/*****************************************************************************/
/*
@@ -207,8 +209,8 @@ module_param(ips, charp, 0);
/*
* DRIVER_VER
*/
-#define IPS_VERSION_HIGH "7.10"
-#define IPS_VERSION_LOW ".18 "
+#define IPS_VERSION_HIGH "7.12"
+#define IPS_VERSION_LOW ".02 "
#if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__)
#warning "This driver has only been tested on the x86/ia64/x86_64 platforms"
diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h
index 480e06f4d6a..505e967013d 100644
--- a/drivers/scsi/ips.h
+++ b/drivers/scsi/ips.h
@@ -87,15 +87,14 @@
#define scsi_set_pci_device(sh,dev) (0)
#endif
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-
- #ifndef irqreturn_t
- typedef void irqreturn_t;
- #endif
-
+ #ifndef IRQ_NONE
+ typedef void irqreturn_t;
#define IRQ_NONE
#define IRQ_HANDLED
#define IRQ_RETVAL(x)
+ #endif
+
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#define IPS_REGISTER_HOSTS(SHT) scsi_register_module(MODULE_SCSI_HA,SHT)
#define IPS_UNREGISTER_HOSTS(SHT) scsi_unregister_module(MODULE_SCSI_HA,SHT)
#define IPS_ADD_HOST(shost,device)
@@ -123,6 +122,10 @@
#ifndef min
#define min(x,y) ((x) < (y) ? x : y)
#endif
+
+ #ifndef __iomem /* For clean compiles in earlier kernels without __iomem annotations */
+ #define __iomem
+ #endif
#define pci_dma_hi32(a) ((a >> 16) >> 16)
#define pci_dma_lo32(a) (a & 0xffffffff)
@@ -1206,13 +1209,13 @@ typedef struct {
#define IPS_VER_MAJOR 7
#define IPS_VER_MAJOR_STRING "7"
-#define IPS_VER_MINOR 10
-#define IPS_VER_MINOR_STRING "10"
-#define IPS_VER_BUILD 18
-#define IPS_VER_BUILD_STRING "18"
-#define IPS_VER_STRING "7.10.18"
+#define IPS_VER_MINOR 12
+#define IPS_VER_MINOR_STRING "12"
+#define IPS_VER_BUILD 02
+#define IPS_VER_BUILD_STRING "02"
+#define IPS_VER_STRING "7.12.02"
#define IPS_RELEASE_ID 0x00020000
-#define IPS_BUILD_IDENT 731
+#define IPS_BUILD_IDENT 761
#define IPS_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2002. All Rights Reserved."
#define IPS_ADAPTECCOPYRIGHT_STRING "(c) Copyright Adaptec, Inc. 2002 to 2004. All Rights Reserved."
#define IPS_DELLCOPYRIGHT_STRING "(c) Copyright Dell 2004. All Rights Reserved."
@@ -1223,12 +1226,12 @@ typedef struct {
#define IPS_VER_SERVERAID2 "2.88.13"
#define IPS_VER_NAVAJO "2.88.13"
#define IPS_VER_SERVERAID3 "6.10.24"
-#define IPS_VER_SERVERAID4H "7.10.11"
-#define IPS_VER_SERVERAID4MLx "7.10.18"
-#define IPS_VER_SARASOTA "7.10.18"
-#define IPS_VER_MARCO "7.10.18"
-#define IPS_VER_SEBRING "7.10.18"
-#define IPS_VER_KEYWEST "7.10.18"
+#define IPS_VER_SERVERAID4H "7.12.02"
+#define IPS_VER_SERVERAID4MLx "7.12.02"
+#define IPS_VER_SARASOTA "7.12.02"
+#define IPS_VER_MARCO "7.12.02"
+#define IPS_VER_SEBRING "7.12.02"
+#define IPS_VER_KEYWEST "7.12.02"
/* Compatability IDs for various adapters */
#define IPS_COMPAT_UNKNOWN ""
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 794fb559efb..6a75ec2187f 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -385,6 +385,7 @@ int ata_scsi_error(struct Scsi_Host *host)
* appropriate place
*/
host->host_failed--;
+ INIT_LIST_HEAD(&host->eh_cmd_q);
DPRINTK("EXIT\n");
return 0;
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index 140cea05de3..efd7d7a6113 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -468,7 +468,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
for (i = 0; i < last; i++) {
buf[idx++] = cpu_to_le32(sg_dma_address(&sg[i]));
buf[idx++] = cpu_to_le32(sg_dma_len(&sg[i]));
- total_len += sg[i].length;
+ total_len += sg_dma_len(&sg[i]);
}
buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT);
sgt_len = idx * 4;
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 2d3c4ac475f..48edd67982a 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -336,9 +336,23 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
unsigned long flags;
const int size = sizeof(struct scsi_target)
+ shost->transportt->target_size;
- struct scsi_target *starget = kmalloc(size, GFP_ATOMIC);
+ struct scsi_target *starget;
struct scsi_target *found_target;
+ /*
+ * Obtain the real parent from the transport. The transport
+ * is allowed to fail (no error) if there is nothing at that
+ * target id.
+ */
+ if (shost->transportt->target_parent) {
+ spin_lock_irqsave(shost->host_lock, flags);
+ parent = shost->transportt->target_parent(shost, channel, id);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ if (!parent)
+ return NULL;
+ }
+
+ starget = kmalloc(size, GFP_KERNEL);
if (!starget) {
printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
return NULL;
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 35d1c1e8e34..e6412fce423 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -1022,6 +1022,23 @@ static int fc_rport_match(struct attribute_container *cont,
return &i->rport_attr_cont.ac == cont;
}
+
+/*
+ * Must be called with shost->host_lock held
+ */
+static struct device *fc_target_parent(struct Scsi_Host *shost,
+ int channel, uint id)
+{
+ struct fc_rport *rport;
+
+ list_for_each_entry(rport, &fc_host_rports(shost), peers)
+ if ((rport->channel == channel) &&
+ (rport->scsi_target_id == id))
+ return &rport->dev;
+
+ return NULL;
+}
+
struct scsi_transport_template *
fc_attach_transport(struct fc_function_template *ft)
{
@@ -1057,6 +1074,8 @@ fc_attach_transport(struct fc_function_template *ft)
/* Transport uses the shost workq for scsi scanning */
i->t.create_work_queue = 1;
+
+ i->t.target_parent = fc_target_parent;
/*
* Setup SCSI Target Attributes.
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 0291a8fb654..0a7839db575 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -4149,12 +4149,10 @@ static int __init init_st(void)
do_create_driverfs_files();
return 0;
}
- if (st_sysfs_class)
- class_destroy(st_sysfs_class);
unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
-
ST_MAX_TAPE_ENTRIES);
}
+ class_destroy(st_sysfs_class);
printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", SCSI_TAPE_MAJOR);
return 1;
@@ -4162,13 +4160,11 @@ static int __init init_st(void)
static void __exit exit_st(void)
{
- if (st_sysfs_class)
- class_destroy(st_sysfs_class);
- st_sysfs_class = NULL;
do_remove_driverfs_files();
scsi_unregister_driver(&st_template.gendrv);
unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
ST_MAX_TAPE_ENTRIES);
+ class_destroy(st_sysfs_class);
kfree(scsi_tapes);
printk(KERN_INFO "st: Unloaded.\n");
}
diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h
index 5f6187baad8..73c8a088c16 100644
--- a/drivers/serial/cpm_uart/cpm_uart.h
+++ b/drivers/serial/cpm_uart/cpm_uart.h
@@ -40,13 +40,15 @@
#define TX_NUM_FIFO 4
#define TX_BUF_SIZE 32
+#define SCC_WAIT_CLOSING 100
+
struct uart_cpm_port {
struct uart_port port;
- u16 rx_nrfifos;
+ u16 rx_nrfifos;
u16 rx_fifosize;
- u16 tx_nrfifos;
+ u16 tx_nrfifos;
u16 tx_fifosize;
- smc_t *smcp;
+ smc_t *smcp;
smc_uart_t *smcup;
scc_t *sccp;
scc_uart_t *sccup;
@@ -67,6 +69,8 @@ struct uart_cpm_port {
int bits;
/* Keep track of 'odd' SMC2 wirings */
int is_portb;
+ /* wait on close if needed */
+ int wait_closing;
};
extern int cpm_uart_port_map[UART_NR];
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 29db677d428..d639ac92a11 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -9,9 +9,10 @@
*
* Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2)
* Pantelis Antoniou (panto@intracom.gr) (CPM1)
- *
+ *
* Copyright (C) 2004 Freescale Semiconductor, Inc.
* (C) 2004 Intracom, S.A.
+ * (C) 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -70,8 +71,22 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo);
/**************************************************************/
+static inline unsigned long cpu2cpm_addr(void *addr)
+{
+ if ((unsigned long)addr >= CPM_ADDR)
+ return (unsigned long)addr;
+ return virt_to_bus(addr);
+}
+
+static inline void *cpm2cpu_addr(unsigned long addr)
+{
+ if (addr >= CPM_ADDR)
+ return (void *)addr;
+ return bus_to_virt(addr);
+}
+
/*
- * Check, if transmit buffers are processed
+ * Check, if transmit buffers are processed
*/
static unsigned int cpm_uart_tx_empty(struct uart_port *port)
{
@@ -143,15 +158,18 @@ static void cpm_uart_start_tx(struct uart_port *port, unsigned int tty_start)
}
if (cpm_uart_tx_pump(port) != 0) {
- if (IS_SMC(pinfo))
+ if (IS_SMC(pinfo)) {
smcp->smc_smcm |= SMCM_TX;
- else
+ smcp->smc_smcmr |= SMCMR_TEN;
+ } else {
sccp->scc_sccm |= UART_SCCM_TX;
+ pinfo->sccp->scc_gsmrl |= SCC_GSMRL_ENT;
+ }
}
}
/*
- * Stop receiver
+ * Stop receiver
*/
static void cpm_uart_stop_rx(struct uart_port *port)
{
@@ -176,7 +194,7 @@ static void cpm_uart_enable_ms(struct uart_port *port)
}
/*
- * Generate a break.
+ * Generate a break.
*/
static void cpm_uart_break_ctl(struct uart_port *port, int break_state)
{
@@ -231,7 +249,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
/* get number of characters, and check spce in flip-buffer */
i = bdp->cbd_datlen;
- /* If we have not enough room in tty flip buffer, then we try
+ /* If we have not enough room in tty flip buffer, then we try
* later, which will be the next rx-interrupt or a timeout
*/
if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) {
@@ -243,7 +261,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
}
/* get pointer */
- cp = (unsigned char *)bus_to_virt(bdp->cbd_bufaddr);
+ cp = cpm2cpu_addr(bdp->cbd_bufaddr);
/* loop through the buffer */
while (i-- > 0) {
@@ -265,13 +283,14 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
} /* End while (i--) */
/* This BD is ready to be used again. Clear status. get next */
- bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
+ bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID);
bdp->cbd_sc |= BD_SC_EMPTY;
if (bdp->cbd_sc & BD_SC_WRAP)
bdp = pinfo->rx_bd_base;
else
bdp++;
+
} /* End for (;;) */
/* Write back buffer pointer */
@@ -336,22 +355,22 @@ static irqreturn_t cpm_uart_int(int irq, void *data, struct pt_regs *regs)
if (IS_SMC(pinfo)) {
events = smcp->smc_smce;
+ smcp->smc_smce = events;
if (events & SMCM_BRKE)
uart_handle_break(port);
if (events & SMCM_RX)
cpm_uart_int_rx(port, regs);
if (events & SMCM_TX)
cpm_uart_int_tx(port, regs);
- smcp->smc_smce = events;
} else {
events = sccp->scc_scce;
+ sccp->scc_scce = events;
if (events & UART_SCCM_BRKE)
uart_handle_break(port);
if (events & UART_SCCM_RX)
cpm_uart_int_rx(port, regs);
if (events & UART_SCCM_TX)
cpm_uart_int_tx(port, regs);
- sccp->scc_scce = events;
}
return (events) ? IRQ_HANDLED : IRQ_NONE;
}
@@ -360,6 +379,7 @@ static int cpm_uart_startup(struct uart_port *port)
{
int retval;
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+ int line = pinfo - cpm_uart_ports;
pr_debug("CPM uart[%d]:startup\n", port->line);
@@ -376,9 +396,19 @@ static int cpm_uart_startup(struct uart_port *port)
pinfo->sccp->scc_sccm |= UART_SCCM_RX;
}
+ if (!(pinfo->flags & FLAG_CONSOLE))
+ cpm_line_cr_cmd(line,CPM_CR_INIT_TRX);
return 0;
}
+inline void cpm_uart_wait_until_send(struct uart_cpm_port *pinfo)
+{
+ unsigned long target_jiffies = jiffies + pinfo->wait_closing;
+
+ while (!time_after(jiffies, target_jiffies))
+ schedule();
+}
+
/*
* Shutdown the uart
*/
@@ -394,6 +424,12 @@ static void cpm_uart_shutdown(struct uart_port *port)
/* If the port is not the console, disable Rx and Tx. */
if (!(pinfo->flags & FLAG_CONSOLE)) {
+ /* Wait for all the BDs marked sent */
+ while(!cpm_uart_tx_empty(port))
+ schedule_timeout(2);
+ if(pinfo->wait_closing)
+ cpm_uart_wait_until_send(pinfo);
+
/* Stop uarts */
if (IS_SMC(pinfo)) {
volatile smc_t *smcp = pinfo->smcp;
@@ -502,7 +538,7 @@ static void cpm_uart_set_termios(struct uart_port *port,
*/
if ((termios->c_cflag & CREAD) == 0)
port->read_status_mask &= ~BD_SC_EMPTY;
-
+
spin_lock_irqsave(&port->lock, flags);
/* Start bit has not been added (so don't, because we would just
@@ -569,7 +605,8 @@ static int cpm_uart_tx_pump(struct uart_port *port)
/* Pick next descriptor and fill from buffer */
bdp = pinfo->tx_cur;
- p = bus_to_virt(bdp->cbd_bufaddr);
+ p = cpm2cpu_addr(bdp->cbd_bufaddr);
+
*p++ = xmit->buf[xmit->tail];
bdp->cbd_datlen = 1;
bdp->cbd_sc |= BD_SC_READY;
@@ -595,7 +632,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
count = 0;
- p = bus_to_virt(bdp->cbd_bufaddr);
+ p = cpm2cpu_addr(bdp->cbd_bufaddr);
while (count < pinfo->tx_fifosize) {
*p++ = xmit->buf[xmit->tail];
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -606,6 +643,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
}
bdp->cbd_datlen = count;
bdp->cbd_sc |= BD_SC_READY;
+ __asm__("eieio");
/* Get next BD. */
if (bdp->cbd_sc & BD_SC_WRAP)
bdp = pinfo->tx_bd_base;
@@ -643,12 +681,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
mem_addr = pinfo->mem_addr;
bdp = pinfo->rx_cur = pinfo->rx_bd_base;
for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) {
- bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+ bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
mem_addr += pinfo->rx_fifosize;
}
-
- bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+
+ bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
/* Set the physical address of the host memory
@@ -658,12 +696,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize);
bdp = pinfo->tx_cur = pinfo->tx_bd_base;
for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) {
- bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+ bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
bdp->cbd_sc = BD_SC_INTRPT;
mem_addr += pinfo->tx_fifosize;
}
-
- bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+
+ bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT;
}
@@ -763,6 +801,8 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
/* Using idle charater time requires some additional tuning. */
up->smc_mrblr = pinfo->rx_fifosize;
up->smc_maxidl = pinfo->rx_fifosize;
+ up->smc_brklen = 0;
+ up->smc_brkec = 0;
up->smc_brkcr = 1;
cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);
@@ -796,7 +836,7 @@ static int cpm_uart_request_port(struct uart_port *port)
/*
* Setup any port IO, connect any baud rate generators,
* etc. This is expected to be handled by board
- * dependant code
+ * dependant code
*/
if (pinfo->set_lineif)
pinfo->set_lineif(pinfo);
@@ -815,6 +855,10 @@ static int cpm_uart_request_port(struct uart_port *port)
return ret;
cpm_uart_initbd(pinfo);
+ if (IS_SMC(pinfo))
+ cpm_uart_init_smc(pinfo);
+ else
+ cpm_uart_init_scc(pinfo);
return 0;
}
@@ -869,7 +913,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.flags = FLAG_SMC,
.tx_nrfifos = TX_NUM_FIFO,
.tx_fifosize = TX_BUF_SIZE,
- .rx_nrfifos = RX_NUM_FIFO,
+ .rx_nrfifos = RX_NUM_FIFO,
.rx_fifosize = RX_BUF_SIZE,
.set_lineif = smc1_lineif,
},
@@ -883,7 +927,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.flags = FLAG_SMC,
.tx_nrfifos = TX_NUM_FIFO,
.tx_fifosize = TX_BUF_SIZE,
- .rx_nrfifos = RX_NUM_FIFO,
+ .rx_nrfifos = RX_NUM_FIFO,
.rx_fifosize = RX_BUF_SIZE,
.set_lineif = smc2_lineif,
#ifdef CONFIG_SERIAL_CPM_ALT_SMC2
@@ -899,9 +943,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
},
.tx_nrfifos = TX_NUM_FIFO,
.tx_fifosize = TX_BUF_SIZE,
- .rx_nrfifos = RX_NUM_FIFO,
+ .rx_nrfifos = RX_NUM_FIFO,
.rx_fifosize = RX_BUF_SIZE,
.set_lineif = scc1_lineif,
+ .wait_closing = SCC_WAIT_CLOSING,
},
[UART_SCC2] = {
.port = {
@@ -912,9 +957,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
},
.tx_nrfifos = TX_NUM_FIFO,
.tx_fifosize = TX_BUF_SIZE,
- .rx_nrfifos = RX_NUM_FIFO,
+ .rx_nrfifos = RX_NUM_FIFO,
.rx_fifosize = RX_BUF_SIZE,
.set_lineif = scc2_lineif,
+ .wait_closing = SCC_WAIT_CLOSING,
},
[UART_SCC3] = {
.port = {
@@ -925,9 +971,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
},
.tx_nrfifos = TX_NUM_FIFO,
.tx_fifosize = TX_BUF_SIZE,
- .rx_nrfifos = RX_NUM_FIFO,
+ .rx_nrfifos = RX_NUM_FIFO,
.rx_fifosize = RX_BUF_SIZE,
.set_lineif = scc3_lineif,
+ .wait_closing = SCC_WAIT_CLOSING,
},
[UART_SCC4] = {
.port = {
@@ -938,9 +985,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
},
.tx_nrfifos = TX_NUM_FIFO,
.tx_fifosize = TX_BUF_SIZE,
- .rx_nrfifos = RX_NUM_FIFO,
+ .rx_nrfifos = RX_NUM_FIFO,
.rx_fifosize = RX_BUF_SIZE,
.set_lineif = scc4_lineif,
+ .wait_closing = SCC_WAIT_CLOSING,
},
};
@@ -983,11 +1031,8 @@ static void cpm_uart_console_write(struct console *co, const char *s,
* If the buffer address is in the CPM DPRAM, don't
* convert it.
*/
- if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR)
- cp = (unsigned char *) (bdp->cbd_bufaddr);
- else
- cp = bus_to_virt(bdp->cbd_bufaddr);
-
+ cp = cpm2cpu_addr(bdp->cbd_bufaddr);
+
*cp = *s;
bdp->cbd_datlen = 1;
@@ -1003,10 +1048,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
while ((bdp->cbd_sc & BD_SC_READY) != 0)
;
- if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR)
- cp = (unsigned char *) (bdp->cbd_bufaddr);
- else
- cp = bus_to_virt(bdp->cbd_bufaddr);
+ cp = cpm2cpu_addr(bdp->cbd_bufaddr);
*cp = 13;
bdp->cbd_datlen = 1;
@@ -1045,7 +1087,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
port =
(struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
pinfo = (struct uart_cpm_port *)port;
-
+
pinfo->flags |= FLAG_CONSOLE;
if (options) {
@@ -1062,7 +1104,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
/*
* Setup any port IO, connect any baud rate generators,
* etc. This is expected to be handled by board
- * dependant code
+ * dependant code
*/
if (pinfo->set_lineif)
pinfo->set_lineif(pinfo);
@@ -1092,14 +1134,14 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
return 0;
}
-extern struct uart_driver cpm_reg;
+static struct uart_driver cpm_reg;
static struct console cpm_scc_uart_console = {
- .name "ttyCPM",
- .write cpm_uart_console_write,
- .device uart_console_device,
- .setup cpm_uart_console_setup,
- .flags CON_PRINTBUFFER,
- .index -1,
+ .name = "ttyCPM",
+ .write = cpm_uart_console_write,
+ .device = uart_console_device,
+ .setup = cpm_uart_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
.data = &cpm_reg,
};
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
index 8efbd6d1d6a..4b0786e7eb7 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
@@ -5,7 +5,7 @@
*
* Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2)
* Pantelis Antoniou (panto@intracom.gr) (CPM1)
- *
+ *
* Copyright (C) 2004 Freescale Semiconductor, Inc.
* (C) 2004 Intracom, S.A.
*
@@ -82,6 +82,17 @@ void cpm_line_cr_cmd(int line, int cmd)
void smc1_lineif(struct uart_cpm_port *pinfo)
{
volatile cpm8xx_t *cp = cpmp;
+
+ (void)cp; /* fix warning */
+#if defined (CONFIG_MPC885ADS)
+ /* Enable SMC1 transceivers */
+ {
+ cp->cp_pepar |= 0x000000c0;
+ cp->cp_pedir &= ~0x000000c0;
+ cp->cp_peso &= ~0x00000040;
+ cp->cp_peso |= 0x00000080;
+ }
+#elif defined (CONFIG_MPC86XADS)
unsigned int iobits = 0x000000c0;
if (!pinfo->is_portb) {
@@ -93,41 +104,33 @@ void smc1_lineif(struct uart_cpm_port *pinfo)
((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
}
-
-#ifdef CONFIG_MPC885ADS
- /* Enable SMC1 transceivers */
- {
- volatile uint __iomem *bcsr1 = ioremap(BCSR1, 4);
- uint tmp;
-
- tmp = in_be32(bcsr1);
- tmp &= ~BCSR1_RS232EN_1;
- out_be32(bcsr1, tmp);
- iounmap(bcsr1);
- }
#endif
-
pinfo->brg = 1;
}
void smc2_lineif(struct uart_cpm_port *pinfo)
{
-#ifdef CONFIG_MPC885ADS
volatile cpm8xx_t *cp = cpmp;
- volatile uint __iomem *bcsr1;
- uint tmp;
+ (void)cp; /* fix warning */
+#if defined (CONFIG_MPC885ADS)
cp->cp_pepar |= 0x00000c00;
cp->cp_pedir &= ~0x00000c00;
cp->cp_peso &= ~0x00000400;
cp->cp_peso |= 0x00000800;
+#elif defined (CONFIG_MPC86XADS)
+ unsigned int iobits = 0x00000c00;
+
+ if (!pinfo->is_portb) {
+ cp->cp_pbpar |= iobits;
+ cp->cp_pbdir &= ~iobits;
+ cp->cp_pbodr &= ~iobits;
+ } else {
+ ((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits;
+ ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
+ ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
+ }
- /* Enable SMC2 transceivers */
- bcsr1 = ioremap(BCSR1, 4);
- tmp = in_be32(bcsr1);
- tmp &= ~BCSR1_RS232EN_2;
- out_be32(bcsr1, tmp);
- iounmap(bcsr1);
#endif
pinfo->brg = 2;
@@ -158,7 +161,7 @@ void scc4_lineif(struct uart_cpm_port *pinfo)
}
/*
- * Allocate DP-Ram and memory buffers. We need to allocate a transmit and
+ * Allocate DP-Ram and memory buffers. We need to allocate a transmit and
* receive buffer descriptors from dual port ram, and a character
* buffer area from host mem. If we are allocating for the console we need
* to do it from bootmem
@@ -185,6 +188,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
if (is_con) {
+ /* was hostalloc but changed cause it blows away the */
+ /* large tlb mapping when pinning the kernel area */
mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
dma_addr = 0;
} else
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 50cb0183107..b01efb6b36f 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -527,7 +527,7 @@ show_periodic (struct class_device *class_dev, char *buf)
p.qh->period,
le32_to_cpup (&p.qh->hw_info2)
/* uframe masks */
- & 0xffff,
+ & (QH_CMASK | QH_SMASK),
p.qh);
size -= temp;
next += temp;
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 4f97a4ad1ed..20df01a79b2 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -222,7 +222,7 @@ __acquires(ehci->lock)
struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv;
/* S-mask in a QH means it's an interrupt urb */
- if ((qh->hw_info2 & __constant_cpu_to_le32 (0x00ff)) != 0) {
+ if ((qh->hw_info2 & __constant_cpu_to_le32 (QH_SMASK)) != 0) {
/* ... update hc-wide periodic stats (for usbfs) */
ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
@@ -428,7 +428,8 @@ halt:
/* should be rare for periodic transfers,
* except maybe high bandwidth ...
*/
- if (qh->period) {
+ if ((__constant_cpu_to_le32 (QH_SMASK)
+ & qh->hw_info2) != 0) {
intr_deschedule (ehci, qh);
(void) qh_schedule (ehci, qh);
} else
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 9af4f64532a..b56f25864ed 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -301,7 +301,7 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
dev_dbg (&qh->dev->dev,
"link qh%d-%04x/%p start %d [%d/%d us]\n",
- period, le32_to_cpup (&qh->hw_info2) & 0xffff,
+ period, le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK),
qh, qh->start, qh->usecs, qh->c_usecs);
/* high bandwidth, or otherwise every microframe */
@@ -385,7 +385,8 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
dev_dbg (&qh->dev->dev,
"unlink qh%d-%04x/%p start %d [%d/%d us]\n",
- qh->period, le32_to_cpup (&qh->hw_info2) & 0xffff,
+ qh->period,
+ le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK),
qh, qh->start, qh->usecs, qh->c_usecs);
/* qh->qh_next still "live" to HC */
@@ -411,7 +412,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
* active high speed queues may need bigger delays...
*/
if (list_empty (&qh->qtd_list)
- || (__constant_cpu_to_le32 (0x0ff << 8)
+ || (__constant_cpu_to_le32 (QH_CMASK)
& qh->hw_info2) != 0)
wait = 2;
else
@@ -533,7 +534,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
/* reuse the previous schedule slots, if we can */
if (frame < qh->period) {
- uframe = ffs (le32_to_cpup (&qh->hw_info2) & 0x00ff);
+ uframe = ffs (le32_to_cpup (&qh->hw_info2) & QH_SMASK);
status = check_intr_schedule (ehci, frame, --uframe,
qh, &c_mask);
} else {
@@ -569,10 +570,10 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
qh->start = frame;
/* reset S-frame and (maybe) C-frame masks */
- qh->hw_info2 &= __constant_cpu_to_le32 (~0xffff);
+ qh->hw_info2 &= __constant_cpu_to_le32(~(QH_CMASK | QH_SMASK));
qh->hw_info2 |= qh->period
? cpu_to_le32 (1 << uframe)
- : __constant_cpu_to_le32 (0xff);
+ : __constant_cpu_to_le32 (QH_SMASK);
qh->hw_info2 |= c_mask;
} else
ehci_dbg (ehci, "reused qh %p schedule\n", qh);
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 4df49823175..a7542157534 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -385,6 +385,11 @@ struct ehci_qh {
__le32 hw_info1; /* see EHCI 3.6.2 */
#define QH_HEAD 0x00008000
__le32 hw_info2; /* see EHCI 3.6.2 */
+#define QH_SMASK 0x000000ff
+#define QH_CMASK 0x0000ff00
+#define QH_HUBADDR 0x007f0000
+#define QH_HUBPORT 0x3f800000
+#define QH_MULT 0xc0000000
__le32 hw_current; /* qtd list - see EHCI 3.6.4 */
/* qtd overlay (hardware parts of a struct ehci_qtd) */
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 50b1970fe6b..76cb496c583 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -229,9 +229,11 @@ static void preproc_atl_queue(struct isp116x *isp116x)
struct isp116x_ep *ep;
struct urb *urb;
struct ptd *ptd;
- u16 toggle = 0, dir = PTD_DIR_SETUP, len;
+ u16 len;
for (ep = isp116x->atl_active; ep; ep = ep->active) {
+ u16 toggle = 0, dir = PTD_DIR_SETUP;
+
BUG_ON(list_empty(&ep->hep->urb_list));
urb = container_of(ep->hep->urb_list.next,
struct urb, urb_list);
diff --git a/drivers/usb/mon/Kconfig b/drivers/usb/mon/Kconfig
index 777642e26b9..deb9ddffa40 100644
--- a/drivers/usb/mon/Kconfig
+++ b/drivers/usb/mon/Kconfig
@@ -9,9 +9,8 @@ config USB_MON
help
If you say Y here, a component which captures the USB traffic
between peripheral-specific drivers and HC drivers will be built.
- The USB_MON is similar in spirit and may be compatible with Dave
- Harding's USBMon.
+ For more information, see <file:Documentation/usb/usbmon.txt>.
- This is somewhat experimental at this time, but it should be safe,
- as long as you aren't using modular USB and try to remove this
- module.
+ This is somewhat experimental at this time, but it should be safe.
+
+ If unsure, say Y.
diff --git a/drivers/usb/mon/Makefile b/drivers/usb/mon/Makefile
index f18d10ce91f..b0015b8a1d1 100644
--- a/drivers/usb/mon/Makefile
+++ b/drivers/usb/mon/Makefile
@@ -4,4 +4,5 @@
usbmon-objs := mon_main.o mon_stat.o mon_text.o
+# This does not use CONFIG_USB_MON because we want this to use a tristate.
obj-$(CONFIG_USB) += usbmon.o
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index ed1d4d1ac4f..1147b899f00 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -414,6 +414,13 @@ static ssize_t show_pan(struct class_device *class_device, char *buf)
fb_info->var.xoffset);
}
+static ssize_t show_name(struct class_device *class_device, char *buf)
+{
+ struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", fb_info->fix.id);
+}
+
static struct class_device_attribute class_device_attrs[] = {
__ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
__ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
@@ -424,6 +431,7 @@ static struct class_device_attribute class_device_attrs[] = {
__ATTR(modes, S_IRUGO|S_IWUSR, show_modes, store_modes),
__ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan),
__ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual),
+ __ATTR(name, S_IRUGO, show_name, NULL),
};
int fb_init_class_device(struct fb_info *fb_info)
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index fbf659b6dab..3edc9f49344 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -246,6 +246,11 @@ static const struct fb_videomode modedb[] = {
/* 480x300 @ 72 Hz, 48.0 kHz hsync */
NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3,
0, FB_VMODE_DOUBLE
+ }, {
+ /* 1920x1200 @ 60 Hz, 74.5 Khz hsync */
+ NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED
},
};
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index b2e6b240786..52b16850a54 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -1324,6 +1324,13 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
fb_videomode_to_var(&nvidiafb_default_var, &modedb);
nvidiafb_default_var.bits_per_pixel = 8;
+ } else if (par->fpWidth && par->fpHeight) {
+ char buf[16];
+
+ memset(buf, 0, 16);
+ snprintf(buf, 15, "%dx%d", par->fpWidth, par->fpHeight);
+ fb_find_mode(&nvidiafb_default_var, info, buf, specs->modedb,
+ specs->modedb_len, &modedb, 8);
}
if (mode_option)
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 16e37a535d8..30112816420 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -717,6 +717,9 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
DPRINTK("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2);
DPRINTK("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
+ /* enable LCD controller clock */
+ pxa_set_cken(CKEN16_LCD, 1);
+
/* Sequence from 11.7.10 */
LCCR3 = fbi->reg_lccr3;
LCCR2 = fbi->reg_lccr2;
@@ -750,6 +753,9 @@ static void pxafb_disable_controller(struct pxafb_info *fbi)
schedule_timeout(20 * HZ / 1000);
remove_wait_queue(&fbi->ctrlr_wait, &wait);
+
+ /* disable LCD controller clock */
+ pxa_set_cken(CKEN16_LCD, 0);
}
/*
@@ -1299,8 +1305,6 @@ int __init pxafb_probe(struct device *dev)
ret = -ENOMEM;
goto failed;
}
- /* enable LCD controller clock */
- pxa_set_cken(CKEN16_LCD, 1);
ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT, "LCD", fbi);
if (ret) {
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index 2d29db7ef80..beeec7b5142 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -598,7 +598,7 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* requests for the LCD controller. If we hit this, it means we're
* doing nothing but LCD DMA.
*/
-static unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var)
+static inline unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var)
{
/*
* Period = pixclock * bits_per_byte * bytes_per_transfer
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index da8004e5d03..698ca9232e7 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -454,13 +454,16 @@ static struct accel_switch accel_image = {
static void tridentfb_fillrect(struct fb_info * info, const struct fb_fillrect *fr)
{
int bpp = info->var.bits_per_pixel;
- int col;
+ int col = 0;
switch (bpp) {
default:
- case 8: col = fr->color;
+ case 8: col |= fr->color;
+ col |= col << 8;
+ col |= col << 16;
break;
case 16: col = ((u32 *)(info->pseudo_palette))[fr->color];
+
break;
case 32: col = ((u32 *)(info->pseudo_palette))[fr->color];
break;
@@ -882,8 +885,9 @@ static int tridentfb_set_par(struct fb_info *info)
write3X4(GraphEngReg, 0x80); //enable GE for text acceleration
-// if (info->var.accel_flags & FB_ACCELF_TEXT)
-//FIXME acc->init_accel(info->var.xres,bpp);
+#ifdef CONFIG_FB_TRIDENT_ACCEL
+ acc->init_accel(info->var.xres,bpp);
+#endif
switch (bpp) {
case 8: tmp = 0x00; break;
@@ -900,7 +904,7 @@ static int tridentfb_set_par(struct fb_info *info)
write3X4(DRAMControl, tmp); //both IO,linear enable
write3X4(InterfaceSel, read3X4(InterfaceSel) | 0x40);
- write3X4(Performance,0x20);
+ write3X4(Performance,0x92);
write3X4(PCIReg,0x07); //MMIO & PCI read and write burst enable
/* convert from picoseconds to MHz */
@@ -981,12 +985,14 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green,
t_outb(green>>10,0x3C9);
t_outb(blue>>10,0x3C9);
- } else
- if (bpp == 16) /* RGB 565 */
- ((u32*)info->pseudo_palette)[regno] = (red & 0xF800) |
- ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
- else
- if (bpp == 32) /* ARGB 8888 */
+ } else if (bpp == 16) { /* RGB 565 */
+ u32 col;
+
+ col = (red & 0xF800) | ((green & 0xFC00) >> 5) |
+ ((blue & 0xF800) >> 11);
+ col |= col << 16;
+ ((u32 *)(info->pseudo_palette))[regno] = col;
+ } else if (bpp == 32) /* ARGB 8888 */
((u32*)info->pseudo_palette)[regno] =
((transp & 0xFF00) <<16) |
((red & 0xFF00) << 8) |
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 8a9c4282250..0bbf029b1ef 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -593,7 +593,7 @@ void w1_search(struct w1_master *dev, w1_slave_found_callback cb)
* Return 0 - device(s) present, 1 - no devices present.
*/
if (w1_reset_bus(dev)) {
- dev_info(&dev->dev, "No devices present on the wire.\n");
+ dev_dbg(&dev->dev, "No devices present on the wire.\n");
break;
}