diff options
Diffstat (limited to 'drivers')
84 files changed, 1905 insertions, 1835 deletions
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index d25ef961415..44ad90c03c2 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -610,7 +610,7 @@ write_led(const char __user * buffer, unsigned long count, (led_out) ? (hotk->status | ledmask) : (hotk->status & ~ledmask); if (invert) /* invert target value */ - led_out = !led_out & 0x1; + led_out = !led_out; if (!write_acpi_int(hotk->handle, ledname, led_out, NULL)) printk(KERN_WARNING "Asus ACPI: LED (%s) write failed\n", diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index f6215e80980..d5729d5dc19 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -293,13 +293,12 @@ static int extract_package(struct acpi_battery *battery, strncpy(ptr, (u8 *)&element->integer.value, sizeof(acpi_integer)); ptr[sizeof(acpi_integer)] = 0; - } else return -EFAULT; + } else + *ptr = 0; /* don't have value */ } else { - if (element->type == ACPI_TYPE_INTEGER) { - int *x = (int *)((u8 *)battery + - offsets[i].offset); - *x = element->integer.value; - } else return -EFAULT; + int *x = (int *)((u8 *)battery + offsets[i].offset); + *x = (element->type == ACPI_TYPE_INTEGER) ? + element->integer.value : -1; } } return 0; diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 307cef65c24..fa44fb96fc3 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -710,6 +710,7 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr, if (!count) return -EINVAL; + begin_undock(dock_station); ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST); return ret ? ret: count; } diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index e7e197e3a4f..7222a18a031 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -129,7 +129,6 @@ static struct acpi_ec { struct mutex lock; wait_queue_head_t wait; struct list_head list; - atomic_t irq_count; u8 handlers_installed; } *boot_ec, *first_ec; @@ -182,8 +181,6 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) { int ret = 0; - atomic_set(&ec->irq_count, 0); - if (unlikely(event == ACPI_EC_EVENT_OBF_1 && test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags))) force_poll = 1; @@ -230,7 +227,6 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) while (time_before(jiffies, delay)) { if (acpi_ec_check_status(ec, event)) goto end; - msleep(5); } } pr_err(PREFIX "acpi_ec_wait timeout," @@ -533,13 +529,6 @@ static u32 acpi_ec_gpe_handler(void *data) struct acpi_ec *ec = data; pr_debug(PREFIX "~~~> interrupt\n"); - atomic_inc(&ec->irq_count); - if (atomic_read(&ec->irq_count) > 5) { - pr_err(PREFIX "GPE storm detected, disabling EC GPE\n"); - acpi_disable_gpe(NULL, ec->gpe, ACPI_ISR); - clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); - return ACPI_INTERRUPT_HANDLED; - } clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) wake_up(&ec->wait); diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 6f3b217699e..e8e2d886923 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -216,8 +216,10 @@ static void acpi_safe_halt(void) * test NEED_RESCHED: */ smp_mb(); - if (!need_resched()) + if (!need_resched()) { safe_halt(); + local_irq_disable(); + } current_thread_info()->status |= TS_POLLING; } @@ -421,7 +423,9 @@ static void acpi_processor_idle(void) else acpi_safe_halt(); - local_irq_enable(); + if (irqs_disabled()) + local_irq_enable(); + return; } @@ -530,7 +534,9 @@ static void acpi_processor_idle(void) * skew otherwise. */ sleep_ticks = 0xFFFFFFFF; - local_irq_enable(); + if (irqs_disabled()) + local_irq_enable(); + break; case ACPI_STATE_C2: diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 1bc0c74f275..12fb44f1676 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -807,40 +807,11 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video) static int acpi_video_bus_check(struct acpi_video_bus *video) { acpi_status status = -ENOENT; - long device_id; - struct device *dev; - struct acpi_device *device; + if (!video) return -EINVAL; - device = video->device; - - status = - acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id); - - if (!ACPI_SUCCESS(status)) - return -ENODEV; - - /* We need to attempt to determine whether the _ADR refers to a - PCI device or not. There's no terribly good way to do this, - so the best we can hope for is to assume that there'll never - be a video device in the host bridge */ - if (device_id >= 0x10000) { - /* It looks like a PCI device. Does it exist? */ - dev = acpi_get_physical_device(device->handle); - } else { - /* It doesn't look like a PCI device. Does its parent - exist? */ - acpi_handle phandle; - if (acpi_get_parent(device->handle, &phandle)) - return -ENODEV; - dev = acpi_get_physical_device(phandle); - } - if (!dev) - return -ENODEV; - put_device(dev); - /* Since there is no HID, CID and so on for VGA driver, we have * to check well known required nodes. */ @@ -1366,37 +1337,8 @@ acpi_video_bus_write_DOS(struct file *file, static int acpi_video_bus_add_fs(struct acpi_device *device) { - long device_id; - int status; struct proc_dir_entry *entry = NULL; struct acpi_video_bus *video; - struct device *dev; - - status = - acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id); - - if (!ACPI_SUCCESS(status)) - return -ENODEV; - - /* We need to attempt to determine whether the _ADR refers to a - PCI device or not. There's no terribly good way to do this, - so the best we can hope for is to assume that there'll never - be a video device in the host bridge */ - if (device_id >= 0x10000) { - /* It looks like a PCI device. Does it exist? */ - dev = acpi_get_physical_device(device->handle); - } else { - /* It doesn't look like a PCI device. Does its parent - exist? */ - acpi_handle phandle; - if (acpi_get_parent(device->handle, &phandle)) - return -ENODEV; - dev = acpi_get_physical_device(phandle); - } - if (!dev) - return -ENODEV; - put_device(dev); - video = acpi_driver_data(device); diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index e469647330d..25aba69b59b 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -30,6 +30,7 @@ config ATA_NONSTANDARD config ATA_ACPI bool depends on ACPI && PCI + select ACPI_DOCK default y help This option adds support for ATA-related ACPI objects. diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index b6d230b3209..0d1d2133d9b 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -44,16 +44,6 @@ config MAC_FLOPPY If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple) floppy controller, say Y here. Most commonly found in PowerMacs. -config BLK_DEV_PS2 - tristate "PS/2 ESDI hard disk support" - depends on MCA && MCA_LEGACY && BROKEN - help - Say Y here if you have a PS/2 machine with a MCA bus and an ESDI - hard disk. - - To compile this driver as a module, choose M here: the - module will be called ps2esdi. - config AMIGA_Z2RAM tristate "Amiga Zorro II ramdisk support" depends on ZORRO diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 01c972415cb..5e584306be9 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -13,7 +13,6 @@ obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o obj-$(CONFIG_BLK_DEV_RAM) += brd.o obj-$(CONFIG_BLK_DEV_LOOP) += loop.o -obj-$(CONFIG_BLK_DEV_PS2) += ps2esdi.o obj-$(CONFIG_BLK_DEV_XD) += xd.o obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c deleted file mode 100644 index 3c796e23625..00000000000 --- a/drivers/block/ps2esdi.c +++ /dev/null @@ -1,1079 +0,0 @@ -/* ps2esdi driver based on assembler code by Arindam Banerji, - written by Peter De Schrijver */ -/* Reassuring note to IBM : This driver was NOT developed by vice-versa - engineering the PS/2's BIOS */ -/* Dedicated to Wannes, Tofke, Ykke, Godot, Killroy and all those - other lovely fish out there... */ -/* This code was written during the long and boring WINA - elections 1994 */ -/* Thanks to Arindam Banerij for giving me the source of his driver */ -/* This code may be freely distributed and modified in any way, - as long as these notes remain intact */ - -/* Revised: 05/07/94 by Arindam Banerji (axb@cse.nd.edu) */ -/* Revised: 09/08/94 by Peter De Schrijver (stud11@cc4.kuleuven.ac.be) - Thanks to Arindam Banerij for sending me the docs of the adapter */ - -/* BA Modified for ThinkPad 720 by Boris Ashkinazi */ -/* (bash@vnet.ibm.com) 08/08/95 */ - -/* Modified further for ThinkPad-720C by Uri Blumenthal */ -/* (uri@watson.ibm.com) Sep 11, 1995 */ - -/* TODO : - + Timeouts - + Get disk parameters - + DMA above 16MB - + reset after read/write error - */ - -#define DEVICE_NAME "PS/2 ESDI" - -#include <linux/major.h> -#include <linux/errno.h> -#include <linux/wait.h> -#include <linux/interrupt.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/genhd.h> -#include <linux/ps2esdi.h> -#include <linux/blkdev.h> -#include <linux/mca-legacy.h> -#include <linux/init.h> -#include <linux/ioport.h> -#include <linux/module.h> -#include <linux/hdreg.h> - -#include <asm/system.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <asm/mca_dma.h> -#include <asm/uaccess.h> - -#define PS2ESDI_IRQ 14 -#define MAX_HD 2 -#define MAX_RETRIES 5 -#define MAX_16BIT 65536 -#define ESDI_TIMEOUT 0xf000 -#define ESDI_STAT_TIMEOUT 4 - -#define TYPE_0_CMD_BLK_LENGTH 2 -#define TYPE_1_CMD_BLK_LENGTH 4 - -static void reset_ctrl(void); - -static int ps2esdi_geninit(void); - -static void do_ps2esdi_request(struct request_queue * q); - -static void ps2esdi_readwrite(int cmd, struct request *req); - -static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd, -u_short cyl, u_short head, u_short sector, u_short length, u_char drive); - -static int ps2esdi_out_cmd_blk(u_short * cmd_blk); - -static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode); - -static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id); -static void (*current_int_handler) (u_int) = NULL; -static void ps2esdi_normal_interrupt_handler(u_int); -static void ps2esdi_initial_reset_int_handler(u_int); -static void ps2esdi_geometry_int_handler(u_int); -static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo); - -static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer); - -static void dump_cmd_complete_status(u_int int_ret_code); - -static void ps2esdi_get_device_cfg(void); - -static void ps2esdi_reset_timer(unsigned long unused); - -static u_int dma_arb_level; /* DMA arbitration level */ - -static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int); - -static int no_int_yet; -static int ps2esdi_drives; -static u_short io_base; -static DEFINE_TIMER(esdi_timer, ps2esdi_reset_timer, 0, 0); -static int reset_status; -static int ps2esdi_slot = -1; -static int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */ -static int intg_esdi = 0; /* If integrated adapter */ -struct ps2esdi_i_struct { - unsigned int head, sect, cyl, wpcom, lzone, ctl; -}; -static DEFINE_SPINLOCK(ps2esdi_lock); -static struct request_queue *ps2esdi_queue; -static struct request *current_req; - -#if 0 -#if 0 /* try both - I don't know which one is better... UB */ -static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] = -{ - {4, 48, 1553, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}}; -#else -static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] = -{ - {64, 32, 161, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}}; -#endif -#endif -static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] = -{ - {0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}}; - -static struct block_device_operations ps2esdi_fops = -{ - .owner = THIS_MODULE, - .getgeo = ps2esdi_getgeo, -}; - -static struct gendisk *ps2esdi_gendisk[2]; - -/* initialization routine called by ll_rw_blk.c */ -static int __init ps2esdi_init(void) -{ - - int error = 0; - - /* register the device - pass the name and major number */ - if (register_blkdev(PS2ESDI_MAJOR, "ed")) - return -EBUSY; - - /* set up some global information - indicating device specific info */ - ps2esdi_queue = blk_init_queue(do_ps2esdi_request, &ps2esdi_lock); - if (!ps2esdi_queue) { - unregister_blkdev(PS2ESDI_MAJOR, "ed"); - return -ENOMEM; - } - - /* some minor housekeeping - setup the global gendisk structure */ - error = ps2esdi_geninit(); - if (error) { - printk(KERN_WARNING "PS2ESDI: error initialising" - " device, releasing resources\n"); - unregister_blkdev(PS2ESDI_MAJOR, "ed"); - blk_cleanup_queue(ps2esdi_queue); - return error; - } - return 0; -} /* ps2esdi_init */ - -#ifndef MODULE - -module_init(ps2esdi_init); - -#else - -static int cyl[MAX_HD] = {-1,-1}; -static int head[MAX_HD] = {-1, -1}; -static int sect[MAX_HD] = {-1, -1}; - -module_param(tp720esdi, bool, 0); -module_param_array(cyl, int, NULL, 0); -module_param_array(head, int, NULL, 0); -module_param_array(sect, int, NULL, 0); -MODULE_LICENSE("GPL"); - -int init_module(void) { - int drive; - - for(drive = 0; drive < MAX_HD; drive++) { - struct ps2esdi_i_struct *info = &ps2esdi_info[drive]; - - if (cyl[drive] != -1) { - info->cyl = info->lzone = cyl[drive]; - info->wpcom = 0; - } - if (head[drive] != -1) { - info->head = head[drive]; - info->ctl = (head[drive] > 8 ? 8 : 0); - } - if (sect[drive] != -1) info->sect = sect[drive]; - } - return ps2esdi_init(); -} - -void -cleanup_module(void) { - int i; - if(ps2esdi_slot) { - mca_mark_as_unused(ps2esdi_slot); - mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL); - } - release_region(io_base, 4); - free_dma(dma_arb_level); - free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk); - unregister_blkdev(PS2ESDI_MAJOR, "ed"); - blk_cleanup_queue(ps2esdi_queue); - for (i = 0; i < ps2esdi_drives; i++) { - del_gendisk(ps2esdi_gendisk[i]); - put_disk(ps2esdi_gendisk[i]); - } -} -#endif /* MODULE */ - -/* handles boot time command line parameters */ -void __init tp720_setup(char *str, int *ints) -{ - /* no params, just sets the tp720esdi flag if it exists */ - - printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME); - tp720esdi = 1; -} - -void __init ed_setup(char *str, int *ints) -{ - int hdind = 0; - - /* handles 3 parameters only - corresponding to - 1. Number of cylinders - 2. Number of heads - 3. Sectors/track - */ - - if (ints[0] != 3) - return; - - /* print out the information - seen at boot time */ - printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n", - DEVICE_NAME, ints[0], ints[1], ints[2], ints[3]); - - /* set the index into device specific information table */ - if (ps2esdi_info[0].head != 0) - hdind = 1; - - /* set up all the device information */ - ps2esdi_info[hdind].head = ints[2]; - ps2esdi_info[hdind].sect = ints[3]; - ps2esdi_info[hdind].cyl = ints[1]; - ps2esdi_info[hdind].wpcom = 0; - ps2esdi_info[hdind].lzone = ints[1]; - ps2esdi_info[hdind].ctl = (ints[2] > 8 ? 8 : 0); -#if 0 /* this may be needed for PS2/Mod.80, but it hurts ThinkPad! */ - ps2esdi_drives = hdind + 1; /* increment index for the next time */ -#endif -} /* ed_setup */ - -static int ps2esdi_getinfo(char *buf, int slot, void *d) -{ - int len = 0; - - len += sprintf(buf + len, "DMA Arbitration Level: %d\n", - dma_arb_level); - len += sprintf(buf + len, "IO Port: %x\n", io_base); - len += sprintf(buf + len, "IRQ: 14\n"); - len += sprintf(buf + len, "Drives: %d\n", ps2esdi_drives); - - return len; -} - -/* ps2 esdi specific initialization - called thru the gendisk chain */ -static int __init ps2esdi_geninit(void) -{ - /* - The first part contains the initialization code - for the ESDI disk subsystem. All we really do - is search for the POS registers of the controller - to do some simple setup operations. First, we - must ensure that the controller is installed, - enabled, and configured as PRIMARY. Then we must - determine the DMA arbitration level being used by - the controller so we can handle data transfer - operations properly. If all of this works, then - we will set the INIT_FLAG to a non-zero value. - */ - - int slot = 0, i, reset_start, reset_end; - u_char status; - unsigned short adapterID; - int error = 0; - - if ((slot = mca_find_adapter(INTG_ESDI_ID, 0)) != MCA_NOTFOUND) { - adapterID = INTG_ESDI_ID; - printk("%s: integrated ESDI adapter found in slot %d\n", - DEVICE_NAME, slot+1); -#ifndef MODULE - mca_set_adapter_name(slot, "PS/2 Integrated ESDI"); -#endif - } else if ((slot = mca_find_adapter(NRML_ESDI_ID, 0)) != -1) { - adapterID = NRML_ESDI_ID; - printk("%s: normal ESDI adapter found in slot %d\n", - DEVICE_NAME, slot+1); - mca_set_adapter_name(slot, "PS/2 ESDI"); - } else { - return -ENODEV; - } - - ps2esdi_slot = slot; - mca_mark_as_used(slot); - mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL); - - /* Found the slot - read the POS register 2 to get the necessary - configuration and status information. POS register 2 has the - following information : - Bit Function - 7 reserved = 0 - 6 arbitration method - 0 - fairness enabled - 1 - fairness disabled, linear priority assignment - 5-2 arbitration level - 1 alternate address - 1 alternate address - 0 - use addresses 0x3510 - 0x3517 - 0 adapter enable - */ - - status = mca_read_stored_pos(slot, 2); - /* is it enabled ? */ - if (!(status & STATUS_ENABLED)) { - printk("%s: ESDI adapter disabled\n", DEVICE_NAME); - error = -ENODEV; - goto err_out1; - } - /* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can - share with the SCSI driver */ - if (request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler, - IRQF_DISABLED | IRQF_SHARED, "PS/2 ESDI", &ps2esdi_gendisk) - && request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler, - IRQF_SHARED, "PS/2 ESDI", &ps2esdi_gendisk) - ) { - printk("%s: Unable to get IRQ %d\n", DEVICE_NAME, PS2ESDI_IRQ); - error = -EBUSY; - goto err_out1; - } - if (status & STATUS_ALTERNATE) - io_base = ALT_IO_BASE; - else - io_base = PRIMARY_IO_BASE; - - if (!request_region(io_base, 4, "ed")) { - printk(KERN_WARNING"Unable to request region 0x%x\n", io_base); - error = -EBUSY; - goto err_out2; - } - /* get the dma arbitration level */ - dma_arb_level = (status >> 2) & 0xf; - - /* BA */ - printk("%s: DMA arbitration level : %d\n", - DEVICE_NAME, dma_arb_level); - - LITE_ON; - current_int_handler = ps2esdi_initial_reset_int_handler; - reset_ctrl(); - reset_status = 0; - reset_start = jiffies; - while (!reset_status) { - init_timer(&esdi_timer); - esdi_timer.expires = jiffies + HZ; - esdi_timer.data = 0; - add_timer(&esdi_timer); - sleep_on(&ps2esdi_int); - } - reset_end = jiffies; - LITE_OFF; - printk("%s: reset interrupt after %d jiffies, %u.%02u secs\n", - DEVICE_NAME, reset_end - reset_start, (reset_end - reset_start) / HZ, - (reset_end - reset_start) % HZ); - - - /* Integrated ESDI Disk and Controller has only one drive! */ - if (adapterID == INTG_ESDI_ID) {/* if not "normal" PS2 ESDI adapter */ - ps2esdi_drives = 1; /* then we have only one physical disk! */ intg_esdi = 1; - } - - - - /* finally this part sets up some global data structures etc. */ - - ps2esdi_get_device_cfg(); - - /* some annoyance in the above routine returns TWO drives? - Is something else happining in the background? - Regaurdless we fix the # of drives again. AJK */ - /* Integrated ESDI Disk and Controller has only one drive! */ - if (adapterID == INTG_ESDI_ID) /* if not "normal" PS2 ESDI adapter */ - ps2esdi_drives = 1; /* Not three or two, ONE DAMNIT! */ - - current_int_handler = ps2esdi_normal_interrupt_handler; - - if (request_dma(dma_arb_level, "ed") !=0) { - printk(KERN_WARNING "PS2ESDI: Can't request dma-channel %d\n" - ,(int) dma_arb_level); - error = -EBUSY; - goto err_out3; - } - blk_queue_max_sectors(ps2esdi_queue, 128); - - error = -ENOMEM; - for (i = 0; i < ps2esdi_drives; i++) { - struct gendisk *disk = alloc_disk(64); - if (!disk) - goto err_out4; - disk->major = PS2ESDI_MAJOR; - disk->first_minor = i<<6; - sprintf(disk->disk_name, "ed%c", 'a'+i); - disk->fops = &ps2esdi_fops; - ps2esdi_gendisk[i] = disk; - } - - for (i = 0; i < ps2esdi_drives; i++) { - struct gendisk *disk = ps2esdi_gendisk[i]; - set_capacity(disk, ps2esdi_info[i].head * ps2esdi_info[i].sect * - ps2esdi_info[i].cyl); - disk->queue = ps2esdi_queue; - disk->private_data = &ps2esdi_info[i]; - add_disk(disk); - } - return 0; -err_out4: - while (i--) - put_disk(ps2esdi_gendisk[i]); -err_out3: - release_region(io_base, 4); -err_out2: - free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk); -err_out1: - if(ps2esdi_slot) { - mca_mark_as_unused(ps2esdi_slot); - mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL); - } - return error; -} - -static void __init ps2esdi_get_device_cfg(void) -{ - u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH]; - - /*BA */ printk("%s: Drive 0\n", DEVICE_NAME); - current_int_handler = ps2esdi_geometry_int_handler; - cmd_blk[0] = CMD_GET_DEV_CONFIG | 0x600; - cmd_blk[1] = 0; - no_int_yet = TRUE; - ps2esdi_out_cmd_blk(cmd_blk); - if (no_int_yet) - sleep_on(&ps2esdi_int); - - if (ps2esdi_drives > 1) { - printk("%s: Drive 1\n", DEVICE_NAME); /*BA */ - cmd_blk[0] = CMD_GET_DEV_CONFIG | (1 << 5) | 0x600; - cmd_blk[1] = 0; - no_int_yet = TRUE; - ps2esdi_out_cmd_blk(cmd_blk); - if (no_int_yet) - sleep_on(&ps2esdi_int); - } /* if second physical drive is present */ - return; -} - -/* strategy routine that handles most of the IO requests */ -static void do_ps2esdi_request(struct request_queue * q) -{ - struct request *req; - /* since, this routine is called with interrupts cleared - they - must be before it finishes */ - - req = elv_next_request(q); - if (!req) - return; - -#if 0 - printk("%s:got request. device : %s command : %d sector : %ld count : %ld, buffer: %p\n", - DEVICE_NAME, - req->rq_disk->disk_name, - req->cmd, req->sector, - req->current_nr_sectors, req->buffer); -#endif - - /* check for above 16Mb dmas */ - if (isa_virt_to_bus(req->buffer + req->current_nr_sectors * 512) > 16 * MB) { - printk("%s: DMA above 16MB not supported\n", DEVICE_NAME); - end_request(req, FAIL); - return; - } - - if (req->sector+req->current_nr_sectors > get_capacity(req->rq_disk)) { - printk("Grrr. error. ps2esdi_drives: %d, %llu %llu\n", - ps2esdi_drives, req->sector, - (unsigned long long)get_capacity(req->rq_disk)); - end_request(req, FAIL); - return; - } - - switch (rq_data_dir(req)) { - case READ: - ps2esdi_readwrite(READ, req); - break; - case WRITE: - ps2esdi_readwrite(WRITE, req); - break; - default: - printk("%s: Unknown command\n", req->rq_disk->disk_name); - end_request(req, FAIL); - break; - } /* handle different commands */ -} /* main strategy routine */ - -/* resets the ESDI adapter */ -static void reset_ctrl(void) -{ - - u_long expire; - u_short status; - - /* enable interrupts on the controller */ - status = inb(ESDI_INTRPT); - outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); /* to be sure we don't have - any interrupt pending... */ - outb_p(CTRL_ENABLE_INTR, ESDI_CONTROL); - - /* read the ESDI status port - if the controller is not busy, - simply do a soft reset (fast) - otherwise we'll have to do a - hard (slow) reset. */ - if (!(inb_p(ESDI_STATUS) & STATUS_BUSY)) { - /*BA */ printk("%s: soft reset...\n", DEVICE_NAME); - outb_p(CTRL_SOFT_RESET, ESDI_ATTN); - } - /* soft reset */ - else { - /*BA */ - printk("%s: hard reset...\n", DEVICE_NAME); - outb_p(CTRL_HARD_RESET, ESDI_CONTROL); - expire = jiffies + 2*HZ; - while (time_before(jiffies, expire)); - outb_p(1, ESDI_CONTROL); - } /* hard reset */ - - -} /* reset the controller */ - -/* called by the strategy routine to handle read and write requests */ -static void ps2esdi_readwrite(int cmd, struct request *req) -{ - struct ps2esdi_i_struct *p = req->rq_disk->private_data; - unsigned block = req->sector; - unsigned count = req->current_nr_sectors; - int drive = p - ps2esdi_info; - u_short track, head, cylinder, sector; - u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH]; - - /* do some relevant arithmatic */ - track = block / p->sect; - head = track % p->head; - cylinder = track / p->head; - sector = block % p->sect; - -#if 0 - printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME, cylinder, head, sector); -#endif - /* call the routine that actually fills out a command block */ - ps2esdi_fill_cmd_block - (cmd_blk, - (cmd == READ) ? CMD_READ : CMD_WRITE, - cylinder, head, sector, count, drive); - - /* send the command block to the controller */ - current_req = req; - spin_unlock_irq(&ps2esdi_lock); - if (ps2esdi_out_cmd_blk(cmd_blk)) { - spin_lock_irq(&ps2esdi_lock); - printk("%s: Controller failed\n", DEVICE_NAME); - if ((++req->errors) >= MAX_RETRIES) - end_request(req, FAIL); - } - /* check for failure to put out the command block */ - else { - spin_lock_irq(&ps2esdi_lock); -#if 0 - printk("%s: waiting for xfer\n", DEVICE_NAME); -#endif - /* turn disk lights on */ - LITE_ON; - } - -} /* ps2esdi_readwrite */ - -/* fill out the command block */ -static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd, - u_short cyl, u_short head, u_short sector, u_short length, u_char drive) -{ - - cmd_blk[0] = (drive << 5) | cmd; - cmd_blk[1] = length; - cmd_blk[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector; - cmd_blk[3] = (cyl & 0x3E0) >> 5; - -} /* fill out the command block */ - -/* write a command block to the controller */ -static int ps2esdi_out_cmd_blk(u_short * cmd_blk) -{ - - int i; - unsigned long jif; - u_char status; - - /* enable interrupts */ - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - - /* do not write to the controller, if it is busy */ - for (jif = jiffies + ESDI_STAT_TIMEOUT; - time_after(jif, jiffies) && - (inb(ESDI_STATUS) & STATUS_BUSY); ) - ; - -#if 0 - printk("%s: i(1)=%ld\n", DEVICE_NAME, jif); -#endif - - /* if device is still busy - then just time out */ - if (inb(ESDI_STATUS) & STATUS_BUSY) { - printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME); - return ERROR; - } /* timeout ??? */ - /* Set up the attention register in the controller */ - outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN); - -#if 0 - printk("%s: sending %d words to controller\n", DEVICE_NAME, (((*cmd_blk) >> 14) + 1) << 1); -#endif - - /* one by one send each word out */ - for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) { - status = inb(ESDI_STATUS); - for (jif = jiffies + ESDI_STAT_TIMEOUT; - time_after(jif, jiffies) && (status & STATUS_BUSY) && - (status & STATUS_CMD_INF); status = inb(ESDI_STATUS)); - if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) { -#if 0 - printk("%s: sending %04X\n", DEVICE_NAME, *cmd_blk); -#endif - outw(*cmd_blk++, ESDI_CMD_INT); - } else { - printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n", - DEVICE_NAME, status); - return ERROR; - } - } /* send all words out */ - return OK; -} /* send out the commands */ - - -/* prepare for dma - do all the necessary setup */ -static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode) -{ - unsigned long flags = claim_dma_lock(); - - mca_disable_dma(dma_arb_level); - - mca_set_dma_addr(dma_arb_level, isa_virt_to_bus(buffer)); - - mca_set_dma_count(dma_arb_level, length * 512 / 2); - - mca_set_dma_mode(dma_arb_level, dma_xmode); - - mca_enable_dma(dma_arb_level); - - release_dma_lock(flags); - -} /* prepare for dma */ - - - -static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id) -{ - u_int int_ret_code; - - if (inb(ESDI_STATUS) & STATUS_INTR) { - int_ret_code = inb(ESDI_INTRPT); - if (current_int_handler) { - /* Disable adapter interrupts till processing is finished */ - outb(CTRL_DISABLE_INTR, ESDI_CONTROL); - current_int_handler(int_ret_code); - } else - printk("%s: help ! No interrupt handler.\n", DEVICE_NAME); - } else { - return IRQ_NONE; - } - return IRQ_HANDLED; -} - -static void ps2esdi_initial_reset_int_handler(u_int int_ret_code) -{ - - switch (int_ret_code & 0xf) { - case INT_RESET: - /*BA */ - printk("%s: initial reset completed.\n", DEVICE_NAME); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - wake_up(&ps2esdi_int); - break; - case INT_ATTN_ERROR: - printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, - int_ret_code); - printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS)); - break; - default: - printk("%s: initial reset handler received interrupt: %02X\n", - DEVICE_NAME, int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - break; - } - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); -} - - -static void ps2esdi_geometry_int_handler(u_int int_ret_code) -{ - u_int status, drive_num; - unsigned long rba; - int i; - - drive_num = int_ret_code >> 5; - switch (int_ret_code & 0xf) { - case INT_CMD_COMPLETE: - for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--); - if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { - printk("%s: timeout reading status word\n", DEVICE_NAME); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - break; - } - status = inw(ESDI_STT_INT); - if ((status & 0x1F) == CMD_GET_DEV_CONFIG) { -#define REPLY_WORDS 5 /* we already read word 0 */ - u_short reply[REPLY_WORDS]; - - if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) { - /*BA */ - printk("%s: Device Configuration Status for drive %u\n", - DEVICE_NAME, drive_num); - - printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8); - - printk - ("Config bits: %s%s%s%s%s\n", - (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "", - ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS)) - ? "Zero Defect, " : "Defects Present, ", - (reply[0] & CONFIG_SF) ? "Skewed Format, " : "", - (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ", - (reply[0] & CONFIG_RT) ? "No Retries" : "Retries"); - - rba = reply[1] | ((unsigned long) reply[2] << 16); - printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba); - - printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n", - DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff); - - if (!ps2esdi_info[drive_num].head) { - ps2esdi_info[drive_num].head = 64; - ps2esdi_info[drive_num].sect = 32; - ps2esdi_info[drive_num].cyl = rba / (64 * 32); - ps2esdi_info[drive_num].wpcom = 0; - ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl; - ps2esdi_info[drive_num].ctl = 8; - if (tp720esdi) { /* store the retrieved parameters */ - ps2esdi_info[0].head = reply[4] & 0Xff; - ps2esdi_info[0].sect = reply[4] >> 8; - ps2esdi_info[0].cyl = reply[3]; - ps2esdi_info[0].wpcom = 0; - ps2esdi_info[0].lzone = reply[3]; - } else { - if (!intg_esdi) - ps2esdi_drives++; - } - } -#ifdef OBSOLETE - if (!ps2esdi_info[drive_num].head) { - ps2esdi_info[drive_num].head = reply[4] & 0Xff; - ps2esdi_info[drive_num].sect = reply[4] >> 8; - ps2esdi_info[drive_num].cyl = reply[3]; - ps2esdi_info[drive_num].wpcom = 0; - ps2esdi_info[drive_num].lzone = reply[3]; - if (tp720esdi) { /* store the retrieved parameters */ - ps2esdi_info[0].head = reply[4] & 0Xff; - ps2esdi_info[0].sect = reply[4] >> 8; - ps2esdi_info[0].cyl = reply[3]; - ps2esdi_info[0].wpcom = 0; - ps2esdi_info[0].lzone = reply[3]; - } else { - ps2esdi_drives++; - } - } -#endif - - } else - printk("%s: failed while getting device config\n", DEVICE_NAME); -#undef REPLY_WORDS - } else - printk("%s: command %02X unknown by geometry handler\n", - DEVICE_NAME, status & 0x1f); - - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - break; - - case INT_ATTN_ERROR: - printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, - int_ret_code); - printk("%s: Device not available\n", DEVICE_NAME); - break; - case INT_CMD_ECC: - case INT_CMD_RETRY: - case INT_CMD_ECC_RETRY: - case INT_CMD_WARNING: - case INT_CMD_ABORT: - case INT_CMD_FAILED: - case INT_DMA_ERR: - case INT_CMD_BLK_ERR: - /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME); - dump_cmd_complete_status(int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - break; - default: - printk("%s: Unknown interrupt reason: %02X\n", - DEVICE_NAME, int_ret_code & 0xf); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - break; - } - - wake_up(&ps2esdi_int); - no_int_yet = FALSE; - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - -} - -static void ps2esdi_normal_interrupt_handler(u_int int_ret_code) -{ - unsigned long flags; - u_int status; - u_int ending; - int i; - - switch (int_ret_code & 0x0f) { - case INT_TRANSFER_REQ: - ps2esdi_prep_dma(current_req->buffer, - current_req->current_nr_sectors, - (rq_data_dir(current_req) == READ) - ? MCA_DMA_MODE_16 | MCA_DMA_MODE_WRITE | MCA_DMA_MODE_XFER - : MCA_DMA_MODE_16 | MCA_DMA_MODE_READ); - outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = -1; - break; - - case INT_ATTN_ERROR: - printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, - int_ret_code); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = FAIL; - break; - - case INT_CMD_COMPLETE: - for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--); - if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { - printk("%s: timeout reading status word\n", DEVICE_NAME); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - if ((++current_req->errors) >= MAX_RETRIES) - ending = FAIL; - else - ending = -1; - break; - } - status = inw(ESDI_STT_INT); - switch (status & 0x1F) { - case (CMD_READ & 0xff): - case (CMD_WRITE & 0xff): - LITE_OFF; - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = SUCCES; - break; - default: - printk("%s: interrupt for unknown command %02X\n", - DEVICE_NAME, status & 0x1f); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = -1; - break; - } - break; - case INT_CMD_ECC: - case INT_CMD_RETRY: - case INT_CMD_ECC_RETRY: - LITE_OFF; - dump_cmd_complete_status(int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = SUCCES; - break; - case INT_CMD_WARNING: - case INT_CMD_ABORT: - case INT_CMD_FAILED: - case INT_DMA_ERR: - LITE_OFF; - dump_cmd_complete_status(int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - if ((++current_req->errors) >= MAX_RETRIES) - ending = FAIL; - else - ending = -1; - break; - - case INT_CMD_BLK_ERR: - dump_cmd_complete_status(int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = FAIL; - break; - - case INT_CMD_FORMAT: - printk("%s: huh ? Who issued this format command ?\n" - ,DEVICE_NAME); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = -1; - break; - - case INT_RESET: - /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ; - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = -1; - break; - - default: - printk("%s: Unknown interrupt reason: %02X\n", - DEVICE_NAME, int_ret_code & 0xf); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - ending = -1; - break; - } - if(ending != -1) { - spin_lock_irqsave(&ps2esdi_lock, flags); - end_request(current_req, ending); - current_req = NULL; - do_ps2esdi_request(ps2esdi_queue); - spin_unlock_irqrestore(&ps2esdi_lock, flags); - } -} /* handle interrupts */ - - - -static int ps2esdi_read_status_words(int num_words, - int max_words, - u_short * buffer) -{ - int i; - - for (; max_words && num_words; max_words--, num_words--, buffer++) { - for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--); - if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { - printk("%s: timeout reading status word\n", DEVICE_NAME); - return FAIL; - } - *buffer = inw(ESDI_STT_INT); - } - return SUCCES; -} - - - - -static void dump_cmd_complete_status(u_int int_ret_code) -{ -#define WAIT_FOR_STATUS \ - for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \ - if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \ - printk("%s: timeout reading status word\n",DEVICE_NAME); \ - return; \ - } - - int i, word_count; - u_short stat_word; - u_long rba; - - printk("%s: Device: %u, interrupt ID: %02X\n", - DEVICE_NAME, int_ret_code >> 5, - int_ret_code & 0xf); - - WAIT_FOR_STATUS; - stat_word = inw(ESDI_STT_INT); - word_count = (stat_word >> 8) - 1; - printk("%s: %u status words, command: %02X\n", DEVICE_NAME, word_count, - stat_word & 0xff); - - if (word_count--) { - WAIT_FOR_STATUS; - stat_word = inw(ESDI_STT_INT); - printk("%s: command status code: %02X, command error code: %02X\n", - DEVICE_NAME, stat_word >> 8, stat_word & 0xff); - } - if (word_count--) { - WAIT_FOR_STATUS; - stat_word = inw(ESDI_STT_INT); - printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME, - (stat_word & 0x1000) ? "Ready, " : "Not Ready, ", - (stat_word & 0x0800) ? "Selected, " : "Not Selected, ", - (stat_word & 0x0400) ? "Write Fault, " : "", - (stat_word & 0x0200) ? "Track 0, " : "", - (stat_word & 0x0100) ? "Seek or command complete, " : "", - stat_word >> 8); - } - if (word_count--) { - WAIT_FOR_STATUS; - stat_word = inw(ESDI_STT_INT); - printk("%s: Blocks to do: %u", DEVICE_NAME, stat_word); - } - if (word_count -= 2) { - WAIT_FOR_STATUS; - rba = inw(ESDI_STT_INT); - WAIT_FOR_STATUS; - rba |= inw(ESDI_STT_INT) << 16; - printk(", Last Cyl: %u Head: %u Sector: %u\n", - (u_short) ((rba & 0x1ff80000) >> 11), - (u_short) ((rba & 0x7E0) >> 5), (u_short) (rba & 0x1f)); - } else - printk("\n"); - - if (word_count--) { - WAIT_FOR_STATUS; - stat_word = inw(ESDI_STT_INT); - printk("%s: Blocks required ECC: %u", DEVICE_NAME, stat_word); - } - printk("\n"); - -#undef WAIT_FOR_STATUS - -} - -static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - struct ps2esdi_i_struct *p = bdev->bd_disk->private_data; - - geo->heads = p->head; - geo->sectors = p->sect; - geo->cylinders = p->cyl; - return 0; -} - -static void ps2esdi_reset_timer(unsigned long unused) -{ - - int status; - - status = inb(ESDI_INTRPT); - if ((status & 0xf) == INT_RESET) { - outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - reset_status = 1; - } - wake_up(&ps2esdi_int); -} diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c index d352dbb4ccf..e5a0e97cfdd 100644 --- a/drivers/char/drm/ati_pcigart.c +++ b/drivers/char/drm/ati_pcigart.c @@ -35,42 +35,23 @@ # define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ -static void *drm_ati_alloc_pcigart_table(int order) +static int drm_ati_alloc_pcigart_table(struct drm_device *dev, + struct drm_ati_pcigart_info *gart_info) { - unsigned long address; - struct page *page; - int i; - - DRM_DEBUG("%d order\n", order); - - address = __get_free_pages(GFP_KERNEL | __GFP_COMP, - order); - if (address == 0UL) { - return NULL; - } - - page = virt_to_page(address); + gart_info->table_handle = drm_pci_alloc(dev, gart_info->table_size, + PAGE_SIZE, + gart_info->table_mask); + if (gart_info->table_handle == NULL) + return -ENOMEM; - for (i = 0; i < order; i++, page++) - SetPageReserved(page); - - DRM_DEBUG("returning 0x%08lx\n", address); - return (void *)address; + return 0; } -static void drm_ati_free_pcigart_table(void *address, int order) +static void drm_ati_free_pcigart_table(struct drm_device *dev, + struct drm_ati_pcigart_info *gart_info) { - struct page *page; - int i; - int num_pages = 1 << order; - DRM_DEBUG("\n"); - - page = virt_to_page((unsigned long)address); - - for (i = 0; i < num_pages; i++, page++) - ClearPageReserved(page); - - free_pages((unsigned long)address, order); + drm_pci_free(dev, gart_info->table_handle); + gart_info->table_handle = NULL; } int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info) @@ -78,8 +59,7 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info struct drm_sg_mem *entry = dev->sg; unsigned long pages; int i; - int order; - int num_pages, max_pages; + int max_pages; /* we need to support large memory configurations */ if (!entry) { @@ -87,15 +67,7 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info return 0; } - order = drm_order((gart_info->table_size + (PAGE_SIZE-1)) / PAGE_SIZE); - num_pages = 1 << order; - if (gart_info->bus_addr) { - if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { - pci_unmap_single(dev->pdev, gart_info->bus_addr, - num_pages * PAGE_SIZE, - PCI_DMA_TODEVICE); - } max_pages = (gart_info->table_size / sizeof(u32)); pages = (entry->pages <= max_pages) @@ -112,10 +84,9 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info gart_info->bus_addr = 0; } - if (gart_info->gart_table_location == DRM_ATI_GART_MAIN - && gart_info->addr) { - drm_ati_free_pcigart_table(gart_info->addr, order); - gart_info->addr = NULL; + if (gart_info->gart_table_location == DRM_ATI_GART_MAIN && + gart_info->table_handle) { + drm_ati_free_pcigart_table(dev, gart_info); } return 1; @@ -127,11 +98,10 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga struct drm_sg_mem *entry = dev->sg; void *address = NULL; unsigned long pages; - u32 *pci_gart, page_base, bus_address = 0; + u32 *pci_gart, page_base; + dma_addr_t bus_address = 0; int i, j, ret = 0; - int order; int max_pages; - int num_pages; if (!entry) { DRM_ERROR("no scatter/gather memory!\n"); @@ -141,31 +111,14 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n"); - order = drm_order((gart_info->table_size + - (PAGE_SIZE-1)) / PAGE_SIZE); - num_pages = 1 << order; - address = drm_ati_alloc_pcigart_table(order); - if (!address) { + ret = drm_ati_alloc_pcigart_table(dev, gart_info); + if (ret) { DRM_ERROR("cannot allocate PCI GART page!\n"); goto done; } - if (!dev->pdev) { - DRM_ERROR("PCI device unknown!\n"); - goto done; - } - - bus_address = pci_map_single(dev->pdev, address, - num_pages * PAGE_SIZE, - PCI_DMA_TODEVICE); - if (bus_address == 0) { - DRM_ERROR("unable to map PCIGART pages!\n"); - order = drm_order((gart_info->table_size + - (PAGE_SIZE-1)) / PAGE_SIZE); - drm_ati_free_pcigart_table(address, order); - address = NULL; - goto done; - } + address = gart_info->table_handle->vaddr; + bus_address = gart_info->table_handle->busaddr; } else { address = gart_info->addr; bus_address = gart_info->bus_addr; diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index a6789f25009..8ea9dd1717a 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -54,6 +54,7 @@ #include <linux/pci.h> #include <linux/jiffies.h> #include <linux/smp_lock.h> /* For (un)lock_kernel */ +#include <linux/dma-mapping.h> #include <linux/mm.h> #include <linux/cdev.h> #include <linux/mutex.h> @@ -551,6 +552,8 @@ struct drm_ati_pcigart_info { int gart_reg_if; void *addr; dma_addr_t bus_addr; + dma_addr_t table_mask; + struct drm_dma_handle *table_handle; drm_local_map_t mapping; int table_size; }; diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c index 3992f73299c..f09d4b5002b 100644 --- a/drivers/char/drm/drm_fops.c +++ b/drivers/char/drm/drm_fops.c @@ -326,6 +326,7 @@ int drm_release(struct inode *inode, struct file *filp) struct drm_file *file_priv = filp->private_data; struct drm_device *dev = file_priv->head->dev; int retcode = 0; + unsigned long irqflags; lock_kernel(); @@ -357,9 +358,11 @@ int drm_release(struct inode *inode, struct file *filp) */ do{ - spin_lock(&dev->lock.spinlock); + spin_lock_irqsave(&dev->lock.spinlock, + irqflags); locked = dev->lock.idle_has_lock; - spin_unlock(&dev->lock.spinlock); + spin_unlock_irqrestore(&dev->lock.spinlock, + irqflags); if (locked) break; schedule(); diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c index bea2a7d5b2b..12dcdd1832f 100644 --- a/drivers/char/drm/drm_lock.c +++ b/drivers/char/drm/drm_lock.c @@ -53,6 +53,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) DECLARE_WAITQUEUE(entry, current); struct drm_lock *lock = data; int ret = 0; + unsigned long irqflags; ++file_priv->lock_count; @@ -71,9 +72,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) return -EINVAL; add_wait_queue(&dev->lock.lock_queue, &entry); - spin_lock(&dev->lock.spinlock); + spin_lock_irqsave(&dev->lock.spinlock, irqflags); dev->lock.user_waiters++; - spin_unlock(&dev->lock.spinlock); + spin_unlock_irqrestore(&dev->lock.spinlock, irqflags); for (;;) { __set_current_state(TASK_INTERRUPTIBLE); if (!dev->lock.hw_lock) { @@ -95,9 +96,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) break; } } - spin_lock(&dev->lock.spinlock); + spin_lock_irqsave(&dev->lock.spinlock, irqflags); dev->lock.user_waiters--; - spin_unlock(&dev->lock.spinlock); + spin_unlock_irqrestore(&dev->lock.spinlock, irqflags); __set_current_state(TASK_RUNNING); remove_wait_queue(&dev->lock.lock_queue, &entry); @@ -198,8 +199,9 @@ int drm_lock_take(struct drm_lock_data *lock_data, { unsigned int old, new, prev; volatile unsigned int *lock = &lock_data->hw_lock->lock; + unsigned long irqflags; - spin_lock(&lock_data->spinlock); + spin_lock_irqsave(&lock_data->spinlock, irqflags); do { old = *lock; if (old & _DRM_LOCK_HELD) @@ -211,7 +213,7 @@ int drm_lock_take(struct drm_lock_data *lock_data, } prev = cmpxchg(lock, old, new); } while (prev != old); - spin_unlock(&lock_data->spinlock); + spin_unlock_irqrestore(&lock_data->spinlock, irqflags); if (_DRM_LOCKING_CONTEXT(old) == context) { if (old & _DRM_LOCK_HELD) { @@ -272,15 +274,16 @@ int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context) { unsigned int old, new, prev; volatile unsigned int *lock = &lock_data->hw_lock->lock; + unsigned long irqflags; - spin_lock(&lock_data->spinlock); + spin_lock_irqsave(&lock_data->spinlock, irqflags); if (lock_data->kernel_waiters != 0) { drm_lock_transfer(lock_data, 0); lock_data->idle_has_lock = 1; - spin_unlock(&lock_data->spinlock); + spin_unlock_irqrestore(&lock_data->spinlock, irqflags); return 1; } - spin_unlock(&lock_data->spinlock); + spin_unlock_irqrestore(&lock_data->spinlock, irqflags); do { old = *lock; @@ -344,19 +347,20 @@ static int drm_notifier(void *priv) void drm_idlelock_take(struct drm_lock_data *lock_data) { int ret = 0; + unsigned long irqflags; - spin_lock(&lock_data->spinlock); + spin_lock_irqsave(&lock_data->spinlock, irqflags); lock_data->kernel_waiters++; if (!lock_data->idle_has_lock) { - spin_unlock(&lock_data->spinlock); + spin_unlock_irqrestore(&lock_data->spinlock, irqflags); ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT); - spin_lock(&lock_data->spinlock); + spin_lock_irqsave(&lock_data->spinlock, irqflags); if (ret == 1) lock_data->idle_has_lock = 1; } - spin_unlock(&lock_data->spinlock); + spin_unlock_irqrestore(&lock_data->spinlock, irqflags); } EXPORT_SYMBOL(drm_idlelock_take); @@ -364,8 +368,9 @@ void drm_idlelock_release(struct drm_lock_data *lock_data) { unsigned int old, prev; volatile unsigned int *lock = &lock_data->hw_lock->lock; + unsigned long irqflags; - spin_lock(&lock_data->spinlock); + spin_lock_irqsave(&lock_data->spinlock, irqflags); if (--lock_data->kernel_waiters == 0) { if (lock_data->idle_has_lock) { do { @@ -376,7 +381,7 @@ void drm_idlelock_release(struct drm_lock_data *lock_data) lock_data->idle_has_lock = 0; } } - spin_unlock(&lock_data->spinlock); + spin_unlock_irqrestore(&lock_data->spinlock, irqflags); } EXPORT_SYMBOL(drm_idlelock_release); diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index 715b361f0c2..a6a499f97e2 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h @@ -205,9 +205,9 @@ {0x1002, 0x71D6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x71DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \ {0x1002, 0x71DE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x7200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x7210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x7211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x7200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x7210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x7211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x7240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \ {0x1002, 0x7243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \ {0x1002, 0x7244, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \ @@ -238,6 +238,7 @@ {0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_NEW_MEMMAP}, \ {0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x791e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \ + {0x1002, 0x791f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \ {0, 0, 0} #define r128_PCI_IDS \ diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c index 892e0a58984..f36adbd3aaf 100644 --- a/drivers/char/drm/r128_cce.c +++ b/drivers/char/drm/r128_cce.c @@ -558,6 +558,7 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) #if __OS_HAS_AGP if (dev_priv->is_pci) { #endif + dev_priv->gart_info.table_mask = DMA_BIT_MASK(32); dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE; dev_priv->gart_info.addr = NULL; diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index 833abc7e55f..9072e4a1894 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c @@ -1807,6 +1807,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) } else #endif { + dev_priv->gart_info.table_mask = DMA_BIT_MASK(32); /* if we have an offset set from userspace */ if (dev_priv->pcigart_offset_set) { dev_priv->gart_info.bus_addr = diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c index 94baec692b5..7a339dba6a6 100644 --- a/drivers/char/drm/via_dma.c +++ b/drivers/char/drm/via_dma.c @@ -126,6 +126,8 @@ via_cmdbuf_wait(drm_via_private_t * dev_priv, unsigned int size) hw_addr, cur_addr, next_addr); return -1; } + if ((cur_addr < hw_addr) && (next_addr >= hw_addr)) + msleep(1); } while ((cur_addr < hw_addr) && (next_addr >= hw_addr)); return 0; } @@ -416,27 +418,50 @@ static int via_hook_segment(drm_via_private_t * dev_priv, int paused, count; volatile uint32_t *paused_at = dev_priv->last_pause_ptr; uint32_t reader,ptr; + uint32_t diff; paused = 0; via_flush_write_combine(); (void) *(volatile uint32_t *)(via_get_dma(dev_priv) -1); + *paused_at = pause_addr_lo; via_flush_write_combine(); (void) *paused_at; + reader = *(dev_priv->hw_addr_ptr); ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) + dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; + dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1; - if ((ptr - reader) <= dev_priv->dma_diff ) { - count = 10000000; - while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--); + /* + * If there is a possibility that the command reader will + * miss the new pause address and pause on the old one, + * In that case we need to program the new start address + * using PCI. + */ + + diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; + count = 10000000; + while(diff == 0 && count--) { + paused = (VIA_READ(0x41c) & 0x80000000); + if (paused) + break; + reader = *(dev_priv->hw_addr_ptr); + diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; } + paused = VIA_READ(0x41c) & 0x80000000; + if (paused && !no_pci_fire) { reader = *(dev_priv->hw_addr_ptr); - if ((ptr - reader) == dev_priv->dma_diff) { - + diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; + diff &= (dev_priv->dma_high - 1); + if (diff != 0 && diff < (dev_priv->dma_high >> 1)) { + DRM_ERROR("Paused at incorrect address. " + "0x%08x, 0x%08x 0x%08x\n", + ptr, reader, dev_priv->dma_diff); + } else if (diff == 0) { /* * There is a concern that these writes may stall the PCI bus * if the GPU is not idle. However, idling the GPU first @@ -577,6 +602,7 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv) uint32_t pause_addr_lo, pause_addr_hi; uint32_t jump_addr_lo, jump_addr_hi; volatile uint32_t *last_pause_ptr; + uint32_t dma_low_save1, dma_low_save2; agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi, @@ -603,8 +629,29 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv) &pause_addr_lo, 0); *last_pause_ptr = pause_addr_lo; + dma_low_save1 = dev_priv->dma_low; - via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0); + /* + * Now, set a trap that will pause the regulator if it tries to rerun the old + * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause + * and reissues the jump command over PCI, while the regulator has already taken the jump + * and actually paused at the current buffer end). + * There appears to be no other way to detect this condition, since the hw_addr_pointer + * does not seem to get updated immediately when a jump occurs. + */ + + last_pause_ptr = + via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, + &pause_addr_lo, 0) - 1; + via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, + &pause_addr_lo, 0); + *last_pause_ptr = pause_addr_lo; + + dma_low_save2 = dev_priv->dma_low; + dev_priv->dma_low = dma_low_save1; + via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0); + dev_priv->dma_low = dma_low_save2; + via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0); } diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c index 33c5197b73c..409e00afdd0 100644 --- a/drivers/char/drm/via_dmablit.c +++ b/drivers/char/drm/via_dmablit.c @@ -603,7 +603,7 @@ via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmabli * (Not a big limitation anyway.) */ - if ((xfer->mem_stride - xfer->line_length) >= PAGE_SIZE) { + if ((xfer->mem_stride - xfer->line_length) > 2*PAGE_SIZE) { DRM_ERROR("Too large system memory stride. Stride: %d, " "Length: %d\n", xfer->mem_stride, xfer->line_length); return -EINVAL; diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 72f289279d8..f585bc8579e 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -83,6 +83,7 @@ #include <linux/pci.h> #include <asm/uaccess.h> #include <asm/atomic.h> +#include <asm/unaligned.h> #include <linux/bitops.h> #include <linux/spinlock.h> #include <linux/init.h> @@ -1312,7 +1313,7 @@ static int rp_tiocmset(struct tty_struct *tty, struct file *file, if (clear & TIOCM_DTR) info->channel.TxControl[3] &= ~SET_DTR; - sOutDW(info->channel.IndexAddr, *(DWord_t *) & (info->channel.TxControl[0])); + out32(info->channel.IndexAddr, info->channel.TxControl); return 0; } @@ -1748,7 +1749,7 @@ static int rp_write(struct tty_struct *tty, /* Write remaining data into the port's xmit_buf */ while (1) { - if (info->tty == 0) /* Seemingly obligatory check... */ + if (!info->tty) /* Seemingly obligatory check... */ goto end; c = min(count, min(XMIT_BUF_SIZE - info->xmit_cnt - 1, XMIT_BUF_SIZE - info->xmit_head)); @@ -2798,7 +2799,7 @@ static int sReadAiopNumChan(WordIO_t io) static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 }; /* write to chan 0 SRAM */ - sOutDW((DWordIO_t) io + _INDX_ADDR, *((DWord_t *) & R[0])); + out32((DWordIO_t) io + _INDX_ADDR, R); sOutW(io + _INDX_ADDR, 0); /* read from SRAM, chan 0 */ x = sInW(io + _INDX_DATA); sOutW(io + _INDX_ADDR, 0x4000); /* read from SRAM, chan 4 */ @@ -2864,7 +2865,7 @@ static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum, R[1] = RData[i + 1] + 0x10 * ChanNum; R[2] = RData[i + 2]; R[3] = RData[i + 3]; - sOutDW(ChP->IndexAddr, *((DWord_t *) & R[0])); + out32(ChP->IndexAddr, R); } ChR = ChP->R; @@ -2887,43 +2888,43 @@ static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum, ChP->BaudDiv[1] = (Byte_t) ((ChOff + _BAUD) >> 8); ChP->BaudDiv[2] = (Byte_t) brd9600; ChP->BaudDiv[3] = (Byte_t) (brd9600 >> 8); - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->BaudDiv[0]); + out32(ChP->IndexAddr, ChP->BaudDiv); ChP->TxControl[0] = (Byte_t) (ChOff + _TX_CTRL); ChP->TxControl[1] = (Byte_t) ((ChOff + _TX_CTRL) >> 8); ChP->TxControl[2] = 0; ChP->TxControl[3] = 0; - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxControl[0]); + out32(ChP->IndexAddr, ChP->TxControl); ChP->RxControl[0] = (Byte_t) (ChOff + _RX_CTRL); ChP->RxControl[1] = (Byte_t) ((ChOff + _RX_CTRL) >> 8); ChP->RxControl[2] = 0; ChP->RxControl[3] = 0; - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->RxControl[0]); + out32(ChP->IndexAddr, ChP->RxControl); ChP->TxEnables[0] = (Byte_t) (ChOff + _TX_ENBLS); ChP->TxEnables[1] = (Byte_t) ((ChOff + _TX_ENBLS) >> 8); ChP->TxEnables[2] = 0; ChP->TxEnables[3] = 0; - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxEnables[0]); + out32(ChP->IndexAddr, ChP->TxEnables); ChP->TxCompare[0] = (Byte_t) (ChOff + _TXCMP1); ChP->TxCompare[1] = (Byte_t) ((ChOff + _TXCMP1) >> 8); ChP->TxCompare[2] = 0; ChP->TxCompare[3] = 0; - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxCompare[0]); + out32(ChP->IndexAddr, ChP->TxCompare); ChP->TxReplace1[0] = (Byte_t) (ChOff + _TXREP1B1); ChP->TxReplace1[1] = (Byte_t) ((ChOff + _TXREP1B1) >> 8); ChP->TxReplace1[2] = 0; ChP->TxReplace1[3] = 0; - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxReplace1[0]); + out32(ChP->IndexAddr, ChP->TxReplace1); ChP->TxReplace2[0] = (Byte_t) (ChOff + _TXREP2); ChP->TxReplace2[1] = (Byte_t) ((ChOff + _TXREP2) >> 8); ChP->TxReplace2[2] = 0; ChP->TxReplace2[3] = 0; - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxReplace2[0]); + out32(ChP->IndexAddr, ChP->TxReplace2); ChP->TxFIFOPtrs = ChOff + _TXF_OUTP; ChP->TxFIFO = ChOff + _TX_FIFO; @@ -2979,7 +2980,7 @@ static void sStopRxProcessor(CHANNEL_T * ChP) R[1] = ChP->R[1]; R[2] = 0x0a; R[3] = ChP->R[3]; - sOutDW(ChP->IndexAddr, *(DWord_t *) & R[0]); + out32(ChP->IndexAddr, R); } /*************************************************************************** @@ -3094,13 +3095,13 @@ static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data) *WordPtr = ChP->TxPrioBuf; /* data byte address */ DWBuf[2] = Data; /* data byte value */ - sOutDW(IndexAddr, *((DWord_t *) (&DWBuf[0]))); /* write it out */ + out32(IndexAddr, DWBuf); /* write it out */ *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */ DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */ DWBuf[3] = 0; /* priority buffer pointer */ - sOutDW(IndexAddr, *((DWord_t *) (&DWBuf[0]))); /* write it out */ + out32(IndexAddr, DWBuf); /* write it out */ } else { /* write it to Tx FIFO */ sWriteTxByte(sGetTxRxDataIO(ChP), Data); @@ -3147,11 +3148,11 @@ static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags) ChP->RxControl[2] |= ((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->RxControl[0]); + out32(ChP->IndexAddr, ChP->RxControl); ChP->TxControl[2] |= ((Byte_t) Flags & TXINT_EN); - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxControl[0]); + out32(ChP->IndexAddr, ChP->TxControl); if (Flags & CHANINT_EN) { Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum]; @@ -3190,9 +3191,9 @@ static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags) ChP->RxControl[2] &= ~((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->RxControl[0]); + out32(ChP->IndexAddr, ChP->RxControl); ChP->TxControl[2] &= ~((Byte_t) Flags & TXINT_EN); - sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxControl[0]); + out32(ChP->IndexAddr, ChP->TxControl); if (Flags & CHANINT_EN) { Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum]; diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h index f3a75791b81..b01d38125a8 100644 --- a/drivers/char/rocket_int.h +++ b/drivers/char/rocket_int.h @@ -26,7 +26,6 @@ typedef unsigned int ByteIO_t; typedef unsigned int Word_t; typedef unsigned int WordIO_t; -typedef unsigned long DWord_t; typedef unsigned int DWordIO_t; /* @@ -38,7 +37,6 @@ typedef unsigned int DWordIO_t; * instruction. */ -#ifdef ROCKET_DEBUG_IO static inline void sOutB(unsigned short port, unsigned char value) { #ifdef ROCKET_DEBUG_IO @@ -55,12 +53,13 @@ static inline void sOutW(unsigned short port, unsigned short value) outw_p(value, port); } -static inline void sOutDW(unsigned short port, unsigned long value) +static inline void out32(unsigned short port, Byte_t *p) { + u32 value = le32_to_cpu(get_unaligned((__le32 *)p)); #ifdef ROCKET_DEBUG_IO - printk(KERN_DEBUG "sOutDW(%x, %lx)...\n", port, value); + printk(KERN_DEBUG "out32(%x, %lx)...\n", port, value); #endif - outl_p(cpu_to_le32(value), port); + outl_p(value, port); } static inline unsigned char sInB(unsigned short port) @@ -73,14 +72,6 @@ static inline unsigned short sInW(unsigned short port) return inw_p(port); } -#else /* !ROCKET_DEBUG_IO */ -#define sOutB(a, b) outb_p(b, a) -#define sOutW(a, b) outw_p(b, a) -#define sOutDW(port, value) outl_p(cpu_to_le32(value), port) -#define sInB(a) (inb_p(a)) -#define sInW(a) (inw_p(a)) -#endif /* ROCKET_DEBUG_IO */ - /* This is used to move arrays of bytes so byte swapping isn't appropriate. */ #define sOutStrW(port, addr, count) if (count) outsw(port, addr, count) #define sInStrW(port, addr, count) if (count) insw(port, addr, count) @@ -390,7 +381,7 @@ Call: sClrBreak(ChP) #define sClrBreak(ChP) \ do { \ (ChP)->TxControl[3] &= ~SETBREAK; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -402,7 +393,7 @@ Call: sClrDTR(ChP) #define sClrDTR(ChP) \ do { \ (ChP)->TxControl[3] &= ~SET_DTR; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -415,7 +406,7 @@ Call: sClrRTS(ChP) do { \ if ((ChP)->rtsToggle) break; \ (ChP)->TxControl[3] &= ~SET_RTS; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -489,7 +480,7 @@ Call: sDisCTSFlowCtl(ChP) #define sDisCTSFlowCtl(ChP) \ do { \ (ChP)->TxControl[2] &= ~CTSFC_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -501,7 +492,7 @@ Call: sDisIXANY(ChP) #define sDisIXANY(ChP) \ do { \ (ChP)->R[0x0e] = 0x86; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x0c]); \ + out32((ChP)->IndexAddr,&(ChP)->R[0x0c]); \ } while (0) /*************************************************************************** @@ -515,7 +506,7 @@ Comments: Function sSetParity() can be used in place of functions sEnParity(), #define sDisParity(ChP) \ do { \ (ChP)->TxControl[2] &= ~PARITY_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -527,7 +518,7 @@ Call: sDisRTSToggle(ChP) #define sDisRTSToggle(ChP) \ do { \ (ChP)->TxControl[2] &= ~RTSTOG_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ (ChP)->rtsToggle = 0; \ } while (0) @@ -540,7 +531,7 @@ Call: sDisRxFIFO(ChP) #define sDisRxFIFO(ChP) \ do { \ (ChP)->R[0x32] = 0x0a; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x30]); \ + out32((ChP)->IndexAddr,&(ChP)->R[0x30]); \ } while (0) /*************************************************************************** @@ -567,7 +558,7 @@ Call: sDisTransmit(ChP) #define sDisTransmit(ChP) \ do { \ (ChP)->TxControl[3] &= ~TX_ENABLE; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -579,7 +570,7 @@ Call: sDisTxSoftFlowCtl(ChP) #define sDisTxSoftFlowCtl(ChP) \ do { \ (ChP)->R[0x06] = 0x8a; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x04]); \ + out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \ } while (0) /*************************************************************************** @@ -604,7 +595,7 @@ Call: sEnCTSFlowCtl(ChP) #define sEnCTSFlowCtl(ChP) \ do { \ (ChP)->TxControl[2] |= CTSFC_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -616,7 +607,7 @@ Call: sEnIXANY(ChP) #define sEnIXANY(ChP) \ do { \ (ChP)->R[0x0e] = 0x21; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x0c]); \ + out32((ChP)->IndexAddr,&(ChP)->R[0x0c]); \ } while (0) /*************************************************************************** @@ -633,7 +624,7 @@ Warnings: Before enabling parity odd or even parity should be chosen using #define sEnParity(ChP) \ do { \ (ChP)->TxControl[2] |= PARITY_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -647,10 +638,10 @@ Comments: This function will disable RTS flow control and clear the RTS #define sEnRTSToggle(ChP) \ do { \ (ChP)->RxControl[2] &= ~RTSFC_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->RxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->RxControl); \ (ChP)->TxControl[2] |= RTSTOG_EN; \ (ChP)->TxControl[3] &= ~SET_RTS; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ (ChP)->rtsToggle = 1; \ } while (0) @@ -663,7 +654,7 @@ Call: sEnRxFIFO(ChP) #define sEnRxFIFO(ChP) \ do { \ (ChP)->R[0x32] = 0x08; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x30]); \ + out32((ChP)->IndexAddr,&(ChP)->R[0x30]); \ } while (0) /*************************************************************************** @@ -684,7 +675,7 @@ Warnings: This function must be called after valid microcode has been #define sEnRxProcessor(ChP) \ do { \ (ChP)->RxControl[2] |= RXPROC_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->RxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->RxControl); \ } while (0) /*************************************************************************** @@ -708,7 +699,7 @@ Call: sEnTransmit(ChP) #define sEnTransmit(ChP) \ do { \ (ChP)->TxControl[3] |= TX_ENABLE; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -720,7 +711,7 @@ Call: sEnTxSoftFlowCtl(ChP) #define sEnTxSoftFlowCtl(ChP) \ do { \ (ChP)->R[0x06] = 0xc5; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x04]); \ + out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \ } while (0) /*************************************************************************** @@ -927,7 +918,7 @@ Call: sSendBreak(ChP) #define sSendBreak(ChP) \ do { \ (ChP)->TxControl[3] |= SETBREAK; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -941,7 +932,7 @@ Call: sSetBaud(ChP,Divisor) do { \ (ChP)->BaudDiv[2] = (Byte_t)(DIVISOR); \ (ChP)->BaudDiv[3] = (Byte_t)((DIVISOR) >> 8); \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->BaudDiv[0]); \ + out32((ChP)->IndexAddr,(ChP)->BaudDiv); \ } while (0) /*************************************************************************** @@ -953,7 +944,7 @@ Call: sSetData7(ChP) #define sSetData7(ChP) \ do { \ (ChP)->TxControl[2] &= ~DATA8BIT; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -965,7 +956,7 @@ Call: sSetData8(ChP) #define sSetData8(ChP) \ do { \ (ChP)->TxControl[2] |= DATA8BIT; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -977,7 +968,7 @@ Call: sSetDTR(ChP) #define sSetDTR(ChP) \ do { \ (ChP)->TxControl[3] |= SET_DTR; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -994,7 +985,7 @@ Warnings: This function has no effect unless parity is enabled with function #define sSetEvenParity(ChP) \ do { \ (ChP)->TxControl[2] |= EVEN_PAR; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -1011,7 +1002,7 @@ Warnings: This function has no effect unless parity is enabled with function #define sSetOddParity(ChP) \ do { \ (ChP)->TxControl[2] &= ~EVEN_PAR; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -1024,7 +1015,7 @@ Call: sSetRTS(ChP) do { \ if ((ChP)->rtsToggle) break; \ (ChP)->TxControl[3] |= SET_RTS; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -1050,7 +1041,7 @@ Comments: An interrupt will be generated when the trigger level is reached do { \ (ChP)->RxControl[2] &= ~TRIG_MASK; \ (ChP)->RxControl[2] |= LEVEL; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->RxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->RxControl); \ } while (0) /*************************************************************************** @@ -1062,7 +1053,7 @@ Call: sSetStop1(ChP) #define sSetStop1(ChP) \ do { \ (ChP)->TxControl[2] &= ~STOP2; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -1074,7 +1065,7 @@ Call: sSetStop2(ChP) #define sSetStop2(ChP) \ do { \ (ChP)->TxControl[2] |= STOP2; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ + out32((ChP)->IndexAddr,(ChP)->TxControl); \ } while (0) /*************************************************************************** @@ -1087,7 +1078,7 @@ Call: sSetTxXOFFChar(ChP,Ch) #define sSetTxXOFFChar(ChP,CH) \ do { \ (ChP)->R[0x07] = (CH); \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x04]); \ + out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \ } while (0) /*************************************************************************** @@ -1100,7 +1091,7 @@ Call: sSetTxXONChar(ChP,Ch) #define sSetTxXONChar(ChP,CH) \ do { \ (ChP)->R[0x0b] = (CH); \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x08]); \ + out32((ChP)->IndexAddr,&(ChP)->R[0x08]); \ } while (0) /*************************************************************************** @@ -1113,7 +1104,7 @@ Comments: This function is used to start a Rx processor after it was will restart both the Rx processor and software input flow control. */ -#define sStartRxProcessor(ChP) sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0]) +#define sStartRxProcessor(ChP) out32((ChP)->IndexAddr,&(ChP)->R[0]) /*************************************************************************** Function: sWriteTxByte diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index ad2f938597e..72692309398 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -123,6 +123,11 @@ static dma_addr_t get_ndar(struct fsl_dma_chan *fsl_chan) return DMA_IN(fsl_chan, &fsl_chan->reg_base->ndar, 64); } +static u32 get_bcr(struct fsl_dma_chan *fsl_chan) +{ + return DMA_IN(fsl_chan, &fsl_chan->reg_base->bcr, 32); +} + static int dma_is_idle(struct fsl_dma_chan *fsl_chan) { u32 sr = get_sr(fsl_chan); @@ -426,6 +431,9 @@ fsl_dma_prep_interrupt(struct dma_chan *chan) new->async_tx.cookie = -EBUSY; new->async_tx.ack = 0; + /* Insert the link descriptor to the LD ring */ + list_add_tail(&new->node, &new->async_tx.tx_list); + /* Set End-of-link to the last link descriptor of new list*/ set_ld_eol(fsl_chan, new); @@ -701,6 +709,23 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data) if (stat & FSL_DMA_SR_TE) dev_err(fsl_chan->dev, "Transfer Error!\n"); + /* Programming Error + * The DMA_INTERRUPT async_tx is a NULL transfer, which will + * triger a PE interrupt. + */ + if (stat & FSL_DMA_SR_PE) { + dev_dbg(fsl_chan->dev, "event: Programming Error INT\n"); + if (get_bcr(fsl_chan) == 0) { + /* BCR register is 0, this is a DMA_INTERRUPT async_tx. + * Now, update the completed cookie, and continue the + * next uncompleted transfer. + */ + fsl_dma_update_completed_cookie(fsl_chan); + fsl_chan_xfer_ld_queue(fsl_chan); + } + stat &= ~FSL_DMA_SR_PE; + } + /* If the link descriptor segment transfer finishes, * we will recycle the used descriptor. */ @@ -841,6 +866,11 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan) tx3 = fsl_dma_prep_memcpy(chan, dma_dest, dma_src, test_size / 4, 0); async_tx_ack(tx3); + /* Interrupt tx test */ + tx1 = fsl_dma_prep_interrupt(chan); + async_tx_ack(tx1); + cookie = fsl_dma_tx_submit(tx1); + /* Test exchanging the prepared tx sort */ cookie = fsl_dma_tx_submit(tx3); cookie = fsl_dma_tx_submit(tx2); diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h index ba78c42121b..fddd6aee2a6 100644 --- a/drivers/dma/fsldma.h +++ b/drivers/dma/fsldma.h @@ -40,6 +40,7 @@ #define FSL_DMA_MR_EOTIE 0x00000080 #define FSL_DMA_SR_CH 0x00000020 +#define FSL_DMA_SR_PE 0x00000010 #define FSL_DMA_SR_CB 0x00000004 #define FSL_DMA_SR_TE 0x00000080 #define FSL_DMA_SR_EOSI 0x00000002 diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 99529e59a0b..e6f1bda3894 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -736,6 +736,12 @@ fw_core_handle_response(struct fw_card *card, struct fw_packet *p) break; } + /* + * The response handler may be executed while the request handler + * is still pending. Cancel the request handler. + */ + card->driver->cancel_packet(card, &t->packet); + t->callback(card, rcode, data, data_length, t->callback_data); } EXPORT_SYMBOL(fw_core_handle_response); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index d73a768e176..f0b00ec1e47 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -968,7 +968,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i size--; } - /* dump the report descriptor */ + /* dump the report */ dbg_hid("report %d (size %u) = ", n, size); for (i = 0; i < size; i++) dbg_hid_line(" %02x", data[i]); diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 5a38fb27d69..c3eb3f13e2c 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -98,18 +98,16 @@ struct hidinput_key_translation { static struct hidinput_key_translation apple_fn_keys[] = { { KEY_BACKSPACE, KEY_DELETE }, - { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, - { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, - { KEY_F3, KEY_CYCLEWINDOWS, APPLE_FLAG_FKEY }, /* Exposé */ - { KEY_F4, KEY_FN_F4, APPLE_FLAG_FKEY }, /* Dashboard */ - { KEY_F5, KEY_FN_F5 }, - { KEY_F6, KEY_FN_F6 }, - { KEY_F7, KEY_BACK, APPLE_FLAG_FKEY }, - { KEY_F8, KEY_PLAYPAUSE, APPLE_FLAG_FKEY }, - { KEY_F9, KEY_FORWARD, APPLE_FLAG_FKEY }, - { KEY_F10, KEY_MUTE, APPLE_FLAG_FKEY }, - { KEY_F11, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY }, - { KEY_F12, KEY_VOLUMEUP, APPLE_FLAG_FKEY }, + { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, + { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, + { KEY_F3, KEY_FN_F5, APPLE_FLAG_FKEY }, /* Exposé */ + { KEY_F4, KEY_FN_F4, APPLE_FLAG_FKEY }, /* Dashboard */ + { KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY }, + { KEY_F8, KEY_PLAYPAUSE, APPLE_FLAG_FKEY }, + { KEY_F9, KEY_NEXTSONG, APPLE_FLAG_FKEY }, + { KEY_F10, KEY_MUTE, APPLE_FLAG_FKEY }, + { KEY_F11, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY }, + { KEY_F12, KEY_VOLUMEUP, APPLE_FLAG_FKEY }, { KEY_UP, KEY_PAGEUP }, { KEY_DOWN, KEY_PAGEDOWN }, { KEY_LEFT, KEY_HOME }, diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index b38e559b7a4..d95979f0e02 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -278,7 +278,7 @@ static int hid_submit_ctrl(struct hid_device *hid) usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0); maxpacket = usb_maxpacket(hid_to_usb_dev(hid), usbhid->urbctrl->pipe, 0); if (maxpacket > 0) { - padlen = (len + maxpacket - 1) / maxpacket; + padlen = DIV_ROUND_UP(len, maxpacket); padlen *= maxpacket; if (padlen > usbhid->bufsize) padlen = usbhid->bufsize; diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index e6d05f6b1c1..e29a057cbea 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -345,6 +345,9 @@ #define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400 #define USB_DEVICE_ID_N_S_HARMONY 0xc359 +#define USB_VENDOR_ID_NATSU 0x08b7 +#define USB_DEVICE_ID_NATSU_GAMEPAD 0x0001 + #define USB_VENDOR_ID_NEC 0x073e #define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301 @@ -426,6 +429,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_NATSU, USB_DEVICE_ID_NATSU_GAMEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, @@ -624,7 +628,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS, HID_QUIRK_APPLE_HAS_FN }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI, HID_QUIRK_APPLE_HAS_FN }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD }, diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 368879ff5d8..4dc76bc45c9 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -337,8 +337,9 @@ config SENSORS_IBMPEX help If you say yes here you get support for the temperature and power sensors in various IBM System X servers that support - PowerExecutive. So far this includes the x3550, x3650, x3655, - x3755, and certain HS20 blades. + PowerExecutive. So far this includes the x3350, x3550, x3650, + x3655, and x3755; the x3800, x3850, and x3950 models that have + PCI Express; and some of the HS2x, LS2x, and QS2x blades. This driver can also be built as a module. If so, the module will be called ibmpex. diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c index 9c9cdb0685e..4e9b19c6732 100644 --- a/drivers/hwmon/ibmpex.c +++ b/drivers/hwmon/ibmpex.c @@ -327,10 +327,14 @@ static int is_temp_sensor(const char *sensor_id, int len) return 0; } -static int power_sensor_multiplier(const char *sensor_id, int len) +static int power_sensor_multiplier(struct ibmpex_bmc_data *data, + const char *sensor_id, int len) { int i; + if (data->sensor_major == 2) + return 1000000; + for (i = PEX_SENSOR_TYPE_LEN; i < len - 1; i++) if (!memcmp(&sensor_id[i], watt_sensor_sig, PEX_MULT_LEN)) return 1000000; @@ -398,14 +402,15 @@ static int ibmpex_find_sensors(struct ibmpex_bmc_data *data) num_power++; sensor_counter = num_power; data->sensors[i].multiplier = - power_sensor_multiplier(data->rx_msg_data, - data->rx_msg_len); + power_sensor_multiplier(data, + data->rx_msg_data, + data->rx_msg_len); } else if (is_temp_sensor(data->rx_msg_data, data->rx_msg_len)) { sensor_type = TEMP_SENSOR; num_temp++; sensor_counter = num_temp; - data->sensors[i].multiplier = 1; + data->sensors[i].multiplier = 1000; } else continue; diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 0518a2e948c..4c86a8d84b4 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -423,6 +423,25 @@ void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) } /* + * We got an interrupt on a task_in case, but no errors and no DRQ. + * + * It might be a spurious irq (shared irq), but it might be a + * command that had no output. + */ +static ide_startstop_t task_in_unexpected(ide_drive_t *drive, struct request *rq, u8 stat) +{ + /* Command all done? */ + if (OK_STAT(stat, READY_STAT, BUSY_STAT)) { + task_end_request(drive, rq, stat); + return ide_stopped; + } + + /* Assume it was a spurious irq */ + ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL); + return ide_started; +} + +/* * Handler for command with PIO data-in phase (Read/Read Multiple). */ static ide_startstop_t task_in_intr(ide_drive_t *drive) @@ -431,18 +450,17 @@ static ide_startstop_t task_in_intr(ide_drive_t *drive) struct request *rq = HWGROUP(drive)->rq; u8 stat = ide_read_status(drive); - /* new way for dealing with premature shared PCI interrupts */ - if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) { - if (stat & (ERR_STAT | DRQ_STAT)) - return task_error(drive, rq, __FUNCTION__, stat); - /* No data yet, so wait for another IRQ. */ - ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL); - return ide_started; - } + /* Error? */ + if (stat & ERR_STAT) + return task_error(drive, rq, __FUNCTION__, stat); + + /* Didn't want any data? Odd. */ + if (!(stat & DRQ_STAT)) + return task_in_unexpected(drive, rq, stat); ide_pio_datablock(drive, rq, 0); - /* If it was the last datablock check status and finish transfer. */ + /* Are we done? Check status and finish transfer. */ if (!hwif->nleft) { stat = wait_drive_not_busy(drive); if (!OK_STAT(stat, 0, BAD_STAT)) diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index 4833b1a8262..5511ef006a6 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c @@ -1,7 +1,7 @@ /* * Cobalt button interface driver. * - * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2007-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * 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 @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include <linux/init.h> #include <linux/input-polldev.h> @@ -55,7 +55,7 @@ static void handle_buttons(struct input_polled_dev *dev) status = ~readl(bdev->reg) >> 24; for (i = 0; i < ARRAY_SIZE(bdev->keymap); i++) { - if (status & (1UL << i)) { + if (status & (1U << i)) { if (++bdev->count[i] == BUTTONS_COUNT_THRESHOLD) { input_event(input, EV_MSC, MSC_SCAN, i); input_report_key(input, bdev->keymap[i], 1); @@ -97,16 +97,16 @@ static int __devinit cobalt_buttons_probe(struct platform_device *pdev) input->name = "Cobalt buttons"; input->phys = "cobalt/input0"; input->id.bustype = BUS_HOST; - input->cdev.dev = &pdev->dev; + input->dev.parent = &pdev->dev; - input->keycode = pdev->keymap; - input->keycodemax = ARRAY_SIZE(pdev->keymap); + input->keycode = bdev->keymap; + input->keycodemax = ARRAY_SIZE(bdev->keymap); input->keycodesize = sizeof(unsigned short); input_set_capability(input, EV_MSC, MSC_SCAN); __set_bit(EV_KEY, input->evbit); - for (i = 0; i < ARRAY_SIZE(buttons_map); i++) - __set_bit(input->keycode[i], input->keybit); + for (i = 0; i < ARRAY_SIZE(cobalt_map); i++) + __set_bit(bdev->keymap[i], input->keybit); __clear_bit(KEY_RESERVED, input->keybit); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index b346a3b418e..385e32bcf6a 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -116,8 +116,8 @@ static void alps_process_packet(struct psmouse *psmouse) } if (priv->i->flags & ALPS_FW_BK_1) { - back = packet[2] & 4; - forward = packet[0] & 0x10; + back = packet[0] & 0x10; + forward = packet[2] & 4; } if (priv->i->flags & ALPS_FW_BK_2) { @@ -483,6 +483,7 @@ int alps_init(struct psmouse *psmouse) dev2->id.vendor = 0x0002; dev2->id.product = PSMOUSE_ALPS; dev2->id.version = 0x0000; + dev2->dev.parent = &psmouse->ps2dev.serio->dev; dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); dev2->relbit[BIT_WORD(REL_X)] |= BIT_MASK(REL_X) | BIT_MASK(REL_Y); diff --git a/drivers/input/serio/i8042-snirm.h b/drivers/input/serio/i8042-snirm.h new file mode 100644 index 00000000000..409a9341143 --- /dev/null +++ b/drivers/input/serio/i8042-snirm.h @@ -0,0 +1,75 @@ +#ifndef _I8042_SNIRM_H +#define _I8042_SNIRM_H + +#include <asm/sni.h> + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +/* + * Names. + */ + +#define I8042_KBD_PHYS_DESC "onboard/serio0" +#define I8042_AUX_PHYS_DESC "onboard/serio1" +#define I8042_MUX_PHYS_DESC "onboard/serio%d" + +/* + * IRQs. + */ +static int i8042_kbd_irq; +static int i8042_aux_irq; +#define I8042_KBD_IRQ i8042_kbd_irq +#define I8042_AUX_IRQ i8042_aux_irq + +static void __iomem *kbd_iobase; + +#define I8042_COMMAND_REG (kbd_iobase + 0x64UL) +#define I8042_DATA_REG (kbd_iobase + 0x60UL) + +static inline int i8042_read_data(void) +{ + return readb(kbd_iobase + 0x60UL); +} + +static inline int i8042_read_status(void) +{ + return readb(kbd_iobase + 0x64UL); +} + +static inline void i8042_write_data(int val) +{ + writeb(val, kbd_iobase + 0x60UL); +} + +static inline void i8042_write_command(int val) +{ + writeb(val, kbd_iobase + 0x64UL); +} +static inline int i8042_platform_init(void) +{ + /* RM200 is strange ... */ + if (sni_brd_type == SNI_BRD_RM200) { + kbd_iobase = ioremap(0x16000000, 4); + i8042_kbd_irq = 33; + i8042_aux_irq = 44; + } else { + kbd_iobase = ioremap(0x14000000, 4); + i8042_kbd_irq = 1; + i8042_aux_irq = 12; + } + if (!kbd_iobase) + return -ENOMEM; + + return 0; +} + +static inline void i8042_platform_exit(void) +{ + +} + +#endif /* _I8042_SNIRM_H */ diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 662e84482c2..60931aceb82 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -277,6 +277,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "M636/A737 platform"), }, }, + { + .ident = "Lenovo 3000 n100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"), + }, + }, { } }; diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 2763394869d..65a74cfc187 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -1151,7 +1151,6 @@ static int __devinit i8042_setup_kbd(void) static int __devinit i8042_probe(struct platform_device *dev) { int error; - char param; error = i8042_controller_selftest(); if (error) @@ -1174,7 +1173,7 @@ static int __devinit i8042_probe(struct platform_device *dev) } #ifdef CONFIG_X86 if (i8042_dritek) { - param = 0x90; + char param = 0x90; error = i8042_command(¶m, 0x1059); if (error) goto out_fail; diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h index c972e5d03a3..cbc1beb6657 100644 --- a/drivers/input/serio/i8042.h +++ b/drivers/input/serio/i8042.h @@ -18,6 +18,8 @@ #include "i8042-jazzio.h" #elif defined(CONFIG_SGI_HAS_I8042) #include "i8042-ip22io.h" +#elif defined(CONFIG_SNI_RM) +#include "i8042-snirm.h" #elif defined(CONFIG_PPC) #include "i8042-ppcio.h" #elif defined(CONFIG_SPARC) diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index 6542edb6f76..acf9830698c 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h @@ -11,7 +11,7 @@ * Copyright (c) 2000 Daniel Egger <egger@suse.de> * Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com> * Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be> - * Copyright (c) 2002-2007 Ping Cheng <pingc@wacom.com> + * Copyright (c) 2002-2008 Ping Cheng <pingc@wacom.com> * * ChangeLog: * v0.1 (vp) - Initial release @@ -65,6 +65,7 @@ * - and wacom_wac.c deals with Wacom specific code * - Support Intuos3 4x6 * v1.47 (pc) - Added support for Bamboo + * v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX */ /* @@ -85,7 +86,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.47" +#define DRIVER_VERSION "v1.48" #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" #define DRIVER_LICENSE "GPL" @@ -125,6 +126,7 @@ extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac); +extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern __u16 wacom_le16_to_cpu(unsigned char *data); extern __u16 wacom_be16_to_cpu(unsigned char *data); extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id); diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index d64b1ea136b..41caaef8e2d 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -171,6 +171,7 @@ void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac) input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_0) | BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3); input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); + input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); } void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac) @@ -180,6 +181,11 @@ void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac) input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); } +void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac) +{ + input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9); +} + void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { input_dev->evbit[0] |= BIT_MASK(EV_MSC) | BIT_MASK(EV_REL); diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index fc03ba256f4..ffe33842143 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -163,7 +163,9 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) } id = STYLUS_DEVICE_ID; - if (data[1] & 0x80) { /* in prox */ + if ((data[1] & 0x80) && ((data[1] & 0x07) || data[2] || data[3] || data[4] + || data[5] || data[6] || (data[7] & 0x07))) { + /* in prox and not a pad data */ switch ((data[1] >> 5) & 3) { @@ -233,7 +235,6 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) if (data[7] & 0xf8) { wacom_input_sync(wcombo); /* sync last event */ wacom->id[1] = 1; - wacom->serial[1] = (data[7] & 0xf8); wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); @@ -252,10 +253,9 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) } break; case WACOM_MO: - if ((data[7] & 0xf8) || (data[8] & 0x80)) { + if ((data[7] & 0xf8) || (data[8] & 0xff)) { wacom_input_sync(wcombo); /* sync last event */ wacom->id[1] = 1; - wacom->serial[1] = (data[7] & 0xf8); wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); wacom_report_key(wcombo, BTN_4, (data[7] & 0x10)); @@ -434,10 +434,12 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_key(wcombo, BTN_5, (data[6] & 0x02)); wacom_report_key(wcombo, BTN_6, (data[6] & 0x04)); wacom_report_key(wcombo, BTN_7, (data[6] & 0x08)); + wacom_report_key(wcombo, BTN_8, (data[5] & 0x10)); + wacom_report_key(wcombo, BTN_9, (data[6] & 0x10)); wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]); wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); - if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) | + if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) | data[2] | (data[3] & 0x1f) | data[4]) wacom_report_key(wcombo, wacom->tool[1], 1); else @@ -481,13 +483,11 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) if (data[1] & 0x02) { /* Rotation packet */ if (wacom->features->type >= INTUOS3S) { - /* I3 marker pen rotation reported as wheel - * due to valuator limitation - */ + /* I3 marker pen rotation */ t = (data[6] << 3) | ((data[7] >> 5) & 7); t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : ((t-1) / 2 + 450)) : (450 - t / 2) ; - wacom_report_abs(wcombo, ABS_WHEEL, t); + wacom_report_abs(wcombo, ABS_Z, t); } else { /* 4D mouse rotation packet */ t = (data[6] << 3) | ((data[7] >> 5) & 7); @@ -558,6 +558,7 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) case INTUOS3: case INTUOS3L: case CINTIQ: + case WACOM_BEE: return (wacom_intuos_irq(wacom_wac, wcombo)); break; default: @@ -577,6 +578,8 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w case GRAPHIRE: input_dev_g(input_dev, wacom_wac); break; + case WACOM_BEE: + input_dev_bee(input_dev, wacom_wac); case INTUOS3: case INTUOS3L: case CINTIQ: @@ -607,12 +610,15 @@ static struct wacom_features wacom_features[] = { { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 63, GRAPHIRE }, { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 63, WACOM_G4 }, { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 63, WACOM_G4 }, + { "Wacom BambooFun 4x5", 9, 14760, 9225, 511, 63, WACOM_MO }, + { "Wacom BambooFun 6x8", 9, 21648, 13530, 511, 63, WACOM_MO }, { "Wacom Volito", 8, 5104, 3712, 511, 63, GRAPHIRE }, { "Wacom PenStation2", 8, 3250, 2320, 255, 63, GRAPHIRE }, { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE }, { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 63, GRAPHIRE }, - { "Wacom PenPartner2", 8, 3250, 2320, 255, 63, GRAPHIRE }, + { "Wacom PenPartner2", 8, 3250, 2320, 511, 63, GRAPHIRE }, { "Wacom Bamboo", 9, 14760, 9225, 511, 63, WACOM_MO }, + { "Wacom Bamboo1", 8, 5104, 3712, 511, 63, GRAPHIRE }, { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 31, INTUOS }, @@ -643,6 +649,7 @@ static struct wacom_features wacom_features[] = { { "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 63, INTUOS3 }, { "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 63, INTUOS3S }, { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ }, + { "Wacom Cintiq 12WX", 10, 53020, 33440, 1023, 63, WACOM_BEE }, { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, { } }; @@ -656,12 +663,15 @@ static struct usb_device_id wacom_ids[] = { { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x17) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x18) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x65) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x69) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) }, @@ -692,6 +702,7 @@ static struct usb_device_id wacom_ids[] = { { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB7) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, { } }; diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index a302e229bb8..3342bc05847 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -25,6 +25,7 @@ enum { INTUOS3, INTUOS3L, CINTIQ, + WACOM_BEE, WACOM_MO, MAX_TYPE }; diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 58934a40f5c..57a1c28bf12 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -213,7 +213,7 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) struct ads7846 *ts = dev_get_drvdata(dev); struct ser_req *req = kzalloc(sizeof *req, GFP_KERNEL); int status; - int sample; + int uninitialized_var(sample); int use_internal; if (!req) diff --git a/drivers/md/md.c b/drivers/md/md.c index ccbbf63727c..61ccbd2683f 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1864,17 +1864,6 @@ static struct rdev_sysfs_entry rdev_state = __ATTR(state, S_IRUGO|S_IWUSR, state_show, state_store); static ssize_t -super_show(mdk_rdev_t *rdev, char *page) -{ - if (rdev->sb_loaded && rdev->sb_size) { - memcpy(page, page_address(rdev->sb_page), rdev->sb_size); - return rdev->sb_size; - } else - return 0; -} -static struct rdev_sysfs_entry rdev_super = __ATTR_RO(super); - -static ssize_t errors_show(mdk_rdev_t *rdev, char *page) { return sprintf(page, "%d\n", atomic_read(&rdev->corrected_errors)); @@ -2060,7 +2049,6 @@ __ATTR(size, S_IRUGO|S_IWUSR, rdev_size_show, rdev_size_store); static struct attribute *rdev_default_attrs[] = { &rdev_state.attr, - &rdev_super.attr, &rdev_errors.attr, &rdev_slot.attr, &rdev_offset.attr, diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 2d6f1a51359..c574cf5efb5 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1143,7 +1143,7 @@ static void raid5_end_read_request(struct bio * bi, int error) rdev = conf->disks[i].rdev; printk(KERN_INFO "raid5:%s: read error corrected (%lu sectors at %llu on %s)\n", mdname(conf->mddev), STRIPE_SECTORS, - (unsigned long long)sh->sector + rdev->data_offset, + (unsigned long long)(sh->sector + rdev->data_offset), bdevname(rdev->bdev, b)); clear_bit(R5_ReadError, &sh->dev[i].flags); clear_bit(R5_ReWrite, &sh->dev[i].flags); @@ -1160,13 +1160,13 @@ static void raid5_end_read_request(struct bio * bi, int error) if (conf->mddev->degraded) printk(KERN_WARNING "raid5:%s: read error not correctable (sector %llu on %s).\n", mdname(conf->mddev), - (unsigned long long)sh->sector + rdev->data_offset, + (unsigned long long)(sh->sector + rdev->data_offset), bdn); else if (test_bit(R5_ReWrite, &sh->dev[i].flags)) /* Oh, no!!! */ printk(KERN_WARNING "raid5:%s: read error NOT corrected!! (sector %llu on %s).\n", mdname(conf->mddev), - (unsigned long long)sh->sector + rdev->data_offset, + (unsigned long long)(sh->sector + rdev->data_offset), bdn); else if (atomic_read(&rdev->read_errors) > conf->max_nr_stripes) diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c index 21935bf7059..302cc67407c 100644 --- a/drivers/media/dvb/dvb-usb/opera1.c +++ b/drivers/media/dvb/dvb-usb/opera1.c @@ -478,9 +478,9 @@ static int opera1_xilinx_load_firmware(struct usb_device *dev, err("could not restart the USB controller CPU."); ret = -EINVAL; } - kfree(p); } } + kfree(p); if (fw) { release_firmware(fw); } diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 37072a21d8c..1832966f53f 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -305,7 +305,7 @@ comment "MPEG video encoders" config VIDEO_CX2341X tristate "Conexant CX2341x MPEG encoders" - depends on VIDEO_V4L2 && EXPERIMENTAL + depends on VIDEO_V4L2 && EXPERIMENTAL && VIDEO_V4L2_COMMON ---help--- Support for the Conexant CX23416 MPEG encoders and CX23415 MPEG encoder/decoders. @@ -382,7 +382,7 @@ endmenu # encoder / decoder chips config VIDEO_VIVI tristate "Virtual Video Driver" - depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 + depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 select VIDEOBUF_VMALLOC default n ---help--- diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 5404fcc5276..a080c149cc6 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -3389,7 +3389,6 @@ static struct video_device bttv_video_template = .vidiocgmbuf = vidiocgmbuf, #endif .vidioc_g_crop = bttv_g_crop, - .vidioc_g_crop = bttv_g_crop, .vidioc_s_crop = bttv_s_crop, .vidioc_g_fbuf = bttv_g_fbuf, .vidioc_s_fbuf = bttv_s_fbuf, diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index e6b7f518c56..8c9a8adf52d 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -2196,6 +2196,11 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) cx88_reset(core); cx88_card_setup_pre_i2c(core); cx88_i2c_init(core, pci); + + /* load tuner module, if needed */ + if (TUNER_ABSENT != core->board.tuner_type) + request_module("tuner"); + cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL); cx88_card_setup(core); cx88_ir_init(core, pci); diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 7f1931aed20..227179620d1 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1826,8 +1826,6 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, cx_set(MO_PCI_INTMSK, core->pci_irqmask); /* load and configure helper modules */ - if (TUNER_ABSENT != core->board.tuner_type) - request_module("tuner"); if (core->board.audio_chip == AUDIO_CHIP_WM8775) request_module("wm8775"); diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 7d1537cab86..c1caaa855b9 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -267,7 +267,7 @@ static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val) for (i = 0; i < 10; i++) { if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0) return ret; - if (!((u8) ret) & 0x01) + if (!(ret & 0x01)) return 0; msleep(5); } diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index d42f120354e..948ca35e7ee 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -54,7 +54,6 @@ #include "ivtv-vbi.h" #include "ivtv-routing.h" #include "ivtv-gpio.h" -#include "ivtv-yuv.h" #include <media/tveeprom.h> #include <media/saa7115.h> @@ -700,6 +699,9 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; itv->vbi.sliced_in = &itv->vbi.in.fmt.sliced; + /* Init the sg table for osd/yuv output */ + sg_init_table(itv->udma.SGlist, IVTV_DMA_SG_OSD_ENT); + /* OSD */ itv->osd_global_alpha_state = 1; itv->osd_global_alpha = 255; @@ -1053,9 +1055,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev, goto free_io; } - /* Check yuv output filter table */ - if (itv->has_cx23415) ivtv_yuv_filter_check(itv); - ivtv_gpio_init(itv); /* active i2c */ diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c index 425eb106390..6dba55b7e25 100644 --- a/drivers/media/video/ivtv/ivtv-firmware.c +++ b/drivers/media/video/ivtv/ivtv-firmware.c @@ -22,6 +22,7 @@ #include "ivtv-driver.h" #include "ivtv-mailbox.h" #include "ivtv-firmware.h" +#include "ivtv-yuv.h" #include <linux/firmware.h> #define IVTV_MASK_SPU_ENABLE 0xFFFFFFFE @@ -225,11 +226,14 @@ int ivtv_firmware_init(struct ivtv *itv) return 0; itv->dec_mbox.mbox = ivtv_search_mailbox(itv->dec_mem, IVTV_DECODER_SIZE); - if (itv->dec_mbox.mbox == NULL) + if (itv->dec_mbox.mbox == NULL) { IVTV_ERR("Decoder mailbox not found\n"); - else if (itv->has_cx23415 && ivtv_vapi(itv, CX2341X_DEC_PING_FW, 0)) { + } else if (itv->has_cx23415 && ivtv_vapi(itv, CX2341X_DEC_PING_FW, 0)) { IVTV_ERR("Decoder firmware dead!\n"); itv->dec_mbox.mbox = NULL; + } else { + /* Firmware okay, so check yuv output filter table */ + ivtv_yuv_filter_check(itv); } return itv->dec_mbox.mbox ? 0 : -ENODEV; } diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 262830da08c..6f5744286e8 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2484,27 +2484,28 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .gpiomask = 0x080200000, - .inputs = {{ - .name = name_tv, - .vmux = 4, - .amux = TV, - .tv = 1, - },{ - .name = name_comp1, - .vmux = 1, - .amux = LINE2, - },{ - .name = name_comp2, - .vmux = 0, - .amux = LINE2, - },{ - .name = name_svideo, - .vmux = 8, - .amux = LINE2, - }}, + .inputs = { { + .name = name_tv, + .vmux = 4, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE2, + }, { + .name = name_comp2, + .vmux = 0, + .amux = LINE2, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + } }, .radio = { - .name = name_radio, - .amux = LINE1, + .name = name_radio, + .amux = TV, + .gpio = 0x0200000, }, }, [SAA7134_BOARD_ASUSTeK_P7131_DUAL] = { diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 52baa4f7f7d..58ab163fdbd 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -1022,12 +1022,13 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, saa7134_i2c_register(dev); /* initialize hardware #2 */ + if (TUNER_ABSENT != dev->tuner_type) + request_module("tuner"); saa7134_board_init2(dev); + saa7134_hwinit2(dev); /* load i2c helpers */ - if (TUNER_ABSENT != dev->tuner_type) - request_module("tuner"); if (card_is_empress(dev)) { request_module("saa6752hs"); } diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 445eba4174d..d28318cb2b8 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -672,7 +672,7 @@ static int tvp5150_set_vbi(struct i2c_client *c, if (std == V4L2_STD_ALL) { tvp5150_err("VBI can't be configured without knowing number of lines\n"); return 0; - } else if (std && V4L2_STD_625_50) { + } else if (std & V4L2_STD_625_50) { /* Don't follow NTSC Line number convension */ line += 3; } @@ -719,7 +719,7 @@ static int tvp5150_get_vbi(struct i2c_client *c, if (std == V4L2_STD_ALL) { tvp5150_err("VBI can't be configured without knowing number of lines\n"); return 0; - } else if (std && V4L2_STD_625_50) { + } else if (std & V4L2_STD_625_50) { /* Don't follow NTSC Line number convension */ line += 3; } diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c index fb434b5602a..5d363be7bc7 100644 --- a/drivers/media/video/usbvideo/usbvideo.c +++ b/drivers/media/video/usbvideo/usbvideo.c @@ -1034,6 +1034,11 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd) info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx", __FUNCTION__, uvd->iface, uvd->video_endp, uvd->paletteBits); } + if (uvd->dev == NULL) { + err("%s: uvd->dev == NULL", __FUNCTION__); + return -EINVAL; + } + uvd->vdev.dev=&(uvd->dev->dev); if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { err("%s: video_register_device failed", __FUNCTION__); return -EPIPE; @@ -1041,10 +1046,6 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd) if (uvd->debug > 1) { info("%s: video_register_device() successful", __FUNCTION__); } - if (uvd->dev == NULL) { - err("%s: uvd->dev == NULL", __FUNCTION__); - return -EINVAL; - } info("%s on /dev/video%d: canvas=%s videosize=%s", (uvd->handle != NULL) ? uvd->handle->drvName : "???", diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index dcf22a3b672..50e1ff9f2be 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -303,7 +303,11 @@ v4l_compat_translate_ioctl(struct inode *inode, { struct video_capability *cap = arg; - cap2 = kzalloc(sizeof(*cap2),GFP_KERNEL); + cap2 = kzalloc(sizeof(*cap2), GFP_KERNEL); + if (!cap2) { + err = -ENOMEM; + break; + } memset(cap, 0, sizeof(*cap)); memset(&fbuf2, 0, sizeof(fbuf2)); @@ -426,7 +430,11 @@ v4l_compat_translate_ioctl(struct inode *inode, { struct video_window *win = arg; - fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL); + fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); + if (!fmt2) { + err = -ENOMEM; + break; + } memset(win,0,sizeof(*win)); fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY; @@ -464,7 +472,11 @@ v4l_compat_translate_ioctl(struct inode *inode, struct video_window *win = arg; int err1,err2; - fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL); + fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); + if (!fmt2) { + err = -ENOMEM; + break; + } fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; drv(inode, file, VIDIOC_STREAMOFF, &fmt2->type); err1 = drv(inode, file, VIDIOC_G_FMT, fmt2); @@ -586,6 +598,12 @@ v4l_compat_translate_ioctl(struct inode *inode, { struct video_picture *pict = arg; + fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); + if (!fmt2) { + err = -ENOMEM; + break; + } + pict->brightness = get_v4l_control(inode, file, V4L2_CID_BRIGHTNESS,drv); pict->hue = get_v4l_control(inode, file, @@ -597,7 +615,6 @@ v4l_compat_translate_ioctl(struct inode *inode, pict->whiteness = get_v4l_control(inode, file, V4L2_CID_WHITENESS, drv); - fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL); fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(inode, file, VIDIOC_G_FMT, fmt2); if (err < 0) { @@ -617,6 +634,11 @@ v4l_compat_translate_ioctl(struct inode *inode, struct video_picture *pict = arg; int mem_err = 0, ovl_err = 0; + fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); + if (!fmt2) { + err = -ENOMEM; + break; + } memset(&fbuf2, 0, sizeof(fbuf2)); set_v4l_control(inode, file, @@ -636,7 +658,6 @@ v4l_compat_translate_ioctl(struct inode *inode, * different pixel formats for memory vs overlay. */ - fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL); fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(inode, file, VIDIOC_G_FMT, fmt2); /* If VIDIOC_G_FMT failed, then the driver likely doesn't @@ -890,7 +911,11 @@ v4l_compat_translate_ioctl(struct inode *inode, { struct video_mmap *mm = arg; - fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL); + fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); + if (!fmt2) { + err = -ENOMEM; + break; + } memset(&buf2,0,sizeof(buf2)); fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -986,7 +1011,11 @@ v4l_compat_translate_ioctl(struct inode *inode, { struct vbi_format *fmt = arg; - fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL); + fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); + if (!fmt2) { + err = -ENOMEM; + break; + } fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; err = drv(inode, file, VIDIOC_G_FMT, fmt2); @@ -1018,8 +1047,11 @@ v4l_compat_translate_ioctl(struct inode *inode, break; } - fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL); - + fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); + if (!fmt2) { + err = -ENOMEM; + break; + } fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line; fmt2->fmt.vbi.sampling_rate = fmt->sampling_rate; diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c index de80dba12f9..946e3d3506a 100644 --- a/drivers/memstick/core/memstick.c +++ b/drivers/memstick/core/memstick.c @@ -276,8 +276,6 @@ void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc, mrq->need_card_int = 1; else mrq->need_card_int = 0; - - mrq->get_int_reg = 0; } EXPORT_SYMBOL(memstick_init_req_sg); @@ -311,8 +309,6 @@ void memstick_init_req(struct memstick_request *mrq, unsigned char tpc, mrq->need_card_int = 1; else mrq->need_card_int = 0; - - mrq->get_int_reg = 0; } EXPORT_SYMBOL(memstick_init_req); @@ -342,6 +338,7 @@ static int h_memstick_read_dev_id(struct memstick_dev *card, card->id.class = id_reg.class; } complete(&card->mrq_complete); + dev_dbg(&card->dev, "if_mode = %02x\n", id_reg.if_mode); return -EAGAIN; } } @@ -422,7 +419,6 @@ static void memstick_power_on(struct memstick_host *host) { host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL); - msleep(1); } static void memstick_check(struct work_struct *work) @@ -579,7 +575,8 @@ EXPORT_SYMBOL(memstick_suspend_host); void memstick_resume_host(struct memstick_host *host) { mutex_lock(&host->lock); - host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); + if (host->card) + memstick_power_on(host); mutex_unlock(&host->lock); memstick_detect_change(host); } diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 1d637e4561d..557dbbba5cb 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -133,6 +133,7 @@ struct mspro_devinfo { struct mspro_block_data { struct memstick_dev *card; unsigned int usage_count; + unsigned int caps; struct gendisk *disk; struct request_queue *queue; spinlock_t q_lock; @@ -577,7 +578,6 @@ static int h_mspro_block_wait_for_ced(struct memstick_dev *card, static int h_mspro_block_transfer_data(struct memstick_dev *card, struct memstick_request **mrq) { - struct memstick_host *host = card->host; struct mspro_block_data *msb = memstick_get_drvdata(card); unsigned char t_val = 0; struct scatterlist t_sg = { 0 }; @@ -591,12 +591,12 @@ static int h_mspro_block_transfer_data(struct memstick_dev *card, switch ((*mrq)->tpc) { case MS_TPC_WRITE_REG: memstick_init_req(*mrq, MS_TPC_SET_CMD, &msb->transfer_cmd, 1); - (*mrq)->get_int_reg = 1; + (*mrq)->need_card_int = 1; return 0; case MS_TPC_SET_CMD: t_val = (*mrq)->int_reg; memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1); - if (host->caps & MEMSTICK_CAP_AUTO_GET_INT) + if (msb->caps & MEMSTICK_CAP_AUTO_GET_INT) goto has_int_reg; return 0; case MS_TPC_GET_INT: @@ -646,12 +646,12 @@ has_int_reg: ? MS_TPC_READ_LONG_DATA : MS_TPC_WRITE_LONG_DATA, &t_sg); - (*mrq)->get_int_reg = 1; + (*mrq)->need_card_int = 1; return 0; case MS_TPC_READ_LONG_DATA: case MS_TPC_WRITE_LONG_DATA: msb->current_page++; - if (host->caps & MEMSTICK_CAP_AUTO_GET_INT) { + if (msb->caps & MEMSTICK_CAP_AUTO_GET_INT) { t_val = (*mrq)->int_reg; goto has_int_reg; } else { @@ -816,12 +816,13 @@ static int mspro_block_wait_for_ced(struct memstick_dev *card) return card->current_mrq.error; } -static int mspro_block_switch_to_parallel(struct memstick_dev *card) +static int mspro_block_set_interface(struct memstick_dev *card, + unsigned char sys_reg) { struct memstick_host *host = card->host; struct mspro_block_data *msb = memstick_get_drvdata(card); struct mspro_param_register param = { - .system = MEMSTICK_SYS_PAR4, + .system = sys_reg, .data_count = 0, .data_address = 0, .tpc_param = 0 @@ -833,41 +834,70 @@ static int mspro_block_switch_to_parallel(struct memstick_dev *card) sizeof(param)); memstick_new_req(host); wait_for_completion(&card->mrq_complete); - if (card->current_mrq.error) - return card->current_mrq.error; + return card->current_mrq.error; +} + +static int mspro_block_switch_interface(struct memstick_dev *card) +{ + struct memstick_host *host = card->host; + struct mspro_block_data *msb = memstick_get_drvdata(card); + int rc = 0; + + if (msb->caps & MEMSTICK_CAP_PAR4) + rc = mspro_block_set_interface(card, MEMSTICK_SYS_PAR4); + else + return 0; + + if (rc) { + printk(KERN_WARNING + "%s: could not switch to 4-bit mode, error %d\n", + card->dev.bus_id, rc); + return 0; + } msb->system = MEMSTICK_SYS_PAR4; host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4); + printk(KERN_INFO "%s: switching to 4-bit parallel mode\n", + card->dev.bus_id); + + if (msb->caps & MEMSTICK_CAP_PAR8) { + rc = mspro_block_set_interface(card, MEMSTICK_SYS_PAR8); + + if (!rc) { + msb->system = MEMSTICK_SYS_PAR8; + host->set_param(host, MEMSTICK_INTERFACE, + MEMSTICK_PAR8); + printk(KERN_INFO + "%s: switching to 8-bit parallel mode\n", + card->dev.bus_id); + } else + printk(KERN_WARNING + "%s: could not switch to 8-bit mode, error %d\n", + card->dev.bus_id, rc); + } card->next_request = h_mspro_block_req_init; msb->mrq_handler = h_mspro_block_default; memstick_init_req(&card->current_mrq, MS_TPC_GET_INT, NULL, 1); memstick_new_req(card->host); wait_for_completion(&card->mrq_complete); + rc = card->current_mrq.error; - if (card->current_mrq.error) { + if (rc) { + printk(KERN_WARNING + "%s: interface error, trying to fall back to serial\n", + card->dev.bus_id); msb->system = MEMSTICK_SYS_SERIAL; host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF); - msleep(1000); + msleep(10); host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL); - if (memstick_set_rw_addr(card)) - return card->current_mrq.error; - - param.system = msb->system; - - card->next_request = h_mspro_block_req_init; - msb->mrq_handler = h_mspro_block_default; - memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, ¶m, - sizeof(param)); - memstick_new_req(host); - wait_for_completion(&card->mrq_complete); - - return -EFAULT; + rc = memstick_set_rw_addr(card); + if (!rc) + rc = mspro_block_set_interface(card, msb->system); } - - return 0; + return rc; } /* Memory allocated for attributes by this function should be freed by @@ -1052,16 +1082,18 @@ static int mspro_block_init_card(struct memstick_dev *card) if (memstick_set_rw_addr(card)) return -EIO; - if (host->caps & MEMSTICK_CAP_PAR4) { - if (mspro_block_switch_to_parallel(card)) - printk(KERN_WARNING "%s: could not switch to " - "parallel interface\n", card->dev.bus_id); - } + msb->caps = host->caps; + rc = mspro_block_switch_interface(card); + if (rc) + return rc; + msleep(200); rc = mspro_block_wait_for_ced(card); if (rc) return rc; dev_dbg(&card->dev, "card activated\n"); + if (msb->system != MEMSTICK_SYS_SERIAL) + msb->caps |= MEMSTICK_CAP_AUTO_GET_INT; card->next_request = h_mspro_block_req_init; msb->mrq_handler = h_mspro_block_get_ro; diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c index 03fe8783b1e..8770a5fac3b 100644 --- a/drivers/memstick/host/jmb38x_ms.c +++ b/drivers/memstick/host/jmb38x_ms.c @@ -12,6 +12,7 @@ #include <linux/spinlock.h> #include <linux/interrupt.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <linux/delay.h> #include <linux/highmem.h> #include <linux/memstick.h> @@ -56,8 +57,6 @@ struct jmb38x_ms_host { unsigned long timeout_jiffies; struct timer_list timer; struct memstick_request *req; - unsigned char eject:1, - use_dma:1; unsigned char cmd_flags; unsigned char io_pos; unsigned int io_word[2]; @@ -94,9 +93,22 @@ struct jmb38x_ms { #define HOST_CONTROL_IF_PAR4 0x1 #define HOST_CONTROL_IF_PAR8 0x3 +#define STATUS_BUSY 0x00080000 +#define STATUS_MS_DAT7 0x00040000 +#define STATUS_MS_DAT6 0x00020000 +#define STATUS_MS_DAT5 0x00010000 +#define STATUS_MS_DAT4 0x00008000 +#define STATUS_MS_DAT3 0x00004000 +#define STATUS_MS_DAT2 0x00002000 +#define STATUS_MS_DAT1 0x00001000 +#define STATUS_MS_DAT0 0x00000800 #define STATUS_HAS_MEDIA 0x00000400 #define STATUS_FIFO_EMPTY 0x00000200 #define STATUS_FIFO_FULL 0x00000100 +#define STATUS_MS_CED 0x00000080 +#define STATUS_MS_ERR 0x00000040 +#define STATUS_MS_BRQ 0x00000020 +#define STATUS_MS_CNK 0x00000001 #define INT_STATUS_TPC_ERR 0x00080000 #define INT_STATUS_CRC_ERR 0x00040000 @@ -119,11 +131,17 @@ struct jmb38x_ms { #define PAD_PU_PD_ON_MS_SOCK0 0x5f8f0000 #define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000 +#define CLOCK_CONTROL_40MHZ 0x00000001 +#define CLOCK_CONTROL_50MHZ 0x00000002 +#define CLOCK_CONTROL_60MHZ 0x00000008 +#define CLOCK_CONTROL_62_5MHZ 0x0000000c +#define CLOCK_CONTROL_OFF 0x00000000 + enum { CMD_READY = 0x01, FIFO_READY = 0x02, REG_DATA = 0x04, - AUTO_GET_INT = 0x08 + DMA_DATA = 0x08 }; static unsigned int jmb38x_ms_read_data(struct jmb38x_ms_host *host, @@ -273,7 +291,7 @@ static int jmb38x_ms_transfer_data(struct jmb38x_ms_host *host) { unsigned int length; unsigned int off; - unsigned int t_size, p_off, p_cnt; + unsigned int t_size, p_cnt; unsigned char *buf; struct page *pg; unsigned long flags = 0; @@ -287,6 +305,8 @@ static int jmb38x_ms_transfer_data(struct jmb38x_ms_host *host) } while (length) { + unsigned int uninitialized_var(p_off); + if (host->req->long_data) { pg = nth_page(sg_page(&host->req->sg), off >> PAGE_SHIFT); @@ -364,28 +384,27 @@ static int jmb38x_ms_issue_cmd(struct memstick_host *msh) cmd |= TPC_DIR; if (host->req->need_card_int) cmd |= TPC_WAIT_INT; - if (host->req->get_int_reg) - cmd |= TPC_GET_INT; data = host->req->data; - host->use_dma = !no_dma; + if (!no_dma) + host->cmd_flags |= DMA_DATA; if (host->req->long_data) { data_len = host->req->sg.length; } else { data_len = host->req->data_len; - host->use_dma = 0; + host->cmd_flags &= ~DMA_DATA; } if (data_len <= 8) { cmd &= ~(TPC_DATA_SEL | 0xf); host->cmd_flags |= REG_DATA; cmd |= data_len & 0xf; - host->use_dma = 0; + host->cmd_flags &= ~DMA_DATA; } - if (host->use_dma) { + if (host->cmd_flags & DMA_DATA) { if (1 != pci_map_sg(host->chip->pdev, &host->req->sg, 1, host->req->data_dir == READ ? PCI_DMA_FROMDEVICE @@ -448,13 +467,12 @@ static void jmb38x_ms_complete_cmd(struct memstick_host *msh, int last) readl(host->addr + INT_STATUS)); dev_dbg(msh->cdev.dev, "c hstatus %08x\n", readl(host->addr + STATUS)); - if (host->req->get_int_reg) { - t_val = readl(host->addr + TPC_P0); - host->req->int_reg = (t_val & 0xff); - } + host->req->int_reg = readl(host->addr + STATUS) & 0xff; + + writel(0, host->addr + BLOCK); + writel(0, host->addr + DMA_CONTROL); - if (host->use_dma) { - writel(0, host->addr + DMA_CONTROL); + if (host->cmd_flags & DMA_DATA) { pci_unmap_sg(host->chip->pdev, &host->req->sg, 1, host->req->data_dir == READ ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); @@ -506,7 +524,7 @@ static irqreturn_t jmb38x_ms_isr(int irq, void *dev_id) else host->req->error = -ETIME; } else { - if (host->use_dma) { + if (host->cmd_flags & DMA_DATA) { if (irq_status & INT_STATUS_EOTRAN) host->cmd_flags |= FIFO_READY; } else { @@ -595,19 +613,18 @@ static void jmb38x_ms_reset(struct jmb38x_ms_host *host) { unsigned int host_ctl = readl(host->addr + HOST_CONTROL); - writel(host_ctl | HOST_CONTROL_RESET_REQ | HOST_CONTROL_RESET, - host->addr + HOST_CONTROL); + writel(HOST_CONTROL_RESET_REQ, host->addr + HOST_CONTROL); while (HOST_CONTROL_RESET_REQ & (host_ctl = readl(host->addr + HOST_CONTROL))) { - ndelay(100); - dev_dbg(&host->chip->pdev->dev, "reset\n"); + ndelay(20); + dev_dbg(&host->chip->pdev->dev, "reset %08x\n", host_ctl); } - writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE); + writel(HOST_CONTROL_RESET, host->addr + HOST_CONTROL); + mmiowb(); writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE); - - dev_dbg(&host->chip->pdev->dev, "reset\n"); + writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE); } static void jmb38x_ms_set_param(struct memstick_host *msh, @@ -615,10 +632,8 @@ static void jmb38x_ms_set_param(struct memstick_host *msh, int value) { struct jmb38x_ms_host *host = memstick_priv(msh); - unsigned int host_ctl; - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); + unsigned int host_ctl = readl(host->addr + HOST_CONTROL); + unsigned int clock_ctl = CLOCK_CONTROL_40MHZ, clock_delay = 0; switch (param) { case MEMSTICK_POWER: @@ -626,60 +641,57 @@ static void jmb38x_ms_set_param(struct memstick_host *msh, jmb38x_ms_reset(host); writel(host->id ? PAD_PU_PD_ON_MS_SOCK1 - : PAD_PU_PD_ON_MS_SOCK0, + : PAD_PU_PD_ON_MS_SOCK0, host->addr + PAD_PU_PD); writel(PAD_OUTPUT_ENABLE_MS, host->addr + PAD_OUTPUT_ENABLE); - host_ctl = readl(host->addr + HOST_CONTROL); - host_ctl |= 7; - writel(host_ctl | (HOST_CONTROL_POWER_EN - | HOST_CONTROL_CLOCK_EN), - host->addr + HOST_CONTROL); + host_ctl = 7; + host_ctl |= HOST_CONTROL_POWER_EN + | HOST_CONTROL_CLOCK_EN; + writel(host_ctl, host->addr + HOST_CONTROL); dev_dbg(&host->chip->pdev->dev, "power on\n"); } else if (value == MEMSTICK_POWER_OFF) { - writel(readl(host->addr + HOST_CONTROL) - & ~(HOST_CONTROL_POWER_EN - | HOST_CONTROL_CLOCK_EN), - host->addr + HOST_CONTROL); + host_ctl &= ~(HOST_CONTROL_POWER_EN + | HOST_CONTROL_CLOCK_EN); + writel(host_ctl, host->addr + HOST_CONTROL); writel(0, host->addr + PAD_OUTPUT_ENABLE); writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD); dev_dbg(&host->chip->pdev->dev, "power off\n"); } break; case MEMSTICK_INTERFACE: - /* jmb38x_ms_reset(host); */ - - host_ctl = readl(host->addr + HOST_CONTROL); host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT); - /* host_ctl |= 7; */ if (value == MEMSTICK_SERIAL) { host_ctl &= ~HOST_CONTROL_FAST_CLK; host_ctl |= HOST_CONTROL_IF_SERIAL << HOST_CONTROL_IF_SHIFT; host_ctl |= HOST_CONTROL_REI; - writel(0, host->addr + CLOCK_DELAY); + clock_ctl = CLOCK_CONTROL_40MHZ; + clock_delay = 0; } else if (value == MEMSTICK_PAR4) { host_ctl |= HOST_CONTROL_FAST_CLK; host_ctl |= HOST_CONTROL_IF_PAR4 << HOST_CONTROL_IF_SHIFT; host_ctl &= ~HOST_CONTROL_REI; - writel(4, host->addr + CLOCK_DELAY); + clock_ctl = CLOCK_CONTROL_40MHZ; + clock_delay = 4; } else if (value == MEMSTICK_PAR8) { host_ctl |= HOST_CONTROL_FAST_CLK; host_ctl |= HOST_CONTROL_IF_PAR8 << HOST_CONTROL_IF_SHIFT; host_ctl &= ~HOST_CONTROL_REI; - writel(4, host->addr + CLOCK_DELAY); + clock_ctl = CLOCK_CONTROL_60MHZ; + clock_delay = 0; } writel(host_ctl, host->addr + HOST_CONTROL); + writel(clock_ctl, host->addr + CLOCK_CONTROL); + writel(clock_delay, host->addr + CLOCK_DELAY); break; }; - - spin_unlock_irqrestore(&host->lock, flags); } #ifdef CONFIG_PM @@ -772,13 +784,10 @@ static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt) snprintf(host->host_id, DEVICE_ID_SIZE, DRIVER_NAME ":slot%d", host->id); host->irq = jm->pdev->irq; - host->timeout_jiffies = msecs_to_jiffies(4000); + host->timeout_jiffies = msecs_to_jiffies(1000); msh->request = jmb38x_ms_request; msh->set_param = jmb38x_ms_set_param; - /* - msh->caps = MEMSTICK_CAP_AUTO_GET_INT | MEMSTICK_CAP_PAR4 - | MEMSTICK_CAP_PAR8; - */ + msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8; setup_timer(&host->timer, jmb38x_ms_abort, (unsigned long)msh); diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c index 2b5bf52a830..eb150dfb637 100644 --- a/drivers/memstick/host/tifm_ms.c +++ b/drivers/memstick/host/tifm_ms.c @@ -340,11 +340,20 @@ static void tifm_ms_complete_cmd(struct tifm_ms *host) del_timer(&host->timer); - if (host->use_dma) + host->req->int_reg = readl(sock->addr + SOCK_MS_STATUS) & 0xff; + host->req->int_reg = (host->req->int_reg & 1) + | ((host->req->int_reg << 4) & 0xe0); + + writel(TIFM_FIFO_INT_SETALL, + sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); + writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL); + + if (host->use_dma) { tifm_unmap_sg(sock, &host->req->sg, 1, host->req->data_dir == READ ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); + } writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), sock->addr + SOCK_CONTROL); @@ -424,12 +433,6 @@ static void tifm_ms_card_event(struct tifm_dev *sock) else if (host_status & TIFM_MS_STAT_CRC) host->req->error = -EILSEQ; - if (host->req->error) { - writel(TIFM_FIFO_INT_SETALL, - sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); - writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL); - } - if (host_status & TIFM_MS_STAT_RDY) host->cmd_flags |= CMD_READY; diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 6b6df867958..c6be6eba7dc 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1430,6 +1430,98 @@ mpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name) sprintf(prod_name, "%s", product_str); } +/** + * mpt_mapresources - map in memory mapped io + * @ioc: Pointer to pointer to IOC adapter + * + **/ +static int +mpt_mapresources(MPT_ADAPTER *ioc) +{ + u8 __iomem *mem; + int ii; + unsigned long mem_phys; + unsigned long port; + u32 msize; + u32 psize; + u8 revision; + int r = -ENODEV; + struct pci_dev *pdev; + + pdev = ioc->pcidev; + ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM); + if (pci_enable_device_mem(pdev)) { + printk(MYIOC_s_ERR_FMT "pci_enable_device_mem() " + "failed\n", ioc->name); + return r; + } + if (pci_request_selected_regions(pdev, ioc->bars, "mpt")) { + printk(MYIOC_s_ERR_FMT "pci_request_selected_regions() with " + "MEM failed\n", ioc->name); + return r; + } + + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); + + if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK) + && !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) { + dinitprintk(ioc, printk(MYIOC_s_INFO_FMT + ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", + ioc->name)); + } else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK) + && !pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) { + dinitprintk(ioc, printk(MYIOC_s_INFO_FMT + ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", + ioc->name)); + } else { + printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n", + ioc->name, pci_name(pdev)); + pci_release_selected_regions(pdev, ioc->bars); + return r; + } + + mem_phys = msize = 0; + port = psize = 0; + for (ii = 0; ii < DEVICE_COUNT_RESOURCE; ii++) { + if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) { + if (psize) + continue; + /* Get I/O space! */ + port = pci_resource_start(pdev, ii); + psize = pci_resource_len(pdev, ii); + } else { + if (msize) + continue; + /* Get memmap */ + mem_phys = pci_resource_start(pdev, ii); + msize = pci_resource_len(pdev, ii); + } + } + ioc->mem_size = msize; + + mem = NULL; + /* Get logical ptr for PciMem0 space */ + /*mem = ioremap(mem_phys, msize);*/ + mem = ioremap(mem_phys, msize); + if (mem == NULL) { + printk(MYIOC_s_ERR_FMT ": ERROR - Unable to map adapter" + " memory!\n", ioc->name); + return -EINVAL; + } + ioc->memmap = mem; + dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %lx\n", + ioc->name, mem, mem_phys)); + + ioc->mem_phys = mem_phys; + ioc->chip = (SYSIF_REGS __iomem *)mem; + + /* Save Port IO values in case we need to do downloadboot */ + ioc->pio_mem_phys = port; + ioc->pio_chip = (SYSIF_REGS __iomem *)port; + + return 0; +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_attach - Install a PCI intelligent MPT adapter. @@ -1452,13 +1544,6 @@ int mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) { MPT_ADAPTER *ioc; - u8 __iomem *mem; - u8 __iomem *pmem; - unsigned long mem_phys; - unsigned long port; - u32 msize; - u32 psize; - int ii; u8 cb_idx; int r = -ENODEV; u8 revision; @@ -1468,52 +1553,32 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) struct proc_dir_entry *dent, *ent; #endif - if (mpt_debug_level) - printk(KERN_INFO MYNAM ": mpt_debug_level=%xh\n", mpt_debug_level); - ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC); if (ioc == NULL) { printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n"); return -ENOMEM; } - ioc->debug_level = mpt_debug_level; + ioc->id = mpt_ids++; sprintf(ioc->name, "ioc%d", ioc->id); - ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM); - if (pci_enable_device_mem(pdev)) { - printk(MYIOC_s_ERR_FMT "pci_enable_device_mem() " - "failed\n", ioc->name); - kfree(ioc); - return r; - } - if (pci_request_selected_regions(pdev, ioc->bars, "mpt")) { - printk(MYIOC_s_ERR_FMT "pci_request_selected_regions() with " - "MEM failed\n", ioc->name); - kfree(ioc); - return r; - } + /* + * set initial debug level + * (refer to mptdebug.h) + * + */ + ioc->debug_level = mpt_debug_level; + if (mpt_debug_level) + printk(KERN_INFO "mpt_debug_level=%xh\n", mpt_debug_level); dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": mpt_adapter_install\n", ioc->name)); - if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { - dprintk(ioc, printk(MYIOC_s_INFO_FMT - ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", ioc->name)); - } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { - printk(MYIOC_s_WARN_FMT ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n", - ioc->name); + ioc->pcidev = pdev; + if (mpt_mapresources(ioc)) { kfree(ioc); return r; } - if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) { - dprintk(ioc, printk(MYIOC_s_INFO_FMT - ": Using 64 bit consistent mask\n", ioc->name)); - } else { - dprintk(ioc, printk(MYIOC_s_INFO_FMT - ": Not using 64 bit consistent mask\n", ioc->name)); - } - ioc->alloc_total = sizeof(MPT_ADAPTER); ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */ ioc->reply_sz = MPT_REPLY_FRAME_SIZE; @@ -1551,48 +1616,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) /* Find lookup slot. */ INIT_LIST_HEAD(&ioc->list); - mem_phys = msize = 0; - port = psize = 0; - for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) { - if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) { - if (psize) - continue; - /* Get I/O space! */ - port = pci_resource_start(pdev, ii); - psize = pci_resource_len(pdev,ii); - } else { - if (msize) - continue; - /* Get memmap */ - mem_phys = pci_resource_start(pdev, ii); - msize = pci_resource_len(pdev,ii); - } - } - ioc->mem_size = msize; - - mem = NULL; - /* Get logical ptr for PciMem0 space */ - /*mem = ioremap(mem_phys, msize);*/ - mem = ioremap(mem_phys, msize); - if (mem == NULL) { - printk(MYIOC_s_ERR_FMT "Unable to map adapter memory!\n", ioc->name); - kfree(ioc); - return -EINVAL; - } - ioc->memmap = mem; - dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %lx\n", ioc->name, mem, mem_phys)); - dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n", ioc->name, &ioc->facts, &ioc->pfacts[0])); - ioc->mem_phys = mem_phys; - ioc->chip = (SYSIF_REGS __iomem *)mem; - - /* Save Port IO values in case we need to do downloadboot */ - ioc->pio_mem_phys = port; - pmem = (u8 __iomem *)port; - ioc->pio_chip = (SYSIF_REGS __iomem *)pmem; - pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); mpt_get_product_name(pdev->vendor, pdev->device, revision, ioc->prod_name); @@ -1688,7 +1714,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) list_del(&ioc->list); if (ioc->alt_ioc) ioc->alt_ioc->alt_ioc = NULL; - iounmap(mem); + iounmap(ioc->memmap); + if (r != -5) + pci_release_selected_regions(pdev, ioc->bars); kfree(ioc); pci_set_drvdata(pdev, NULL); return r; @@ -1784,13 +1812,10 @@ mpt_suspend(struct pci_dev *pdev, pm_message_t state) u32 device_state; MPT_ADAPTER *ioc = pci_get_drvdata(pdev); - device_state=pci_choose_state(pdev, state); - - printk(MYIOC_s_INFO_FMT - "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n", - ioc->name, pdev, pci_name(pdev), device_state); - - pci_save_state(pdev); + device_state = pci_choose_state(pdev, state); + printk(MYIOC_s_INFO_FMT "pci-suspend: pdev=0x%p, slot=%s, Entering " + "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev), + device_state); /* put ioc into READY_STATE */ if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) { @@ -1805,10 +1830,14 @@ mpt_suspend(struct pci_dev *pdev, pm_message_t state) /* Clear any lingering interrupt */ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); + free_irq(ioc->pci_irq, ioc); + if (mpt_msi_enable) + pci_disable_msi(ioc->pcidev); + ioc->pci_irq = -1; + pci_save_state(pdev); pci_disable_device(pdev); pci_release_selected_regions(pdev, ioc->bars); pci_set_power_state(pdev, device_state); - return 0; } @@ -1823,48 +1852,54 @@ mpt_resume(struct pci_dev *pdev) MPT_ADAPTER *ioc = pci_get_drvdata(pdev); u32 device_state = pdev->current_state; int recovery_state; + int err; - printk(MYIOC_s_INFO_FMT - "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n", - ioc->name, pdev, pci_name(pdev), device_state); + printk(MYIOC_s_INFO_FMT "pci-resume: pdev=0x%p, slot=%s, Previous " + "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev), + device_state); - pci_set_power_state(pdev, 0); + pci_set_power_state(pdev, PCI_D0); + pci_enable_wake(pdev, PCI_D0, 0); pci_restore_state(pdev); - if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) { - ioc->bars = pci_select_bars(ioc->pcidev, IORESOURCE_MEM | - IORESOURCE_IO); - if (pci_enable_device(pdev)) - return 0; - } else { - ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM); - if (pci_enable_device_mem(pdev)) - return 0; - } - if (pci_request_selected_regions(pdev, ioc->bars, "mpt")) - return 0; + ioc->pcidev = pdev; + err = mpt_mapresources(ioc); + if (err) + return err; - /* enable interrupts */ - CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); - ioc->active = 1; + printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n", + ioc->name, (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT), + CHIPREG_READ32(&ioc->chip->Doorbell)); - printk(MYIOC_s_INFO_FMT - "pci-resume: ioc-state=0x%x,doorbell=0x%x\n", - ioc->name, - (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT), - CHIPREG_READ32(&ioc->chip->Doorbell)); + /* + * Errata workaround for SAS pci express: + * Upon returning to the D0 state, the contents of the doorbell will be + * stale data, and this will incorrectly signal to the host driver that + * the firmware is ready to process mpt commands. The workaround is + * to issue a diagnostic reset. + */ + if (ioc->bus_type == SAS && (pdev->device == + MPI_MANUFACTPAGE_DEVID_SAS1068E || pdev->device == + MPI_MANUFACTPAGE_DEVID_SAS1064E)) { + if (KickStart(ioc, 1, CAN_SLEEP) < 0) { + printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover\n", + ioc->name); + goto out; + } + } /* bring ioc to operational state */ - if ((recovery_state = mpt_do_ioc_recovery(ioc, - MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) { - printk(MYIOC_s_INFO_FMT - "pci-resume: Cannot recover, error:[%x]\n", - ioc->name, recovery_state); - } else { + printk(MYIOC_s_INFO_FMT "Sending mpt_do_ioc_recovery\n", ioc->name); + recovery_state = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, + CAN_SLEEP); + if (recovery_state != 0) + printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover, " + "error:[%x]\n", ioc->name, recovery_state); + else printk(MYIOC_s_INFO_FMT - "pci-resume: success\n", ioc->name); - } - + "pci-resume: success\n", ioc->name); + out: return 0; + } #endif @@ -1903,6 +1938,7 @@ mpt_signal_reset(u8 index, MPT_ADAPTER *ioc, int reset_phase) * -3 if READY but PrimeIOCFifos Failed * -4 if READY but IOCInit Failed * -5 if failed to enable_device and/or request_selected_regions + * -6 if failed to upload firmware */ static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) @@ -2097,7 +2133,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) } else { printk(MYIOC_s_WARN_FMT "firmware upload failure!\n", ioc->name); - ret = -5; + ret = -6; } } } diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 0c252f60c4c..c207bda6723 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1170,6 +1170,10 @@ mptscsih_shutdown(struct pci_dev *pdev) int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state) { + MPT_ADAPTER *ioc = pci_get_drvdata(pdev); + + scsi_block_requests(ioc->sh); + flush_scheduled_work(); mptscsih_shutdown(pdev); return mpt_suspend(pdev,state); } @@ -1183,7 +1187,12 @@ mptscsih_suspend(struct pci_dev *pdev, pm_message_t state) int mptscsih_resume(struct pci_dev *pdev) { - return mpt_resume(pdev); + MPT_ADAPTER *ioc = pci_get_drvdata(pdev); + int rc; + + rc = mpt_resume(pdev); + scsi_unblock_requests(ioc->sh); + return rc; } #endif diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 7f4836b8e71..5fa4ba0d993 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -467,7 +467,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ - if (value) { + if (value && pciehp_force) { rc = pciehp_enable_slot(t_slot); if (rc) /* -ENODEV: shouldn't happen, but deal with it */ value = 0; diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 82f5ad9c3af..9e7de63b26e 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -16,7 +16,7 @@ menuconfig RTC_CLASS probably want to enable one or more of the interfaces below. This driver can also be built as a module. If so, the module - will be called rtc-class. + will be called rtc-core. if RTC_CLASS diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index bbf10ecf416..56728a2a338 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c @@ -274,7 +274,7 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *_rtc) * SR clears it, so we must only read it in this irq handler! */ mr = rtt_readl(rtc, MR) & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); - sr = rtt_readl(rtc, SR) & mr; + sr = rtt_readl(rtc, SR) & (mr >> 16); if (!sr) return IRQ_NONE; @@ -321,6 +321,10 @@ static int __init at91_rtc_probe(struct platform_device *pdev) if (!rtc) return -ENOMEM; + /* platform setup code should have handled this; sigh */ + if (!device_can_wakeup(&pdev->dev)) + device_init_wakeup(&pdev->dev, 1); + platform_set_drvdata(pdev, rtc); rtc->rtt = (void __force __iomem *) (AT91_VA_BASE_SYS - AT91_BASE_SYS); rtc->rtt += r->start; diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index c46666a2480..b9d374082b6 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -325,7 +325,7 @@ menuconfig SCSI_LOWLEVEL depends on SCSI!=n default y -if SCSI_LOWLEVEL +if SCSI_LOWLEVEL && SCSI config ISCSI_TCP tristate "iSCSI Initiator over TCP/IP" diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c index f608d4a1d6d..792b2e807bf 100644 --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c @@ -674,12 +674,13 @@ static struct orc_scb *__orc_alloc_scb(struct orc_host * host) for (index = 0; index < 32; index++) { if ((host->allocation_map[channel][i] >> index) & 0x01) { host->allocation_map[channel][i] &= ~(1 << index); - break; + idx = index + 32 * i; + /* + * Translate the index to a structure instance + */ + return host->scb_virt + idx; } } - idx = index + 32 * i; - /* Translate the index to a structure instance */ - return (struct orc_scb *) ((unsigned long) host->scb_virt + (idx * sizeof(struct orc_scb))); } return NULL; } diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 3c2d6888bb8..8591585e5cc 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -6439,7 +6439,7 @@ static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size, i += 2; len += 2; } else { - unsigned char off = buf[i] * 2; + unsigned int off = buf[i] * 2; unsigned short word = (buf[off + 1] << 8) | buf[off]; AdvWriteWordAutoIncLram(iop_base, word); len += 2; diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index 0393707bdfc..3288be2e49f 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h @@ -341,13 +341,13 @@ struct MessageUnit_B uint32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; uint32_t postq_index; uint32_t doneq_index; - uint32_t __iomem *drv2iop_doorbell_reg; - uint32_t __iomem *drv2iop_doorbell_mask_reg; - uint32_t __iomem *iop2drv_doorbell_reg; - uint32_t __iomem *iop2drv_doorbell_mask_reg; - uint32_t __iomem *msgcode_rwbuffer_reg; - uint32_t __iomem *ioctl_wbuffer_reg; - uint32_t __iomem *ioctl_rbuffer_reg; + void __iomem *drv2iop_doorbell_reg; + void __iomem *drv2iop_doorbell_mask_reg; + void __iomem *iop2drv_doorbell_reg; + void __iomem *iop2drv_doorbell_mask_reg; + void __iomem *msgcode_rwbuffer_reg; + void __iomem *ioctl_wbuffer_reg; + void __iomem *ioctl_rbuffer_reg; }; /* diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 27ebd336409..0b2080d3357 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -493,6 +493,12 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, if (!scp) return -ENOMEM; + scp->sense_buffer = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); + if (!scp->sense_buffer) { + kfree(scp); + return -ENOMEM; + } + scp->device = sdev; memset(&cmndinfo, 0, sizeof(cmndinfo)); @@ -513,6 +519,7 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, rval = cmndinfo.status; if (info) *info = cmndinfo.info; + kfree(scp->sense_buffer); kfree(scp); return rval; } diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index ba21d97d185..f40898dc2d1 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2162,10 +2162,15 @@ void sdev_evt_send(struct scsi_device *sdev, struct scsi_event *evt) { unsigned long flags; +#if 0 + /* FIXME: currently this check eliminates all media change events + * for polled devices. Need to update to discriminate between AN + * and polled events */ if (!test_bit(evt->evt_type, sdev->supported_events)) { kfree(evt); return; } +#endif spin_lock_irqsave(&sdev->list_lock, flags); list_add_tail(&evt->node, &sdev->event_list); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index ed83cdb6e67..b9b09a70458 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -294,6 +294,7 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work) } if (sdev->request_queue) { + bsg_unregister_queue(sdev->request_queue); sdev->request_queue->queuedata = NULL; /* user context needed to free queue */ scsi_free_queue(sdev->request_queue); @@ -857,7 +858,6 @@ void __scsi_remove_device(struct scsi_device *sdev) if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0) return; - bsg_unregister_queue(sdev->request_queue); class_device_unregister(&sdev->sdev_classdev); transport_remove_device(dev); device_del(dev); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 7aee64dbfbe..5fe7aaed904 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1654,6 +1654,7 @@ static int sd_probe(struct device *dev) sdkp->disk = gd; sdkp->index = index; sdkp->openers = 0; + sdkp->previous_state = 1; if (!sdp->timeout) { if (sdp->type != TYPE_MOD) diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 208565bdbe8..7ee86d4a761 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -623,6 +623,7 @@ static int sr_probe(struct device *dev) cd->disk = disk; cd->capacity = 0x1fffff; cd->device->changed = 1; /* force recheck CD type */ + cd->previous_state = 1; cd->use = 1; cd->readcd_known = 0; cd->readcd_cdda = 0; diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index a8c116b80bf..9d244d1644e 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -414,12 +414,12 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) defined(CONFIG_CPU_SUBTYPE_SH7785) static inline int scif_txroom(struct uart_port *port) { - return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0x7f); + return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0xff); } static inline int scif_rxroom(struct uart_port *port) { - return sci_in(port, SCRFDR) & 0x7f; + return sci_in(port, SCRFDR) & 0xff; } #else static inline int scif_txroom(struct uart_port *port) diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 3ab313ed441..17e71d56f31 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -4,8 +4,6 @@ menuconfig THERMAL bool "Generic Thermal sysfs driver" - select HWMON - default y help Generic Thermal Sysfs driver offers a generic mechanism for thermal management. Usually it's made up of one or more thermal diff --git a/drivers/thermal/thermal.c b/drivers/thermal/thermal.c index 41bd4c805ac..8b86e53ccf7 100644 --- a/drivers/thermal/thermal.c +++ b/drivers/thermal/thermal.c @@ -30,10 +30,8 @@ #include <linux/idr.h> #include <linux/thermal.h> #include <linux/spinlock.h> -#include <linux/hwmon.h> -#include <linux/hwmon-sysfs.h> -MODULE_AUTHOR("Zhang Rui"); +MODULE_AUTHOR("Zhang Rui") MODULE_DESCRIPTION("Generic thermal management sysfs support"); MODULE_LICENSE("GPL"); @@ -58,9 +56,6 @@ static LIST_HEAD(thermal_tz_list); static LIST_HEAD(thermal_cdev_list); static DEFINE_MUTEX(thermal_list_lock); -static struct device *thermal_hwmon; -#define MAX_THERMAL_ZONES 10 - static int get_idr(struct idr *idr, struct mutex *lock, int *id) { int err; @@ -92,67 +87,7 @@ static void release_idr(struct idr *idr, struct mutex *lock, int id) mutex_unlock(lock); } -/* hwmon sys I/F*/ -static ssize_t -name_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "thermal_sys_class\n"); -} - -static ssize_t -temp_input_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct thermal_zone_device *tz; - struct sensor_device_attribute *sensor_attr - = to_sensor_dev_attr(attr); - - list_for_each_entry(tz, &thermal_tz_list, node) - if (tz->id == sensor_attr->index) - return tz->ops->get_temp(tz, buf); - - return -ENODEV; -} - -static ssize_t -temp_crit_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct thermal_zone_device *tz; - struct sensor_device_attribute *sensor_attr - = to_sensor_dev_attr(attr); - - list_for_each_entry(tz, &thermal_tz_list, node) - if (tz->id == sensor_attr->index) - return tz->ops->get_trip_temp(tz, 0, buf); - - return -ENODEV; -} - -static DEVICE_ATTR(name, 0444, name_show, NULL); -static struct sensor_device_attribute sensor_attrs[] = { - SENSOR_ATTR(temp1_input, 0444, temp_input_show, NULL, 0), - SENSOR_ATTR(temp1_crit, 0444, temp_crit_show, NULL, 0), - SENSOR_ATTR(temp2_input, 0444, temp_input_show, NULL, 1), - SENSOR_ATTR(temp2_crit, 0444, temp_crit_show, NULL, 1), - SENSOR_ATTR(temp3_input, 0444, temp_input_show, NULL, 2), - SENSOR_ATTR(temp3_crit, 0444, temp_crit_show, NULL, 2), - SENSOR_ATTR(temp4_input, 0444, temp_input_show, NULL, 3), - SENSOR_ATTR(temp4_crit, 0444, temp_crit_show, NULL, 3), - SENSOR_ATTR(temp5_input, 0444, temp_input_show, NULL, 4), - SENSOR_ATTR(temp5_crit, 0444, temp_crit_show, NULL, 4), - SENSOR_ATTR(temp6_input, 0444, temp_input_show, NULL, 5), - SENSOR_ATTR(temp6_crit, 0444, temp_crit_show, NULL, 5), - SENSOR_ATTR(temp7_input, 0444, temp_input_show, NULL, 6), - SENSOR_ATTR(temp7_crit, 0444, temp_crit_show, NULL, 6), - SENSOR_ATTR(temp8_input, 0444, temp_input_show, NULL, 7), - SENSOR_ATTR(temp8_crit, 0444, temp_crit_show, NULL, 7), - SENSOR_ATTR(temp9_input, 0444, temp_input_show, NULL, 8), - SENSOR_ATTR(temp9_crit, 0444, temp_crit_show, NULL, 8), - SENSOR_ATTR(temp10_input, 0444, temp_input_show, NULL, 9), - SENSOR_ATTR(temp10_crit, 0444, temp_crit_show, NULL, 9), -}; - -/* thermal zone sys I/F */ +/* sys I/F for thermal zone */ #define to_thermal_zone(_dev) \ container_of(_dev, struct thermal_zone_device, device) @@ -279,7 +214,7 @@ do { \ device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]); \ } while (0) -/* cooling device sys I/F */ +/* sys I/F for cooling device */ #define to_cooling_device(_dev) \ container_of(_dev, struct thermal_cooling_device, device) @@ -512,9 +447,6 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *type, struct thermal_zone_device *pos; int result; - if (!type) - return ERR_PTR(-EINVAL); - if (strlen(type) >= THERMAL_NAME_LENGTH) return ERR_PTR(-EINVAL); @@ -545,9 +477,11 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *type, } /* sys I/F */ - result = device_create_file(&cdev->device, &dev_attr_cdev_type); - if (result) - goto unregister; + if (type) { + result = device_create_file(&cdev->device, &dev_attr_cdev_type); + if (result) + goto unregister; + } result = device_create_file(&cdev->device, &dev_attr_max_state); if (result) @@ -613,8 +547,8 @@ void thermal_cooling_device_unregister(struct tz->ops->unbind(tz, cdev); } mutex_unlock(&thermal_list_lock); - - device_remove_file(&cdev->device, &dev_attr_cdev_type); + if (cdev->type[0]) + device_remove_file(&cdev->device, &dev_attr_cdev_type); device_remove_file(&cdev->device, &dev_attr_max_state); device_remove_file(&cdev->device, &dev_attr_cur_state); @@ -646,9 +580,6 @@ struct thermal_zone_device *thermal_zone_device_register(char *type, int result; int count; - if (!type) - return ERR_PTR(-EINVAL); - if (strlen(type) >= THERMAL_NAME_LENGTH) return ERR_PTR(-EINVAL); @@ -670,13 +601,6 @@ struct thermal_zone_device *thermal_zone_device_register(char *type, kfree(tz); return ERR_PTR(result); } - if (tz->id >= MAX_THERMAL_ZONES) { - printk(KERN_ERR PREFIX - "Too many thermal zones\n"); - release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); - kfree(tz); - return ERR_PTR(-EINVAL); - } strcpy(tz->type, type); tz->ops = ops; @@ -691,27 +615,12 @@ struct thermal_zone_device *thermal_zone_device_register(char *type, return ERR_PTR(result); } - /* hwmon sys I/F */ - result = device_create_file(thermal_hwmon, - &sensor_attrs[tz->id * 2].dev_attr); - if (result) - goto unregister; - - if (trips > 0) { - char buf[40]; - result = tz->ops->get_trip_type(tz, 0, buf); - if (result > 0 && !strcmp(buf, "critical\n")) { - result = device_create_file(thermal_hwmon, - &sensor_attrs[tz->id * 2 + 1].dev_attr); - if (result) - goto unregister; - } - } - /* sys I/F */ - result = device_create_file(&tz->device, &dev_attr_type); - if (result) - goto unregister; + if (type) { + result = device_create_file(&tz->device, &dev_attr_type); + if (result) + goto unregister; + } result = device_create_file(&tz->device, &dev_attr_temp); if (result) @@ -778,17 +687,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) tz->ops->unbind(tz, cdev); mutex_unlock(&thermal_list_lock); - device_remove_file(thermal_hwmon, - &sensor_attrs[tz->id * 2].dev_attr); - if (tz->trips > 0) { - char buf[40]; - if (tz->ops->get_trip_type(tz, 0, buf) > 0) - if (!strcmp(buf, "critical\n")) - device_remove_file(thermal_hwmon, - &sensor_attrs[tz->id * 2 + 1].dev_attr); - } - - device_remove_file(&tz->device, &dev_attr_type); + if (tz->type[0]) + device_remove_file(&tz->device, &dev_attr_type); device_remove_file(&tz->device, &dev_attr_temp); if (tz->ops->get_mode) device_remove_file(&tz->device, &dev_attr_mode); @@ -805,19 +705,6 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) EXPORT_SYMBOL(thermal_zone_device_unregister); -static void thermal_exit(void) -{ - if (thermal_hwmon) { - device_remove_file(thermal_hwmon, &dev_attr_name); - hwmon_device_unregister(thermal_hwmon); - } - class_unregister(&thermal_class); - idr_destroy(&thermal_tz_idr); - idr_destroy(&thermal_cdev_idr); - mutex_destroy(&thermal_idr_lock); - mutex_destroy(&thermal_list_lock); -} - static int __init thermal_init(void) { int result = 0; @@ -829,21 +716,17 @@ static int __init thermal_init(void) mutex_destroy(&thermal_idr_lock); mutex_destroy(&thermal_list_lock); } - - thermal_hwmon = hwmon_device_register(NULL); - if (IS_ERR(thermal_hwmon)) { - result = PTR_ERR(thermal_hwmon); - thermal_hwmon = NULL; - printk(KERN_ERR PREFIX - "unable to register hwmon device\n"); - thermal_exit(); - return result; - } - - result = device_create_file(thermal_hwmon, &dev_attr_name); - return result; } +static void __exit thermal_exit(void) +{ + class_unregister(&thermal_class); + idr_destroy(&thermal_tz_idr); + idr_destroy(&thermal_cdev_idr); + mutex_destroy(&thermal_idr_lock); + mutex_destroy(&thermal_list_lock); +} + subsys_initcall(thermal_init); module_exit(thermal_exit); diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 2ae1e8673b1..9d3f28b92cb 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -1469,6 +1469,7 @@ static void isd200_free_info_ptrs(void *info_) if (info) { kfree(info->id); kfree(info->RegsBuf); + kfree(info->srb.sense_buffer); } } @@ -1494,7 +1495,9 @@ static int isd200_init_info(struct us_data *us) kzalloc(sizeof(struct hd_driveid), GFP_KERNEL); info->RegsBuf = (unsigned char *) kmalloc(sizeof(info->ATARegs), GFP_KERNEL); - if (!info->id || !info->RegsBuf) { + info->srb.sense_buffer = + kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); + if (!info->id || !info->RegsBuf || !info->srb.sense_buffer) { isd200_free_info_ptrs(info); kfree(info); retStatus = ISD200_ERROR; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index e0b0580705e..1bd5fb30237 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1893,6 +1893,20 @@ config FB_XILINX framebuffer. ML300 carries a 640*480 LCD display on the board, ML403 uses a standard DB15 VGA connector. +config FB_METRONOME + tristate "Metronome display controller support" + depends on FB && ARCH_PXA && MMU + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + select FB_DEFERRED_IO + help + This enables support for the Metronome display controller. Tested + with an E-Ink 800x600 display and Gumstix Connex through an AMLCD + interface. Please read <file:Documentation/fb/metronomefb.txt> + for more information. + config FB_VIRTUAL tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" depends on FB diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 03371c78903..11c0e5e05f2 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -103,6 +103,7 @@ obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o obj-$(CONFIG_FB_MAXINE) += maxinefb.o +obj-$(CONFIG_FB_METRONOME) += metronomefb.o obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o obj-$(CONFIG_FB_IMX) += imxfb.o obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index 0f8cfb988c9..24843fdd539 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c @@ -4,7 +4,7 @@ * Copyright (C) 2006 Jaya Kumar * * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive + * License. See the file COPYING in the main directory of this archive * for more details. */ @@ -31,7 +31,7 @@ static int fb_deferred_io_fault(struct vm_area_struct *vma, unsigned long offset; struct page *page; struct fb_info *info = vma->vm_private_data; - /* info->screen_base is in System RAM */ + /* info->screen_base is virtual memory */ void *screen_base = (void __force *) info->screen_base; offset = vmf->pgoff << PAGE_SHIFT; @@ -43,6 +43,15 @@ static int fb_deferred_io_fault(struct vm_area_struct *vma, return VM_FAULT_SIGBUS; get_page(page); + + if (vma->vm_file) + page->mapping = vma->vm_file->f_mapping; + else + printk(KERN_ERR "no mapping available\n"); + + BUG_ON(!page->mapping); + page->index = vmf->pgoff; + vmf->page = page; return 0; } @@ -138,11 +147,20 @@ EXPORT_SYMBOL_GPL(fb_deferred_io_init); void fb_deferred_io_cleanup(struct fb_info *info) { + void *screen_base = (void __force *) info->screen_base; struct fb_deferred_io *fbdefio = info->fbdefio; + struct page *page; + int i; BUG_ON(!fbdefio); cancel_delayed_work(&info->deferred_work); flush_scheduled_work(); + + /* clear out the mapping that we setup */ + for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) { + page = vmalloc_to_page(screen_base + i); + page->mapping = NULL; + } } EXPORT_SYMBOL_GPL(fb_deferred_io_cleanup); diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 1d13dd099af..a24e680d2b9 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -1476,7 +1476,7 @@ static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor) struct i810fb_par *par = info->par; u8 __iomem *mmio = par->mmio_start_virtual; - if (!(par->dev_flags & LOCKUP)) + if (par->dev_flags & LOCKUP) return -ENXIO; if (cursor->image.width > 64 || cursor->image.height > 64) diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c new file mode 100644 index 00000000000..e9a89fd8275 --- /dev/null +++ b/drivers/video/metronomefb.c @@ -0,0 +1,999 @@ +/* + * linux/drivers/video/metronomefb.c -- FB driver for Metronome controller + * + * Copyright (C) 2008, Jaya Kumar + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven. + * + * This work was made possible by help and equipment support from E-Ink + * Corporation. http://support.eink.com/community + * + * This driver is written to be used with the Metronome display controller. + * It was tested with an E-Ink 800x600 Vizplex EPD on a Gumstix Connex board + * using the Lyre interface board. + * + * General notes: + * - User must set metronomefb_enable=1 to enable it. + * - See Documentation/fb/metronomefb.txt for how metronome works. + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/list.h> +#include <linux/firmware.h> +#include <linux/dma-mapping.h> +#include <linux/uaccess.h> +#include <linux/irq.h> + +#include <asm/arch/pxa-regs.h> +#include <asm/unaligned.h> + +#define DEBUG 1 +#ifdef DEBUG +#define DPRINTK(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a) +#else +#define DPRINTK(f, a...) +#endif + + +/* Display specific information */ +#define DPY_W 832 +#define DPY_H 622 + +struct metromem_desc { + u32 mFDADR0; + u32 mFSADR0; + u32 mFIDR0; + u32 mLDCMD0; +}; + +struct metromem_cmd { + u16 opcode; + u16 args[((64-2)/2)]; + u16 csum; +}; + +struct metronomefb_par { + unsigned char *metromem; + struct metromem_desc *metromem_desc; + struct metromem_cmd *metromem_cmd; + unsigned char *metromem_wfm; + unsigned char *metromem_img; + u16 *metromem_img_csum; + u16 *csum_table; + int metromemsize; + dma_addr_t metromem_dma; + dma_addr_t metromem_desc_dma; + struct fb_info *info; + wait_queue_head_t waitq; + u8 frame_count; +}; + +/* frame differs from image. frame includes non-visible pixels */ +struct epd_frame { + int fw; /* frame width */ + int fh; /* frame height */ +}; + +static struct epd_frame epd_frame_table[] = { + { + .fw = 832, + .fh = 622 + }, +}; + +static struct fb_fix_screeninfo metronomefb_fix __devinitdata = { + .id = "metronomefb", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_STATIC_PSEUDOCOLOR, + .xpanstep = 0, + .ypanstep = 0, + .ywrapstep = 0, + .line_length = DPY_W, + .accel = FB_ACCEL_NONE, +}; + +static struct fb_var_screeninfo metronomefb_var __devinitdata = { + .xres = DPY_W, + .yres = DPY_H, + .xres_virtual = DPY_W, + .yres_virtual = DPY_H, + .bits_per_pixel = 8, + .grayscale = 1, + .nonstd = 1, + .red = { 4, 3, 0 }, + .green = { 0, 0, 0 }, + .blue = { 0, 0, 0 }, + .transp = { 0, 0, 0 }, +}; + +static unsigned int metronomefb_enable; + +struct waveform_hdr { + u8 stuff[32]; + + u8 wmta[3]; + u8 fvsn; + + u8 luts; + u8 mc; + u8 trc; + u8 stuff3; + + u8 endb; + u8 swtb; + u8 stuff2a[2]; + + u8 stuff2b[3]; + u8 wfm_cs; +} __attribute__ ((packed)); + +/* main metronomefb functions */ +static u8 calc_cksum(int start, int end, u8 *mem) +{ + u8 tmp = 0; + int i; + + for (i = start; i < end; i++) + tmp += mem[i]; + + return tmp; +} + +static u16 calc_img_cksum(u16 *start, int length) +{ + u16 tmp = 0; + + while (length--) + tmp += *start++; + + return tmp; +} + +/* here we decode the incoming waveform file and populate metromem */ +#define EXP_WFORM_SIZE 47001 +static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t, + u8 *frame_count) +{ + int tta; + int wmta; + int trn = 0; + int i; + unsigned char v; + u8 cksum; + int cksum_idx; + int wfm_idx, owfm_idx; + int mem_idx = 0; + struct waveform_hdr *wfm_hdr; + + if (size != EXP_WFORM_SIZE) { + printk(KERN_ERR "Error: unexpected size %d != %d\n", size, + EXP_WFORM_SIZE); + return -EINVAL; + } + + wfm_hdr = (struct waveform_hdr *) mem; + + if (wfm_hdr->fvsn != 1) { + printk(KERN_ERR "Error: bad fvsn %x\n", wfm_hdr->fvsn); + return -EINVAL; + } + if (wfm_hdr->luts != 0) { + printk(KERN_ERR "Error: bad luts %x\n", wfm_hdr->luts); + return -EINVAL; + } + cksum = calc_cksum(32, 47, mem); + if (cksum != wfm_hdr->wfm_cs) { + printk(KERN_ERR "Error: bad cksum %x != %x\n", cksum, + wfm_hdr->wfm_cs); + return -EINVAL; + } + wfm_hdr->mc += 1; + wfm_hdr->trc += 1; + for (i = 0; i < 5; i++) { + if (*(wfm_hdr->stuff2a + i) != 0) { + printk(KERN_ERR "Error: unexpected value in padding\n"); + return -EINVAL; + } + } + + /* calculating trn. trn is something used to index into + the waveform. presumably selecting the right one for the + desired temperature. it works out the offset of the first + v that exceeds the specified temperature */ + if ((sizeof(*wfm_hdr) + wfm_hdr->trc) > size) + return -EINVAL; + + for (i = sizeof(*wfm_hdr); i <= sizeof(*wfm_hdr) + wfm_hdr->trc; i++) { + if (mem[i] > t) { + trn = i - sizeof(*wfm_hdr) - 1; + break; + } + } + + /* check temperature range table checksum */ + cksum_idx = sizeof(*wfm_hdr) + wfm_hdr->trc + 1; + if (cksum_idx > size) + return -EINVAL; + cksum = calc_cksum(sizeof(*wfm_hdr), cksum_idx, mem); + if (cksum != mem[cksum_idx]) { + printk(KERN_ERR "Error: bad temperature range table cksum" + " %x != %x\n", cksum, mem[cksum_idx]); + return -EINVAL; + } + + /* check waveform mode table address checksum */ + wmta = le32_to_cpu(get_unaligned((__le32 *) wfm_hdr->wmta)); + wmta &= 0x00FFFFFF; + cksum_idx = wmta + m*4 + 3; + if (cksum_idx > size) + return -EINVAL; + cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem); + if (cksum != mem[cksum_idx]) { + printk(KERN_ERR "Error: bad mode table address cksum" + " %x != %x\n", cksum, mem[cksum_idx]); + return -EINVAL; + } + + /* check waveform temperature table address checksum */ + tta = le32_to_cpu(get_unaligned((int *) (mem + wmta + m*4))); + tta &= 0x00FFFFFF; + cksum_idx = tta + trn*4 + 3; + if (cksum_idx > size) + return -EINVAL; + cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem); + if (cksum != mem[cksum_idx]) { + printk(KERN_ERR "Error: bad temperature table address cksum" + " %x != %x\n", cksum, mem[cksum_idx]); + return -EINVAL; + } + + /* here we do the real work of putting the waveform into the + metromem buffer. this does runlength decoding of the waveform */ + wfm_idx = le32_to_cpu(get_unaligned((__le32 *) (mem + tta + trn*4))); + wfm_idx &= 0x00FFFFFF; + owfm_idx = wfm_idx; + if (wfm_idx > size) + return -EINVAL; + while (wfm_idx < size) { + unsigned char rl; + v = mem[wfm_idx++]; + if (v == wfm_hdr->swtb) { + while (((v = mem[wfm_idx++]) != wfm_hdr->swtb) && + wfm_idx < size) + metromem[mem_idx++] = v; + + continue; + } + + if (v == wfm_hdr->endb) + break; + + rl = mem[wfm_idx++]; + for (i = 0; i <= rl; i++) + metromem[mem_idx++] = v; + } + + cksum_idx = wfm_idx; + if (cksum_idx > size) + return -EINVAL; + cksum = calc_cksum(owfm_idx, cksum_idx, mem); + if (cksum != mem[cksum_idx]) { + printk(KERN_ERR "Error: bad waveform data cksum" + " %x != %x\n", cksum, mem[cksum_idx]); + return -EINVAL; + } + *frame_count = (mem_idx/64); + + return 0; +} + +/* register offsets for gpio control */ +#define LED_GPIO_PIN 51 +#define STDBY_GPIO_PIN 48 +#define RST_GPIO_PIN 49 +#define RDY_GPIO_PIN 32 +#define ERR_GPIO_PIN 17 +#define PCBPWR_GPIO_PIN 16 + +#define AF_SEL_GPIO_N 0x3 +#define GAFR0_U_OFFSET(pin) ((pin - 16) * 2) +#define GAFR1_L_OFFSET(pin) ((pin - 32) * 2) +#define GAFR1_U_OFFSET(pin) ((pin - 48) * 2) +#define GPDR1_OFFSET(pin) (pin - 32) +#define GPCR1_OFFSET(pin) (pin - 32) +#define GPSR1_OFFSET(pin) (pin - 32) +#define GPCR0_OFFSET(pin) (pin) +#define GPSR0_OFFSET(pin) (pin) + +static void metronome_set_gpio_output(int pin, int val) +{ + u8 index; + + index = pin >> 4; + + switch (index) { + case 1: + if (val) + GPSR0 |= (1 << GPSR0_OFFSET(pin)); + else + GPCR0 |= (1 << GPCR0_OFFSET(pin)); + break; + case 2: + break; + case 3: + if (val) + GPSR1 |= (1 << GPSR1_OFFSET(pin)); + else + GPCR1 |= (1 << GPCR1_OFFSET(pin)); + break; + default: + printk(KERN_ERR "unimplemented\n"); + } +} + +static void __devinit metronome_init_gpio_pin(int pin, int dir) +{ + u8 index; + /* dir 0 is output, 1 is input + - do 2 things here: + - set gpio alternate function to standard gpio + - set gpio direction to input or output */ + + index = pin >> 4; + switch (index) { + case 1: + GAFR0_U &= ~(AF_SEL_GPIO_N << GAFR0_U_OFFSET(pin)); + + if (dir) + GPDR0 &= ~(1 << pin); + else + GPDR0 |= (1 << pin); + break; + case 2: + GAFR1_L &= ~(AF_SEL_GPIO_N << GAFR1_L_OFFSET(pin)); + + if (dir) + GPDR1 &= ~(1 << GPDR1_OFFSET(pin)); + else + GPDR1 |= (1 << GPDR1_OFFSET(pin)); + break; + case 3: + GAFR1_U &= ~(AF_SEL_GPIO_N << GAFR1_U_OFFSET(pin)); + + if (dir) + GPDR1 &= ~(1 << GPDR1_OFFSET(pin)); + else + GPDR1 |= (1 << GPDR1_OFFSET(pin)); + break; + default: + printk(KERN_ERR "unimplemented\n"); + } +} + +static void __devinit metronome_init_gpio_regs(void) +{ + metronome_init_gpio_pin(LED_GPIO_PIN, 0); + metronome_set_gpio_output(LED_GPIO_PIN, 0); + + metronome_init_gpio_pin(STDBY_GPIO_PIN, 0); + metronome_set_gpio_output(STDBY_GPIO_PIN, 0); + + metronome_init_gpio_pin(RST_GPIO_PIN, 0); + metronome_set_gpio_output(RST_GPIO_PIN, 0); + + metronome_init_gpio_pin(RDY_GPIO_PIN, 1); + + metronome_init_gpio_pin(ERR_GPIO_PIN, 1); + + metronome_init_gpio_pin(PCBPWR_GPIO_PIN, 0); + metronome_set_gpio_output(PCBPWR_GPIO_PIN, 0); +} + +static void metronome_disable_lcd_controller(struct metronomefb_par *par) +{ + LCSR = 0xffffffff; /* Clear LCD Status Register */ + LCCR0 |= LCCR0_DIS; /* Disable LCD Controller */ + + /* we reset and just wait for things to settle */ + msleep(200); +} + +static void metronome_enable_lcd_controller(struct metronomefb_par *par) +{ + LCSR = 0xffffffff; + FDADR0 = par->metromem_desc_dma; + LCCR0 |= LCCR0_ENB; +} + +static void __devinit metronome_init_lcdc_regs(struct metronomefb_par *par) +{ + /* here we do: + - disable the lcd controller + - setup lcd control registers + - setup dma descriptor + - reenable lcd controller + */ + + /* disable the lcd controller */ + metronome_disable_lcd_controller(par); + + /* setup lcd control registers */ + LCCR0 = LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | LCCR0_PAS + | LCCR0_QDM | LCCR0_BM | LCCR0_OUM; + + LCCR1 = (epd_frame_table[0].fw/2 - 1) /* pixels per line */ + | (27 << 10) /* hsync pulse width - 1 */ + | (33 << 16) /* eol pixel count */ + | (33 << 24); /* bol pixel count */ + + LCCR2 = (epd_frame_table[0].fh - 1) /* lines per panel */ + | (24 << 10) /* vsync pulse width - 1 */ + | (2 << 16) /* eof pixel count */ + | (0 << 24); /* bof pixel count */ + + LCCR3 = 2 /* pixel clock divisor */ + | (24 << 8) /* AC Bias pin freq */ + | LCCR3_16BPP /* BPP */ + | LCCR3_PCP; /* PCP falling edge */ + + /* setup dma descriptor */ + par->metromem_desc->mFDADR0 = par->metromem_desc_dma; + par->metromem_desc->mFSADR0 = par->metromem_dma; + par->metromem_desc->mFIDR0 = 0; + par->metromem_desc->mLDCMD0 = epd_frame_table[0].fw + * epd_frame_table[0].fh; + /* reenable lcd controller */ + metronome_enable_lcd_controller(par); +} + +static int metronome_display_cmd(struct metronomefb_par *par) +{ + int i; + u16 cs; + u16 opcode; + static u8 borderval; + u8 *ptr; + + /* setup display command + we can't immediately set the opcode since the controller + will try parse the command before we've set it all up + so we just set cs here and set the opcode at the end */ + + ptr = par->metromem; + + if (par->metromem_cmd->opcode == 0xCC40) + opcode = cs = 0xCC41; + else + opcode = cs = 0xCC40; + + /* set the args ( 2 bytes ) for display */ + i = 0; + par->metromem_cmd->args[i] = 1 << 3 /* border update */ + | ((borderval++ % 4) & 0x0F) << 4 + | (par->frame_count - 1) << 8; + cs += par->metromem_cmd->args[i++]; + + /* the rest are 0 */ + memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2); + + par->metromem_cmd->csum = cs; + par->metromem_cmd->opcode = opcode; /* display cmd */ + + i = wait_event_interruptible_timeout(par->waitq, (GPLR1 & 0x01), HZ); + return i; +} + +static int __devinit metronome_powerup_cmd(struct metronomefb_par *par) +{ + int i; + u16 cs; + + /* setup power up command */ + par->metromem_cmd->opcode = 0x1234; /* pwr up pseudo cmd */ + cs = par->metromem_cmd->opcode; + + /* set pwr1,2,3 to 1024 */ + for (i = 0; i < 3; i++) { + par->metromem_cmd->args[i] = 1024; + cs += par->metromem_cmd->args[i]; + } + + /* the rest are 0 */ + memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2); + + par->metromem_cmd->csum = cs; + + msleep(1); + metronome_set_gpio_output(RST_GPIO_PIN, 1); + + msleep(1); + metronome_set_gpio_output(STDBY_GPIO_PIN, 1); + + i = wait_event_timeout(par->waitq, (GPLR1 & 0x01), HZ); + return i; +} + +static int __devinit metronome_config_cmd(struct metronomefb_par *par) +{ + int i; + u16 cs; + + /* setup config command + we can't immediately set the opcode since the controller + will try parse the command before we've set it all up + so we just set cs here and set the opcode at the end */ + + cs = 0xCC10; + + /* set the 12 args ( 8 bytes ) for config. see spec for meanings */ + i = 0; + par->metromem_cmd->args[i] = 15 /* sdlew */ + | 2 << 8 /* sdosz */ + | 0 << 11 /* sdor */ + | 0 << 12 /* sdces */ + | 0 << 15; /* sdcer */ + cs += par->metromem_cmd->args[i++]; + + par->metromem_cmd->args[i] = 42 /* gdspl */ + | 1 << 8 /* gdr1 */ + | 1 << 9 /* sdshr */ + | 0 << 15; /* gdspp */ + cs += par->metromem_cmd->args[i++]; + + par->metromem_cmd->args[i] = 18 /* gdspw */ + | 0 << 15; /* dispc */ + cs += par->metromem_cmd->args[i++]; + + par->metromem_cmd->args[i] = 599 /* vdlc */ + | 0 << 11 /* dsi */ + | 0 << 12; /* dsic */ + cs += par->metromem_cmd->args[i++]; + + /* the rest are 0 */ + memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2); + + par->metromem_cmd->csum = cs; + par->metromem_cmd->opcode = 0xCC10; /* config cmd */ + + i = wait_event_timeout(par->waitq, (GPLR1 & 0x01), HZ); + return i; +} + +static int __devinit metronome_init_cmd(struct metronomefb_par *par) +{ + int i; + u16 cs; + + /* setup init command + we can't immediately set the opcode since the controller + will try parse the command before we've set it all up + so we just set cs here and set the opcode at the end */ + + cs = 0xCC20; + + /* set the args ( 2 bytes ) for init */ + i = 0; + par->metromem_cmd->args[i] = 0; + cs += par->metromem_cmd->args[i++]; + + /* the rest are 0 */ + memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2); + + par->metromem_cmd->csum = cs; + par->metromem_cmd->opcode = 0xCC20; /* init cmd */ + + i = wait_event_timeout(par->waitq, (GPLR1 & 0x01), HZ); + return i; +} + +static int __devinit metronome_init_regs(struct metronomefb_par *par) +{ + int res; + + metronome_init_gpio_regs(); + metronome_init_lcdc_regs(par); + + res = metronome_powerup_cmd(par); + if (res) + return res; + + res = metronome_config_cmd(par); + if (res) + return res; + + res = metronome_init_cmd(par); + if (res) + return res; + + return res; +} + +static void metronomefb_dpy_update(struct metronomefb_par *par) +{ + u16 cksum; + unsigned char *buf = (unsigned char __force *)par->info->screen_base; + + /* copy from vm to metromem */ + memcpy(par->metromem_img, buf, DPY_W*DPY_H); + + cksum = calc_img_cksum((u16 *) par->metromem_img, + (epd_frame_table[0].fw * DPY_H)/2); + *((u16 *) (par->metromem_img) + + (epd_frame_table[0].fw * DPY_H)/2) = cksum; + metronome_display_cmd(par); +} + +static u16 metronomefb_dpy_update_page(struct metronomefb_par *par, int index) +{ + int i; + u16 csum = 0; + u16 *buf = (u16 __force *) (par->info->screen_base + index); + u16 *img = (u16 *) (par->metromem_img + index); + + /* swizzle from vm to metromem and recalc cksum at the same time*/ + for (i = 0; i < PAGE_SIZE/2; i++) { + *(img + i) = (buf[i] << 5) & 0xE0E0; + csum += *(img + i); + } + return csum; +} + +/* this is called back from the deferred io workqueue */ +static void metronomefb_dpy_deferred_io(struct fb_info *info, + struct list_head *pagelist) +{ + u16 cksum; + struct page *cur; + struct fb_deferred_io *fbdefio = info->fbdefio; + struct metronomefb_par *par = info->par; + + /* walk the written page list and swizzle the data */ + list_for_each_entry(cur, &fbdefio->pagelist, lru) { + cksum = metronomefb_dpy_update_page(par, + (cur->index << PAGE_SHIFT)); + par->metromem_img_csum -= par->csum_table[cur->index]; + par->csum_table[cur->index] = cksum; + par->metromem_img_csum += cksum; + } + + metronome_display_cmd(par); +} + +static void metronomefb_fillrect(struct fb_info *info, + const struct fb_fillrect *rect) +{ + struct metronomefb_par *par = info->par; + + cfb_fillrect(info, rect); + metronomefb_dpy_update(par); +} + +static void metronomefb_copyarea(struct fb_info *info, + const struct fb_copyarea *area) +{ + struct metronomefb_par *par = info->par; + + cfb_copyarea(info, area); + metronomefb_dpy_update(par); +} + +static void metronomefb_imageblit(struct fb_info *info, + const struct fb_image *image) +{ + struct metronomefb_par *par = info->par; + + cfb_imageblit(info, image); + metronomefb_dpy_update(par); +} + +/* + * this is the slow path from userspace. they can seek and write to + * the fb. it is based on fb_sys_write + */ +static ssize_t metronomefb_write(struct fb_info *info, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct metronomefb_par *par = info->par; + unsigned long p = *ppos; + void *dst; + int err = 0; + unsigned long total_size; + + if (info->state != FBINFO_STATE_RUNNING) + return -EPERM; + + total_size = info->fix.smem_len; + + if (p > total_size) + return -EFBIG; + + if (count > total_size) { + err = -EFBIG; + count = total_size; + } + + if (count + p > total_size) { + if (!err) + err = -ENOSPC; + + count = total_size - p; + } + + dst = (void __force *) (info->screen_base + p); + + if (copy_from_user(dst, buf, count)) + err = -EFAULT; + + if (!err) + *ppos += count; + + metronomefb_dpy_update(par); + + return (err) ? err : count; +} + +static struct fb_ops metronomefb_ops = { + .owner = THIS_MODULE, + .fb_write = metronomefb_write, + .fb_fillrect = metronomefb_fillrect, + .fb_copyarea = metronomefb_copyarea, + .fb_imageblit = metronomefb_imageblit, +}; + +static struct fb_deferred_io metronomefb_defio = { + .delay = HZ, + .deferred_io = metronomefb_dpy_deferred_io, +}; + +static irqreturn_t metronome_handle_irq(int irq, void *dev_id) +{ + struct fb_info *info = dev_id; + struct metronomefb_par *par = info->par; + + wake_up_interruptible(&par->waitq); + return IRQ_HANDLED; +} + +static int __devinit metronomefb_probe(struct platform_device *dev) +{ + struct fb_info *info; + int retval = -ENOMEM; + int videomemorysize; + unsigned char *videomemory; + struct metronomefb_par *par; + const struct firmware *fw_entry; + int cmd_size, wfm_size, img_size, padding_size, totalsize; + int i; + + /* we have two blocks of memory. + info->screen_base which is vm, and is the fb used by apps. + par->metromem which is physically contiguous memory and + contains the display controller commands, waveform, + processed image data and padding. this is the data pulled + by the pxa255's LCD controller and pushed to Metronome */ + + videomemorysize = (DPY_W*DPY_H); + videomemory = vmalloc(videomemorysize); + if (!videomemory) + return retval; + + memset(videomemory, 0, videomemorysize); + + info = framebuffer_alloc(sizeof(struct metronomefb_par), &dev->dev); + if (!info) + goto err_vfree; + + info->screen_base = (char __iomem *) videomemory; + info->fbops = &metronomefb_ops; + + info->var = metronomefb_var; + info->fix = metronomefb_fix; + info->fix.smem_len = videomemorysize; + par = info->par; + par->info = info; + init_waitqueue_head(&par->waitq); + + /* this table caches per page csum values. */ + par->csum_table = vmalloc(videomemorysize/PAGE_SIZE); + if (!par->csum_table) + goto err_csum_table; + + /* the metromem buffer is divided as follows: + command | CRC | padding + 16kb waveform data | CRC | padding + image data | CRC + and an extra 256 bytes for dma descriptors + eg: IW=832 IH=622 WS=128 + */ + + cmd_size = 1 * epd_frame_table[0].fw; + wfm_size = ((16*1024 + 2 + epd_frame_table[0].fw - 1) + / epd_frame_table[0].fw) * epd_frame_table[0].fw; + img_size = epd_frame_table[0].fh * epd_frame_table[0].fw; + padding_size = 4 * epd_frame_table[0].fw; + totalsize = cmd_size + wfm_size + img_size + padding_size; + par->metromemsize = PAGE_ALIGN(totalsize + 256); + DPRINTK("desired memory size = %d\n", par->metromemsize); + dev->dev.coherent_dma_mask = 0xffffffffull; + par->metromem = dma_alloc_writecombine(&dev->dev, par->metromemsize, + &par->metromem_dma, GFP_KERNEL); + if (!par->metromem) { + printk(KERN_ERR + "metronomefb: unable to allocate dma buffer\n"); + goto err_vfree; + } + + info->fix.smem_start = par->metromem_dma; + par->metromem_cmd = (struct metromem_cmd *) par->metromem; + par->metromem_wfm = par->metromem + cmd_size; + par->metromem_img = par->metromem + cmd_size + wfm_size; + par->metromem_img_csum = (u16 *) (par->metromem_img + + (epd_frame_table[0].fw * DPY_H)); + DPRINTK("img offset=0x%x\n", cmd_size + wfm_size); + par->metromem_desc = (struct metromem_desc *) (par->metromem + cmd_size + + wfm_size + img_size + padding_size); + par->metromem_desc_dma = par->metromem_dma + cmd_size + wfm_size + + img_size + padding_size; + + /* load the waveform in. assume mode 3, temp 31 for now */ + /* a) request the waveform file from userspace + b) process waveform and decode into metromem */ + + retval = request_firmware(&fw_entry, "waveform.wbf", &dev->dev); + if (retval < 0) { + printk(KERN_ERR "metronomefb: couldn't get waveform\n"); + goto err_dma_free; + } + + retval = load_waveform((u8 *) fw_entry->data, fw_entry->size, + par->metromem_wfm, 3, 31, &par->frame_count); + if (retval < 0) { + printk(KERN_ERR "metronomefb: couldn't process waveform\n"); + goto err_ld_wfm; + } + release_firmware(fw_entry); + + retval = request_irq(IRQ_GPIO(RDY_GPIO_PIN), metronome_handle_irq, + IRQF_DISABLED, "Metronome", info); + if (retval) { + dev_err(&dev->dev, "request_irq failed: %d\n", retval); + goto err_ld_wfm; + } + set_irq_type(IRQ_GPIO(RDY_GPIO_PIN), IRQT_FALLING); + + retval = metronome_init_regs(par); + if (retval < 0) + goto err_free_irq; + + info->flags = FBINFO_FLAG_DEFAULT; + + info->fbdefio = &metronomefb_defio; + fb_deferred_io_init(info); + + retval = fb_alloc_cmap(&info->cmap, 8, 0); + if (retval < 0) { + printk(KERN_ERR "Failed to allocate colormap\n"); + goto err_fb_rel; + } + + /* set cmap */ + for (i = 0; i < 8; i++) + info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/16; + memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*8); + memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*8); + + retval = register_framebuffer(info); + if (retval < 0) + goto err_cmap; + + platform_set_drvdata(dev, info); + + printk(KERN_INFO + "fb%d: Metronome frame buffer device, using %dK of video" + " memory\n", info->node, videomemorysize >> 10); + + return 0; + +err_cmap: + fb_dealloc_cmap(&info->cmap); +err_fb_rel: + framebuffer_release(info); +err_free_irq: + free_irq(IRQ_GPIO(RDY_GPIO_PIN), info); +err_ld_wfm: + release_firmware(fw_entry); +err_dma_free: + dma_free_writecombine(&dev->dev, par->metromemsize, par->metromem, + par->metromem_dma); +err_csum_table: + vfree(par->csum_table); +err_vfree: + vfree(videomemory); + return retval; +} + +static int __devexit metronomefb_remove(struct platform_device *dev) +{ + struct fb_info *info = platform_get_drvdata(dev); + + if (info) { + struct metronomefb_par *par = info->par; + fb_deferred_io_cleanup(info); + dma_free_writecombine(&dev->dev, par->metromemsize, + par->metromem, par->metromem_dma); + fb_dealloc_cmap(&info->cmap); + vfree(par->csum_table); + unregister_framebuffer(info); + vfree((void __force *)info->screen_base); + free_irq(IRQ_GPIO(RDY_GPIO_PIN), info); + framebuffer_release(info); + } + return 0; +} + +static struct platform_driver metronomefb_driver = { + .probe = metronomefb_probe, + .remove = metronomefb_remove, + .driver = { + .name = "metronomefb", + }, +}; + +static struct platform_device *metronomefb_device; + +static int __init metronomefb_init(void) +{ + int ret; + + if (!metronomefb_enable) { + printk(KERN_ERR + "Use metronomefb_enable to enable the device\n"); + return -ENXIO; + } + + ret = platform_driver_register(&metronomefb_driver); + if (!ret) { + metronomefb_device = platform_device_alloc("metronomefb", 0); + if (metronomefb_device) + ret = platform_device_add(metronomefb_device); + else + ret = -ENOMEM; + + if (ret) { + platform_device_put(metronomefb_device); + platform_driver_unregister(&metronomefb_driver); + } + } + return ret; + +} + +static void __exit metronomefb_exit(void) +{ + platform_device_unregister(metronomefb_device); + platform_driver_unregister(&metronomefb_driver); +} + +module_param(metronomefb_enable, uint, 0); +MODULE_PARM_DESC(metronomefb_enable, "Enable communication with Metronome"); + +module_init(metronomefb_init); +module_exit(metronomefb_exit); + +MODULE_DESCRIPTION("fbdev driver for Metronome controller"); +MODULE_AUTHOR("Jaya Kumar"); +MODULE_LICENSE("GPL"); |