diff --git a/[refs] b/[refs] index 1b8f1b4c4136..e7cb7e1ff160 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: aeb24d2fb08653a39abb50281b1ffa2d2a6879ab +refs/heads/master: ef79df263062fd04fe9db4ee1b9f014a87a8e924 diff --git a/trunk/Documentation/lguest/lguest.c b/trunk/Documentation/lguest/lguest.c index bec5a32e4095..0f23d67f958f 100644 --- a/trunk/Documentation/lguest/lguest.c +++ b/trunk/Documentation/lguest/lguest.c @@ -486,12 +486,9 @@ static void concat(char *dst, char *args[]) unsigned int i, len = 0; for (i = 0; args[i]; i++) { - if (i) { - strcat(dst+len, " "); - len++; - } strcpy(dst+len, args[i]); - len += strlen(args[i]); + strcat(dst+len, " "); + len += strlen(args[i]) + 1; } /* In case it's empty. */ dst[len] = '\0'; diff --git a/trunk/Documentation/pci.txt b/trunk/Documentation/pci.txt index d2c2e6e2b224..bb7bd27d4682 100644 --- a/trunk/Documentation/pci.txt +++ b/trunk/Documentation/pci.txt @@ -123,7 +123,7 @@ initialization with a pointer to a structure describing the driver The ID table is an array of struct pci_device_id entries ending with an -all-zero entry; use of the macro DEFINE_PCI_DEVICE_TABLE is the preferred +all-zero entry; use of the macro DECLARE_PCI_DEVICE_TABLE is the preferred method of declaring the table. Each entry consists of: vendor,device Vendor and device ID to match (or PCI_ANY_ID) @@ -193,7 +193,7 @@ Tips on when/where to use the above attributes: o Do not mark the struct pci_driver. o The ID table array should be marked __devinitconst; this is done - automatically if the table is declared with DEFINE_PCI_DEVICE_TABLE(). + automatically if the table is declared with DECLARE_PCI_DEVICE_TABLE(). o The probe() and remove() functions should be marked __devinit and __devexit respectively. All initialization functions diff --git a/trunk/Documentation/scheduler/sched-stats.txt b/trunk/Documentation/scheduler/sched-stats.txt index 01e69404ee5e..442e14d35dea 100644 --- a/trunk/Documentation/scheduler/sched-stats.txt +++ b/trunk/Documentation/scheduler/sched-stats.txt @@ -142,7 +142,7 @@ of idleness (idle, busy, and newly idle): /proc//schedstat ---------------- -schedstats also adds a new /proc//schedstat file to include some of +schedstats also adds a new /proc/kset.kobj)); INIT_LIST_HEAD(&cls->drivers); + memset(&cls->kset.kobj, 0x00, sizeof(struct kobject)); cls->kset.kobj.parent = &system_kset->kobj; cls->kset.kobj.ktype = &ktype_sysdev_class; cls->kset.kobj.kset = system_kset; @@ -227,6 +228,9 @@ int sysdev_register(struct sys_device * sysdev) pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj)); + /* initialize the kobject to 0, in case it had previously been used */ + memset(&sysdev->kobj, 0x00, sizeof(struct kobject)); + /* Make sure the kset is set */ sysdev->kobj.kset = &cls->kset; diff --git a/trunk/drivers/char/riscom8.c b/trunk/drivers/char/riscom8.c index 589ac6f65b9a..8fc4fe4e38f1 100644 --- a/trunk/drivers/char/riscom8.c +++ b/trunk/drivers/char/riscom8.c @@ -1620,8 +1620,14 @@ static int __init rc_init_drivers(void) static void rc_release_drivers(void) { + unsigned long flags; + + spin_lock_irqsave(&riscom_lock, flags); + tty_unregister_driver(riscom_driver); put_tty_driver(riscom_driver); + + spin_unlock_irqrestore(&riscom_lock, flags); } #ifndef MODULE diff --git a/trunk/drivers/gpio/pca953x.c b/trunk/drivers/gpio/pca953x.c index 6e72fd31184d..92583cd4bffd 100644 --- a/trunk/drivers/gpio/pca953x.c +++ b/trunk/drivers/gpio/pca953x.c @@ -184,7 +184,6 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) gc->direction_output = pca953x_gpio_direction_output; gc->get = pca953x_gpio_get_value; gc->set = pca953x_gpio_set_value; - gc->can_sleep = 1; gc->base = chip->gpio_start; gc->ngpio = gpios; diff --git a/trunk/drivers/input/serio/i8042.h b/trunk/drivers/input/serio/i8042.h index c972e5d03a3f..dd22d91f8b39 100644 --- a/trunk/drivers/input/serio/i8042.h +++ b/trunk/drivers/input/serio/i8042.h @@ -16,7 +16,7 @@ #if defined(CONFIG_MACH_JAZZ) #include "i8042-jazzio.h" -#elif defined(CONFIG_SGI_HAS_I8042) +#elif defined(CONFIG_SGI_IP22) #include "i8042-ip22io.h" #elif defined(CONFIG_PPC) #include "i8042-ppcio.h" diff --git a/trunk/drivers/lguest/core.c b/trunk/drivers/lguest/core.c index c632c08cbbdc..7743d73768df 100644 --- a/trunk/drivers/lguest/core.c +++ b/trunk/drivers/lguest/core.c @@ -69,22 +69,11 @@ static __init int map_switcher(void) switcher_page[i] = virt_to_page(addr); } - /* First we check that the Switcher won't overlap the fixmap area at - * the top of memory. It's currently nowhere near, but it could have - * very strange effects if it ever happened. */ - if (SWITCHER_ADDR + (TOTAL_SWITCHER_PAGES+1)*PAGE_SIZE > FIXADDR_START){ - err = -ENOMEM; - printk("lguest: mapping switcher would thwack fixmap\n"); - goto free_pages; - } - /* Now we reserve the "virtual memory area" we want: 0xFFC00000 * (SWITCHER_ADDR). We might not get it in theory, but in practice - * it's worked so far. The end address needs +1 because __get_vm_area - * allocates an extra guard page, so we need space for that. */ + * it's worked so far. */ switcher_vma = __get_vm_area(TOTAL_SWITCHER_PAGES * PAGE_SIZE, - VM_ALLOC, SWITCHER_ADDR, SWITCHER_ADDR - + (TOTAL_SWITCHER_PAGES+1) * PAGE_SIZE); + VM_ALLOC, SWITCHER_ADDR, VMALLOC_END); if (!switcher_vma) { err = -ENOMEM; printk("lguest: could not map switcher pages high\n"); diff --git a/trunk/drivers/lguest/lguest_user.c b/trunk/drivers/lguest/lguest_user.c index 2221485b0773..85d42d3d01a9 100644 --- a/trunk/drivers/lguest/lguest_user.c +++ b/trunk/drivers/lguest/lguest_user.c @@ -241,16 +241,15 @@ static ssize_t write(struct file *file, const char __user *in, cpu = &lg->cpus[cpu_id]; if (!cpu) return -EINVAL; + } - /* Once the Guest is dead, you can only read() why it died. */ - if (lg->dead) - return -ENOENT; + /* Once the Guest is dead, all you can do is read() why it died. */ + if (lg && lg->dead) + return -ENOENT; - /* If you're not the task which owns the Guest, all you can do - * is break the Launcher out of running the Guest. */ - if (current != cpu->tsk && req != LHREQ_BREAK) - return -EPERM; - } + /* If you're not the task which owns the Guest, you can only break */ + if (lg && current != cpu->tsk && req != LHREQ_BREAK) + return -EPERM; switch (req) { case LHREQ_INITIALIZE: diff --git a/trunk/drivers/lguest/page_tables.c b/trunk/drivers/lguest/page_tables.c index a7f64a9d67e0..275f23c2deb4 100644 --- a/trunk/drivers/lguest/page_tables.c +++ b/trunk/drivers/lguest/page_tables.c @@ -391,7 +391,7 @@ static unsigned int find_pgdir(struct lguest *lg, unsigned long pgtable) { unsigned int i; for (i = 0; i < ARRAY_SIZE(lg->pgdirs); i++) - if (lg->pgdirs[i].pgdir && lg->pgdirs[i].gpgdir == pgtable) + if (lg->pgdirs[i].gpgdir == pgtable) break; return i; } diff --git a/trunk/drivers/md/bitmap.c b/trunk/drivers/md/bitmap.c index c14dacdacfac..831aed9c56ff 100644 --- a/trunk/drivers/md/bitmap.c +++ b/trunk/drivers/md/bitmap.c @@ -1045,8 +1045,7 @@ void bitmap_daemon_work(struct bitmap *bitmap) if (bitmap == NULL) return; if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ)) - goto done; - + return; bitmap->daemon_lastrun = jiffies; if (bitmap->allclean) { bitmap->mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; @@ -1143,7 +1142,6 @@ void bitmap_daemon_work(struct bitmap *bitmap) } } - done: if (bitmap->allclean == 0) bitmap->mddev->thread->timeout = bitmap->daemon_sleep * HZ; } diff --git a/trunk/drivers/md/md.c b/trunk/drivers/md/md.c index ccbbf63727cc..827824a9f3e9 100644 --- a/trunk/drivers/md/md.c +++ b/trunk/drivers/md/md.c @@ -5149,7 +5149,7 @@ static int md_seq_show(struct seq_file *seq, void *v) if (mddev->ro==1) seq_printf(seq, " (read-only)"); if (mddev->ro==2) - seq_printf(seq, " (auto-read-only)"); + seq_printf(seq, "(auto-read-only)"); seq_printf(seq, " %s", mddev->pers->name); } diff --git a/trunk/drivers/memstick/Kconfig b/trunk/drivers/memstick/Kconfig index f0ca41c20323..1093fdb07297 100644 --- a/trunk/drivers/memstick/Kconfig +++ b/trunk/drivers/memstick/Kconfig @@ -8,7 +8,7 @@ menuconfig MEMSTICK Sony MemoryStick is a proprietary storage/extension card protocol. If you want MemoryStick support, you should say Y here and also - to the specific driver for your MemoryStick interface. + to the specific driver for your MMC interface. if MEMSTICK diff --git a/trunk/drivers/memstick/core/memstick.c b/trunk/drivers/memstick/core/memstick.c index de80dba12f9b..bba467fe4bce 100644 --- a/trunk/drivers/memstick/core/memstick.c +++ b/trunk/drivers/memstick/core/memstick.c @@ -18,6 +18,7 @@ #include #define DRIVER_NAME "memstick" +#define DRIVER_VERSION "0.2" static unsigned int cmd_retries = 3; module_param(cmd_retries, uint, 0644); @@ -235,7 +236,7 @@ int memstick_next_req(struct memstick_host *host, struct memstick_request **mrq) rc = host->card->next_request(host->card, mrq); if (!rc) - host->retries = cmd_retries > 1 ? cmd_retries - 1 : 1; + host->retries = cmd_retries; else *mrq = NULL; @@ -270,7 +271,7 @@ void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc, mrq->data_dir = READ; mrq->sg = *sg; - mrq->long_data = 1; + mrq->io_type = MEMSTICK_IO_SG; if (tpc == MS_TPC_SET_CMD || tpc == MS_TPC_EX_SET_CMD) mrq->need_card_int = 1; @@ -305,7 +306,7 @@ void memstick_init_req(struct memstick_request *mrq, unsigned char tpc, if (mrq->data_dir == WRITE) memcpy(mrq->data, buf, mrq->data_len); - mrq->long_data = 0; + mrq->io_type = MEMSTICK_IO_VAL; if (tpc == MS_TPC_SET_CMD || tpc == MS_TPC_EX_SET_CMD) mrq->need_card_int = 1; @@ -560,31 +561,6 @@ void memstick_free_host(struct memstick_host *host) } EXPORT_SYMBOL(memstick_free_host); -/** - * memstick_suspend_host - notify bus driver of host suspension - * @host - host to use - */ -void memstick_suspend_host(struct memstick_host *host) -{ - mutex_lock(&host->lock); - host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF); - mutex_unlock(&host->lock); -} -EXPORT_SYMBOL(memstick_suspend_host); - -/** - * memstick_resume_host - notify bus driver of host resumption - * @host - host to use - */ -void memstick_resume_host(struct memstick_host *host) -{ - mutex_lock(&host->lock); - host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); - mutex_unlock(&host->lock); - memstick_detect_change(host); -} -EXPORT_SYMBOL(memstick_resume_host); - int memstick_register_driver(struct memstick_driver *drv) { drv->driver.bus = &memstick_bus_type; @@ -635,3 +611,4 @@ module_exit(memstick_exit); MODULE_AUTHOR("Alex Dubov"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Sony MemoryStick core driver"); +MODULE_VERSION(DRIVER_VERSION); diff --git a/trunk/drivers/memstick/core/mspro_block.c b/trunk/drivers/memstick/core/mspro_block.c index 1d637e4561d3..423ad8cf4bb9 100644 --- a/trunk/drivers/memstick/core/mspro_block.c +++ b/trunk/drivers/memstick/core/mspro_block.c @@ -16,10 +16,10 @@ #include #include #include -#include #include #define DRIVER_NAME "mspro_block" +#define DRIVER_VERSION "0.2" static int major; module_param(major, int, 0644); @@ -110,17 +110,6 @@ struct mspro_mbr { unsigned int sectors_per_partition; } __attribute__((packed)); -struct mspro_specfile { - char name[8]; - char ext[3]; - unsigned char attr; - unsigned char reserved[10]; - unsigned short time; - unsigned short date; - unsigned short cluster; - unsigned int size; -} __attribute__((packed)); - struct mspro_devinfo { unsigned short cylinders; unsigned short heads; @@ -304,20 +293,6 @@ static ssize_t mspro_block_attr_show_sysinfo(struct device *dev, dev_attr); struct mspro_sys_info *x_sys = x_attr->data; ssize_t rc = 0; - int date_tz = 0, date_tz_f = 0; - - if (x_sys->assembly_date[0] > 0x80U) { - date_tz = (~x_sys->assembly_date[0]) + 1; - date_tz_f = date_tz & 3; - date_tz >>= 2; - date_tz = -date_tz; - date_tz_f *= 15; - } else if (x_sys->assembly_date[0] < 0x80U) { - date_tz = x_sys->assembly_date[0]; - date_tz_f = date_tz & 3; - date_tz >>= 2; - date_tz_f *= 15; - } rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "class: %x\n", x_sys->class); @@ -330,8 +305,8 @@ static ssize_t mspro_block_attr_show_sysinfo(struct device *dev, rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "page size: %x\n", be16_to_cpu(x_sys->page_size)); rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "assembly date: " - "GMT%+d:%d %04u-%02u-%02u %02u:%02u:%02u\n", - date_tz, date_tz_f, + "%d %04u-%02u-%02u %02u:%02u:%02u\n", + x_sys->assembly_date[0], be16_to_cpu(*(unsigned short *) &x_sys->assembly_date[1]), x_sys->assembly_date[3], x_sys->assembly_date[4], @@ -423,41 +398,6 @@ static ssize_t mspro_block_attr_show_mbr(struct device *dev, return rc; } -static ssize_t mspro_block_attr_show_specfile(struct device *dev, - struct device_attribute *attr, - char *buffer) -{ - struct mspro_sys_attr *x_attr = container_of(attr, - struct mspro_sys_attr, - dev_attr); - struct mspro_specfile *x_spfile = x_attr->data; - char name[9], ext[4]; - ssize_t rc = 0; - - memcpy(name, x_spfile->name, 8); - name[8] = 0; - memcpy(ext, x_spfile->ext, 3); - ext[3] = 0; - - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "name: %s\n", name); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "ext: %s\n", ext); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "attribute: %x\n", - x_spfile->attr); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "time: %d:%d:%d\n", - x_spfile->time >> 11, - (x_spfile->time >> 5) & 0x3f, - (x_spfile->time & 0x1f) * 2); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "date: %d-%d-%d\n", - (x_spfile->date >> 9) + 1980, - (x_spfile->date >> 5) & 0xf, - x_spfile->date & 0x1f); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start cluster: %x\n", - x_spfile->cluster); - rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "size: %x\n", - x_spfile->size); - return rc; -} - static ssize_t mspro_block_attr_show_devinfo(struct device *dev, struct device_attribute *attr, char *buffer) @@ -490,9 +430,6 @@ static sysfs_show_t mspro_block_attr_show(unsigned char tag) return mspro_block_attr_show_modelname; case MSPRO_BLOCK_ID_MBR: return mspro_block_attr_show_mbr; - case MSPRO_BLOCK_ID_SPECFILEVALUES1: - case MSPRO_BLOCK_ID_SPECFILEVALUES2: - return mspro_block_attr_show_specfile; case MSPRO_BLOCK_ID_DEVINFO: return mspro_block_attr_show_devinfo; default: @@ -692,7 +629,7 @@ static void mspro_block_process_request(struct memstick_dev *card, param.system = msb->system; param.data_count = cpu_to_be16(page_count); param.data_address = cpu_to_be32((uint32_t)t_sec); - param.tpc_param = 0; + param.cmd_param = 0; msb->data_dir = rq_data_dir(req); msb->transfer_cmd = msb->data_dir == READ @@ -821,10 +758,10 @@ static int mspro_block_switch_to_parallel(struct memstick_dev *card) 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 = 0, .data_count = 0, .data_address = 0, - .tpc_param = 0 + .cmd_param = 0 }; card->next_request = h_mspro_block_req_init; @@ -836,8 +773,8 @@ static int mspro_block_switch_to_parallel(struct memstick_dev *card) if (card->current_mrq.error) return card->current_mrq.error; - msb->system = MEMSTICK_SYS_PAR4; - host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4); + msb->system = 0; + host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PARALLEL); card->next_request = h_mspro_block_req_init; msb->mrq_handler = h_mspro_block_default; @@ -846,24 +783,8 @@ static int mspro_block_switch_to_parallel(struct memstick_dev *card) wait_for_completion(&card->mrq_complete); if (card->current_mrq.error) { - msb->system = MEMSTICK_SYS_SERIAL; - host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF); - msleep(1000); - host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); + msb->system = 0x80; 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; } @@ -881,7 +802,7 @@ static int mspro_block_read_attributes(struct memstick_dev *card) .system = msb->system, .data_count = cpu_to_be16(1), .data_address = 0, - .tpc_param = 0 + .cmd_param = 0 }; struct mspro_attribute *attr = NULL; struct mspro_sys_attr *s_attr = NULL; @@ -1001,7 +922,7 @@ static int mspro_block_read_attributes(struct memstick_dev *card) param.system = msb->system; param.data_count = cpu_to_be16((rc / msb->page_size) + 1); param.data_address = cpu_to_be32(addr / msb->page_size); - param.tpc_param = 0; + param.cmd_param = 0; sg_init_one(&msb->req_sg[0], buffer, be16_to_cpu(param.data_count) * msb->page_size); @@ -1043,7 +964,7 @@ static int mspro_block_init_card(struct memstick_dev *card) struct memstick_host *host = card->host; int rc = 0; - msb->system = MEMSTICK_SYS_SERIAL; + msb->system = 0x80; card->reg_addr.r_offset = offsetof(struct mspro_register, status); card->reg_addr.r_length = sizeof(struct ms_status_register); card->reg_addr.w_offset = offsetof(struct mspro_register, param); @@ -1052,7 +973,7 @@ 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 (host->caps & MEMSTICK_CAP_PARALLEL) { if (mspro_block_switch_to_parallel(card)) printk(KERN_WARNING "%s: could not switch to " "parallel interface\n", card->dev.bus_id); @@ -1427,3 +1348,4 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Alex Dubov"); MODULE_DESCRIPTION("Sony MemoryStickPro block device driver"); MODULE_DEVICE_TABLE(memstick, mspro_block_id_tbl); +MODULE_VERSION(DRIVER_VERSION); diff --git a/trunk/drivers/memstick/host/Kconfig b/trunk/drivers/memstick/host/Kconfig index 4ce5c8dffb68..c002fcc3c879 100644 --- a/trunk/drivers/memstick/host/Kconfig +++ b/trunk/drivers/memstick/host/Kconfig @@ -20,13 +20,3 @@ config MEMSTICK_TIFM_MS To compile this driver as a module, choose M here: the module will be called tifm_ms. -config MEMSTICK_JMICRON_38X - tristate "JMicron JMB38X MemoryStick interface support (EXPERIMENTAL)" - depends on EXPERIMENTAL && PCI - - help - Say Y here if you want to be able to access MemoryStick cards with - the JMicron(R) JMB38X MemoryStick card reader. - - To compile this driver as a module, choose M here: the - module will be called jmb38x_ms. diff --git a/trunk/drivers/memstick/host/Makefile b/trunk/drivers/memstick/host/Makefile index 12530e4311d3..ee666380efa1 100644 --- a/trunk/drivers/memstick/host/Makefile +++ b/trunk/drivers/memstick/host/Makefile @@ -3,8 +3,8 @@ # ifeq ($(CONFIG_MEMSTICK_DEBUG),y) - EXTRA_CFLAGS += -DDEBUG + EXTRA_CFLAGS += -DDEBUG endif -obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o -obj-$(CONFIG_MEMSTICK_JMICRON_38X) += jmb38x_ms.o +obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o + diff --git a/trunk/drivers/memstick/host/jmb38x_ms.c b/trunk/drivers/memstick/host/jmb38x_ms.c deleted file mode 100644 index 03fe8783b1ee..000000000000 --- a/trunk/drivers/memstick/host/jmb38x_ms.c +++ /dev/null @@ -1,945 +0,0 @@ -/* - * jmb38x_ms.c - JMicron jmb38x MemoryStick card reader - * - * Copyright (C) 2008 Alex Dubov - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include - -#define DRIVER_NAME "jmb38x_ms" - -static int no_dma; -module_param(no_dma, bool, 0644); - -enum { - DMA_ADDRESS = 0x00, - BLOCK = 0x04, - DMA_CONTROL = 0x08, - TPC_P0 = 0x0c, - TPC_P1 = 0x10, - TPC = 0x14, - HOST_CONTROL = 0x18, - DATA = 0x1c, - STATUS = 0x20, - INT_STATUS = 0x24, - INT_STATUS_ENABLE = 0x28, - INT_SIGNAL_ENABLE = 0x2c, - TIMER = 0x30, - TIMER_CONTROL = 0x34, - PAD_OUTPUT_ENABLE = 0x38, - PAD_PU_PD = 0x3c, - CLOCK_DELAY = 0x40, - ADMA_ADDRESS = 0x44, - CLOCK_CONTROL = 0x48, - LED_CONTROL = 0x4c, - VERSION = 0x50 -}; - -struct jmb38x_ms_host { - struct jmb38x_ms *chip; - void __iomem *addr; - spinlock_t lock; - int id; - char host_id[DEVICE_ID_SIZE]; - int irq; - unsigned int block_pos; - 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]; -}; - -struct jmb38x_ms { - struct pci_dev *pdev; - int host_cnt; - struct memstick_host *hosts[]; -}; - -#define BLOCK_COUNT_MASK 0xffff0000 -#define BLOCK_SIZE_MASK 0x00000fff - -#define DMA_CONTROL_ENABLE 0x00000001 - -#define TPC_DATA_SEL 0x00008000 -#define TPC_DIR 0x00004000 -#define TPC_WAIT_INT 0x00002000 -#define TPC_GET_INT 0x00000800 -#define TPC_CODE_SZ_MASK 0x00000700 -#define TPC_DATA_SZ_MASK 0x00000007 - -#define HOST_CONTROL_RESET_REQ 0x00008000 -#define HOST_CONTROL_REI 0x00004000 -#define HOST_CONTROL_LED 0x00000400 -#define HOST_CONTROL_FAST_CLK 0x00000200 -#define HOST_CONTROL_RESET 0x00000100 -#define HOST_CONTROL_POWER_EN 0x00000080 -#define HOST_CONTROL_CLOCK_EN 0x00000040 -#define HOST_CONTROL_IF_SHIFT 4 - -#define HOST_CONTROL_IF_SERIAL 0x0 -#define HOST_CONTROL_IF_PAR4 0x1 -#define HOST_CONTROL_IF_PAR8 0x3 - -#define STATUS_HAS_MEDIA 0x00000400 -#define STATUS_FIFO_EMPTY 0x00000200 -#define STATUS_FIFO_FULL 0x00000100 - -#define INT_STATUS_TPC_ERR 0x00080000 -#define INT_STATUS_CRC_ERR 0x00040000 -#define INT_STATUS_TIMER_TO 0x00020000 -#define INT_STATUS_HSK_TO 0x00010000 -#define INT_STATUS_ANY_ERR 0x00008000 -#define INT_STATUS_FIFO_WRDY 0x00000080 -#define INT_STATUS_FIFO_RRDY 0x00000040 -#define INT_STATUS_MEDIA_OUT 0x00000010 -#define INT_STATUS_MEDIA_IN 0x00000008 -#define INT_STATUS_DMA_BOUNDARY 0x00000004 -#define INT_STATUS_EOTRAN 0x00000002 -#define INT_STATUS_EOTPC 0x00000001 - -#define INT_STATUS_ALL 0x000f801f - -#define PAD_OUTPUT_ENABLE_MS 0x0F3F - -#define PAD_PU_PD_OFF 0x7FFF0000 -#define PAD_PU_PD_ON_MS_SOCK0 0x5f8f0000 -#define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000 - -enum { - CMD_READY = 0x01, - FIFO_READY = 0x02, - REG_DATA = 0x04, - AUTO_GET_INT = 0x08 -}; - -static unsigned int jmb38x_ms_read_data(struct jmb38x_ms_host *host, - unsigned char *buf, unsigned int length) -{ - unsigned int off = 0; - - while (host->io_pos && length) { - buf[off++] = host->io_word[0] & 0xff; - host->io_word[0] >>= 8; - length--; - host->io_pos--; - } - - if (!length) - return off; - - while (!(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) { - if (length < 4) - break; - *(unsigned int *)(buf + off) = __raw_readl(host->addr + DATA); - length -= 4; - off += 4; - } - - if (length - && !(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) { - host->io_word[0] = readl(host->addr + DATA); - for (host->io_pos = 4; host->io_pos; --host->io_pos) { - buf[off++] = host->io_word[0] & 0xff; - host->io_word[0] >>= 8; - length--; - if (!length) - break; - } - } - - return off; -} - -static unsigned int jmb38x_ms_read_reg_data(struct jmb38x_ms_host *host, - unsigned char *buf, - unsigned int length) -{ - unsigned int off = 0; - - while (host->io_pos > 4 && length) { - buf[off++] = host->io_word[0] & 0xff; - host->io_word[0] >>= 8; - length--; - host->io_pos--; - } - - if (!length) - return off; - - while (host->io_pos && length) { - buf[off++] = host->io_word[1] & 0xff; - host->io_word[1] >>= 8; - length--; - host->io_pos--; - } - - return off; -} - -static unsigned int jmb38x_ms_write_data(struct jmb38x_ms_host *host, - unsigned char *buf, - unsigned int length) -{ - unsigned int off = 0; - - if (host->io_pos) { - while (host->io_pos < 4 && length) { - host->io_word[0] |= buf[off++] << (host->io_pos * 8); - host->io_pos++; - length--; - } - } - - if (host->io_pos == 4 - && !(STATUS_FIFO_FULL & readl(host->addr + STATUS))) { - writel(host->io_word[0], host->addr + DATA); - host->io_pos = 0; - host->io_word[0] = 0; - } else if (host->io_pos) { - return off; - } - - if (!length) - return off; - - while (!(STATUS_FIFO_FULL & readl(host->addr + STATUS))) { - if (length < 4) - break; - - __raw_writel(*(unsigned int *)(buf + off), - host->addr + DATA); - length -= 4; - off += 4; - } - - switch (length) { - case 3: - host->io_word[0] |= buf[off + 2] << 16; - host->io_pos++; - case 2: - host->io_word[0] |= buf[off + 1] << 8; - host->io_pos++; - case 1: - host->io_word[0] |= buf[off]; - host->io_pos++; - } - - off += host->io_pos; - - return off; -} - -static unsigned int jmb38x_ms_write_reg_data(struct jmb38x_ms_host *host, - unsigned char *buf, - unsigned int length) -{ - unsigned int off = 0; - - while (host->io_pos < 4 && length) { - host->io_word[0] &= ~(0xff << (host->io_pos * 8)); - host->io_word[0] |= buf[off++] << (host->io_pos * 8); - host->io_pos++; - length--; - } - - if (!length) - return off; - - while (host->io_pos < 8 && length) { - host->io_word[1] &= ~(0xff << (host->io_pos * 8)); - host->io_word[1] |= buf[off++] << (host->io_pos * 8); - host->io_pos++; - length--; - } - - return off; -} - -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 char *buf; - struct page *pg; - unsigned long flags = 0; - - if (host->req->long_data) { - length = host->req->sg.length - host->block_pos; - off = host->req->sg.offset + host->block_pos; - } else { - length = host->req->data_len - host->block_pos; - off = 0; - } - - while (length) { - if (host->req->long_data) { - pg = nth_page(sg_page(&host->req->sg), - off >> PAGE_SHIFT); - p_off = offset_in_page(off); - p_cnt = PAGE_SIZE - p_off; - p_cnt = min(p_cnt, length); - - local_irq_save(flags); - buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + p_off; - } else { - buf = host->req->data + host->block_pos; - p_cnt = host->req->data_len - host->block_pos; - } - - if (host->req->data_dir == WRITE) - t_size = !(host->cmd_flags & REG_DATA) - ? jmb38x_ms_write_data(host, buf, p_cnt) - : jmb38x_ms_write_reg_data(host, buf, p_cnt); - else - t_size = !(host->cmd_flags & REG_DATA) - ? jmb38x_ms_read_data(host, buf, p_cnt) - : jmb38x_ms_read_reg_data(host, buf, p_cnt); - - if (host->req->long_data) { - kunmap_atomic(buf - p_off, KM_BIO_SRC_IRQ); - local_irq_restore(flags); - } - - if (!t_size) - break; - host->block_pos += t_size; - length -= t_size; - off += t_size; - } - - if (!length && host->req->data_dir == WRITE) { - if (host->cmd_flags & REG_DATA) { - writel(host->io_word[0], host->addr + TPC_P0); - writel(host->io_word[1], host->addr + TPC_P1); - } else if (host->io_pos) { - writel(host->io_word[0], host->addr + DATA); - } - } - - return length; -} - -static int jmb38x_ms_issue_cmd(struct memstick_host *msh) -{ - struct jmb38x_ms_host *host = memstick_priv(msh); - unsigned char *data; - unsigned int data_len, cmd, t_val; - - if (!(STATUS_HAS_MEDIA & readl(host->addr + STATUS))) { - dev_dbg(msh->cdev.dev, "no media status\n"); - host->req->error = -ETIME; - return host->req->error; - } - - dev_dbg(msh->cdev.dev, "control %08x\n", - readl(host->addr + HOST_CONTROL)); - dev_dbg(msh->cdev.dev, "status %08x\n", readl(host->addr + INT_STATUS)); - dev_dbg(msh->cdev.dev, "hstatus %08x\n", readl(host->addr + STATUS)); - - host->cmd_flags = 0; - host->block_pos = 0; - host->io_pos = 0; - host->io_word[0] = 0; - host->io_word[1] = 0; - - cmd = host->req->tpc << 16; - cmd |= TPC_DATA_SEL; - - if (host->req->data_dir == READ) - 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 (host->req->long_data) { - data_len = host->req->sg.length; - } else { - data_len = host->req->data_len; - host->use_dma = 0; - } - - if (data_len <= 8) { - cmd &= ~(TPC_DATA_SEL | 0xf); - host->cmd_flags |= REG_DATA; - cmd |= data_len & 0xf; - host->use_dma = 0; - } - - if (host->use_dma) { - if (1 != pci_map_sg(host->chip->pdev, &host->req->sg, 1, - host->req->data_dir == READ - ? PCI_DMA_FROMDEVICE - : PCI_DMA_TODEVICE)) { - host->req->error = -ENOMEM; - return host->req->error; - } - data_len = sg_dma_len(&host->req->sg); - writel(sg_dma_address(&host->req->sg), - host->addr + DMA_ADDRESS); - writel(((1 << 16) & BLOCK_COUNT_MASK) - | (data_len & BLOCK_SIZE_MASK), - host->addr + BLOCK); - writel(DMA_CONTROL_ENABLE, host->addr + DMA_CONTROL); - } else if (!(host->cmd_flags & REG_DATA)) { - writel(((1 << 16) & BLOCK_COUNT_MASK) - | (data_len & BLOCK_SIZE_MASK), - host->addr + BLOCK); - t_val = readl(host->addr + INT_STATUS_ENABLE); - t_val |= host->req->data_dir == READ - ? INT_STATUS_FIFO_RRDY - : INT_STATUS_FIFO_WRDY; - - writel(t_val, host->addr + INT_STATUS_ENABLE); - writel(t_val, host->addr + INT_SIGNAL_ENABLE); - } else { - cmd &= ~(TPC_DATA_SEL | 0xf); - host->cmd_flags |= REG_DATA; - cmd |= data_len & 0xf; - - if (host->req->data_dir == WRITE) { - jmb38x_ms_transfer_data(host); - writel(host->io_word[0], host->addr + TPC_P0); - writel(host->io_word[1], host->addr + TPC_P1); - } - } - - mod_timer(&host->timer, jiffies + host->timeout_jiffies); - writel(HOST_CONTROL_LED | readl(host->addr + HOST_CONTROL), - host->addr + HOST_CONTROL); - host->req->error = 0; - - writel(cmd, host->addr + TPC); - dev_dbg(msh->cdev.dev, "executing TPC %08x, len %x\n", cmd, data_len); - - return 0; -} - -static void jmb38x_ms_complete_cmd(struct memstick_host *msh, int last) -{ - struct jmb38x_ms_host *host = memstick_priv(msh); - unsigned int t_val = 0; - int rc; - - del_timer(&host->timer); - - dev_dbg(msh->cdev.dev, "c control %08x\n", - readl(host->addr + HOST_CONTROL)); - dev_dbg(msh->cdev.dev, "c status %08x\n", - 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); - } - - if (host->use_dma) { - writel(0, host->addr + DMA_CONTROL); - pci_unmap_sg(host->chip->pdev, &host->req->sg, 1, - host->req->data_dir == READ - ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); - } else { - t_val = readl(host->addr + INT_STATUS_ENABLE); - if (host->req->data_dir == READ) - t_val &= ~INT_STATUS_FIFO_RRDY; - else - t_val &= ~INT_STATUS_FIFO_WRDY; - - writel(t_val, host->addr + INT_STATUS_ENABLE); - writel(t_val, host->addr + INT_SIGNAL_ENABLE); - } - - writel((~HOST_CONTROL_LED) & readl(host->addr + HOST_CONTROL), - host->addr + HOST_CONTROL); - - if (!last) { - do { - rc = memstick_next_req(msh, &host->req); - } while (!rc && jmb38x_ms_issue_cmd(msh)); - } else { - do { - rc = memstick_next_req(msh, &host->req); - if (!rc) - host->req->error = -ETIME; - } while (!rc); - } -} - -static irqreturn_t jmb38x_ms_isr(int irq, void *dev_id) -{ - struct memstick_host *msh = dev_id; - struct jmb38x_ms_host *host = memstick_priv(msh); - unsigned int irq_status; - - spin_lock(&host->lock); - irq_status = readl(host->addr + INT_STATUS); - dev_dbg(&host->chip->pdev->dev, "irq_status = %08x\n", irq_status); - if (irq_status == 0 || irq_status == (~0)) { - spin_unlock(&host->lock); - return IRQ_NONE; - } - - if (host->req) { - if (irq_status & INT_STATUS_ANY_ERR) { - if (irq_status & INT_STATUS_CRC_ERR) - host->req->error = -EILSEQ; - else - host->req->error = -ETIME; - } else { - if (host->use_dma) { - if (irq_status & INT_STATUS_EOTRAN) - host->cmd_flags |= FIFO_READY; - } else { - if (irq_status & (INT_STATUS_FIFO_RRDY - | INT_STATUS_FIFO_WRDY)) - jmb38x_ms_transfer_data(host); - - if (irq_status & INT_STATUS_EOTRAN) { - jmb38x_ms_transfer_data(host); - host->cmd_flags |= FIFO_READY; - } - } - - if (irq_status & INT_STATUS_EOTPC) { - host->cmd_flags |= CMD_READY; - if (host->cmd_flags & REG_DATA) { - if (host->req->data_dir == READ) { - host->io_word[0] - = readl(host->addr - + TPC_P0); - host->io_word[1] - = readl(host->addr - + TPC_P1); - host->io_pos = 8; - - jmb38x_ms_transfer_data(host); - } - host->cmd_flags |= FIFO_READY; - } - } - } - } - - if (irq_status & (INT_STATUS_MEDIA_IN | INT_STATUS_MEDIA_OUT)) { - dev_dbg(&host->chip->pdev->dev, "media changed\n"); - memstick_detect_change(msh); - } - - writel(irq_status, host->addr + INT_STATUS); - - if (host->req - && (((host->cmd_flags & CMD_READY) - && (host->cmd_flags & FIFO_READY)) - || host->req->error)) - jmb38x_ms_complete_cmd(msh, 0); - - spin_unlock(&host->lock); - return IRQ_HANDLED; -} - -static void jmb38x_ms_abort(unsigned long data) -{ - struct memstick_host *msh = (struct memstick_host *)data; - struct jmb38x_ms_host *host = memstick_priv(msh); - unsigned long flags; - - dev_dbg(&host->chip->pdev->dev, "abort\n"); - spin_lock_irqsave(&host->lock, flags); - if (host->req) { - host->req->error = -ETIME; - jmb38x_ms_complete_cmd(msh, 0); - } - spin_unlock_irqrestore(&host->lock, flags); -} - -static void jmb38x_ms_request(struct memstick_host *msh) -{ - struct jmb38x_ms_host *host = memstick_priv(msh); - unsigned long flags; - int rc; - - spin_lock_irqsave(&host->lock, flags); - if (host->req) { - spin_unlock_irqrestore(&host->lock, flags); - BUG(); - return; - } - - do { - rc = memstick_next_req(msh, &host->req); - } while (!rc && jmb38x_ms_issue_cmd(msh)); - spin_unlock_irqrestore(&host->lock, flags); -} - -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); - - while (HOST_CONTROL_RESET_REQ - & (host_ctl = readl(host->addr + HOST_CONTROL))) { - ndelay(100); - dev_dbg(&host->chip->pdev->dev, "reset\n"); - } - - writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE); - writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE); - - dev_dbg(&host->chip->pdev->dev, "reset\n"); -} - -static void jmb38x_ms_set_param(struct memstick_host *msh, - enum memstick_param param, - int value) -{ - struct jmb38x_ms_host *host = memstick_priv(msh); - unsigned int host_ctl; - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); - - switch (param) { - case MEMSTICK_POWER: - if (value == MEMSTICK_POWER_ON) { - jmb38x_ms_reset(host); - - writel(host->id ? PAD_PU_PD_ON_MS_SOCK1 - : 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); - - 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); - 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); - } 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); - } 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); - } - writel(host_ctl, host->addr + HOST_CONTROL); - break; - }; - - spin_unlock_irqrestore(&host->lock, flags); -} - -#ifdef CONFIG_PM - -static int jmb38x_ms_suspend(struct pci_dev *dev, pm_message_t state) -{ - struct jmb38x_ms *jm = pci_get_drvdata(dev); - int cnt; - - for (cnt = 0; cnt < jm->host_cnt; ++cnt) { - if (!jm->hosts[cnt]) - break; - memstick_suspend_host(jm->hosts[cnt]); - } - - pci_save_state(dev); - pci_enable_wake(dev, pci_choose_state(dev, state), 0); - pci_disable_device(dev); - pci_set_power_state(dev, pci_choose_state(dev, state)); - return 0; -} - -static int jmb38x_ms_resume(struct pci_dev *dev) -{ - struct jmb38x_ms *jm = pci_get_drvdata(dev); - int rc; - - pci_set_power_state(dev, PCI_D0); - pci_restore_state(dev); - rc = pci_enable_device(dev); - if (rc) - return rc; - pci_set_master(dev); - - pci_read_config_dword(dev, 0xac, &rc); - pci_write_config_dword(dev, 0xac, rc | 0x00470000); - - for (rc = 0; rc < jm->host_cnt; ++rc) { - if (!jm->hosts[rc]) - break; - memstick_resume_host(jm->hosts[rc]); - memstick_detect_change(jm->hosts[rc]); - } - - return 0; -} - -#else - -#define jmb38x_ms_suspend NULL -#define jmb38x_ms_resume NULL - -#endif /* CONFIG_PM */ - -static int jmb38x_ms_count_slots(struct pci_dev *pdev) -{ - int cnt, rc = 0; - - for (cnt = 0; cnt < PCI_ROM_RESOURCE; ++cnt) { - if (!(IORESOURCE_MEM & pci_resource_flags(pdev, cnt))) - break; - - if (256 != pci_resource_len(pdev, cnt)) - break; - - ++rc; - } - return rc; -} - -static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt) -{ - struct memstick_host *msh; - struct jmb38x_ms_host *host; - - msh = memstick_alloc_host(sizeof(struct jmb38x_ms_host), - &jm->pdev->dev); - if (!msh) - return NULL; - - host = memstick_priv(msh); - host->chip = jm; - host->addr = ioremap(pci_resource_start(jm->pdev, cnt), - pci_resource_len(jm->pdev, cnt)); - if (!host->addr) - goto err_out_free; - - spin_lock_init(&host->lock); - host->id = 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); - 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); - - if (!request_irq(host->irq, jmb38x_ms_isr, IRQF_SHARED, host->host_id, - msh)) - return msh; - - iounmap(host->addr); -err_out_free: - kfree(msh); - return NULL; -} - -static void jmb38x_ms_free_host(struct memstick_host *msh) -{ - struct jmb38x_ms_host *host = memstick_priv(msh); - - free_irq(host->irq, msh); - iounmap(host->addr); - memstick_free_host(msh); -} - -static int jmb38x_ms_probe(struct pci_dev *pdev, - const struct pci_device_id *dev_id) -{ - struct jmb38x_ms *jm; - int pci_dev_busy = 0; - int rc, cnt; - - rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (rc) - return rc; - - rc = pci_enable_device(pdev); - if (rc) - return rc; - - pci_set_master(pdev); - - rc = pci_request_regions(pdev, DRIVER_NAME); - if (rc) { - pci_dev_busy = 1; - goto err_out; - } - - pci_read_config_dword(pdev, 0xac, &rc); - pci_write_config_dword(pdev, 0xac, rc | 0x00470000); - - cnt = jmb38x_ms_count_slots(pdev); - if (!cnt) { - rc = -ENODEV; - pci_dev_busy = 1; - goto err_out; - } - - jm = kzalloc(sizeof(struct jmb38x_ms) - + cnt * sizeof(struct memstick_host *), GFP_KERNEL); - if (!jm) { - rc = -ENOMEM; - goto err_out_int; - } - - jm->pdev = pdev; - jm->host_cnt = cnt; - pci_set_drvdata(pdev, jm); - - for (cnt = 0; cnt < jm->host_cnt; ++cnt) { - jm->hosts[cnt] = jmb38x_ms_alloc_host(jm, cnt); - if (!jm->hosts[cnt]) - break; - - rc = memstick_add_host(jm->hosts[cnt]); - - if (rc) { - jmb38x_ms_free_host(jm->hosts[cnt]); - jm->hosts[cnt] = NULL; - break; - } - } - - if (cnt) - return 0; - - rc = -ENODEV; - - pci_set_drvdata(pdev, NULL); - kfree(jm); -err_out_int: - pci_release_regions(pdev); -err_out: - if (!pci_dev_busy) - pci_disable_device(pdev); - return rc; -} - -static void jmb38x_ms_remove(struct pci_dev *dev) -{ - struct jmb38x_ms *jm = pci_get_drvdata(dev); - struct jmb38x_ms_host *host; - int cnt; - unsigned long flags; - - for (cnt = 0; cnt < jm->host_cnt; ++cnt) { - if (!jm->hosts[cnt]) - break; - - host = memstick_priv(jm->hosts[cnt]); - - writel(0, host->addr + INT_SIGNAL_ENABLE); - writel(0, host->addr + INT_STATUS_ENABLE); - mmiowb(); - dev_dbg(&jm->pdev->dev, "interrupts off\n"); - spin_lock_irqsave(&host->lock, flags); - if (host->req) { - host->req->error = -ETIME; - jmb38x_ms_complete_cmd(jm->hosts[cnt], 1); - } - spin_unlock_irqrestore(&host->lock, flags); - - memstick_remove_host(jm->hosts[cnt]); - dev_dbg(&jm->pdev->dev, "host removed\n"); - - jmb38x_ms_free_host(jm->hosts[cnt]); - } - - pci_set_drvdata(dev, NULL); - pci_release_regions(dev); - pci_disable_device(dev); - kfree(jm); -} - -static struct pci_device_id jmb38x_ms_id_tbl [] = { - { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_MS, PCI_ANY_ID, - PCI_ANY_ID, 0, 0, 0 }, - { } -}; - -static struct pci_driver jmb38x_ms_driver = { - .name = DRIVER_NAME, - .id_table = jmb38x_ms_id_tbl, - .probe = jmb38x_ms_probe, - .remove = jmb38x_ms_remove, - .suspend = jmb38x_ms_suspend, - .resume = jmb38x_ms_resume -}; - -static int __init jmb38x_ms_init(void) -{ - return pci_register_driver(&jmb38x_ms_driver); -} - -static void __exit jmb38x_ms_exit(void) -{ - pci_unregister_driver(&jmb38x_ms_driver); -} - -MODULE_AUTHOR("Alex Dubov"); -MODULE_DESCRIPTION("JMicron jmb38x MemoryStick driver"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, jmb38x_ms_id_tbl); - -module_init(jmb38x_ms_init); -module_exit(jmb38x_ms_exit); diff --git a/trunk/drivers/memstick/host/tifm_ms.c b/trunk/drivers/memstick/host/tifm_ms.c index 2b5bf52a8302..4fb24215bd95 100644 --- a/trunk/drivers/memstick/host/tifm_ms.c +++ b/trunk/drivers/memstick/host/tifm_ms.c @@ -20,315 +20,293 @@ #include #define DRIVER_NAME "tifm_ms" +#define DRIVER_VERSION "0.1" static int no_dma; module_param(no_dma, bool, 0644); -/* - * Some control bits of TIFM appear to conform to Sony's reference design, - * so I'm just assuming they all are. - */ +#define TIFM_MS_TIMEOUT 0x00100 +#define TIFM_MS_BADCRC 0x00200 +#define TIFM_MS_EOTPC 0x01000 +#define TIFM_MS_INT 0x02000 -#define TIFM_MS_STAT_DRQ 0x04000 -#define TIFM_MS_STAT_MSINT 0x02000 -#define TIFM_MS_STAT_RDY 0x01000 -#define TIFM_MS_STAT_CRC 0x00200 -#define TIFM_MS_STAT_TOE 0x00100 -#define TIFM_MS_STAT_EMP 0x00020 -#define TIFM_MS_STAT_FUL 0x00010 -#define TIFM_MS_STAT_CED 0x00008 -#define TIFM_MS_STAT_ERR 0x00004 -#define TIFM_MS_STAT_BRQ 0x00002 -#define TIFM_MS_STAT_CNK 0x00001 - -#define TIFM_MS_SYS_DMA 0x10000 -#define TIFM_MS_SYS_RESET 0x08000 -#define TIFM_MS_SYS_SRAC 0x04000 -#define TIFM_MS_SYS_INTEN 0x02000 -#define TIFM_MS_SYS_NOCRC 0x01000 -#define TIFM_MS_SYS_INTCLR 0x00800 -#define TIFM_MS_SYS_MSIEN 0x00400 -#define TIFM_MS_SYS_FCLR 0x00200 -#define TIFM_MS_SYS_FDIR 0x00100 -#define TIFM_MS_SYS_DAM 0x00080 -#define TIFM_MS_SYS_DRM 0x00040 -#define TIFM_MS_SYS_DRQSL 0x00020 -#define TIFM_MS_SYS_REI 0x00010 -#define TIFM_MS_SYS_REO 0x00008 -#define TIFM_MS_SYS_BSY_MASK 0x00007 - -#define TIFM_MS_SYS_FIFO (TIFM_MS_SYS_INTEN | TIFM_MS_SYS_MSIEN \ - | TIFM_MS_SYS_FCLR | TIFM_MS_SYS_BSY_MASK) +/* The meaning of the bit majority in this constant is unknown. */ +#define TIFM_MS_SERIAL 0x04010 + +#define TIFM_MS_SYS_LATCH 0x00100 +#define TIFM_MS_SYS_NOT_RDY 0x00800 +#define TIFM_MS_SYS_DATA 0x10000 /* Hardware flags */ enum { - CMD_READY = 0x01, - FIFO_READY = 0x02, - CARD_INT = 0x04 + CMD_READY = 0x0001, + FIFO_READY = 0x0002, + CARD_READY = 0x0004, + DATA_CARRY = 0x0008 }; struct tifm_ms { struct tifm_dev *dev; - struct timer_list timer; - struct memstick_request *req; + unsigned short eject:1, + no_dma:1; + unsigned short cmd_flags; unsigned int mode_mask; unsigned int block_pos; unsigned long timeout_jiffies; - unsigned char eject:1, - use_dma:1; - unsigned char cmd_flags; - unsigned char io_pos; + + struct timer_list timer; + struct memstick_request *req; unsigned int io_word; }; -static unsigned int tifm_ms_read_data(struct tifm_ms *host, - unsigned char *buf, unsigned int length) +static void tifm_ms_read_fifo(struct tifm_ms *host, unsigned int fifo_offset, + struct page *pg, unsigned int page_off, + unsigned int length) { struct tifm_dev *sock = host->dev; - unsigned int off = 0; - - while (host->io_pos && length) { - buf[off++] = host->io_word & 0xff; - host->io_word >>= 8; - length--; - host->io_pos--; - } + unsigned int cnt = 0, off = 0; + unsigned char *buf = kmap_atomic(pg, KM_BIO_DST_IRQ) + page_off; - if (!length) - return off; - - while (!(TIFM_MS_STAT_EMP & readl(sock->addr + SOCK_MS_STATUS))) { - if (length < 4) - break; - *(unsigned int *)(buf + off) = __raw_readl(sock->addr - + SOCK_MS_DATA); - length -= 4; - off += 4; - } - - if (length - && !(TIFM_MS_STAT_EMP & readl(sock->addr + SOCK_MS_STATUS))) { - host->io_word = readl(sock->addr + SOCK_MS_DATA); - for (host->io_pos = 4; host->io_pos; --host->io_pos) { + if (host->cmd_flags & DATA_CARRY) { + while ((fifo_offset & 3) && length) { buf[off++] = host->io_word & 0xff; host->io_word >>= 8; length--; - if (!length) - break; + fifo_offset++; } + if (!(fifo_offset & 3)) + host->cmd_flags &= ~DATA_CARRY; + if (!length) + return; } - return off; + do { + host->io_word = readl(sock->addr + SOCK_FIFO_ACCESS + + fifo_offset); + cnt = 4; + while (length && cnt) { + buf[off++] = (host->io_word >> 8) & 0xff; + cnt--; + length--; + } + fifo_offset += 4 - cnt; + } while (length); + + if (cnt) + host->cmd_flags |= DATA_CARRY; + + kunmap_atomic(buf - page_off, KM_BIO_DST_IRQ); } -static unsigned int tifm_ms_write_data(struct tifm_ms *host, - unsigned char *buf, unsigned int length) +static void tifm_ms_write_fifo(struct tifm_ms *host, unsigned int fifo_offset, + struct page *pg, unsigned int page_off, + unsigned int length) { struct tifm_dev *sock = host->dev; - unsigned int off = 0; + unsigned int cnt = 0, off = 0; + unsigned char *buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + page_off; - if (host->io_pos) { - while (host->io_pos < 4 && length) { - host->io_word |= buf[off++] << (host->io_pos * 8); - host->io_pos++; + if (host->cmd_flags & DATA_CARRY) { + while (fifo_offset & 3) { + host->io_word |= buf[off++] << (8 * (fifo_offset & 3)); length--; + fifo_offset++; } + if (!(fifo_offset & 3)) { + writel(host->io_word, sock->addr + SOCK_FIFO_ACCESS + + fifo_offset - 4); + + host->cmd_flags &= ~DATA_CARRY; + } + if (!length) + return; } - if (host->io_pos == 4 - && !(TIFM_MS_STAT_FUL & readl(sock->addr + SOCK_MS_STATUS))) { - writel(TIFM_MS_SYS_FDIR | readl(sock->addr + SOCK_MS_SYSTEM), - sock->addr + SOCK_MS_SYSTEM); - writel(host->io_word, sock->addr + SOCK_MS_DATA); - host->io_pos = 0; + do { + cnt = 4; host->io_word = 0; - } else if (host->io_pos) { - return off; - } + while (length && cnt) { + host->io_word |= buf[off++] << (4 - cnt); + cnt--; + length--; + } + fifo_offset += 4 - cnt; + if (!cnt) + writel(host->io_word, sock->addr + SOCK_FIFO_ACCESS + + fifo_offset - 4); - if (!length) - return off; + } while (length); - while (!(TIFM_MS_STAT_FUL & readl(sock->addr + SOCK_MS_STATUS))) { - if (length < 4) - break; - writel(TIFM_MS_SYS_FDIR | readl(sock->addr + SOCK_MS_SYSTEM), - sock->addr + SOCK_MS_SYSTEM); - __raw_writel(*(unsigned int *)(buf + off), - sock->addr + SOCK_MS_DATA); - length -= 4; - off += 4; - } + if (cnt) + host->cmd_flags |= DATA_CARRY; - switch (length) { - case 3: - host->io_word |= buf[off + 2] << 16; - host->io_pos++; - case 2: - host->io_word |= buf[off + 1] << 8; - host->io_pos++; - case 1: - host->io_word |= buf[off]; - host->io_pos++; - } + kunmap_atomic(buf - page_off, KM_BIO_SRC_IRQ); +} + +static void tifm_ms_move_block(struct tifm_ms *host, unsigned int length) +{ + unsigned int t_size; + unsigned int off = host->req->sg.offset + host->block_pos; + unsigned int p_off, p_cnt; + struct page *pg; + unsigned long flags; + + dev_dbg(&host->dev->dev, "moving block\n"); + local_irq_save(flags); + t_size = length; + while (t_size) { + pg = nth_page(sg_page(&host->req->sg), off >> PAGE_SHIFT); + p_off = offset_in_page(off); + p_cnt = PAGE_SIZE - p_off; + p_cnt = min(p_cnt, t_size); - off += host->io_pos; + if (host->req->data_dir == WRITE) + tifm_ms_write_fifo(host, length - t_size, + pg, p_off, p_cnt); + else + tifm_ms_read_fifo(host, length - t_size, + pg, p_off, p_cnt); - return off; + t_size -= p_cnt; + } + local_irq_restore(flags); } -static unsigned int tifm_ms_transfer_data(struct tifm_ms *host) +static int tifm_ms_transfer_data(struct tifm_ms *host, int skip) { struct tifm_dev *sock = host->dev; - unsigned int length; - unsigned int off; - unsigned int t_size, p_off, p_cnt; - unsigned char *buf; - struct page *pg; - unsigned long flags = 0; - - if (host->req->long_data) { - length = host->req->sg.length - host->block_pos; - off = host->req->sg.offset + host->block_pos; - } else { - length = host->req->data_len - host->block_pos; - off = 0; - } - dev_dbg(&sock->dev, "fifo data transfer, %d, %d\n", length, - host->block_pos); - - while (length) { - if (host->req->long_data) { - pg = nth_page(sg_page(&host->req->sg), - off >> PAGE_SHIFT); - p_off = offset_in_page(off); - p_cnt = PAGE_SIZE - p_off; - p_cnt = min(p_cnt, length); - - local_irq_save(flags); - buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + p_off; - } else { - buf = host->req->data + host->block_pos; - p_cnt = host->req->data_len - host->block_pos; - } + unsigned int length = host->req->sg.length - host->block_pos; - t_size = host->req->data_dir == WRITE - ? tifm_ms_write_data(host, buf, p_cnt) - : tifm_ms_read_data(host, buf, p_cnt); + if (!length) + return 1; - if (host->req->long_data) { - kunmap_atomic(buf - p_off, KM_BIO_SRC_IRQ); - local_irq_restore(flags); - } + if (length > TIFM_FIFO_SIZE) + length = TIFM_FIFO_SIZE; - if (!t_size) - break; - host->block_pos += t_size; - length -= t_size; - off += t_size; + if (!skip) { + tifm_ms_move_block(host, length); + host->block_pos += length; } - dev_dbg(&sock->dev, "fifo data transfer, %d remaining\n", length); - if (!length && (host->req->data_dir == WRITE)) { - if (host->io_pos) { - writel(TIFM_MS_SYS_FDIR - | readl(sock->addr + SOCK_MS_SYSTEM), - sock->addr + SOCK_MS_SYSTEM); - writel(host->io_word, sock->addr + SOCK_MS_DATA); - } - writel(TIFM_MS_SYS_FDIR - | readl(sock->addr + SOCK_MS_SYSTEM), - sock->addr + SOCK_MS_SYSTEM); - writel(0, sock->addr + SOCK_MS_DATA); - } else { - readl(sock->addr + SOCK_MS_DATA); - } + if ((host->req->data_dir == READ) + && (host->block_pos == host->req->sg.length)) + return 1; + + writel(ilog2(length) - 2, sock->addr + SOCK_FIFO_PAGE_SIZE); + if (host->req->data_dir == WRITE) + writel((1 << 8) | TIFM_DMA_TX, sock->addr + SOCK_DMA_CONTROL); + else + writel((1 << 8), sock->addr + SOCK_DMA_CONTROL); - return length; + return 0; } static int tifm_ms_issue_cmd(struct tifm_ms *host) { struct tifm_dev *sock = host->dev; unsigned char *data; - unsigned int data_len, cmd, sys_param; + unsigned int data_len = 0, cmd = 0, cmd_mask = 0, cnt, tval = 0; host->cmd_flags = 0; - host->block_pos = 0; - host->io_pos = 0; - host->io_word = 0; - host->cmd_flags = 0; - - data = host->req->data; - host->use_dma = !no_dma; + if (host->req->io_type == MEMSTICK_IO_SG) { + if (!host->no_dma) { + if (1 != tifm_map_sg(sock, &host->req->sg, 1, + host->req->data_dir == READ + ? PCI_DMA_FROMDEVICE + : PCI_DMA_TODEVICE)) { + host->req->error = -ENOMEM; + return host->req->error; + } + data_len = sg_dma_len(&host->req->sg); + } else + data_len = host->req->sg.length; - if (host->req->long_data) { - data_len = host->req->sg.length; - if (!is_power_of_2(data_len)) - host->use_dma = 0; - } else { - data_len = host->req->data_len; - host->use_dma = 0; - } + writel(TIFM_FIFO_INT_SETALL, + sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); + writel(TIFM_FIFO_ENABLE, + sock->addr + SOCK_FIFO_CONTROL); + writel(TIFM_FIFO_INTMASK, + sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); - writel(TIFM_FIFO_INT_SETALL, - sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); - writel(TIFM_FIFO_ENABLE, - sock->addr + SOCK_FIFO_CONTROL); - - if (host->use_dma) { - if (1 != tifm_map_sg(sock, &host->req->sg, 1, - host->req->data_dir == READ - ? PCI_DMA_FROMDEVICE - : PCI_DMA_TODEVICE)) { - host->req->error = -ENOMEM; - return host->req->error; + if (!host->no_dma) { + writel(ilog2(data_len) - 2, + sock->addr + SOCK_FIFO_PAGE_SIZE); + writel(sg_dma_address(&host->req->sg), + sock->addr + SOCK_DMA_ADDRESS); + if (host->req->data_dir == WRITE) + writel((1 << 8) | TIFM_DMA_TX | TIFM_DMA_EN, + sock->addr + SOCK_DMA_CONTROL); + else + writel((1 << 8) | TIFM_DMA_EN, + sock->addr + SOCK_DMA_CONTROL); + } else { + tifm_ms_transfer_data(host, + host->req->data_dir == READ); } - data_len = sg_dma_len(&host->req->sg); - writel(ilog2(data_len) - 2, - sock->addr + SOCK_FIFO_PAGE_SIZE); - writel(TIFM_FIFO_INTMASK, - sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); - sys_param = TIFM_DMA_EN | (1 << 8); - if (host->req->data_dir == WRITE) - sys_param |= TIFM_DMA_TX; + cmd_mask = readl(sock->addr + SOCK_MS_SYSTEM); + cmd_mask |= TIFM_MS_SYS_DATA | TIFM_MS_SYS_NOT_RDY; + writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM); + } else if (host->req->io_type == MEMSTICK_IO_VAL) { + data = host->req->data; + data_len = host->req->data_len; - writel(TIFM_FIFO_INTMASK, - sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); + cmd_mask = host->mode_mask | 0x2607; /* unknown constant */ + + if (host->req->data_dir == WRITE) { + cmd_mask |= TIFM_MS_SYS_LATCH; + writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM); + for (cnt = 0; (data_len - cnt) >= 4; cnt += 4) { + writel(TIFM_MS_SYS_LATCH + | readl(sock->addr + SOCK_MS_SYSTEM), + sock->addr + SOCK_MS_SYSTEM); + __raw_writel(*(unsigned int *)(data + cnt), + sock->addr + SOCK_MS_DATA); + dev_dbg(&sock->dev, "writing %x\n", + *(int *)(data + cnt)); + } + switch (data_len - cnt) { + case 3: + tval |= data[cnt + 2] << 16; + case 2: + tval |= data[cnt + 1] << 8; + case 1: + tval |= data[cnt]; + writel(TIFM_MS_SYS_LATCH + | readl(sock->addr + SOCK_MS_SYSTEM), + sock->addr + SOCK_MS_SYSTEM); + writel(tval, sock->addr + SOCK_MS_DATA); + dev_dbg(&sock->dev, "writing %x\n", tval); + } - writel(sg_dma_address(&host->req->sg), - sock->addr + SOCK_DMA_ADDRESS); - writel(sys_param, sock->addr + SOCK_DMA_CONTROL); - } else { - writel(host->mode_mask | TIFM_MS_SYS_FIFO, - sock->addr + SOCK_MS_SYSTEM); + writel(TIFM_MS_SYS_LATCH + | readl(sock->addr + SOCK_MS_SYSTEM), + sock->addr + SOCK_MS_SYSTEM); + writel(0, sock->addr + SOCK_MS_DATA); + dev_dbg(&sock->dev, "writing %x\n", 0); - writel(TIFM_FIFO_MORE, - sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); - } + } else + writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM); + + cmd_mask = readl(sock->addr + SOCK_MS_SYSTEM); + cmd_mask &= ~TIFM_MS_SYS_DATA; + cmd_mask |= TIFM_MS_SYS_NOT_RDY; + dev_dbg(&sock->dev, "mask %x\n", cmd_mask); + writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM); + } else + BUG(); mod_timer(&host->timer, jiffies + host->timeout_jiffies); writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL), sock->addr + SOCK_CONTROL); host->req->error = 0; - sys_param = readl(sock->addr + SOCK_MS_SYSTEM); - sys_param |= TIFM_MS_SYS_INTCLR; - - if (host->use_dma) - sys_param |= TIFM_MS_SYS_DMA; - else - sys_param &= ~TIFM_MS_SYS_DMA; - - writel(sys_param, sock->addr + SOCK_MS_SYSTEM); - cmd = (host->req->tpc & 0xf) << 12; cmd |= data_len; writel(cmd, sock->addr + SOCK_MS_COMMAND); - dev_dbg(&sock->dev, "executing TPC %x, %x\n", cmd, sys_param); + dev_dbg(&sock->dev, "executing TPC %x, %x\n", cmd, cmd_mask); return 0; } @@ -336,20 +314,47 @@ static void tifm_ms_complete_cmd(struct tifm_ms *host) { struct tifm_dev *sock = host->dev; struct memstick_host *msh = tifm_get_drvdata(sock); + unsigned int tval = 0, data_len; + unsigned char *data; int rc; del_timer(&host->timer); + if (host->req->io_type == MEMSTICK_IO_SG) { + if (!host->no_dma) + tifm_unmap_sg(sock, &host->req->sg, 1, + host->req->data_dir == READ + ? PCI_DMA_FROMDEVICE + : PCI_DMA_TODEVICE); + } else if (host->req->io_type == MEMSTICK_IO_VAL) { + writel(~TIFM_MS_SYS_DATA & readl(sock->addr + SOCK_MS_SYSTEM), + sock->addr + SOCK_MS_SYSTEM); + + data = host->req->data; + data_len = host->req->data_len; - if (host->use_dma) - tifm_unmap_sg(sock, &host->req->sg, 1, - host->req->data_dir == READ - ? PCI_DMA_FROMDEVICE - : PCI_DMA_TODEVICE); + if (host->req->data_dir == READ) { + for (rc = 0; (data_len - rc) >= 4; rc += 4) + *(int *)(data + rc) + = __raw_readl(sock->addr + + SOCK_MS_DATA); + + if (data_len - rc) + tval = readl(sock->addr + SOCK_MS_DATA); + switch (data_len - rc) { + case 3: + data[rc + 2] = (tval >> 16) & 0xff; + case 2: + data[rc + 1] = (tval >> 8) & 0xff; + case 1: + data[rc] = tval & 0xff; + } + readl(sock->addr + SOCK_MS_DATA); + } + } writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), sock->addr + SOCK_CONTROL); - dev_dbg(&sock->dev, "TPC complete\n"); do { rc = memstick_next_req(msh, &host->req); } while (!rc && tifm_ms_issue_cmd(host)); @@ -360,10 +365,11 @@ static int tifm_ms_check_status(struct tifm_ms *host) if (!host->req->error) { if (!(host->cmd_flags & CMD_READY)) return 1; - if (!(host->cmd_flags & FIFO_READY)) + if ((host->req->io_type == MEMSTICK_IO_SG) + && !(host->cmd_flags & FIFO_READY)) return 1; if (host->req->need_card_int - && !(host->cmd_flags & CARD_INT)) + && !(host->cmd_flags & CARD_READY)) return 1; } return 0; @@ -373,24 +379,18 @@ static int tifm_ms_check_status(struct tifm_ms *host) static void tifm_ms_data_event(struct tifm_dev *sock) { struct tifm_ms *host; - unsigned int fifo_status = 0, host_status = 0; + unsigned int fifo_status = 0; int rc = 1; spin_lock(&sock->lock); host = memstick_priv((struct memstick_host *)tifm_get_drvdata(sock)); fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS); - host_status = readl(sock->addr + SOCK_MS_STATUS); - dev_dbg(&sock->dev, - "data event: fifo_status %x, host_status %x, flags %x\n", - fifo_status, host_status, host->cmd_flags); + dev_dbg(&sock->dev, "data event: fifo_status %x, flags %x\n", + fifo_status, host->cmd_flags); if (host->req) { - if (host->use_dma && (fifo_status & 1)) { - host->cmd_flags |= FIFO_READY; - rc = tifm_ms_check_status(host); - } - if (!host->use_dma && (fifo_status & TIFM_FIFO_MORE)) { - if (!tifm_ms_transfer_data(host)) { + if (fifo_status & TIFM_FIFO_READY) { + if (!host->no_dma || tifm_ms_transfer_data(host, 0)) { host->cmd_flags |= FIFO_READY; rc = tifm_ms_check_status(host); } @@ -419,9 +419,9 @@ static void tifm_ms_card_event(struct tifm_dev *sock) host_status, host->cmd_flags); if (host->req) { - if (host_status & TIFM_MS_STAT_TOE) + if (host_status & TIFM_MS_TIMEOUT) host->req->error = -ETIME; - else if (host_status & TIFM_MS_STAT_CRC) + else if (host_status & TIFM_MS_BADCRC) host->req->error = -EILSEQ; if (host->req->error) { @@ -430,17 +430,18 @@ static void tifm_ms_card_event(struct tifm_dev *sock) writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL); } - if (host_status & TIFM_MS_STAT_RDY) + if (host_status & TIFM_MS_EOTPC) host->cmd_flags |= CMD_READY; - - if (host_status & TIFM_MS_STAT_MSINT) - host->cmd_flags |= CARD_INT; + if (host_status & TIFM_MS_INT) + host->cmd_flags |= CARD_READY; rc = tifm_ms_check_status(host); } - writel(TIFM_MS_SYS_INTCLR | readl(sock->addr + SOCK_MS_SYSTEM), + writel(TIFM_MS_SYS_NOT_RDY | readl(sock->addr + SOCK_MS_SYSTEM), + sock->addr + SOCK_MS_SYSTEM); + writel((~TIFM_MS_SYS_DATA) & readl(sock->addr + SOCK_MS_SYSTEM), sock->addr + SOCK_MS_SYSTEM); if (!rc) @@ -496,26 +497,15 @@ static void tifm_ms_set_param(struct memstick_host *msh, switch (param) { case MEMSTICK_POWER: - /* also affected by media detection mechanism */ - if (value == MEMSTICK_POWER_ON) { - host->mode_mask = TIFM_MS_SYS_SRAC | TIFM_MS_SYS_REI; - writel(TIFM_MS_SYS_RESET, sock->addr + SOCK_MS_SYSTEM); - writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR, - sock->addr + SOCK_MS_SYSTEM); - writel(0xffffffff, sock->addr + SOCK_MS_STATUS); - } else if (value == MEMSTICK_POWER_OFF) { - writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR, - sock->addr + SOCK_MS_SYSTEM); - writel(0xffffffff, sock->addr + SOCK_MS_STATUS); - } + /* this is set by card detection mechanism */ break; case MEMSTICK_INTERFACE: if (value == MEMSTICK_SERIAL) { - host->mode_mask = TIFM_MS_SYS_SRAC | TIFM_MS_SYS_REI; + host->mode_mask = TIFM_MS_SERIAL; writel((~TIFM_CTRL_FAST_CLK) & readl(sock->addr + SOCK_CONTROL), sock->addr + SOCK_CONTROL); - } else if (value == MEMSTICK_PAR4) { + } else if (value == MEMSTICK_PARALLEL) { host->mode_mask = 0; writel(TIFM_CTRL_FAST_CLK | readl(sock->addr + SOCK_CONTROL), @@ -542,6 +532,21 @@ static void tifm_ms_abort(unsigned long data) tifm_eject(host->dev); } +static int tifm_ms_initialize_host(struct tifm_ms *host) +{ + struct tifm_dev *sock = host->dev; + struct memstick_host *msh = tifm_get_drvdata(sock); + + host->mode_mask = TIFM_MS_SERIAL; + writel(0x8000, sock->addr + SOCK_MS_SYSTEM); + writel(0x0200 | TIFM_MS_SYS_NOT_RDY, sock->addr + SOCK_MS_SYSTEM); + writel(0xffffffff, sock->addr + SOCK_MS_STATUS); + if (tifm_has_ms_pif(sock)) + msh->caps |= MEMSTICK_CAP_PARALLEL; + + return 0; +} + static int tifm_ms_probe(struct tifm_dev *sock) { struct memstick_host *msh; @@ -563,6 +568,7 @@ static int tifm_ms_probe(struct tifm_dev *sock) tifm_set_drvdata(sock, msh); host->dev = sock; host->timeout_jiffies = msecs_to_jiffies(1000); + host->no_dma = no_dma; setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host); @@ -570,10 +576,10 @@ static int tifm_ms_probe(struct tifm_dev *sock) msh->set_param = tifm_ms_set_param; sock->card_event = tifm_ms_card_event; sock->data_event = tifm_ms_data_event; - if (tifm_has_ms_pif(sock)) - msh->caps |= MEMSTICK_CAP_PAR4; + rc = tifm_ms_initialize_host(host); - rc = memstick_add_host(msh); + if (!rc) + rc = memstick_add_host(msh); if (!rc) return 0; @@ -595,7 +601,7 @@ static void tifm_ms_remove(struct tifm_dev *sock) 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) + if ((host->req->io_type == MEMSTICK_IO_SG) && !host->no_dma) tifm_unmap_sg(sock, &host->req->sg, 1, host->req->data_dir == READ ? PCI_DMA_TODEVICE @@ -611,6 +617,10 @@ static void tifm_ms_remove(struct tifm_dev *sock) spin_unlock_irqrestore(&sock->lock, flags); memstick_remove_host(msh); + + writel(0x0200 | TIFM_MS_SYS_NOT_RDY, sock->addr + SOCK_MS_SYSTEM); + writel(0xffffffff, sock->addr + SOCK_MS_STATUS); + memstick_free_host(msh); } @@ -618,17 +628,17 @@ static void tifm_ms_remove(struct tifm_dev *sock) static int tifm_ms_suspend(struct tifm_dev *sock, pm_message_t state) { - struct memstick_host *msh = tifm_get_drvdata(sock); - - memstick_suspend_host(msh); return 0; } static int tifm_ms_resume(struct tifm_dev *sock) { struct memstick_host *msh = tifm_get_drvdata(sock); + struct tifm_ms *host = memstick_priv(msh); + + tifm_ms_initialize_host(host); + memstick_detect_change(msh); - memstick_resume_host(msh); return 0; } @@ -669,6 +679,7 @@ MODULE_AUTHOR("Alex Dubov"); MODULE_DESCRIPTION("TI FlashMedia MemoryStick driver"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(tifm, tifm_ms_id_tbl); +MODULE_VERSION(DRIVER_VERSION); module_init(tifm_ms_init); module_exit(tifm_ms_exit); diff --git a/trunk/drivers/misc/tifm_7xx1.c b/trunk/drivers/misc/tifm_7xx1.c index 67503ea71d21..63a089b29545 100644 --- a/trunk/drivers/misc/tifm_7xx1.c +++ b/trunk/drivers/misc/tifm_7xx1.c @@ -367,8 +367,6 @@ static int tifm_7xx1_probe(struct pci_dev *dev, if (rc) goto err_out_irq; - writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), - fm->addr + FM_CLEAR_INTERRUPT_ENABLE); writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), fm->addr + FM_SET_INTERRUPT_ENABLE); return 0; diff --git a/trunk/drivers/serial/of_serial.c b/trunk/drivers/serial/of_serial.c index c0e50a461055..a64d85821996 100644 --- a/trunk/drivers/serial/of_serial.c +++ b/trunk/drivers/serial/of_serial.c @@ -138,7 +138,7 @@ static struct of_device_id __devinitdata of_platform_serial_table[] = { { /* end of list */ }, }; -static struct of_platform_driver of_platform_serial_driver = { +static struct of_platform_driver __devinitdata of_platform_serial_driver = { .owner = THIS_MODULE, .name = "of_serial", .probe = of_platform_serial_probe, diff --git a/trunk/drivers/video/Kconfig b/trunk/drivers/video/Kconfig index e0b0580705e4..758435f8a6f8 100644 --- a/trunk/drivers/video/Kconfig +++ b/trunk/drivers/video/Kconfig @@ -553,19 +553,6 @@ config FB_BF54X_LQ043 help This is the framebuffer device driver for a SHARP LQ043T1DG01 TFT LCD -config FB_BFIN_T350MCQB - tristate "Varitronix COG-T350MCQB TFT LCD display (BF527 EZKIT)" - depends on FB && BLACKFIN - select BFIN_GPTIMERS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the framebuffer device driver for a Varitronix VL-PS-COG-T350MCQB-01 display TFT LCD - This display is a QVGA 320x240 24-bit RGB display interfaced by an 8-bit wide PPI - It uses PPI[0..7] PPI_FS1, PPI_FS2 and PPI_CLK. - - config FB_STI tristate "HP STI frame buffer device support" depends on FB && PARISC diff --git a/trunk/drivers/video/Makefile b/trunk/drivers/video/Makefile index 03371c789039..83e02b3429b6 100644 --- a/trunk/drivers/video/Makefile +++ b/trunk/drivers/video/Makefile @@ -122,7 +122,6 @@ obj-$(CONFIG_FB_EFI) += efifb.o obj-$(CONFIG_FB_VGA16) += vga16fb.o obj-$(CONFIG_FB_OF) += offb.o obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o -obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o # the test framebuffer is last obj-$(CONFIG_FB_VIRTUAL) += vfb.o diff --git a/trunk/drivers/video/bf54x-lq043fb.c b/trunk/drivers/video/bf54x-lq043fb.c index 986a550c0439..0ce791e6f79c 100644 --- a/trunk/drivers/video/bf54x-lq043fb.c +++ b/trunk/drivers/video/bf54x-lq043fb.c @@ -8,7 +8,7 @@ * * * Modified: - * Copyright 2007-2008 Analog Devices Inc. + * Copyright 2004-2007 Analog Devices Inc. * * Bugs: Enter bugs at http://blackfin.uclinux.org/ * @@ -241,7 +241,7 @@ static int request_ports(struct bfin_bf54xfb_info *fbi) u16 eppi_req_18[] = EPPI0_18; u16 disp = fbi->mach_info->disp; - if (gpio_request(disp, DRIVER_NAME)) { + if (gpio_request(disp, NULL)) { printk(KERN_ERR "Requesting GPIO %d faild\n", disp); return -EFAULT; } @@ -672,7 +672,7 @@ static int __init bfin_bf54x_probe(struct platform_device *pdev) &bfin_lq043fb_bl_ops); bl_dev->props.max_brightness = 255; - lcd_dev = lcd_device_register(DRIVER_NAME, &pdev->dev, NULL, &bfin_lcd_ops); + lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops); lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n"); #endif diff --git a/trunk/drivers/video/bfin-t350mcqb-fb.c b/trunk/drivers/video/bfin-t350mcqb-fb.c deleted file mode 100644 index a2bb2de9e020..000000000000 --- a/trunk/drivers/video/bfin-t350mcqb-fb.c +++ /dev/null @@ -1,685 +0,0 @@ -/* - * File: drivers/video/bfin-t350mcqb-fb.c - * Based on: - * Author: Michael Hennerich - * - * Created: - * Description: Blackfin LCD Framebufer driver - * - * - * Modified: - * Copyright 2004-2007 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#define NO_BL_SUPPORT - -#define LCD_X_RES 320 /* Horizontal Resolution */ -#define LCD_Y_RES 240 /* Vertical Resolution */ -#define LCD_BPP 24 /* Bit Per Pixel */ - -#define DMA_BUS_SIZE 16 -#define LCD_CLK (12*1000*1000) /* 12MHz */ - -#define CLOCKS_PER_PIX 3 - - /* - * HS and VS timing parameters (all in number of PPI clk ticks) - */ - -#define U_LINE 1 /* Blanking Lines */ - -#define H_ACTPIX (LCD_X_RES * CLOCKS_PER_PIX) /* active horizontal pixel */ -#define H_PERIOD (408 * CLOCKS_PER_PIX) /* HS period */ -#define H_PULSE 90 /* HS pulse width */ -#define H_START 204 /* first valid pixel */ - -#define V_LINES (LCD_Y_RES + U_LINE) /* total vertical lines */ -#define V_PULSE (3 * H_PERIOD) /* VS pulse width (1-5 H_PERIODs) */ -#define V_PERIOD (H_PERIOD * V_LINES) /* VS period */ - -#define ACTIVE_VIDEO_MEM_OFFSET (U_LINE * H_ACTPIX) - -#define BFIN_LCD_NBR_PALETTE_ENTRIES 256 - -#define DRIVER_NAME "bfin-t350mcqb" -static char driver_name[] = DRIVER_NAME; - -struct bfin_t350mcqbfb_info { - struct fb_info *fb; - struct device *dev; - unsigned char *fb_buffer; /* RGB Buffer */ - dma_addr_t dma_handle; - int lq043_mmap; - int lq043_open_cnt; - int irq; - spinlock_t lock; /* lock */ -}; - -static int nocursor; -module_param(nocursor, int, 0644); -MODULE_PARM_DESC(nocursor, "cursor enable/disable"); - -#define PPI_TX_MODE 0x2 -#define PPI_XFER_TYPE_11 0xC -#define PPI_PORT_CFG_01 0x10 -#define PPI_PACK_EN 0x80 -#define PPI_POLS_1 0x8000 - -static void bfin_t350mcqb_config_ppi(struct bfin_t350mcqbfb_info *fbi) -{ - bfin_write_PPI_DELAY(H_START); - bfin_write_PPI_COUNT(H_ACTPIX-1); - bfin_write_PPI_FRAME(V_LINES); - - bfin_write_PPI_CONTROL(PPI_TX_MODE | /* output mode , PORT_DIR */ - PPI_XFER_TYPE_11 | /* sync mode XFR_TYPE */ - PPI_PORT_CFG_01 | /* two frame sync PORT_CFG */ - PPI_PACK_EN | /* packing enabled PACK_EN */ - PPI_POLS_1); /* faling edge syncs POLS */ -} - -static inline void bfin_t350mcqb_disable_ppi(void) -{ - bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN); -} - -static inline void bfin_t350mcqb_enable_ppi(void) -{ - bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN); -} - -static void bfin_t350mcqb_start_timers(void) -{ - unsigned long flags; - - local_irq_save(flags); - enable_gptimers(TIMER1bit); - enable_gptimers(TIMER0bit); - local_irq_restore(flags); -} - -static void bfin_t350mcqb_stop_timers(void) -{ - disable_gptimers(TIMER0bit | TIMER1bit); - - set_gptimer_status(0, TIMER_STATUS_TRUN0 | TIMER_STATUS_TRUN1 | - TIMER_STATUS_TIMIL0 | TIMER_STATUS_TIMIL1 | - TIMER_STATUS_TOVF0 | TIMER_STATUS_TOVF1); - -} - -static void bfin_t350mcqb_init_timers(void) -{ - - bfin_t350mcqb_stop_timers(); - - set_gptimer_period(TIMER0_id, H_PERIOD); - set_gptimer_pwidth(TIMER0_id, H_PULSE); - set_gptimer_config(TIMER0_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT | - TIMER_TIN_SEL | TIMER_CLK_SEL| - TIMER_EMU_RUN); - - set_gptimer_period(TIMER1_id, V_PERIOD); - set_gptimer_pwidth(TIMER1_id, V_PULSE); - set_gptimer_config(TIMER1_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT | - TIMER_TIN_SEL | TIMER_CLK_SEL | - TIMER_EMU_RUN); - -} - -static void bfin_t350mcqb_config_dma(struct bfin_t350mcqbfb_info *fbi) -{ - - set_dma_config(CH_PPI, - set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO, - INTR_DISABLE, DIMENSION_2D, - DATA_SIZE_16, - DMA_NOSYNC_KEEP_DMA_BUF)); - set_dma_x_count(CH_PPI, (LCD_X_RES * LCD_BPP) / DMA_BUS_SIZE); - set_dma_x_modify(CH_PPI, DMA_BUS_SIZE / 8); - set_dma_y_count(CH_PPI, V_LINES); - - set_dma_y_modify(CH_PPI, DMA_BUS_SIZE / 8); - set_dma_start_addr(CH_PPI, (unsigned long)fbi->fb_buffer); - -} - -static int bfin_t350mcqb_request_ports(int action) -{ - u16 ppi0_req_8[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, - P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, - P_PPI0_D3, P_PPI0_D4, P_PPI0_D5, - P_PPI0_D6, P_PPI0_D7, 0}; - - if (action) { - if (peripheral_request_list(ppi0_req_8, DRIVER_NAME)) { - printk(KERN_ERR "Requesting Peripherals faild\n"); - return -EFAULT; - } - } else - peripheral_free_list(ppi0_req_8); - - return 0; -} - -static int bfin_t350mcqb_fb_open(struct fb_info *info, int user) -{ - struct bfin_t350mcqbfb_info *fbi = info->par; - - spin_lock(&fbi->lock); - fbi->lq043_open_cnt++; - - if (fbi->lq043_open_cnt <= 1) { - - bfin_t350mcqb_disable_ppi(); - SSYNC(); - - bfin_t350mcqb_config_dma(fbi); - bfin_t350mcqb_config_ppi(fbi); - bfin_t350mcqb_init_timers(); - - /* start dma */ - enable_dma(CH_PPI); - bfin_t350mcqb_enable_ppi(); - bfin_t350mcqb_start_timers(); - } - - spin_unlock(&fbi->lock); - - return 0; -} - -static int bfin_t350mcqb_fb_release(struct fb_info *info, int user) -{ - struct bfin_t350mcqbfb_info *fbi = info->par; - - spin_lock(&fbi->lock); - - fbi->lq043_open_cnt--; - fbi->lq043_mmap = 0; - - if (fbi->lq043_open_cnt <= 0) { - bfin_t350mcqb_disable_ppi(); - SSYNC(); - disable_dma(CH_PPI); - bfin_t350mcqb_stop_timers(); - memset(fbi->fb_buffer, 0, info->fix.smem_len); - } - - spin_unlock(&fbi->lock); - - return 0; -} - -static int bfin_t350mcqb_fb_check_var(struct fb_var_screeninfo *var, - struct fb_info *info) -{ - - if (var->bits_per_pixel != LCD_BPP) { - pr_debug("%s: depth not supported: %u BPP\n", __FUNCTION__, - var->bits_per_pixel); - return -EINVAL; - } - - if (info->var.xres != var->xres || info->var.yres != var->yres || - info->var.xres_virtual != var->xres_virtual || - info->var.yres_virtual != var->yres_virtual) { - pr_debug("%s: Resolution not supported: X%u x Y%u \n", - __FUNCTION__, var->xres, var->yres); - return -EINVAL; - } - - /* - * Memory limit - */ - - if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) { - pr_debug("%s: Memory Limit requested yres_virtual = %u\n", - __FUNCTION__, var->yres_virtual); - return -ENOMEM; - } - - return 0; -} - -static int bfin_t350mcqb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) -{ - struct bfin_t350mcqbfb_info *fbi = info->par; - - if (fbi->lq043_mmap) - return -1; - - spin_lock(&fbi->lock); - fbi->lq043_mmap = 1; - spin_unlock(&fbi->lock); - - vma->vm_start = (unsigned long)(fbi->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET); - - vma->vm_end = vma->vm_start + info->fix.smem_len; - /* For those who don't understand how mmap works, go read - * Documentation/nommu-mmap.txt. - * For those that do, you will know that the VM_MAYSHARE flag - * must be set in the vma->vm_flags structure on noMMU - * Other flags can be set, and are documented in - * include/linux/mm.h - */ - vma->vm_flags |= VM_MAYSHARE; - - return 0; -} - -int bfin_t350mcqb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) -{ - if (nocursor) - return 0; - else - return -EINVAL; /* just to force soft_cursor() call */ -} - -static int bfin_t350mcqb_fb_setcolreg(u_int regno, u_int red, u_int green, - u_int blue, u_int transp, - struct fb_info *info) -{ - if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES) - return -EINVAL; - - if (info->var.grayscale) { - /* grayscale = 0.30*R + 0.59*G + 0.11*B */ - red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; - } - - if (info->fix.visual == FB_VISUAL_TRUECOLOR) { - - u32 value; - /* Place color in the pseudopalette */ - if (regno > 16) - return -EINVAL; - - red >>= (16 - info->var.red.length); - green >>= (16 - info->var.green.length); - blue >>= (16 - info->var.blue.length); - - value = (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset); - value &= 0xFFFFFF; - - ((u32 *) (info->pseudo_palette))[regno] = value; - - } - - return 0; -} - -static struct fb_ops bfin_t350mcqb_fb_ops = { - .owner = THIS_MODULE, - .fb_open = bfin_t350mcqb_fb_open, - .fb_release = bfin_t350mcqb_fb_release, - .fb_check_var = bfin_t350mcqb_fb_check_var, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_mmap = bfin_t350mcqb_fb_mmap, - .fb_cursor = bfin_t350mcqb_fb_cursor, - .fb_setcolreg = bfin_t350mcqb_fb_setcolreg, -}; - -#ifndef NO_BL_SUPPORT -static int bl_get_brightness(struct backlight_device *bd) -{ - return 0; -} - -static struct backlight_ops bfin_lq043fb_bl_ops = { - .get_brightness = bl_get_brightness, -}; - -static struct backlight_device *bl_dev; - -static int bfin_lcd_get_power(struct lcd_device *dev) -{ - return 0; -} - -static int bfin_lcd_set_power(struct lcd_device *dev, int power) -{ - return 0; -} - -static int bfin_lcd_get_contrast(struct lcd_device *dev) -{ - return 0; -} - -static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast) -{ - - return 0; -} - -static int bfin_lcd_check_fb(struct fb_info *fi) -{ - if (!fi || (fi == &bfin_t350mcqb_fb)) - return 1; - return 0; -} - -static struct lcd_ops bfin_lcd_ops = { - .get_power = bfin_lcd_get_power, - .set_power = bfin_lcd_set_power, - .get_contrast = bfin_lcd_get_contrast, - .set_contrast = bfin_lcd_set_contrast, - .check_fb = bfin_lcd_check_fb, -}; - -static struct lcd_device *lcd_dev; -#endif - -static irqreturn_t bfin_t350mcqb_irq_error(int irq, void *dev_id) -{ - /*struct bfin_t350mcqbfb_info *info = (struct bfin_t350mcqbfb_info *)dev_id;*/ - - u16 status = bfin_read_PPI_STATUS(); - bfin_write_PPI_STATUS(0xFFFF); - - if (status) { - bfin_t350mcqb_disable_ppi(); - disable_dma(CH_PPI); - - /* start dma */ - enable_dma(CH_PPI); - bfin_t350mcqb_enable_ppi(); - bfin_write_PPI_STATUS(0xFFFF); - } - - return IRQ_HANDLED; -} - -static int __init bfin_t350mcqb_probe(struct platform_device *pdev) -{ - struct bfin_t350mcqbfb_info *info; - struct fb_info *fbinfo; - int ret; - - printk(KERN_INFO DRIVER_NAME ": %dx%d %d-bit RGB FrameBuffer initializing...\n", - LCD_X_RES, LCD_Y_RES, LCD_BPP); - - if (request_dma(CH_PPI, "CH_PPI") < 0) { - printk(KERN_ERR DRIVER_NAME - ": couldn't request CH_PPI DMA\n"); - ret = -EFAULT; - goto out1; - } - - fbinfo = - framebuffer_alloc(sizeof(struct bfin_t350mcqbfb_info), &pdev->dev); - if (!fbinfo) { - ret = -ENOMEM; - goto out2; - } - - info = fbinfo->par; - info->fb = fbinfo; - info->dev = &pdev->dev; - - platform_set_drvdata(pdev, fbinfo); - - strcpy(fbinfo->fix.id, driver_name); - - fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; - fbinfo->fix.type_aux = 0; - fbinfo->fix.xpanstep = 0; - fbinfo->fix.ypanstep = 0; - fbinfo->fix.ywrapstep = 0; - fbinfo->fix.accel = FB_ACCEL_NONE; - fbinfo->fix.visual = FB_VISUAL_TRUECOLOR; - - fbinfo->var.nonstd = 0; - fbinfo->var.activate = FB_ACTIVATE_NOW; - fbinfo->var.height = -1; - fbinfo->var.width = -1; - fbinfo->var.accel_flags = 0; - fbinfo->var.vmode = FB_VMODE_NONINTERLACED; - - fbinfo->var.xres = LCD_X_RES; - fbinfo->var.xres_virtual = LCD_X_RES; - fbinfo->var.yres = LCD_Y_RES; - fbinfo->var.yres_virtual = LCD_Y_RES; - fbinfo->var.bits_per_pixel = LCD_BPP; - - fbinfo->var.red.offset = 0; - fbinfo->var.green.offset = 8; - fbinfo->var.blue.offset = 16; - fbinfo->var.transp.offset = 0; - fbinfo->var.red.length = 8; - fbinfo->var.green.length = 8; - fbinfo->var.blue.length = 8; - fbinfo->var.transp.length = 0; - fbinfo->fix.smem_len = LCD_X_RES * LCD_Y_RES * LCD_BPP / 8; - - fbinfo->fix.line_length = fbinfo->var.xres_virtual * - fbinfo->var.bits_per_pixel / 8; - - - fbinfo->fbops = &bfin_t350mcqb_fb_ops; - fbinfo->flags = FBINFO_FLAG_DEFAULT; - - info->fb_buffer = - dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle, - GFP_KERNEL); - - if (NULL == info->fb_buffer) { - printk(KERN_ERR DRIVER_NAME - ": couldn't allocate dma buffer.\n"); - ret = -ENOMEM; - goto out3; - } - - memset(info->fb_buffer, 0, fbinfo->fix.smem_len); - - fbinfo->screen_base = (void *)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET; - fbinfo->fix.smem_start = (int)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET; - - fbinfo->fbops = &bfin_t350mcqb_fb_ops; - - fbinfo->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL); - if (!fbinfo->pseudo_palette) { - printk(KERN_ERR DRIVER_NAME - "Fail to allocate pseudo_palette\n"); - - ret = -ENOMEM; - goto out4; - } - - memset(fbinfo->pseudo_palette, 0, sizeof(u32) * 16); - - if (fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0) - < 0) { - printk(KERN_ERR DRIVER_NAME - "Fail to allocate colormap (%d entries)\n", - BFIN_LCD_NBR_PALETTE_ENTRIES); - ret = -EFAULT; - goto out5; - } - - if (bfin_t350mcqb_request_ports(1)) { - printk(KERN_ERR DRIVER_NAME ": couldn't request gpio port.\n"); - ret = -EFAULT; - goto out6; - } - - info->irq = platform_get_irq(pdev, 0); - if (info->irq < 0) { - ret = -EINVAL; - goto out7; - } - - if (request_irq(info->irq, (void *)bfin_t350mcqb_irq_error, IRQF_DISABLED, - "PPI ERROR", info) < 0) { - printk(KERN_ERR DRIVER_NAME - ": unable to request PPI ERROR IRQ\n"); - ret = -EFAULT; - goto out7; - } - - if (register_framebuffer(fbinfo) < 0) { - printk(KERN_ERR DRIVER_NAME - ": unable to register framebuffer.\n"); - ret = -EINVAL; - goto out8; - } -#ifndef NO_BL_SUPPORT - bl_dev = - backlight_device_register("bf52x-bl", NULL, NULL, - &bfin_lq043fb_bl_ops); - bl_dev->props.max_brightness = 255; - - lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops); - lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n"); -#endif - - return 0; - -out8: - free_irq(info->irq, info); -out7: - bfin_t350mcqb_request_ports(0); -out6: - fb_dealloc_cmap(&fbinfo->cmap); -out5: - kfree(fbinfo->pseudo_palette); -out4: - dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, - info->dma_handle); -out3: - framebuffer_release(fbinfo); -out2: - free_dma(CH_PPI); -out1: - platform_set_drvdata(pdev, NULL); - - return ret; -} - -static int bfin_t350mcqb_remove(struct platform_device *pdev) -{ - - struct fb_info *fbinfo = platform_get_drvdata(pdev); - struct bfin_t350mcqbfb_info *info = fbinfo->par; - - free_dma(CH_PPI); - free_irq(info->irq, info); - - if (info->fb_buffer != NULL) - dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, - info->dma_handle); - - kfree(fbinfo->pseudo_palette); - fb_dealloc_cmap(&fbinfo->cmap); - -#ifndef NO_BL_SUPPORT - lcd_device_unregister(lcd_dev); - backlight_device_unregister(bl_dev); -#endif - - unregister_framebuffer(fbinfo); - - bfin_t350mcqb_request_ports(0); - - printk(KERN_INFO DRIVER_NAME ": Unregister LCD driver.\n"); - - return 0; -} - -#ifdef CONFIG_PM -static int bfin_t350mcqb_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct fb_info *fbinfo = platform_get_drvdata(pdev); - struct bfin_t350mcqbfb_info *info = fbinfo->par; - - bfin_t350mcqb_disable_ppi(); - disable_dma(CH_PPI); - bfin_write_PPI_STATUS(0xFFFF); - - return 0; -} - -static int bfin_t350mcqb_resume(struct platform_device *pdev) -{ - struct fb_info *fbinfo = platform_get_drvdata(pdev); - struct bfin_t350mcqbfb_info *info = fbinfo->par; - - enable_dma(CH_PPI); - bfin_t350mcqb_enable_ppi(); - - return 0; -} -#else -#define bfin_t350mcqb_suspend NULL -#define bfin_t350mcqb_resume NULL -#endif - -static struct platform_driver bfin_t350mcqb_driver = { - .probe = bfin_t350mcqb_probe, - .remove = bfin_t350mcqb_remove, - .suspend = bfin_t350mcqb_suspend, - .resume = bfin_t350mcqb_resume, - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, -}; - -static int __devinit bfin_t350mcqb_driver_init(void) -{ - return platform_driver_register(&bfin_t350mcqb_driver); -} - -static void __exit bfin_t350mcqb_driver_cleanup(void) -{ - platform_driver_unregister(&bfin_t350mcqb_driver); -} - -MODULE_DESCRIPTION("Blackfin TFT LCD Driver"); -MODULE_LICENSE("GPL"); - -module_init(bfin_t350mcqb_driver_init); -module_exit(bfin_t350mcqb_driver_cleanup); diff --git a/trunk/drivers/video/mbx/mbxfb.c b/trunk/drivers/video/mbx/mbxfb.c index 01f77bcc68f9..80cd117ca65c 100644 --- a/trunk/drivers/video/mbx/mbxfb.c +++ b/trunk/drivers/video/mbx/mbxfb.c @@ -889,7 +889,7 @@ static int __devinit mbxfb_probe(struct platform_device *dev) struct mbxfb_info *mfbi; struct mbxfb_platform_data *pdata; - dev_dbg(&dev->dev, "mbxfb_probe\n"); + dev_dbg(dev, "mbxfb_probe\n"); pdata = dev->dev.platform_data; if (!pdata) { diff --git a/trunk/drivers/video/stifb.c b/trunk/drivers/video/stifb.c index f98be301140c..e7c8db2eb49b 100644 --- a/trunk/drivers/video/stifb.c +++ b/trunk/drivers/video/stifb.c @@ -505,24 +505,16 @@ ngleSetupAttrPlanes(struct stifb_info *fb, int BufferNumber) static void rattlerSetupPlanes(struct stifb_info *fb) { - int saved_id, y; - - /* Write RAMDAC pixel read mask register so all overlay - * planes are display-enabled. (CRX24 uses Bt462 pixel - * read mask register for overlay planes, not image planes). - */ CRX24_SETUP_RAMDAC(fb); - /* change fb->id temporarily to fool SETUP_FB() */ - saved_id = fb->id; - fb->id = CRX24_OVERLAY_PLANES; - SETUP_FB(fb); - fb->id = saved_id; - - for (y = 0; y < fb->info.var.yres; ++y) - memset(fb->info.screen_base + y * fb->info.fix.line_length, - 0xff, fb->info.var.xres * fb->info.var.bits_per_pixel/8); + /* replacement for: SETUP_FB(fb, CRX24_OVERLAY_PLANES); */ + WRITE_WORD(0x83000300, fb, REG_14); + SETUP_HW(fb); + WRITE_BYTE(1, fb, REG_16b1); + fb_memset((void*)fb->info.fix.smem_start, 0xff, + fb->info.var.yres*fb->info.fix.line_length); + CRX24_SET_OVLY_MASK(fb); SETUP_FB(fb); } diff --git a/trunk/drivers/video/tridentfb.c b/trunk/drivers/video/tridentfb.c index 0a4e07d43d2d..919ce75db9e2 100644 --- a/trunk/drivers/video/tridentfb.c +++ b/trunk/drivers/video/tridentfb.c @@ -566,32 +566,44 @@ static inline void write3CE(int reg, unsigned char val) static void enable_mmio(void) { + unsigned char tmp; + /* Goto New Mode */ outb(0x0B, 0x3C4); inb(0x3C5); /* Unprotect registers */ outb(NewMode1, 0x3C4); + tmp = inb(0x3C5); outb(0x80, 0x3C5); /* Enable MMIO */ outb(PCIReg, 0x3D4); outb(inb(0x3D5) | 0x01, 0x3D5); + + t_outb(NewMode1, 0x3C4); + t_outb(tmp, 0x3C5); } static void disable_mmio(void) { + unsigned char tmp; + /* Goto New Mode */ t_outb(0x0B, 0x3C4); t_inb(0x3C5); /* Unprotect registers */ t_outb(NewMode1, 0x3C4); + tmp = t_inb(0x3C5); t_outb(0x80, 0x3C5); /* Disable MMIO */ t_outb(PCIReg, 0x3D4); t_outb(t_inb(0x3D5) & ~0x01, 0x3D5); + + outb(NewMode1, 0x3C4); + outb(tmp, 0x3C5); } #define crtc_unlock() write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F) @@ -745,7 +757,7 @@ static unsigned int __devinit get_memsize(void) switch (tmp) { case 0x01: - k = 512 * Kb; + k = 512; break; case 0x02: k = 6 * Mb; /* XP */ diff --git a/trunk/drivers/watchdog/cpu5wdt.c b/trunk/drivers/watchdog/cpu5wdt.c index df72f90123df..5941ca601a3a 100644 --- a/trunk/drivers/watchdog/cpu5wdt.c +++ b/trunk/drivers/watchdog/cpu5wdt.c @@ -59,9 +59,9 @@ static int ticks = 10000; static struct { struct completion stop; - int running; + volatile int running; struct timer_list timer; - int queue; + volatile int queue; int default_ticks; unsigned long inuse; } cpu5wdt_device; diff --git a/trunk/drivers/watchdog/hpwdt.c b/trunk/drivers/watchdog/hpwdt.c index 6483d1066b95..a2e174b09fe7 100644 --- a/trunk/drivers/watchdog/hpwdt.c +++ b/trunk/drivers/watchdog/hpwdt.c @@ -58,6 +58,41 @@ struct bios32_service_dir { u8 reserved[5]; }; +/* + * smbios_entry_point - defines SMBIOS entry point structure + * + * anchor[4] - anchor string (_SM_) + * checksum - checksum of the entry point structure + * length - length of the entry point structure + * major_ver - major version (02h for revision 2.1) + * minor_ver - minor version (01h for revision 2.1) + * max_struct_size - size of the largest SMBIOS structure + * revision - entry point structure revision implemented + * formatted_area[5] - reserved + * intermediate_anchor[5] - intermediate anchor string (_DMI_) + * intermediate_checksum - intermediate checksum + * table_length - structure table length + * table_address - structure table address + * table_num_structs - number of SMBIOS structures present + * bcd_revision - BCD revision + */ +struct smbios_entry_point { + u8 anchor[4]; + u8 checksum; + u8 length; + u8 major_ver; + u8 minor_ver; + u16 max_struct_size; + u8 revision; + u8 formatted_area[5]; + u8 intermediate_anchor[5]; + u8 intermediate_checksum; + u16 table_length; + u64 table_address; + u16 table_num_structs; + u8 bcd_revision; +}; + /* type 212 */ struct smbios_cru64_info { u8 type; @@ -140,13 +175,31 @@ static struct pci_device_id hpwdt_devices[] = { }; MODULE_DEVICE_TABLE(pci, hpwdt_devices); +/* + * bios_checksum + */ +static int __devinit bios_checksum(const char __iomem *ptr, int len) +{ + char sum = 0; + int i; + + /* + * calculate checksum of size bytes. This should add up + * to zero if we have a valid header. + */ + for (i = 0; i < len; i++) + sum += ptr[i]; + + return ((sum == 0) && (len > 0)); +} + #ifndef CONFIG_X86_64 /* --32 Bit Bios------------------------------------------------------------ */ #define HPWDT_ARCH 32 -static void asminline_call(struct cmn_registers *pi86Regs, - unsigned long *pRomEntry) +asmlinkage void asminline_call(struct cmn_registers *pi86Regs, + unsigned long *pRomEntry) { asm("pushl %ebp \n\t" "movl %esp, %ebp \n\t" @@ -249,24 +302,6 @@ static int __devinit cru_detect(unsigned long map_entry, return retval; } -/* - * bios_checksum - */ -static int __devinit bios_checksum(const char __iomem *ptr, int len) -{ - char sum = 0; - int i; - - /* - * calculate checksum of size bytes. This should add up - * to zero if we have a valid header. - */ - for (i = 0; i < len; i++) - sum += ptr[i]; - - return ((sum == 0) && (len > 0)); -} - /* * bios32_present * @@ -333,8 +368,8 @@ static int __devinit detect_cru_service(void) #define HPWDT_ARCH 64 -static void asminline_call(struct cmn_registers *pi86Regs, - unsigned long *pRomEntry) +asmlinkage void asminline_call(struct cmn_registers *pi86Regs, + unsigned long *pRomEntry) { asm("pushq %rbp \n\t" "movq %rsp, %rbp \n\t" @@ -375,8 +410,12 @@ static void asminline_call(struct cmn_registers *pi86Regs, * dmi_find_cru * * Routine Description: - * This function checks whether or not a SMBIOS/DMI record is + * This function checks wether or not a SMBIOS/DMI record is * the 64bit CRU info or not + * + * Return Value: + * 0 : SUCCESS - if record found + * <0 : FAILURE - if record not found */ static void __devinit dmi_find_cru(const struct dmi_header *dm) { @@ -395,11 +434,138 @@ static void __devinit dmi_find_cru(const struct dmi_header *dm) } } +/* + * dmi_table + * + * Routine Description: + * Decode the SMBIOS/DMI table and check if we have a 64bit CRU record + * or not. + * + * We have to be cautious here. We have seen BIOSes with DMI pointers + * pointing to completely the wrong place for example + */ +static void __devinit dmi_table(u8 *buf, int len, int num, + void (*decode)(const struct dmi_header *)) +{ + u8 *data = buf; + int i = 0; + + /* + * Stop when we see all the items the table claimed to have + * OR we run off the end of the table (also happens) + */ + while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) { + const struct dmi_header *dm = (const struct dmi_header *)data; + + /* + * We want to know the total length (formated area and strings) + * before decoding to make sure we won't run off the table in + * dmi_decode or dmi_string + */ + data += dm->length; + while ((data - buf < len - 1) && (data[0] || data[1])) + data++; + if (data - buf < len - 1) + decode(dm); + data += 2; + i++; + } +} + +/* + * smbios_present + * + * Routine Description: + * This function parses the SMBIOS entry point table to retrieve + * the 64 bit CRU Service. + * + * Return Value: + * 0 : SUCCESS + * <0 : FAILURE + */ +static int __devinit smbios_present(const char __iomem *p) +{ + struct smbios_entry_point *eps = + (struct smbios_entry_point *) p; + int length; + u8 *buf; + + /* check if we have indeed the SMBIOS table entry point */ + if ((strncmp((char *)eps->anchor, "_SM_", + sizeof(eps->anchor))) == 0) { + length = eps->length; + + /* SMBIOS v2.1 implementation might use 0x1e */ + if ((length == 0x1e) && + (eps->major_ver == 2) && + (eps->minor_ver == 1)) + length = 0x1f; + + /* + * Now we will check: + * - SMBIOS checksum must be 0 + * - intermediate anchor should be _DMI_ + * - intermediate checksum should be 0 + */ + if ((bios_checksum(p, length)) && + (strncmp((char *)eps->intermediate_anchor, "_DMI_", + sizeof(eps->intermediate_anchor)) == 0) && + (bios_checksum(p+0x10, 15))) { + buf = ioremap(eps->table_address, eps->table_length); + if (buf == NULL) + return -ENODEV; + + + /* Scan the DMI table for the 64 bit CRU service */ + dmi_table(buf, eps->table_length, + eps->table_num_structs, dmi_find_cru); + + iounmap(buf); + return 0; + } + } + + return -ENODEV; +} + +static int __devinit smbios_scan_machine(void) +{ + char __iomem *p, *q; + int rc; + + if (efi_enabled) { + if (efi.smbios == EFI_INVALID_TABLE_ADDR) + return -ENODEV; + + p = ioremap(efi.smbios, 32); + if (p == NULL) + return -ENOMEM; + + rc = smbios_present(p); + iounmap(p); + } else { + /* + * Search from 0x0f0000 through 0x0fffff, inclusive. + */ + p = ioremap(PCI_ROM_BASE1, ROM_SIZE); + if (p == NULL) + return -ENOMEM; + + for (q = p; q < p + ROM_SIZE; q += 16) { + rc = smbios_present(q); + if (!rc) { + break; + } + } + iounmap(p); + } +} + static int __devinit detect_cru_service(void) { cru_rom_addr = NULL; - dmi_walk(dmi_find_cru); + smbios_scan_machine(); /* will become dmi_walk(dmi_find_cru); */ /* if cru_rom_addr has been set then we found a CRU service */ return ((cru_rom_addr != NULL)? 0: -ENODEV); diff --git a/trunk/drivers/watchdog/it8712f_wdt.c b/trunk/drivers/watchdog/it8712f_wdt.c index 1efcad3b6fca..1b6d7d1b715d 100644 --- a/trunk/drivers/watchdog/it8712f_wdt.c +++ b/trunk/drivers/watchdog/it8712f_wdt.c @@ -7,8 +7,7 @@ * * drivers/char/watchdog/scx200_wdt.c * drivers/hwmon/it87.c - * IT8712F EC-LPC I/O Preliminary Specification 0.8.2 - * IT8712F EC-LPC I/O Preliminary Specification 0.9.3 + * IT8712F EC-LPC I/O Preliminary Specification 0.9.2.pdf * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -41,7 +40,6 @@ MODULE_DESCRIPTION("IT8712F Watchdog Driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -static int max_units = 255; static int margin = 60; /* in seconds */ module_param(margin, int, 0); MODULE_PARM_DESC(margin, "Watchdog margin in seconds"); @@ -53,7 +51,6 @@ MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); static struct semaphore it8712f_wdt_sem; static unsigned expect_close; static spinlock_t io_lock; -static unsigned char revision; /* Dog Food address - We use the game port address */ static unsigned short address; @@ -111,15 +108,6 @@ superio_inw(int reg) return val; } -static void -superio_outw(int val, int reg) -{ - outb(reg++, REG); - outb((val >> 8) & 0xff, VAL); - outb(reg, REG); - outb(val & 0xff, VAL); -} - static inline void superio_select(int ldn) { @@ -155,33 +143,15 @@ static void it8712f_wdt_update_margin(void) { int config = WDT_OUT_KRST | WDT_OUT_PWROK; - int units = margin; - - /* Switch to minutes precision if the configured margin - * value does not fit within the register width. - */ - if (units <= max_units) { - config |= WDT_UNIT_SEC; /* else UNIT is MINUTES */ - printk(KERN_INFO NAME ": timer margin %d seconds\n", units); - } else { - units /= 60; - printk(KERN_INFO NAME ": timer margin %d minutes\n", units); - } - superio_outb(config, WDT_CONFIG); - if (revision >= 0x08) - superio_outw(units, WDT_TIMEOUT); - else - superio_outb(units, WDT_TIMEOUT); -} + printk(KERN_INFO NAME ": timer margin %d seconds\n", margin); -static int -it8712f_wdt_get_status(void) -{ - if (superio_inb(WDT_CONTROL) & 0x01) - return WDIOF_CARDRESET; - else - return 0; + /* The timeout register only has 8bits wide */ + if (margin < 256) + config |= WDT_UNIT_SEC; /* else UNIT are MINUTES */ + superio_outb(config, WDT_CONFIG); + + superio_outb((margin > 255) ? (margin / 60) : margin, WDT_TIMEOUT); } static void @@ -264,7 +234,7 @@ it8712f_wdt_ioctl(struct inode *inode, struct file *file, .firmware_version = 1, .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, }; - int value; + int new_margin; switch (cmd) { default: @@ -274,27 +244,17 @@ it8712f_wdt_ioctl(struct inode *inode, struct file *file, return -EFAULT; return 0; case WDIOC_GETSTATUS: - superio_enter(); - superio_select(LDN_GPIO); - - value = it8712f_wdt_get_status(); - - superio_exit(); - - return put_user(value, p); case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_KEEPALIVE: it8712f_wdt_ping(); return 0; case WDIOC_SETTIMEOUT: - if (get_user(value, p)) + if (get_user(new_margin, p)) return -EFAULT; - if (value < 1) - return -EINVAL; - if (value > (max_units * 60)) + if (new_margin < 1) return -EINVAL; - margin = value; + margin = new_margin; superio_enter(); superio_select(LDN_GPIO); @@ -302,7 +262,6 @@ it8712f_wdt_ioctl(struct inode *inode, struct file *file, superio_exit(); it8712f_wdt_ping(); - /* Fall through */ case WDIOC_GETTIMEOUT: if (put_user(margin, p)) return -EFAULT; @@ -377,18 +336,9 @@ it8712f_wdt_find(unsigned short *address) } err = 0; - revision = superio_inb(DEVREV) & 0x0f; - - /* Later revisions have 16-bit values per datasheet 0.9.1 */ - if (revision >= 0x08) - max_units = 65535; - - if (margin > (max_units * 60)) - margin = (max_units * 60); - - printk(KERN_INFO NAME ": Found IT%04xF chip revision %d - " + printk(KERN_DEBUG NAME ": Found IT%04xF chip revision %d - " "using DogFood address 0x%x\n", - chip_type, revision, *address); + chip_type, superio_inb(DEVREV) & 0x0f, *address); exit: superio_exit(); diff --git a/trunk/drivers/watchdog/machzwd.c b/trunk/drivers/watchdog/machzwd.c index 6905135a776c..e6e07b4575eb 100644 --- a/trunk/drivers/watchdog/machzwd.c +++ b/trunk/drivers/watchdog/machzwd.c @@ -141,7 +141,7 @@ static unsigned long next_heartbeat = 0; #ifndef ZF_DEBUG # define dprintk(format, args...) #else -# define dprintk(format, args...) printk(KERN_DEBUG PFX ":%s:%d: " format, __func__, __LINE__ , ## args) +# define dprintk(format, args...) printk(KERN_DEBUG PFX ":%s:%d: " format, __FUNCTION__, __LINE__ , ## args) #endif diff --git a/trunk/drivers/watchdog/mtx-1_wdt.c b/trunk/drivers/watchdog/mtx-1_wdt.c index 10b89f2703bd..789831b3fa00 100644 --- a/trunk/drivers/watchdog/mtx-1_wdt.c +++ b/trunk/drivers/watchdog/mtx-1_wdt.c @@ -59,9 +59,9 @@ static int ticks = 100 * HZ; static struct { struct completion stop; - int running; + volatile int running; struct timer_list timer; - int queue; + volatile int queue; int default_ticks; unsigned long inuse; unsigned gpio; diff --git a/trunk/drivers/watchdog/pcwd_usb.c b/trunk/drivers/watchdog/pcwd_usb.c index bf443d077a1e..0f3fd6c9c354 100644 --- a/trunk/drivers/watchdog/pcwd_usb.c +++ b/trunk/drivers/watchdog/pcwd_usb.c @@ -179,11 +179,11 @@ static void usb_pcwd_intr_done(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __func__, urb->status); + dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); return; /* -EPIPE: should clear the halt */ default: /* error */ - dbg("%s - nonzero urb status received: %d", __func__, urb->status); + dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); goto resubmit; } diff --git a/trunk/drivers/watchdog/s3c2410_wdt.c b/trunk/drivers/watchdog/s3c2410_wdt.c index 7645e8812156..5d1c15f83d23 100644 --- a/trunk/drivers/watchdog/s3c2410_wdt.c +++ b/trunk/drivers/watchdog/s3c2410_wdt.c @@ -144,7 +144,7 @@ static int s3c2410wdt_start(void) } DBG("%s: wdt_count=0x%08x, wtcon=%08lx\n", - __func__, wdt_count, wtcon); + __FUNCTION__, wdt_count, wtcon); writel(wdt_count, wdt_base + S3C2410_WTDAT); writel(wdt_count, wdt_base + S3C2410_WTCNT); @@ -167,7 +167,7 @@ static int s3c2410wdt_set_heartbeat(int timeout) count = timeout * freq; DBG("%s: count=%d, timeout=%d, freq=%d\n", - __func__, count, timeout, freq); + __FUNCTION__, count, timeout, freq); /* if the count is bigger than the watchdog register, then work out what we need to do (and if) we can @@ -189,7 +189,7 @@ static int s3c2410wdt_set_heartbeat(int timeout) tmr_margin = timeout; DBG("%s: timeout=%d, divisor=%d, count=%d (%08x)\n", - __func__, timeout, divisor, count, count/divisor); + __FUNCTION__, timeout, divisor, count, count/divisor); count /= divisor; wdt_count = count; @@ -355,7 +355,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev) int ret; int size; - DBG("%s: probe=%p\n", __func__, pdev); + DBG("%s: probe=%p\n", __FUNCTION__, pdev); dev = &pdev->dev; wdt_dev = &pdev->dev; diff --git a/trunk/drivers/watchdog/shwdt.c b/trunk/drivers/watchdog/shwdt.c index 1277f7e9cc54..61dde863bd40 100644 --- a/trunk/drivers/watchdog/shwdt.c +++ b/trunk/drivers/watchdog/shwdt.c @@ -298,7 +298,7 @@ static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma) if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT, PAGE_SIZE, vma->vm_page_prot)) { printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n", - __func__); + __FUNCTION__); return -EAGAIN; } diff --git a/trunk/fs/ocfs2/cluster/tcp.c b/trunk/fs/ocfs2/cluster/tcp.c index b8057c51b205..ee50c9610e7f 100644 --- a/trunk/fs/ocfs2/cluster/tcp.c +++ b/trunk/fs/ocfs2/cluster/tcp.c @@ -451,9 +451,9 @@ static void o2net_set_nn_state(struct o2net_node *nn, /* delay if we're withing a RECONNECT_DELAY of the * last attempt */ delay = (nn->nn_last_connect_attempt + - msecs_to_jiffies(o2net_reconnect_delay(NULL))) + msecs_to_jiffies(o2net_reconnect_delay(sc->sc_node))) - jiffies; - if (delay > msecs_to_jiffies(o2net_reconnect_delay(NULL))) + if (delay > msecs_to_jiffies(o2net_reconnect_delay(sc->sc_node))) delay = 0; mlog(ML_CONN, "queueing conn attempt in %lu jiffies\n", delay); queue_delayed_work(o2net_wq, &nn->nn_connect_work, delay); @@ -1552,11 +1552,12 @@ static void o2net_connect_expired(struct work_struct *work) spin_lock(&nn->nn_lock); if (!nn->nn_sc_valid) { + struct o2nm_node *node = nn->nn_sc->sc_node; mlog(ML_ERROR, "no connection established with node %u after " "%u.%u seconds, giving up and returning errors.\n", o2net_num_from_nn(nn), - o2net_idle_timeout(NULL) / 1000, - o2net_idle_timeout(NULL) % 1000); + o2net_idle_timeout(node) / 1000, + o2net_idle_timeout(node) % 1000); o2net_set_nn_state(nn, NULL, 0, -ENOTCONN); } diff --git a/trunk/fs/ocfs2/dlm/dlmcommon.h b/trunk/fs/ocfs2/dlm/dlmcommon.h index dc8ea666efdb..9843ee17ea27 100644 --- a/trunk/fs/ocfs2/dlm/dlmcommon.h +++ b/trunk/fs/ocfs2/dlm/dlmcommon.h @@ -176,7 +176,6 @@ struct dlm_mig_lockres_priv { struct dlm_lock_resource *lockres; u8 real_master; - u8 extra_ref; }; struct dlm_assert_master_priv @@ -603,19 +602,17 @@ enum dlm_query_join_response_code { JOIN_PROTOCOL_MISMATCH, }; -struct dlm_query_join_packet { - u8 code; /* Response code. dlm_minor and fs_minor - are only valid if this is JOIN_OK */ - u8 dlm_minor; /* The minor version of the protocol the - dlm is speaking. */ - u8 fs_minor; /* The minor version of the protocol the - filesystem is speaking. */ - u8 reserved; -}; - union dlm_query_join_response { u32 intval; - struct dlm_query_join_packet packet; + struct { + u8 code; /* Response code. dlm_minor and fs_minor + are only valid if this is JOIN_OK */ + u8 dlm_minor; /* The minor version of the protocol the + dlm is speaking. */ + u8 fs_minor; /* The minor version of the protocol the + filesystem is speaking. */ + u8 reserved; + } packet; }; struct dlm_lock_request diff --git a/trunk/fs/ocfs2/dlm/dlmconvert.c b/trunk/fs/ocfs2/dlm/dlmconvert.c index 75997b4deaf3..ecb4d997221e 100644 --- a/trunk/fs/ocfs2/dlm/dlmconvert.c +++ b/trunk/fs/ocfs2/dlm/dlmconvert.c @@ -487,7 +487,7 @@ int dlm_convert_lock_handler(struct o2net_msg *msg, u32 len, void *data, "cookie=%u:%llu\n", dlm_get_lock_cookie_node(be64_to_cpu(cnv->cookie)), dlm_get_lock_cookie_seq(be64_to_cpu(cnv->cookie))); - dlm_print_one_lock_resource(res); + __dlm_print_one_lock_resource(res); goto leave; } diff --git a/trunk/fs/ocfs2/dlm/dlmdomain.c b/trunk/fs/ocfs2/dlm/dlmdomain.c index 0879d86113e3..638d2ebb892b 100644 --- a/trunk/fs/ocfs2/dlm/dlmdomain.c +++ b/trunk/fs/ocfs2/dlm/dlmdomain.c @@ -713,46 +713,14 @@ static int dlm_query_join_proto_check(char *proto_type, int node, return rc; } -/* - * struct dlm_query_join_packet is made up of four one-byte fields. They - * are effectively in big-endian order already. However, little-endian - * machines swap them before putting the packet on the wire (because - * query_join's response is a status, and that status is treated as a u32 - * on the wire). Thus, a big-endian and little-endian machines will treat - * this structure differently. - * - * The solution is to have little-endian machines swap the structure when - * converting from the structure to the u32 representation. This will - * result in the structure having the correct format on the wire no matter - * the host endian format. - */ -static void dlm_query_join_packet_to_wire(struct dlm_query_join_packet *packet, - u32 *wire) -{ - union dlm_query_join_response response; - - response.packet = *packet; - *wire = cpu_to_be32(response.intval); -} - -static void dlm_query_join_wire_to_packet(u32 wire, - struct dlm_query_join_packet *packet) -{ - union dlm_query_join_response response; - - response.intval = cpu_to_be32(wire); - *packet = response.packet; -} - static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, void **ret_data) { struct dlm_query_join_request *query; - struct dlm_query_join_packet packet = { - .code = JOIN_DISALLOW, + union dlm_query_join_response response = { + .packet.code = JOIN_DISALLOW, }; struct dlm_ctxt *dlm = NULL; - u32 response; u8 nodenum; query = (struct dlm_query_join_request *) msg->buf; @@ -769,11 +737,11 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, mlog(0, "node %u is not in our live map yet\n", query->node_idx); - packet.code = JOIN_DISALLOW; + response.packet.code = JOIN_DISALLOW; goto respond; } - packet.code = JOIN_OK_NO_MAP; + response.packet.code = JOIN_OK_NO_MAP; spin_lock(&dlm_domain_lock); dlm = __dlm_lookup_domain_full(query->domain, query->name_len); @@ -792,7 +760,7 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, mlog(0, "disallow join as node %u does not " "have node %u in its nodemap\n", query->node_idx, nodenum); - packet.code = JOIN_DISALLOW; + response.packet.code = JOIN_DISALLOW; goto unlock_respond; } } @@ -812,23 +780,23 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, /*If this is a brand new context and we * haven't started our join process yet, then * the other node won the race. */ - packet.code = JOIN_OK_NO_MAP; + response.packet.code = JOIN_OK_NO_MAP; } else if (dlm->joining_node != DLM_LOCK_RES_OWNER_UNKNOWN) { /* Disallow parallel joins. */ - packet.code = JOIN_DISALLOW; + response.packet.code = JOIN_DISALLOW; } else if (dlm->reco.state & DLM_RECO_STATE_ACTIVE) { mlog(0, "node %u trying to join, but recovery " "is ongoing.\n", bit); - packet.code = JOIN_DISALLOW; + response.packet.code = JOIN_DISALLOW; } else if (test_bit(bit, dlm->recovery_map)) { mlog(0, "node %u trying to join, but it " "still needs recovery.\n", bit); - packet.code = JOIN_DISALLOW; + response.packet.code = JOIN_DISALLOW; } else if (test_bit(bit, dlm->domain_map)) { mlog(0, "node %u trying to join, but it " "is still in the domain! needs recovery?\n", bit); - packet.code = JOIN_DISALLOW; + response.packet.code = JOIN_DISALLOW; } else { /* Alright we're fully a part of this domain * so we keep some state as to who's joining @@ -839,15 +807,19 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, if (dlm_query_join_proto_check("DLM", bit, &dlm->dlm_locking_proto, &query->dlm_proto)) { - packet.code = JOIN_PROTOCOL_MISMATCH; + response.packet.code = + JOIN_PROTOCOL_MISMATCH; } else if (dlm_query_join_proto_check("fs", bit, &dlm->fs_locking_proto, &query->fs_proto)) { - packet.code = JOIN_PROTOCOL_MISMATCH; + response.packet.code = + JOIN_PROTOCOL_MISMATCH; } else { - packet.dlm_minor = query->dlm_proto.pv_minor; - packet.fs_minor = query->fs_proto.pv_minor; - packet.code = JOIN_OK; + response.packet.dlm_minor = + query->dlm_proto.pv_minor; + response.packet.fs_minor = + query->fs_proto.pv_minor; + response.packet.code = JOIN_OK; __dlm_set_joining_node(dlm, query->node_idx); } } @@ -858,10 +830,9 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, spin_unlock(&dlm_domain_lock); respond: - mlog(0, "We respond with %u\n", packet.code); + mlog(0, "We respond with %u\n", response.packet.code); - dlm_query_join_packet_to_wire(&packet, &response); - return response; + return response.intval; } static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data, @@ -966,7 +937,7 @@ static int dlm_send_join_cancels(struct dlm_ctxt *dlm, sizeof(unsigned long))) { mlog(ML_ERROR, "map_size %u != BITS_TO_LONGS(O2NM_MAX_NODES) %u\n", - map_size, (unsigned)BITS_TO_LONGS(O2NM_MAX_NODES)); + map_size, BITS_TO_LONGS(O2NM_MAX_NODES)); return -EINVAL; } @@ -997,8 +968,7 @@ static int dlm_request_join(struct dlm_ctxt *dlm, { int status; struct dlm_query_join_request join_msg; - struct dlm_query_join_packet packet; - u32 join_resp; + union dlm_query_join_response join_resp; mlog(0, "querying node %d\n", node); @@ -1014,12 +984,11 @@ static int dlm_request_join(struct dlm_ctxt *dlm, status = o2net_send_message(DLM_QUERY_JOIN_MSG, DLM_MOD_KEY, &join_msg, sizeof(join_msg), node, - &join_resp); + &join_resp.intval); if (status < 0 && status != -ENOPROTOOPT) { mlog_errno(status); goto bail; } - dlm_query_join_wire_to_packet(join_resp, &packet); /* -ENOPROTOOPT from the net code means the other side isn't listening for our message type -- that's fine, it means @@ -1028,10 +997,10 @@ static int dlm_request_join(struct dlm_ctxt *dlm, if (status == -ENOPROTOOPT) { status = 0; *response = JOIN_OK_NO_MAP; - } else if (packet.code == JOIN_DISALLOW || - packet.code == JOIN_OK_NO_MAP) { - *response = packet.code; - } else if (packet.code == JOIN_PROTOCOL_MISMATCH) { + } else if (join_resp.packet.code == JOIN_DISALLOW || + join_resp.packet.code == JOIN_OK_NO_MAP) { + *response = join_resp.packet.code; + } else if (join_resp.packet.code == JOIN_PROTOCOL_MISMATCH) { mlog(ML_NOTICE, "This node requested DLM locking protocol %u.%u and " "filesystem locking protocol %u.%u. At least one of " @@ -1043,12 +1012,14 @@ static int dlm_request_join(struct dlm_ctxt *dlm, dlm->fs_locking_proto.pv_minor, node); status = -EPROTO; - *response = packet.code; - } else if (packet.code == JOIN_OK) { - *response = packet.code; + *response = join_resp.packet.code; + } else if (join_resp.packet.code == JOIN_OK) { + *response = join_resp.packet.code; /* Use the same locking protocol as the remote node */ - dlm->dlm_locking_proto.pv_minor = packet.dlm_minor; - dlm->fs_locking_proto.pv_minor = packet.fs_minor; + dlm->dlm_locking_proto.pv_minor = + join_resp.packet.dlm_minor; + dlm->fs_locking_proto.pv_minor = + join_resp.packet.fs_minor; mlog(0, "Node %d responds JOIN_OK with DLM locking protocol " "%u.%u and fs locking protocol %u.%u\n", @@ -1060,11 +1031,11 @@ static int dlm_request_join(struct dlm_ctxt *dlm, } else { status = -EINVAL; mlog(ML_ERROR, "invalid response %d from node %u\n", - packet.code, node); + join_resp.packet.code, node); } mlog(0, "status %d, node %d response is %d\n", status, node, - *response); + *response); bail: return status; diff --git a/trunk/fs/ocfs2/dlm/dlmmaster.c b/trunk/fs/ocfs2/dlm/dlmmaster.c index ea6b89577860..c92d1b19fc0b 100644 --- a/trunk/fs/ocfs2/dlm/dlmmaster.c +++ b/trunk/fs/ocfs2/dlm/dlmmaster.c @@ -1663,12 +1663,7 @@ int dlm_master_request_handler(struct o2net_msg *msg, u32 len, void *data, dlm_put_mle(tmpmle); } send_response: - /* - * __dlm_lookup_lockres() grabbed a reference to this lockres. - * The reference is released by dlm_assert_master_worker() under - * the call to dlm_dispatch_assert_master(). If - * dlm_assert_master_worker() isn't called, we drop it here. - */ + if (dispatch_assert) { if (response != DLM_MASTER_RESP_YES) mlog(ML_ERROR, "invalid response %d\n", response); @@ -1683,11 +1678,7 @@ int dlm_master_request_handler(struct o2net_msg *msg, u32 len, void *data, if (ret < 0) { mlog(ML_ERROR, "failed to dispatch assert master work\n"); response = DLM_MASTER_RESP_ERROR; - dlm_lockres_put(res); } - } else { - if (res) - dlm_lockres_put(res); } dlm_put(dlm); @@ -2357,7 +2348,7 @@ int dlm_deref_lockres_handler(struct o2net_msg *msg, u32 len, void *data, mlog(ML_ERROR, "%s:%.*s: node %u trying to drop ref " "but it is already dropped!\n", dlm->name, res->lockname.len, res->lockname.name, node); - dlm_print_one_lock_resource(res); + __dlm_print_one_lock_resource(res); } ret = 0; goto done; @@ -2417,7 +2408,7 @@ static void dlm_deref_lockres_worker(struct dlm_work_item *item, void *data) mlog(ML_ERROR, "%s:%.*s: node %u trying to drop ref " "but it is already dropped!\n", dlm->name, res->lockname.len, res->lockname.name, node); - dlm_print_one_lock_resource(res); + __dlm_print_one_lock_resource(res); } dlm_lockres_put(res); @@ -2942,9 +2933,6 @@ static void dlm_remove_nonlocal_locks(struct dlm_ctxt *dlm, dlm_lockres_clear_refmap_bit(lock->ml.node, res); list_del_init(&lock->list); dlm_lock_put(lock); - /* In a normal unlock, we would have added a - * DLM_UNLOCK_FREE_LOCK action. Force it. */ - dlm_lock_put(lock); } } queue++; diff --git a/trunk/fs/ocfs2/dlm/dlmrecovery.c b/trunk/fs/ocfs2/dlm/dlmrecovery.c index bcb9260c3735..91f747b8a538 100644 --- a/trunk/fs/ocfs2/dlm/dlmrecovery.c +++ b/trunk/fs/ocfs2/dlm/dlmrecovery.c @@ -519,9 +519,9 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm) return 0; master_here: - mlog(ML_NOTICE, "(%d) Node %u is the Recovery Master for the Dead Node " - "%u for Domain %s\n", task_pid_nr(dlm->dlm_reco_thread_task), - dlm->node_num, dlm->reco.dead_node, dlm->name); + mlog(0, "(%d) mastering recovery of %s:%u here(this=%u)!\n", + task_pid_nr(dlm->dlm_reco_thread_task), + dlm->name, dlm->reco.dead_node, dlm->node_num); status = dlm_remaster_locks(dlm, dlm->reco.dead_node); if (status < 0) { @@ -1191,7 +1191,7 @@ static int dlm_add_lock_to_array(struct dlm_lock *lock, (ml->type == LKM_EXMODE || memcmp(mres->lvb, lock->lksb->lvb, DLM_LVB_LEN))) { mlog(ML_ERROR, "mismatched lvbs!\n"); - dlm_print_one_lock_resource(lock->lockres); + __dlm_print_one_lock_resource(lock->lockres); BUG(); } memcpy(mres->lvb, lock->lksb->lvb, DLM_LVB_LEN); @@ -1327,7 +1327,6 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data, (struct dlm_migratable_lockres *)msg->buf; int ret = 0; u8 real_master; - u8 extra_refs = 0; char *buf = NULL; struct dlm_work_item *item = NULL; struct dlm_lock_resource *res = NULL; @@ -1405,28 +1404,16 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data, __dlm_insert_lockres(dlm, res); spin_unlock(&dlm->spinlock); - /* Add an extra ref for this lock-less lockres lest the - * dlm_thread purges it before we get the chance to add - * locks to it */ - dlm_lockres_get(res); - - /* There are three refs that need to be put. - * 1. Taken above. - * 2. kref_init in dlm_new_lockres()->dlm_init_lockres(). - * 3. dlm_lookup_lockres() - * The first one is handled at the end of this function. The - * other two are handled in the worker thread after locks have - * been attached. Yes, we don't wait for purge time to match - * kref_init. The lockres will still have atleast one ref - * added because it is in the hash __dlm_insert_lockres() */ - extra_refs++; - /* now that the new lockres is inserted, * make it usable by other processes */ spin_lock(&res->spinlock); res->state &= ~DLM_LOCK_RES_IN_PROGRESS; spin_unlock(&res->spinlock); wake_up(&res->wq); + + /* add an extra ref for just-allocated lockres + * otherwise the lockres will be purged immediately */ + dlm_lockres_get(res); } /* at this point we have allocated everything we need, @@ -1456,17 +1443,12 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data, dlm_init_work_item(dlm, item, dlm_mig_lockres_worker, buf); item->u.ml.lockres = res; /* already have a ref */ item->u.ml.real_master = real_master; - item->u.ml.extra_ref = extra_refs; spin_lock(&dlm->work_lock); list_add_tail(&item->list, &dlm->work_list); spin_unlock(&dlm->work_lock); queue_work(dlm->dlm_worker, &dlm->dispatched_work); leave: - /* One extra ref taken needs to be put here */ - if (extra_refs) - dlm_lockres_put(res); - dlm_put(dlm); if (ret < 0) { if (buf) @@ -1482,19 +1464,17 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data, static void dlm_mig_lockres_worker(struct dlm_work_item *item, void *data) { - struct dlm_ctxt *dlm; + struct dlm_ctxt *dlm = data; struct dlm_migratable_lockres *mres; int ret = 0; struct dlm_lock_resource *res; u8 real_master; - u8 extra_ref; dlm = item->dlm; mres = (struct dlm_migratable_lockres *)data; res = item->u.ml.lockres; real_master = item->u.ml.real_master; - extra_ref = item->u.ml.extra_ref; if (real_master == DLM_LOCK_RES_OWNER_UNKNOWN) { /* this case is super-rare. only occurs if @@ -1537,12 +1517,6 @@ static void dlm_mig_lockres_worker(struct dlm_work_item *item, void *data) } leave: - /* See comment in dlm_mig_lockres_handler() */ - if (res) { - if (extra_ref) - dlm_lockres_put(res); - dlm_lockres_put(res); - } kfree(data); mlog_exit(ret); } @@ -1670,8 +1644,7 @@ int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data, /* retry!? */ BUG(); } - } else /* put.. incase we are not the master */ - dlm_lockres_put(res); + } spin_unlock(&res->spinlock); } spin_unlock(&dlm->spinlock); @@ -1948,7 +1921,6 @@ void dlm_move_lockres_to_recovery_list(struct dlm_ctxt *dlm, "Recovering res %s:%.*s, is already on recovery list!\n", dlm->name, res->lockname.len, res->lockname.name); list_del_init(&res->recovering); - dlm_lockres_put(res); } /* We need to hold a reference while on the recovery list */ dlm_lockres_get(res); @@ -2158,16 +2130,11 @@ static void dlm_free_dead_locks(struct dlm_ctxt *dlm, assert_spin_locked(&dlm->spinlock); assert_spin_locked(&res->spinlock); - /* We do two dlm_lock_put(). One for removing from list and the other is - * to force the DLM_UNLOCK_FREE_LOCK action so as to free the locks */ - /* TODO: check pending_asts, pending_basts here */ list_for_each_entry_safe(lock, next, &res->granted, list) { if (lock->ml.node == dead_node) { list_del_init(&lock->list); dlm_lock_put(lock); - /* Can't schedule DLM_UNLOCK_FREE_LOCK - do manually */ - dlm_lock_put(lock); freed++; } } @@ -2175,8 +2142,6 @@ static void dlm_free_dead_locks(struct dlm_ctxt *dlm, if (lock->ml.node == dead_node) { list_del_init(&lock->list); dlm_lock_put(lock); - /* Can't schedule DLM_UNLOCK_FREE_LOCK - do manually */ - dlm_lock_put(lock); freed++; } } @@ -2184,8 +2149,6 @@ static void dlm_free_dead_locks(struct dlm_ctxt *dlm, if (lock->ml.node == dead_node) { list_del_init(&lock->list); dlm_lock_put(lock); - /* Can't schedule DLM_UNLOCK_FREE_LOCK - do manually */ - dlm_lock_put(lock); freed++; } } diff --git a/trunk/fs/ocfs2/dlm/dlmthread.c b/trunk/fs/ocfs2/dlm/dlmthread.c index 4060bb328bc8..cebd089f8955 100644 --- a/trunk/fs/ocfs2/dlm/dlmthread.c +++ b/trunk/fs/ocfs2/dlm/dlmthread.c @@ -176,14 +176,12 @@ static int dlm_purge_lockres(struct dlm_ctxt *dlm, res->lockname.name, master); if (!master) { - /* drop spinlock... retake below */ - spin_unlock(&dlm->spinlock); - spin_lock(&res->spinlock); /* This ensures that clear refmap is sent after the set */ __dlm_wait_on_lockres_flags(res, DLM_LOCK_RES_SETREF_INPROG); spin_unlock(&res->spinlock); - + /* drop spinlock to do messaging, retake below */ + spin_unlock(&dlm->spinlock); /* clear our bit from the master's refmap, ignore errors */ ret = dlm_drop_lockres_ref(dlm, res); if (ret < 0) { diff --git a/trunk/fs/ocfs2/dlmglue.c b/trunk/fs/ocfs2/dlmglue.c index 1f1873bf41fb..f7794306b2bd 100644 --- a/trunk/fs/ocfs2/dlmglue.c +++ b/trunk/fs/ocfs2/dlmglue.c @@ -2409,7 +2409,7 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v) return 0; } -static const struct seq_operations ocfs2_dlm_seq_ops = { +static struct seq_operations ocfs2_dlm_seq_ops = { .start = ocfs2_dlm_seq_start, .stop = ocfs2_dlm_seq_stop, .next = ocfs2_dlm_seq_next, diff --git a/trunk/fs/ocfs2/resize.c b/trunk/fs/ocfs2/resize.c index 8166968e9015..37835ffcb039 100644 --- a/trunk/fs/ocfs2/resize.c +++ b/trunk/fs/ocfs2/resize.c @@ -597,7 +597,7 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input) memset(cr, 0, sizeof(struct ocfs2_chain_rec)); } - cr->c_blkno = cpu_to_le64(input->group); + cr->c_blkno = le64_to_cpu(input->group); le32_add_cpu(&cr->c_total, input->clusters * cl_bpc); le32_add_cpu(&cr->c_free, input->frees * cl_bpc); diff --git a/trunk/include/linux/memstick.h b/trunk/include/linux/memstick.h index b7ee25888836..334d059d6794 100644 --- a/trunk/include/linux/memstick.h +++ b/trunk/include/linux/memstick.h @@ -22,8 +22,6 @@ struct ms_status_register { unsigned char reserved; unsigned char interrupt; #define MEMSTICK_INT_CMDNAK 0x0001 -#define MEMSTICK_INT_IOREQ 0x0008 -#define MEMSTICK_INT_IOBREQ 0x0010 #define MEMSTICK_INT_BREQ 0x0020 #define MEMSTICK_INT_ERR 0x0040 #define MEMSTICK_INT_CED 0x0080 @@ -49,17 +47,13 @@ struct ms_status_register { struct ms_id_register { unsigned char type; - unsigned char if_mode; + unsigned char reserved; unsigned char category; unsigned char class; } __attribute__((packed)); struct ms_param_register { unsigned char system; -#define MEMSTICK_SYS_ATEN 0xc0 -#define MEMSTICK_SYS_BAMD 0x80 -#define MEMSTICK_SYS_PAM 0x08 - unsigned char block_address_msb; unsigned short block_address; unsigned char cp; @@ -96,48 +90,16 @@ struct ms_register { struct mspro_param_register { unsigned char system; -#define MEMSTICK_SYS_SERIAL 0x80 -#define MEMSTICK_SYS_PAR4 0x00 -#define MEMSTICK_SYS_PAR8 0x40 - - unsigned short data_count; - unsigned int data_address; - unsigned char tpc_param; -} __attribute__((packed)); - -struct mspro_io_info_register { - unsigned char version; - unsigned char io_category; - unsigned char current_req; - unsigned char card_opt_info; - unsigned char rdy_wait_time; -} __attribute__((packed)); - -struct mspro_io_func_register { - unsigned char func_enable; - unsigned char func_select; - unsigned char func_intmask; - unsigned char transfer_mode; -} __attribute__((packed)); - -struct mspro_io_cmd_register { - unsigned short tpc_param; unsigned short data_count; unsigned int data_address; + unsigned char cmd_param; } __attribute__((packed)); struct mspro_register { - struct ms_status_register status; - struct ms_id_register id; - unsigned char reserved0[8]; - struct mspro_param_register param; - unsigned char reserved1[8]; - struct mspro_io_info_register io_info; - struct mspro_io_func_register io_func; - unsigned char reserved2[7]; - struct mspro_io_cmd_register io_cmd; - unsigned char io_int; - unsigned char io_int_func; + struct ms_status_register status; + struct ms_id_register id; + unsigned char reserved[8]; + struct mspro_param_register param; } __attribute__((packed)); struct ms_register_addr { @@ -148,55 +110,49 @@ struct ms_register_addr { } __attribute__((packed)); enum { - MS_TPC_READ_MG_STATUS = 0x01, MS_TPC_READ_LONG_DATA = 0x02, MS_TPC_READ_SHORT_DATA = 0x03, - MS_TPC_READ_MG_DATA = 0x03, MS_TPC_READ_REG = 0x04, - MS_TPC_READ_QUAD_DATA = 0x05, - MS_TPC_READ_IO_DATA = 0x05, + MS_TPC_READ_IO_DATA = 0x05, /* unverified */ MS_TPC_GET_INT = 0x07, MS_TPC_SET_RW_REG_ADRS = 0x08, MS_TPC_EX_SET_CMD = 0x09, - MS_TPC_WRITE_QUAD_DATA = 0x0a, - MS_TPC_WRITE_IO_DATA = 0x0a, + MS_TPC_WRITE_IO_DATA = 0x0a, /* unverified */ MS_TPC_WRITE_REG = 0x0b, MS_TPC_WRITE_SHORT_DATA = 0x0c, - MS_TPC_WRITE_MG_DATA = 0x0c, MS_TPC_WRITE_LONG_DATA = 0x0d, MS_TPC_SET_CMD = 0x0e }; enum { - MS_CMD_BLOCK_END = 0x33, - MS_CMD_RESET = 0x3c, - MS_CMD_BLOCK_WRITE = 0x55, - MS_CMD_SLEEP = 0x5a, - MS_CMD_BLOCK_ERASE = 0x99, - MS_CMD_BLOCK_READ = 0xaa, - MS_CMD_CLEAR_BUF = 0xc3, - MS_CMD_FLASH_STOP = 0xcc, - MS_CMD_LOAD_ID = 0x60, - MS_CMD_CMP_ICV = 0x7f, - MSPRO_CMD_FORMAT = 0x10, - MSPRO_CMD_SLEEP = 0x11, - MSPRO_CMD_WAKEUP = 0x12, - MSPRO_CMD_READ_DATA = 0x20, - MSPRO_CMD_WRITE_DATA = 0x21, - MSPRO_CMD_READ_ATRB = 0x24, - MSPRO_CMD_STOP = 0x25, - MSPRO_CMD_ERASE = 0x26, - MSPRO_CMD_READ_QUAD = 0x27, - MSPRO_CMD_WRITE_QUAD = 0x28, - MSPRO_CMD_SET_IBD = 0x46, - MSPRO_CMD_GET_IBD = 0x47, - MSPRO_CMD_IN_IO_DATA = 0xb0, - MSPRO_CMD_OUT_IO_DATA = 0xb1, - MSPRO_CMD_READ_IO_ATRB = 0xb2, - MSPRO_CMD_IN_IO_FIFO = 0xb3, - MSPRO_CMD_OUT_IO_FIFO = 0xb4, - MSPRO_CMD_IN_IOM = 0xb5, - MSPRO_CMD_OUT_IOM = 0xb6, + MS_CMD_BLOCK_END = 0x33, + MS_CMD_RESET = 0x3c, + MS_CMD_BLOCK_WRITE = 0x55, + MS_CMD_SLEEP = 0x5a, + MS_CMD_BLOCK_ERASE = 0x99, + MS_CMD_BLOCK_READ = 0xaa, + MS_CMD_CLEAR_BUF = 0xc3, + MS_CMD_FLASH_STOP = 0xcc, + MSPRO_CMD_FORMAT = 0x10, + MSPRO_CMD_SLEEP = 0x11, + MSPRO_CMD_READ_DATA = 0x20, + MSPRO_CMD_WRITE_DATA = 0x21, + MSPRO_CMD_READ_ATRB = 0x24, + MSPRO_CMD_STOP = 0x25, + MSPRO_CMD_ERASE = 0x26, + MSPRO_CMD_SET_IBA = 0x46, + MSPRO_CMD_SET_IBD = 0x47 +/* + MSPRO_CMD_RESET + MSPRO_CMD_WAKEUP + MSPRO_CMD_IN_IO_DATA + MSPRO_CMD_OUT_IO_DATA + MSPRO_CMD_READ_IO_ATRB + MSPRO_CMD_IN_IO_FIFO + MSPRO_CMD_OUT_IO_FIFO + MSPRO_CMD_IN_IOM + MSPRO_CMD_OUT_IOM +*/ }; /*** Driver structures and functions ***/ @@ -209,8 +165,7 @@ enum memstick_param { MEMSTICK_POWER = 1, MEMSTICK_INTERFACE }; #define MEMSTICK_POWER_ON 1 #define MEMSTICK_SERIAL 0 -#define MEMSTICK_PAR4 1 -#define MEMSTICK_PAR8 2 +#define MEMSTICK_PARALLEL 1 struct memstick_host; struct memstick_driver; @@ -240,7 +195,11 @@ struct memstick_request { unsigned char data_dir:1, need_card_int:1, get_int_reg:1, - long_data:1; + io_type:2; +#define MEMSTICK_IO_NONE 0 +#define MEMSTICK_IO_VAL 1 +#define MEMSTICK_IO_SG 2 + unsigned char int_reg; int error; union { @@ -272,9 +231,8 @@ struct memstick_host { struct mutex lock; unsigned int id; unsigned int caps; -#define MEMSTICK_CAP_AUTO_GET_INT 1 -#define MEMSTICK_CAP_PAR4 2 -#define MEMSTICK_CAP_PAR8 4 +#define MEMSTICK_CAP_PARALLEL 1 +#define MEMSTICK_CAP_AUTO_GET_INT 2 struct work_struct media_checker; struct class_device cdev; @@ -312,8 +270,6 @@ int memstick_add_host(struct memstick_host *host); void memstick_remove_host(struct memstick_host *host); void memstick_free_host(struct memstick_host *host); void memstick_detect_change(struct memstick_host *host); -void memstick_suspend_host(struct memstick_host *host); -void memstick_resume_host(struct memstick_host *host); void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc, struct scatterlist *sg); diff --git a/trunk/include/linux/pci.h b/trunk/include/linux/pci.h index 38eff1947750..f3165e7ac431 100644 --- a/trunk/include/linux/pci.h +++ b/trunk/include/linux/pci.h @@ -389,13 +389,13 @@ struct pci_driver { #define to_pci_driver(drv) container_of(drv, struct pci_driver, driver) /** - * DEFINE_PCI_DEVICE_TABLE - macro used to describe a pci device table + * DECLARE_PCI_DEVICE_TABLE - macro used to describe a pci device table * @_table: device table name * * This macro is used to create a struct pci_device_id array (a device table) * in a generic manner. */ -#define DEFINE_PCI_DEVICE_TABLE(_table) \ +#define DECLARE_PCI_DEVICE_TABLE(_table) \ const struct pci_device_id _table[] __devinitconst /** diff --git a/trunk/include/linux/pci_ids.h b/trunk/include/linux/pci_ids.h index 70eb3c803d47..effdb558a588 100644 --- a/trunk/include/linux/pci_ids.h +++ b/trunk/include/linux/pci_ids.h @@ -2184,7 +2184,6 @@ #define PCI_DEVICE_ID_JMICRON_JMB366 0x2366 #define PCI_DEVICE_ID_JMICRON_JMB368 0x2368 #define PCI_DEVICE_ID_JMICRON_JMB38X_SD 0x2381 -#define PCI_DEVICE_ID_JMICRON_JMB38X_MS 0x2383 #define PCI_VENDOR_ID_KORENIX 0x1982 #define PCI_DEVICE_ID_KORENIX_JETCARDF0 0x1600 diff --git a/trunk/include/linux/tifm.h b/trunk/include/linux/tifm.h index 848c0f392541..da76ed85f595 100644 --- a/trunk/include/linux/tifm.h +++ b/trunk/include/linux/tifm.h @@ -70,9 +70,9 @@ enum { #define TIFM_FIFO_ENABLE 0x00000001 #define TIFM_FIFO_READY 0x00000001 -#define TIFM_FIFO_MORE 0x00000008 #define TIFM_FIFO_INT_SETALL 0x0000ffff #define TIFM_FIFO_INTMASK 0x00000005 +#define TIFM_FIFO_SIZE 0x00000200 #define TIFM_DMA_RESET 0x00000002 #define TIFM_DMA_TX 0x00008000 diff --git a/trunk/init/Kconfig b/trunk/init/Kconfig index a97924bc5b8d..074ac97f55e3 100644 --- a/trunk/init/Kconfig +++ b/trunk/init/Kconfig @@ -865,10 +865,38 @@ source "block/Kconfig" config PREEMPT_NOTIFIERS bool +choice + prompt "RCU implementation type:" + default CLASSIC_RCU + help + This allows you to choose either the classic RCU implementation + that is designed for best read-side performance on non-realtime + systems, or the preemptible RCU implementation for best latency + on realtime systems. Note that some kernel preemption modes + will restrict your choice. + + Select the default if you are unsure. + config CLASSIC_RCU - def_bool !PREEMPT_RCU + bool "Classic RCU" help This option selects the classic RCU implementation that is designed for best read-side performance on non-realtime - systems. Classic RCU is the default. Note that the - PREEMPT_RCU symbol is used to select/deselect this option. + systems. + + Say Y if you are unsure. + +config PREEMPT_RCU + bool "Preemptible RCU" + depends on PREEMPT + help + This option reduces the latency of the kernel by making certain + RCU sections preemptible. Normally RCU code is non-preemptible, if + this option is selected then read-only RCU sections become + preemptible. This helps latency, but may expose bugs due to + now-naive assumptions about each RCU read-side critical section + remaining on a given CPU through its execution. + + Say N if you are unsure. + +endchoice diff --git a/trunk/ipc/shm.c b/trunk/ipc/shm.c index cc63fae02f06..c47e87278a92 100644 --- a/trunk/ipc/shm.c +++ b/trunk/ipc/shm.c @@ -271,10 +271,9 @@ static struct mempolicy *shm_get_policy(struct vm_area_struct *vma, if (sfd->vm_ops->get_policy) pol = sfd->vm_ops->get_policy(vma, addr); - else if (vma->vm_policy) { + else if (vma->vm_policy) pol = vma->vm_policy; - mpol_get(pol); /* get_vma_policy() expects this */ - } else + else pol = current->mempolicy; return pol; } diff --git a/trunk/kernel/Kconfig.preempt b/trunk/kernel/Kconfig.preempt index 9fdba03dc1fc..0669b70fa6a3 100644 --- a/trunk/kernel/Kconfig.preempt +++ b/trunk/kernel/Kconfig.preempt @@ -52,23 +52,8 @@ config PREEMPT endchoice -config PREEMPT_RCU - bool "Preemptible RCU" - depends on PREEMPT - default n - help - This option reduces the latency of the kernel by making certain - RCU sections preemptible. Normally RCU code is non-preemptible, if - this option is selected then read-only RCU sections become - preemptible. This helps latency, but may expose bugs due to - now-naive assumptions about each RCU read-side critical section - remaining on a given CPU through its execution. - - Say N if you are unsure. - config RCU_TRACE bool "Enable tracing for RCU - currently stats in debugfs" - depends on PREEMPT_RCU select DEBUG_FS default y help diff --git a/trunk/kernel/module.c b/trunk/kernel/module.c index 5d437bffd8dc..be4807fb90e4 100644 --- a/trunk/kernel/module.c +++ b/trunk/kernel/module.c @@ -2178,20 +2178,10 @@ sys_init_module(void __user *umod, wake_up(&module_wq); return ret; } - if (ret > 0) { - printk(KERN_WARNING "%s: '%s'->init suspiciously returned %d, " - "it should follow 0/-E convention\n" - KERN_WARNING "%s: loading module anyway...\n", - __func__, mod->name, ret, - __func__); - dump_stack(); - } - - /* Now it's a first class citizen! Wake up anyone waiting for it. */ - mod->state = MODULE_STATE_LIVE; - wake_up(&module_wq); + /* Now it's a first class citizen! */ mutex_lock(&module_mutex); + mod->state = MODULE_STATE_LIVE; /* Drop initial reference. */ module_put(mod); unwind_remove_table(mod->unwind_info, 1); @@ -2200,6 +2190,7 @@ sys_init_module(void __user *umod, mod->init_size = 0; mod->init_text_size = 0; mutex_unlock(&module_mutex); + wake_up(&module_wq); return 0; } diff --git a/trunk/mm/filemap.c b/trunk/mm/filemap.c index df343d1e6345..ab98557e228e 100644 --- a/trunk/mm/filemap.c +++ b/trunk/mm/filemap.c @@ -1742,27 +1742,21 @@ size_t iov_iter_copy_from_user(struct page *page, } EXPORT_SYMBOL(iov_iter_copy_from_user); -void iov_iter_advance(struct iov_iter *i, size_t bytes) +static void __iov_iter_advance_iov(struct iov_iter *i, size_t bytes) { - BUG_ON(i->count < bytes); - if (likely(i->nr_segs == 1)) { i->iov_offset += bytes; - i->count -= bytes; } else { const struct iovec *iov = i->iov; size_t base = i->iov_offset; /* * The !iov->iov_len check ensures we skip over unlikely - * zero-length segments (without overruning the iovec). + * zero-length segments. */ - while (bytes || unlikely(!iov->iov_len && i->count)) { - int copy; + while (bytes || !iov->iov_len) { + int copy = min(bytes, iov->iov_len - base); - copy = min(bytes, iov->iov_len - base); - BUG_ON(!i->count || i->count < copy); - i->count -= copy; bytes -= copy; base += copy; if (iov->iov_len == base) { @@ -1774,6 +1768,14 @@ void iov_iter_advance(struct iov_iter *i, size_t bytes) i->iov_offset = base; } } + +void iov_iter_advance(struct iov_iter *i, size_t bytes) +{ + BUG_ON(i->count < bytes); + + __iov_iter_advance_iov(i, bytes); + i->count -= bytes; +} EXPORT_SYMBOL(iov_iter_advance); /* diff --git a/trunk/mm/hugetlb.c b/trunk/mm/hugetlb.c index 74c1b6b0b37b..dcacc811e70e 100644 --- a/trunk/mm/hugetlb.c +++ b/trunk/mm/hugetlb.c @@ -286,12 +286,6 @@ static struct page *alloc_buddy_huge_page(struct vm_area_struct *vma, spin_lock(&hugetlb_lock); if (page) { - /* - * This page is now managed by the hugetlb allocator and has - * no users -- drop the buddy allocator's reference. - */ - put_page_testzero(page); - VM_BUG_ON(page_count(page)); nid = page_to_nid(page); set_compound_page_dtor(page, free_huge_page); /* @@ -375,14 +369,13 @@ static int gather_surplus_pages(int delta) enqueue_huge_page(page); else { /* - * The page has a reference count of zero already, so - * call free_huge_page directly instead of using - * put_page. This must be done with hugetlb_lock + * Decrement the refcount and free the page using its + * destructor. This must be done with hugetlb_lock * unlocked which is safe because free_huge_page takes * hugetlb_lock before deciding how to free the page. */ spin_unlock(&hugetlb_lock); - free_huge_page(page); + put_page(page); spin_lock(&hugetlb_lock); } } diff --git a/trunk/mm/mempolicy.c b/trunk/mm/mempolicy.c index 3c3601121509..6c7ba1a63d23 100644 --- a/trunk/mm/mempolicy.c +++ b/trunk/mm/mempolicy.c @@ -1296,9 +1296,7 @@ struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr, unsigned nid; nid = interleave_nid(pol, vma, addr, HPAGE_SHIFT); - if (unlikely(pol != &default_policy && - pol != current->mempolicy)) - __mpol_free(pol); /* finished with pol */ + __mpol_free(pol); /* finished with pol */ return NODE_DATA(nid)->node_zonelists + gfp_zone(gfp_flags); } @@ -1362,9 +1360,6 @@ alloc_page_vma(gfp_t gfp, struct vm_area_struct *vma, unsigned long addr) unsigned nid; nid = interleave_nid(pol, vma, addr, PAGE_SHIFT); - if (unlikely(pol != &default_policy && - pol != current->mempolicy)) - __mpol_free(pol); /* finished with pol */ return alloc_page_interleave(gfp, 0, nid); } zl = zonelist_policy(gfp, pol);