From 73fd546aa75e9db02526bf304d4f736c4ec82b4b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 26 Oct 2007 09:32:16 +0200 Subject: SG: clear termination bit in sg_chain() Since we are using the last entry in the list, clear any possible termination bit that may have already been set. Pointed out by Rusty. Signed-off-by: Jens Axboe --- include/linux/scatterlist.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 457123171389..b2ec8421b89f 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -179,7 +179,11 @@ static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents, #ifndef ARCH_HAS_SG_CHAIN BUG(); #endif - prv[prv_nents - 1].page_link = (unsigned long) sgl | 0x01; + /* + * Set lowest bit to indicate a link pointer, and make sure to clear + * the termination bit if it happens to be set. + */ + prv[prv_nents - 1].page_link = ((unsigned long) sgl | 0x01) & ~0x02; } /** -- cgit v1.2.3 From 74eb94f7b84f4e631a0e020991fb16f17ce85ab7 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Fri, 26 Oct 2007 19:29:47 +0200 Subject: sg_last() should use unsigned loop index variable Clean up: fix a mixed sign comparison in sg_last() accidentally introduced by commit 70eb8040. The sign of the loop index variable should match the sign of the "nents" argument. Signed-off-by: Chuck Lever Signed-off-by: Jens Axboe --- include/linux/scatterlist.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index b2ec8421b89f..19b751aabd16 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -150,7 +150,7 @@ static inline struct scatterlist *sg_last(struct scatterlist *sgl, struct scatterlist *ret = &sgl[nents - 1]; #else struct scatterlist *sg, *ret = NULL; - int i; + unsigned int i; for_each_sg(sgl, sg, nents, i) ret = sg; -- cgit v1.2.3 From 513f54b78f9594927ede66b6c66a70c1bae0c4ca Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Fri, 26 Oct 2007 19:29:48 +0200 Subject: sg_init_table() should use unsigned loop index variable Clean up: fix a mixed sign comparison in sg_init_table() accidentally introduced by commit d6ec0842. The sign of the loop index variable should match the sign of the "nents" argument. Signed-off-by: Chuck Lever Cc: Jens Axboe Signed-off-by: Jens Axboe --- include/linux/scatterlist.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 19b751aabd16..32326c293d7b 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -243,7 +243,7 @@ static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents) sg_mark_end(sgl, nents); #ifdef CONFIG_DEBUG_SG { - int i; + unsigned int i; for (i = 0; i < nents; i++) sgl[i].sg_magic = SG_MAGIC; } -- cgit v1.2.3 From 054a5fbaceb2eb3a31ea843c1cf0b8e10b91478c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 25 Oct 2007 18:30:36 +0900 Subject: libata: track SLEEP state and issue SRST to wake it up ATA devices in SLEEP mode don't respond to any commands. SRST is necessary to wake it up. Till now, when a command is issued to a device in SLEEP mode, the command times out, which makes EH reset the device and retry the command after that, causing a long delay. This patch makes libata track SLEEP state and issue SRST automatically if a command is about to be issued to a device in SLEEP. Signed-off-by: Tejun Heo Cc: Bruce Allen Cc: Andrew Paprocki Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 12 ++++++++++++ drivers/ata/libata-eh.c | 4 +++- include/linux/ata.h | 1 + include/linux/libata.h | 1 + 4 files changed, 17 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 5aedd1af06e6..50ae20101d10 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5630,6 +5630,10 @@ void ata_qc_complete(struct ata_queued_cmd *qc) ehi->dev_action[dev->devno] |= ATA_EH_REVALIDATE; ata_port_schedule_eh(ap); break; + + case ATA_CMD_SLEEP: + dev->flags |= ATA_DFLAG_SLEEPING; + break; } __ata_qc_complete(qc); @@ -5769,6 +5773,14 @@ void ata_qc_issue(struct ata_queued_cmd *qc) qc->flags &= ~ATA_QCFLAG_DMAMAP; } + /* if device is sleeping, schedule softreset and abort the link */ + if (unlikely(qc->dev->flags & ATA_DFLAG_SLEEPING)) { + link->eh_info.action |= ATA_EH_SOFTRESET; + ata_ehi_push_desc(&link->eh_info, "waking up from sleep"); + ata_link_abort(link); + return; + } + ap->ops->qc_prep(qc); qc->err_mask |= ap->ops->qc_issue(qc); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 8cb35bb87605..496edaff119a 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2208,9 +2208,11 @@ int ata_eh_reset(struct ata_link *link, int classify, ata_link_for_each_dev(dev, link) { /* After the reset, the device state is PIO 0 * and the controller state is undefined. - * Record the mode. + * Reset also wakes up drives from sleeping + * mode. */ dev->pio_mode = XFER_PIO_0; + dev->flags &= ~ATA_DFLAG_SLEEPING; if (ata_link_offline(link)) continue; diff --git a/include/linux/ata.h b/include/linux/ata.h index 8263a7b74d34..e21c002c3a4a 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -180,6 +180,7 @@ enum { ATA_CMD_VERIFY_EXT = 0x42, ATA_CMD_STANDBYNOW1 = 0xE0, ATA_CMD_IDLEIMMEDIATE = 0xE1, + ATA_CMD_SLEEP = 0xE6, ATA_CMD_INIT_DEV_PARAMS = 0x91, ATA_CMD_READ_NATIVE_MAX = 0xF8, ATA_CMD_READ_NATIVE_MAX_EXT = 0x27, diff --git a/include/linux/libata.h b/include/linux/libata.h index 6fd24e03622e..2f0fc636b4b6 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -138,6 +138,7 @@ enum { ATA_DFLAG_PIO = (1 << 12), /* device limited to PIO mode */ ATA_DFLAG_NCQ_OFF = (1 << 13), /* device limited to non-NCQ mode */ ATA_DFLAG_SPUNDOWN = (1 << 14), /* XXX: for spindown_compat */ + ATA_DFLAG_SLEEPING = (1 << 15), /* device is sleeping */ ATA_DFLAG_INIT_MASK = (1 << 16) - 1, ATA_DFLAG_DETACH = (1 << 16), -- cgit v1.2.3 From 88ff6eafbb2a1c55f0f0e2e16d72e7b10d8ae8a5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 16 Oct 2007 14:21:24 -0700 Subject: libata: implement ata_wait_after_reset() On certain device/controller combination, 0xff status is asserted after reset and doesn't get cleared during 150ms post-reset wait. As 0xff status is interpreted as no device (for good reasons), this can lead to misdetection on such cases. This patch implements ata_wait_after_reset() which replaces the 150ms sleep and waits upto ATA_TMOUT_FF_WAIT if status is 0xff. ATA_TMOUT_FF_WAIT is currently 800ms which is enough for HHD424020F7SV00 to get detected but not enough for Quantum GoVault drive which is known to take upto 2s. Without parallel probing, spending 2s on 0xff port would incur too much delay on ata_piix's which use 0xff to indicate empty port and doesn't have SCR register, so GoVault needs to wait till parallel probing. Signed-off-by: Tejun Heo Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 11 ++------ drivers/ata/libata-core.c | 67 ++++++++++++++++++++++++++++++++++++--------- drivers/ata/pata_scc.c | 13 ++------- drivers/ata/sata_inic162x.c | 2 +- include/linux/libata.h | 8 ++++++ 5 files changed, 67 insertions(+), 34 deletions(-) (limited to 'include/linux') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 49cf4cf1a5a2..93bcb2cb3d35 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1153,15 +1153,8 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class, tf.ctl &= ~ATA_SRST; ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0); - /* spec mandates ">= 2ms" before checking status. - * We wait 150ms, because that was the magic delay used for - * ATAPI devices in Hale Landis's ATADRVR, for the period of time - * between when the ATA command register is written, and then - * status is checked. Because waiting for "a while" before - * checking status is fine, post SRST, we perform this magic - * delay here as well. - */ - msleep(150); + /* wait a while before checking status */ + ata_wait_after_reset(ap, deadline); rc = ata_wait_ready(ap, deadline); /* link occupied, -ENODEV too is an error */ diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 50ae20101d10..8ee56e5cfb0c 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -3117,6 +3117,55 @@ int ata_busy_sleep(struct ata_port *ap, return 0; } +/** + * ata_wait_after_reset - wait before checking status after reset + * @ap: port containing status register to be polled + * @deadline: deadline jiffies for the operation + * + * After reset, we need to pause a while before reading status. + * Also, certain combination of controller and device report 0xff + * for some duration (e.g. until SATA PHY is up and running) + * which is interpreted as empty port in ATA world. This + * function also waits for such devices to get out of 0xff + * status. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline) +{ + unsigned long until = jiffies + ATA_TMOUT_FF_WAIT; + + if (time_before(until, deadline)) + deadline = until; + + /* Spec mandates ">= 2ms" before checking status. We wait + * 150ms, because that was the magic delay used for ATAPI + * devices in Hale Landis's ATADRVR, for the period of time + * between when the ATA command register is written, and then + * status is checked. Because waiting for "a while" before + * checking status is fine, post SRST, we perform this magic + * delay here as well. + * + * Old drivers/ide uses the 2mS rule and then waits for ready. + */ + msleep(150); + + /* Wait for 0xff to clear. Some SATA devices take a long time + * to clear 0xff after reset. For example, HHD424020F7SV00 + * iVDR needs >= 800ms while. Quantum GoVault needs even more + * than that. + */ + while (1) { + u8 status = ata_chk_status(ap); + + if (status != 0xff || time_after(jiffies, deadline)) + return; + + msleep(50); + } +} + /** * ata_wait_ready - sleep until BSY clears, or timeout * @ap: port containing status register to be polled @@ -3254,17 +3303,8 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask, ap->ops->set_piomode(ap, dev); } - /* spec mandates ">= 2ms" before checking status. - * We wait 150ms, because that was the magic delay used for - * ATAPI devices in Hale Landis's ATADRVR, for the period of time - * between when the ATA command register is written, and then - * status is checked. Because waiting for "a while" before - * checking status is fine, post SRST, we perform this magic - * delay here as well. - * - * Old drivers/ide uses the 2mS rule and then waits for ready - */ - msleep(150); + /* wait a while before checking status */ + ata_wait_after_reset(ap, deadline); /* Before we perform post reset processing we want to see if * the bus shows 0xFF because the odd clown forgets the D7 @@ -3691,8 +3731,8 @@ int sata_std_hardreset(struct ata_link *link, unsigned int *class, return 0; } - /* wait a while before checking status, see SRST for more info */ - msleep(150); + /* wait a while before checking status */ + ata_wait_after_reset(ap, deadline); /* If PMP is supported, we have to do follow-up SRST. Note * that some PMPs don't send D2H Reg FIS after hardreset at @@ -7358,6 +7398,7 @@ EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); EXPORT_SYMBOL_GPL(ata_wait_register); EXPORT_SYMBOL_GPL(ata_busy_sleep); +EXPORT_SYMBOL_GPL(ata_wait_after_reset); EXPORT_SYMBOL_GPL(ata_wait_ready); EXPORT_SYMBOL_GPL(ata_port_queue_task); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index 55576138faea..ea2ef9fc15be 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c @@ -570,17 +570,8 @@ static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask, udelay(20); out_be32(ioaddr->ctl_addr, ap->ctl); - /* spec mandates ">= 2ms" before checking status. - * We wait 150ms, because that was the magic delay used for - * ATAPI devices in Hale Landis's ATADRVR, for the period of time - * between when the ATA command register is written, and then - * status is checked. Because waiting for "a while" before - * checking status is fine, post SRST, we perform this magic - * delay here as well. - * - * Old drivers/ide uses the 2mS rule and then waits for ready - */ - msleep(150); + /* wait a while before checking status */ + ata_wait_after_reset(ap, deadline); /* Before we perform post reset processing we want to see if * the bus shows 0xFF because the odd clown forgets the D7 diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 08595f34b3e8..b97d077e61b5 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -448,7 +448,7 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class, struct ata_taskfile tf; /* wait a while before checking status */ - msleep(150); + ata_wait_after_reset(ap, deadline); rc = ata_wait_ready(ap, deadline); /* link occupied, -ENODEV too is an error */ diff --git a/include/linux/libata.h b/include/linux/libata.h index 2f0fc636b4b6..439d40f86c55 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -235,6 +235,13 @@ enum { ATA_TMOUT_INTERNAL = 30 * HZ, ATA_TMOUT_INTERNAL_QUICK = 5 * HZ, + /* FIXME: GoVault needs 2s but we can't afford that without + * parallel probing. 800ms is enough for iVDR disk + * HHD424020F7SV00. Increase to 2secs when parallel probing + * is in place. + */ + ATA_TMOUT_FF_WAIT = 4 * HZ / 5, + /* ATA bus states */ BUS_UNKNOWN = 0, BUS_DMA = 1, @@ -800,6 +807,7 @@ extern void ata_host_resume(struct ata_host *host); extern int ata_ratelimit(void); extern int ata_busy_sleep(struct ata_port *ap, unsigned long timeout_pat, unsigned long timeout); +extern void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline); extern int ata_wait_ready(struct ata_port *ap, unsigned long deadline); extern void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data, unsigned long delay); -- cgit v1.2.3 From 6eca9004dfcb274a502438a591df5b197690afb1 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 25 Oct 2007 10:14:47 +0200 Subject: [BLOCK] Fix bad sharing of tag busy list on queues with shared tag maps For the locking to work, only the tag map and tag bit map may be shared (incidentally, I was just explaining this to Nick yesterday, but I apparently didn't review the code well enough myself). But we also share the busy list! The busy_list must be queue private, or we need a block_queue_tag covering lock as well. So we have to move the busy_list to the queue. This'll work fine, and it'll actually also fix a problem with blk_queue_invalidate_tags() which will invalidate tags across all shared queues. This is a bit confusing, the low level driver should call it for each queue seperately since otherwise you cannot kill tags on just a single queue for eg a hard drive that stops responding. Since the function has no callers currently, it's not an issue. Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 8 +++----- include/linux/blkdev.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index a8a181072bf8..56f2646612e6 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -791,7 +791,6 @@ static int __blk_free_tags(struct blk_queue_tag *bqt) retval = atomic_dec_and_test(&bqt->refcnt); if (retval) { BUG_ON(bqt->busy); - BUG_ON(!list_empty(&bqt->busy_list)); kfree(bqt->tag_index); bqt->tag_index = NULL; @@ -903,7 +902,6 @@ static struct blk_queue_tag *__blk_queue_init_tags(struct request_queue *q, if (init_tag_map(q, tags, depth)) goto fail; - INIT_LIST_HEAD(&tags->busy_list); tags->busy = 0; atomic_set(&tags->refcnt, 1); return tags; @@ -954,6 +952,7 @@ int blk_queue_init_tags(struct request_queue *q, int depth, */ q->queue_tags = tags; q->queue_flags |= (1 << QUEUE_FLAG_QUEUED); + INIT_LIST_HEAD(&q->tag_busy_list); return 0; fail: kfree(tags); @@ -1122,7 +1121,7 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq) rq->tag = tag; bqt->tag_index[tag] = rq; blkdev_dequeue_request(rq); - list_add(&rq->queuelist, &bqt->busy_list); + list_add(&rq->queuelist, &q->tag_busy_list); bqt->busy++; return 0; } @@ -1143,11 +1142,10 @@ EXPORT_SYMBOL(blk_queue_start_tag); **/ void blk_queue_invalidate_tags(struct request_queue *q) { - struct blk_queue_tag *bqt = q->queue_tags; struct list_head *tmp, *n; struct request *rq; - list_for_each_safe(tmp, n, &bqt->busy_list) { + list_for_each_safe(tmp, n, &q->tag_busy_list) { rq = list_entry_rq(tmp); if (rq->tag == -1) { diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index bbf906a0b419..8396db24d019 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -341,7 +341,6 @@ enum blk_queue_state { struct blk_queue_tag { struct request **tag_index; /* map of busy tags */ unsigned long *tag_map; /* bit map of free/busy tags */ - struct list_head busy_list; /* fifo list of busy tags */ int busy; /* current depth */ int max_depth; /* what we will send to device */ int real_max_depth; /* what the array can hold */ @@ -435,6 +434,7 @@ struct request_queue unsigned int dma_alignment; struct blk_queue_tag *queue_tags; + struct list_head tag_busy_list; unsigned int nr_sorted; unsigned int in_flight; -- cgit v1.2.3 From ca5cd877ae699e758e6f26efc11b01bf6631d427 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 29 Oct 2007 04:31:16 +0000 Subject: x86 merge fallout: uml Don't undef __i386__/__x86_64__ in uml anymore, make sure that (few) places that required adjusting the ifdefs got those. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/um/Makefile-i386 | 3 +-- arch/um/Makefile-x86_64 | 5 +---- drivers/char/mem.c | 4 ++-- drivers/md/raid6algos.c | 4 ++-- drivers/md/raid6mmx.c | 2 +- drivers/md/raid6sse1.c | 2 +- drivers/md/raid6sse2.c | 4 ++-- drivers/md/raid6x86.h | 2 +- include/asm-um/unistd.h | 1 - include/linux/eventpoll.h | 7 +------ kernel/signal.c | 2 +- 11 files changed, 13 insertions(+), 23 deletions(-) (limited to 'include/linux') diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index 0178df306939..08433f85189c 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 @@ -9,6 +9,7 @@ ELF_ARCH := $(SUBARCH) ELF_FORMAT := elf32-$(SUBARCH) OBJCOPYFLAGS := -O binary -R .note -R .comment -S HEADER_ARCH := x86 +CHECKFLAGS += -D__i386__ ifeq ("$(origin SUBARCH)", "command line") ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)") @@ -26,8 +27,6 @@ AFLAGS += -DCONFIG_X86_32 CONFIG_X86_32 := y export CONFIG_X86_32 -ARCH_KERNEL_DEFINES += -U__$(SUBARCH)__ -U$(SUBARCH) - # First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y. include $(srctree)/arch/i386/Makefile.cpu diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64 index fe5316f0c6a5..8ed362f93582 100644 --- a/arch/um/Makefile-x86_64 +++ b/arch/um/Makefile-x86_64 @@ -6,12 +6,9 @@ START := 0x60000000 _extra_flags_ = -fno-builtin -m64 -#We #undef __x86_64__ for kernelspace, not for userspace where -#it's needed for headers to work! -ARCH_KERNEL_DEFINES = -U__$(SUBARCH)__ KBUILD_CFLAGS += $(_extra_flags_) -CHECKFLAGS += -m64 +CHECKFLAGS += -m64 -D__x86_64__ KBUILD_AFLAGS += -m64 LDFLAGS += -m elf_x86_64 KBUILD_CPPFLAGS += -m64 diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 0e937f64a789..20070b7c573d 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -41,7 +41,7 @@ */ static inline int uncached_access(struct file *file, unsigned long addr) { -#if defined(__i386__) +#if defined(__i386__) && !defined(__arch_um__) /* * On the PPro and successors, the MTRRs are used to set * memory types for physical addresses outside main memory, @@ -57,7 +57,7 @@ static inline int uncached_access(struct file *file, unsigned long addr) test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) || test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) ) && addr >= __pa(high_memory); -#elif defined(__x86_64__) +#elif defined(__x86_64__) && !defined(__arch_um__) /* * This is broken because it can generate memory type aliases, * which can cause cache corruptions diff --git a/drivers/md/raid6algos.c b/drivers/md/raid6algos.c index 926576156578..77a6e4bf503d 100644 --- a/drivers/md/raid6algos.c +++ b/drivers/md/raid6algos.c @@ -52,7 +52,7 @@ const struct raid6_calls * const raid6_algos[] = { &raid6_intx16, &raid6_intx32, #endif -#if defined(__i386__) +#if defined(__i386__) && !defined(__arch_um__) &raid6_mmxx1, &raid6_mmxx2, &raid6_sse1x1, @@ -60,7 +60,7 @@ const struct raid6_calls * const raid6_algos[] = { &raid6_sse2x1, &raid6_sse2x2, #endif -#if defined(__x86_64__) +#if defined(__x86_64__) && !defined(__arch_um__) &raid6_sse2x1, &raid6_sse2x2, &raid6_sse2x4, diff --git a/drivers/md/raid6mmx.c b/drivers/md/raid6mmx.c index 6181a5a3365a..d4e4a1bd70ad 100644 --- a/drivers/md/raid6mmx.c +++ b/drivers/md/raid6mmx.c @@ -16,7 +16,7 @@ * MMX implementation of RAID-6 syndrome functions */ -#if defined(__i386__) +#if defined(__i386__) && !defined(__arch_um__) #include "raid6.h" #include "raid6x86.h" diff --git a/drivers/md/raid6sse1.c b/drivers/md/raid6sse1.c index f0a1ba8f40ba..0666237276ff 100644 --- a/drivers/md/raid6sse1.c +++ b/drivers/md/raid6sse1.c @@ -21,7 +21,7 @@ * worthwhile as a separate implementation. */ -#if defined(__i386__) +#if defined(__i386__) && !defined(__arch_um__) #include "raid6.h" #include "raid6x86.h" diff --git a/drivers/md/raid6sse2.c b/drivers/md/raid6sse2.c index 0f019762a7c3..b034ad868039 100644 --- a/drivers/md/raid6sse2.c +++ b/drivers/md/raid6sse2.c @@ -17,7 +17,7 @@ * */ -#if defined(__i386__) || defined(__x86_64__) +#if (defined(__i386__) || defined(__x86_64__)) && !defined(__arch_um__) #include "raid6.h" #include "raid6x86.h" @@ -161,7 +161,7 @@ const struct raid6_calls raid6_sse2x2 = { #endif -#ifdef __x86_64__ +#if defined(__x86_64__) && !defined(__arch_um__) /* * Unrolled-by-4 SSE2 implementation diff --git a/drivers/md/raid6x86.h b/drivers/md/raid6x86.h index 9111950414ff..99fea7a70ca7 100644 --- a/drivers/md/raid6x86.h +++ b/drivers/md/raid6x86.h @@ -19,7 +19,7 @@ #ifndef LINUX_RAID_RAID6X86_H #define LINUX_RAID_RAID6X86_H -#if defined(__i386__) || defined(__x86_64__) +#if (defined(__i386__) || defined(__x86_64__)) && !defined(__arch_um__) #ifdef __KERNEL__ /* Real code */ diff --git a/include/asm-um/unistd.h b/include/asm-um/unistd.h index 732c83f04c3d..38bd9d94ee46 100644 --- a/include/asm-um/unistd.h +++ b/include/asm-um/unistd.h @@ -14,7 +14,6 @@ extern int um_execve(const char *file, char *const argv[], char *const env[]); #ifdef __KERNEL__ /* We get __ARCH_WANT_OLD_STAT and __ARCH_WANT_STAT64 from the base arch */ -#define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_SYS_ALARM #define __ARCH_WANT_SYS_GETHOSTNAME diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h index d2a96cbf4f0e..cf79853967ff 100644 --- a/include/linux/eventpoll.h +++ b/include/linux/eventpoll.h @@ -32,18 +32,13 @@ * On x86-64 make the 64bit structure have the same alignment as the * 32bit structure. This makes 32bit emulation easier. * - * UML/x86_64 needs the same packing as x86_64 - UML + UML_X86 + - * 64_BIT adds up to UML/x86_64. + * UML/x86_64 needs the same packing as x86_64 */ #ifdef __x86_64__ #define EPOLL_PACKED __attribute__((packed)) #else -#if defined(CONFIG_UML) && defined(CONFIG_UML_X86) && defined(CONFIG_64BIT) -#define EPOLL_PACKED __attribute__((packed)) -#else #define EPOLL_PACKED #endif -#endif struct epoll_event { __u32 events; diff --git a/kernel/signal.c b/kernel/signal.c index 12006308c7eb..4537bdda1ebf 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -732,7 +732,7 @@ static void print_fatal_signal(struct pt_regs *regs, int signr) printk("%s/%d: potentially unexpected fatal signal %d.\n", current->comm, task_pid_nr(current), signr); -#ifdef __i386__ +#if defined(__i386__) && !defined(__arch_um__) printk("code at %08lx: ", regs->eip); { int i; -- cgit v1.2.3 From 2d8a972661832719931b0dd5b80e97215cb93d94 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 29 Oct 2007 04:37:58 +0000 Subject: SUNRPC endianness annotations rpcrdma stuff lacks endianness annotations for on-the-wire data. Signed-off-by: Al Viro Acked-by: David S. Miller Signed-off-by: Linus Torvalds --- include/linux/sunrpc/rpc_rdma.h | 32 ++++++++++++++++---------------- net/sunrpc/xprtrdma/rpc_rdma.c | 24 ++++++++++++------------ 2 files changed, 28 insertions(+), 28 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/rpc_rdma.h b/include/linux/sunrpc/rpc_rdma.h index 0013a0d8dc6b..87b895d5c786 100644 --- a/include/linux/sunrpc/rpc_rdma.h +++ b/include/linux/sunrpc/rpc_rdma.h @@ -41,17 +41,17 @@ #define _LINUX_SUNRPC_RPC_RDMA_H struct rpcrdma_segment { - uint32_t rs_handle; /* Registered memory handle */ - uint32_t rs_length; /* Length of the chunk in bytes */ - uint64_t rs_offset; /* Chunk virtual address or offset */ + __be32 rs_handle; /* Registered memory handle */ + __be32 rs_length; /* Length of the chunk in bytes */ + __be64 rs_offset; /* Chunk virtual address or offset */ }; /* * read chunk(s), encoded as a linked list. */ struct rpcrdma_read_chunk { - uint32_t rc_discrim; /* 1 indicates presence */ - uint32_t rc_position; /* Position in XDR stream */ + __be32 rc_discrim; /* 1 indicates presence */ + __be32 rc_position; /* Position in XDR stream */ struct rpcrdma_segment rc_target; }; @@ -66,29 +66,29 @@ struct rpcrdma_write_chunk { * write chunk(s), encoded as a counted array. */ struct rpcrdma_write_array { - uint32_t wc_discrim; /* 1 indicates presence */ - uint32_t wc_nchunks; /* Array count */ + __be32 wc_discrim; /* 1 indicates presence */ + __be32 wc_nchunks; /* Array count */ struct rpcrdma_write_chunk wc_array[0]; }; struct rpcrdma_msg { - uint32_t rm_xid; /* Mirrors the RPC header xid */ - uint32_t rm_vers; /* Version of this protocol */ - uint32_t rm_credit; /* Buffers requested/granted */ - uint32_t rm_type; /* Type of message (enum rpcrdma_proc) */ + __be32 rm_xid; /* Mirrors the RPC header xid */ + __be32 rm_vers; /* Version of this protocol */ + __be32 rm_credit; /* Buffers requested/granted */ + __be32 rm_type; /* Type of message (enum rpcrdma_proc) */ union { struct { /* no chunks */ - uint32_t rm_empty[3]; /* 3 empty chunk lists */ + __be32 rm_empty[3]; /* 3 empty chunk lists */ } rm_nochunks; struct { /* no chunks and padded */ - uint32_t rm_align; /* Padding alignment */ - uint32_t rm_thresh; /* Padding threshold */ - uint32_t rm_pempty[3]; /* 3 empty chunk lists */ + __be32 rm_align; /* Padding alignment */ + __be32 rm_thresh; /* Padding threshold */ + __be32 rm_pempty[3]; /* 3 empty chunk lists */ } rm_padded; - uint32_t rm_chunks[0]; /* read, write and reply chunks */ + __be32 rm_chunks[0]; /* read, write and reply chunks */ } rm_body; }; diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 12db63580427..f877b88091ce 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c @@ -181,7 +181,7 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target, struct rpcrdma_read_chunk *cur_rchunk = NULL; struct rpcrdma_write_array *warray = NULL; struct rpcrdma_write_chunk *cur_wchunk = NULL; - u32 *iptr = headerp->rm_body.rm_chunks; + __be32 *iptr = headerp->rm_body.rm_chunks; if (type == rpcrdma_readch || type == rpcrdma_areadch) { /* a read chunk - server will RDMA Read our memory */ @@ -217,7 +217,7 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target, cur_rchunk->rc_target.rs_handle = htonl(seg->mr_rkey); cur_rchunk->rc_target.rs_length = htonl(seg->mr_len); xdr_encode_hyper( - (u32 *)&cur_rchunk->rc_target.rs_offset, + (__be32 *)&cur_rchunk->rc_target.rs_offset, seg->mr_base); dprintk("RPC: %s: read chunk " "elem %d@0x%llx:0x%x pos %d (%s)\n", __func__, @@ -229,7 +229,7 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target, cur_wchunk->wc_target.rs_handle = htonl(seg->mr_rkey); cur_wchunk->wc_target.rs_length = htonl(seg->mr_len); xdr_encode_hyper( - (u32 *)&cur_wchunk->wc_target.rs_offset, + (__be32 *)&cur_wchunk->wc_target.rs_offset, seg->mr_base); dprintk("RPC: %s: %s chunk " "elem %d@0x%llx:0x%x (%s)\n", __func__, @@ -257,14 +257,14 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target, * finish off header. If write, marshal discrim and nchunks. */ if (cur_rchunk) { - iptr = (u32 *) cur_rchunk; + iptr = (__be32 *) cur_rchunk; *iptr++ = xdr_zero; /* finish the read chunk list */ *iptr++ = xdr_zero; /* encode a NULL write chunk list */ *iptr++ = xdr_zero; /* encode a NULL reply chunk */ } else { warray->wc_discrim = xdr_one; warray->wc_nchunks = htonl(nchunks); - iptr = (u32 *) cur_wchunk; + iptr = (__be32 *) cur_wchunk; if (type == rpcrdma_writech) { *iptr++ = xdr_zero; /* finish the write chunk list */ *iptr++ = xdr_zero; /* encode a NULL reply chunk */ @@ -559,7 +559,7 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst) * RDMA'd by server. See map at rpcrdma_create_chunks()! :-) */ static int -rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, u32 **iptrp) +rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, __be32 **iptrp) { unsigned int i, total_len; struct rpcrdma_write_chunk *cur_wchunk; @@ -573,7 +573,7 @@ rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, u32 **iptrp) struct rpcrdma_segment *seg = &cur_wchunk->wc_target; ifdebug(FACILITY) { u64 off; - xdr_decode_hyper((u32 *)&seg->rs_offset, &off); + xdr_decode_hyper((__be32 *)&seg->rs_offset, &off); dprintk("RPC: %s: chunk %d@0x%llx:0x%x\n", __func__, ntohl(seg->rs_length), @@ -585,7 +585,7 @@ rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, u32 **iptrp) } /* check and adjust for properly terminated write chunk */ if (wrchunk) { - u32 *w = (u32 *) cur_wchunk; + __be32 *w = (__be32 *) cur_wchunk; if (*w++ != xdr_zero) return -1; cur_wchunk = (struct rpcrdma_write_chunk *) w; @@ -593,7 +593,7 @@ rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, u32 **iptrp) if ((char *) cur_wchunk > rep->rr_base + rep->rr_len) return -1; - *iptrp = (u32 *) cur_wchunk; + *iptrp = (__be32 *) cur_wchunk; return total_len; } @@ -721,7 +721,7 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep) struct rpc_rqst *rqst; struct rpc_xprt *xprt = rep->rr_xprt; struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); - u32 *iptr; + __be32 *iptr; int i, rdmalen, status; /* Check status. If bad, signal disconnect and return rep to pool */ @@ -801,7 +801,7 @@ repost: r_xprt->rx_stats.total_rdma_reply += rdmalen; } else { /* else ordinary inline */ - iptr = (u32 *)((unsigned char *)headerp + 28); + iptr = (__be32 *)((unsigned char *)headerp + 28); rep->rr_len -= 28; /*sizeof *headerp;*/ status = rep->rr_len; } @@ -816,7 +816,7 @@ repost: headerp->rm_body.rm_chunks[2] != xdr_one || req->rl_nchunks == 0) goto badheader; - iptr = (u32 *)((unsigned char *)headerp + 28); + iptr = (__be32 *)((unsigned char *)headerp + 28); rdmalen = rpcrdma_count_chunks(rep, req->rl_nchunks, 0, &iptr); if (rdmalen < 0) goto badheader; -- cgit v1.2.3 From 142956af525002c5378e7d91d81a01189841a785 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 29 Oct 2007 05:11:28 +0000 Subject: fix abuses of ptrdiff_t Use of ptrdiff_t in places like - if (!access_ok(VERIFY_WRITE, u_tmp->rx_buf, u_tmp->len)) + if (!access_ok(VERIFY_WRITE, (u8 __user *) + (ptrdiff_t) u_tmp->rx_buf, + u_tmp->len)) is wrong; for one thing, it's a bad C (it's what uintptr_t is for; in general we are not even promised that ptrdiff_t is large enough to hold a pointer, just enough to hold a difference between two pointers within the same object). For another, it confuses the fsck out of sparse. Use unsigned long or uintptr_t instead. There are several places misusing ptrdiff_t; fixed. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/scsi/aacraid/commctrl.c | 12 ++++++------ drivers/scsi/aacraid/comminit.c | 2 +- drivers/scsi/aacraid/dpcsup.c | 2 +- drivers/spi/spidev.c | 6 +++--- include/linux/types.h | 2 ++ 5 files changed, 13 insertions(+), 11 deletions(-) (limited to 'include/linux') diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 72b0393b4596..1e6d7a9c75bf 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -391,7 +391,7 @@ static int close_getadapter_fib(struct aac_dev * dev, void __user *arg) /* * Extract the fibctx from the input parameters */ - if (fibctx->unique == (u32)(ptrdiff_t)arg) /* We found a winner */ + if (fibctx->unique == (u32)(uintptr_t)arg) /* We found a winner */ break; entry = entry->next; fibctx = NULL; @@ -590,7 +590,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) } addr = (u64)upsg->sg[i].addr[0]; addr += ((u64)upsg->sg[i].addr[1]) << 32; - sg_user[i] = (void __user *)(ptrdiff_t)addr; + sg_user[i] = (void __user *)(uintptr_t)addr; sg_list[i] = p; // save so we can clean up later sg_indx = i; @@ -633,7 +633,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) rcode = -ENOMEM; goto cleanup; } - sg_user[i] = (void __user *)(ptrdiff_t)usg->sg[i].addr; + sg_user[i] = (void __user *)(uintptr_t)usg->sg[i].addr; sg_list[i] = p; // save so we can clean up later sg_indx = i; @@ -664,7 +664,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) if (actual_fibsize64 == fibsize) { struct user_sgmap64* usg = (struct user_sgmap64 *)upsg; for (i = 0; i < upsg->count; i++) { - u64 addr; + uintptr_t addr; void* p; /* Does this really need to be GFP_DMA? */ p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA); @@ -676,7 +676,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) } addr = (u64)usg->sg[i].addr[0]; addr += ((u64)usg->sg[i].addr[1]) << 32; - sg_user[i] = (void __user *)(ptrdiff_t)addr; + sg_user[i] = (void __user *)addr; sg_list[i] = p; // save so we can clean up later sg_indx = i; @@ -704,7 +704,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) rcode = -ENOMEM; goto cleanup; } - sg_user[i] = (void __user *)(ptrdiff_t)upsg->sg[i].addr; + sg_user[i] = (void __user *)(uintptr_t)upsg->sg[i].addr; sg_list[i] = p; // save so we can clean up later sg_indx = i; diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 3009ad8c4073..8736813a0296 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -110,7 +110,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co /* * Align the beginning of Headers to commalign */ - align = (commalign - ((ptrdiff_t)(base) & (commalign - 1))); + align = (commalign - ((uintptr_t)(base) & (commalign - 1))); base = base + align; phys = phys + align; /* diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index fcd25f7d0bc6..e6032ffc66a6 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c @@ -254,7 +254,7 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index) kfree (fib); return 1; } - memcpy(hw_fib, (struct hw_fib *)(((ptrdiff_t)(dev->regs.sa)) + + memcpy(hw_fib, (struct hw_fib *)(((uintptr_t)(dev->regs.sa)) + (index & ~0x00000002L)), sizeof(struct hw_fib)); INIT_LIST_HEAD(&fib->fiblink); fib->type = FSAFS_NTC_FIB_CONTEXT; diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index c55459c592b8..b3518ca9f04e 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -184,14 +184,14 @@ static int spidev_message(struct spidev_data *spidev, if (u_tmp->rx_buf) { k_tmp->rx_buf = buf; if (!access_ok(VERIFY_WRITE, (u8 __user *) - (ptrdiff_t) u_tmp->rx_buf, + (uintptr_t) u_tmp->rx_buf, u_tmp->len)) goto done; } if (u_tmp->tx_buf) { k_tmp->tx_buf = buf; if (copy_from_user(buf, (const u8 __user *) - (ptrdiff_t) u_tmp->tx_buf, + (uintptr_t) u_tmp->tx_buf, u_tmp->len)) goto done; } @@ -224,7 +224,7 @@ static int spidev_message(struct spidev_data *spidev, for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) { if (u_tmp->rx_buf) { if (__copy_to_user((u8 __user *) - (ptrdiff_t) u_tmp->rx_buf, buf, + (uintptr_t) u_tmp->rx_buf, buf, u_tmp->len)) { status = -EFAULT; goto done; diff --git a/include/linux/types.h b/include/linux/types.h index 4f0dad21c917..f4f8d19158e4 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -37,6 +37,8 @@ typedef __kernel_gid32_t gid_t; typedef __kernel_uid16_t uid16_t; typedef __kernel_gid16_t gid16_t; +typedef unsigned long uintptr_t; + #ifdef CONFIG_UID16 /* This is defined by include/asm-{arch}/posix_types.h */ typedef __kernel_old_uid_t old_uid_t; -- cgit v1.2.3 From ca77329fb713b7fea6a307068e0dd0248e7aa640 Mon Sep 17 00:00:00 2001 From: Kristen Carlson Accardi Date: Thu, 25 Oct 2007 00:58:59 -0400 Subject: [libata] Link power management infrastructure Device Initiated Power Management, which is defined in SATA 2.5 can be enabled for disks which support it. This patch enables DIPM when the user sets the link power management policy to "min_power". Additionally, libata drivers can define a function (enable_pm) that will perform hardware specific actions to enable whatever power management policy the user set up for Host Initiated Power management (HIPM). This power management policy will be activated after all disks have been enumerated and intialized. Drivers should also define disable_pm, which will turn off link power management, but not change link power management policy. Documentation/scsi/link_power_management_policy.txt has additional information. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Jeff Garzik --- .../scsi/link_power_management_policy.txt | 19 ++ drivers/ata/libata-core.c | 196 ++++++++++++++++++++- drivers/ata/libata-eh.c | 4 + drivers/ata/libata-scsi.c | 68 +++++++ drivers/ata/libata.h | 2 + include/linux/ata.h | 21 +++ include/linux/libata.h | 21 ++- 7 files changed, 329 insertions(+), 2 deletions(-) create mode 100644 Documentation/scsi/link_power_management_policy.txt (limited to 'include/linux') diff --git a/Documentation/scsi/link_power_management_policy.txt b/Documentation/scsi/link_power_management_policy.txt new file mode 100644 index 000000000000..d18993d01884 --- /dev/null +++ b/Documentation/scsi/link_power_management_policy.txt @@ -0,0 +1,19 @@ +This parameter allows the user to set the link (interface) power management. +There are 3 possible options: + +Value Effect +---------------------------------------------------------------------------- +min_power Tell the controller to try to make the link use the + least possible power when possible. This may + sacrifice some performance due to increased latency + when coming out of lower power states. + +max_performance Generally, this means no power management. Tell + the controller to have performance be a priority + over power management. + +medium_power Tell the controller to enter a lower power state + when possible, but do not enter the lowest power + state, thus improving latency over min_power setting. + + diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 3891cdc6bd3d..513babe6a143 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -620,6 +620,177 @@ void ata_dev_disable(struct ata_device *dev) } } +static int ata_dev_set_dipm(struct ata_device *dev, enum link_pm policy) +{ + struct ata_link *link = dev->link; + struct ata_port *ap = link->ap; + u32 scontrol; + unsigned int err_mask; + int rc; + + /* + * disallow DIPM for drivers which haven't set + * ATA_FLAG_IPM. This is because when DIPM is enabled, + * phy ready will be set in the interrupt status on + * state changes, which will cause some drivers to + * think there are errors - additionally drivers will + * need to disable hot plug. + */ + if (!(ap->flags & ATA_FLAG_IPM) || !ata_dev_enabled(dev)) { + ap->pm_policy = NOT_AVAILABLE; + return -EINVAL; + } + + /* + * For DIPM, we will only enable it for the + * min_power setting. + * + * Why? Because Disks are too stupid to know that + * If the host rejects a request to go to SLUMBER + * they should retry at PARTIAL, and instead it + * just would give up. So, for medium_power to + * work at all, we need to only allow HIPM. + */ + rc = sata_scr_read(link, SCR_CONTROL, &scontrol); + if (rc) + return rc; + + switch (policy) { + case MIN_POWER: + /* no restrictions on IPM transitions */ + scontrol &= ~(0x3 << 8); + rc = sata_scr_write(link, SCR_CONTROL, scontrol); + if (rc) + return rc; + + /* enable DIPM */ + if (dev->flags & ATA_DFLAG_DIPM) + err_mask = ata_dev_set_feature(dev, + SETFEATURES_SATA_ENABLE, SATA_DIPM); + break; + case MEDIUM_POWER: + /* allow IPM to PARTIAL */ + scontrol &= ~(0x1 << 8); + scontrol |= (0x2 << 8); + rc = sata_scr_write(link, SCR_CONTROL, scontrol); + if (rc) + return rc; + + /* disable DIPM */ + if (ata_dev_enabled(dev) && (dev->flags & ATA_DFLAG_DIPM)) + err_mask = ata_dev_set_feature(dev, + SETFEATURES_SATA_DISABLE, SATA_DIPM); + break; + case NOT_AVAILABLE: + case MAX_PERFORMANCE: + /* disable all IPM transitions */ + scontrol |= (0x3 << 8); + rc = sata_scr_write(link, SCR_CONTROL, scontrol); + if (rc) + return rc; + + /* disable DIPM */ + if (ata_dev_enabled(dev) && (dev->flags & ATA_DFLAG_DIPM)) + err_mask = ata_dev_set_feature(dev, + SETFEATURES_SATA_DISABLE, SATA_DIPM); + break; + } + + /* FIXME: handle SET FEATURES failure */ + (void) err_mask; + + return 0; +} + +/** + * ata_dev_enable_pm - enable SATA interface power management + * @device - device to enable ipm for + * @policy - the link power management policy + * + * Enable SATA Interface power management. This will enable + * Device Interface Power Management (DIPM) for min_power + * policy, and then call driver specific callbacks for + * enabling Host Initiated Power management. + * + * Locking: Caller. + * Returns: -EINVAL if IPM is not supported, 0 otherwise. + */ +void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy) +{ + int rc = 0; + struct ata_port *ap = dev->link->ap; + + /* set HIPM first, then DIPM */ + if (ap->ops->enable_pm) + rc = ap->ops->enable_pm(ap, policy); + if (rc) + goto enable_pm_out; + rc = ata_dev_set_dipm(dev, policy); + +enable_pm_out: + if (rc) + ap->pm_policy = MAX_PERFORMANCE; + else + ap->pm_policy = policy; + return /* rc */; /* hopefully we can use 'rc' eventually */ +} + +/** + * ata_dev_disable_pm - disable SATA interface power management + * @device - device to enable ipm for + * + * Disable SATA Interface power management. This will disable + * Device Interface Power Management (DIPM) without changing + * policy, call driver specific callbacks for disabling Host + * Initiated Power management. + * + * Locking: Caller. + * Returns: void + */ +static void ata_dev_disable_pm(struct ata_device *dev) +{ + struct ata_port *ap = dev->link->ap; + + ata_dev_set_dipm(dev, MAX_PERFORMANCE); + if (ap->ops->disable_pm) + ap->ops->disable_pm(ap); +} + +void ata_lpm_schedule(struct ata_port *ap, enum link_pm policy) +{ + ap->pm_policy = policy; + ap->link.eh_info.action |= ATA_EHI_LPM; + ap->link.eh_info.flags |= ATA_EHI_NO_AUTOPSY; + ata_port_schedule_eh(ap); +} + +static void ata_lpm_enable(struct ata_host *host) +{ + struct ata_link *link; + struct ata_port *ap; + struct ata_device *dev; + int i; + + for (i = 0; i < host->n_ports; i++) { + ap = host->ports[i]; + ata_port_for_each_link(link, ap) { + ata_link_for_each_dev(dev, link) + ata_dev_disable_pm(dev); + } + } +} + +static void ata_lpm_disable(struct ata_host *host) +{ + int i; + + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap = host->ports[i]; + ata_lpm_schedule(ap, ap->pm_policy); + } +} + + /** * ata_devchk - PATA device presence detection * @ap: ATA channel to examine @@ -2101,6 +2272,13 @@ int ata_dev_configure(struct ata_device *dev) if (dev->flags & ATA_DFLAG_LBA48) dev->max_sectors = ATA_MAX_SECTORS_LBA48; + if (!(dev->horkage & ATA_HORKAGE_IPM)) { + if (ata_id_has_hipm(dev->id)) + dev->flags |= ATA_DFLAG_HIPM; + if (ata_id_has_dipm(dev->id)) + dev->flags |= ATA_DFLAG_DIPM; + } + if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) { /* Let the user know. We don't want to disallow opens for rescue purposes, or in case the vendor is just a blithering @@ -2126,6 +2304,13 @@ int ata_dev_configure(struct ata_device *dev) dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128, dev->max_sectors); + if (ata_dev_blacklisted(dev) & ATA_HORKAGE_IPM) { + dev->horkage |= ATA_HORKAGE_IPM; + + /* reset link pm_policy for this port to no pm */ + ap->pm_policy = MAX_PERFORMANCE; + } + if (ap->ops->dev_config) ap->ops->dev_config(dev); @@ -6361,6 +6546,12 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg) { int rc; + /* + * disable link pm on all ports before requesting + * any pm activity + */ + ata_lpm_enable(host); + rc = ata_host_request_pm(host, mesg, 0, ATA_EHI_QUIET, 1); if (rc == 0) host->dev->power.power_state = mesg; @@ -6383,6 +6574,9 @@ void ata_host_resume(struct ata_host *host) ata_host_request_pm(host, PMSG_ON, ATA_EH_SOFTRESET, ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0); host->dev->power.power_state = PMSG_ON; + + /* reenable link pm */ + ata_lpm_disable(host); } #endif @@ -6925,6 +7119,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) struct ata_port *ap = host->ports[i]; ata_scsi_scan_host(ap, 1); + ata_lpm_schedule(ap, ap->pm_policy); } return 0; @@ -7321,7 +7516,6 @@ const struct ata_port_info ata_dummy_port_info = { * likely to change as new drivers are added and updated. * Do not depend on ABI/API stability. */ - EXPORT_SYMBOL_GPL(sata_deb_timing_normal); EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug); EXPORT_SYMBOL_GPL(sata_deb_timing_long); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index ec55d63cf20e..fefea7470e51 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2628,6 +2628,10 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, ehc->i.flags &= ~ATA_EHI_SETMODE; } + if (ehc->i.action & ATA_EHI_LPM) + ata_link_for_each_dev(dev, link) + ata_dev_enable_pm(dev, ap->pm_policy); + /* this link is okay now */ ehc->i.flags = 0; continue; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index f752eddc19ed..93bd36c19690 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -110,6 +110,74 @@ static struct scsi_transport_template ata_scsi_transport_template = { }; +static const struct { + enum link_pm value; + const char *name; +} link_pm_policy[] = { + { NOT_AVAILABLE, "max_performance" }, + { MIN_POWER, "min_power" }, + { MAX_PERFORMANCE, "max_performance" }, + { MEDIUM_POWER, "medium_power" }, +}; + +const char *ata_scsi_lpm_get(enum link_pm policy) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(link_pm_policy); i++) + if (link_pm_policy[i].value == policy) + return link_pm_policy[i].name; + + return NULL; +} + +static ssize_t ata_scsi_lpm_put(struct class_device *class_dev, + const char *buf, size_t count) +{ + struct Scsi_Host *shost = class_to_shost(class_dev); + struct ata_port *ap = ata_shost_to_port(shost); + enum link_pm policy = 0; + int i; + + /* + * we are skipping array location 0 on purpose - this + * is because a value of NOT_AVAILABLE is displayed + * to the user as max_performance, but when the user + * writes "max_performance", they actually want the + * value to match MAX_PERFORMANCE. + */ + for (i = 1; i < ARRAY_SIZE(link_pm_policy); i++) { + const int len = strlen(link_pm_policy[i].name); + if (strncmp(link_pm_policy[i].name, buf, len) == 0 && + buf[len] == '\n') { + policy = link_pm_policy[i].value; + break; + } + } + if (!policy) + return -EINVAL; + + ata_lpm_schedule(ap, policy); + return count; +} + +static ssize_t +ata_scsi_lpm_show(struct class_device *class_dev, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(class_dev); + struct ata_port *ap = ata_shost_to_port(shost); + const char *policy = + ata_scsi_lpm_get(ap->pm_policy); + + if (!policy) + return -EINVAL; + + return snprintf(buf, 23, "%s\n", policy); +} +CLASS_DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR, + ata_scsi_lpm_show, ata_scsi_lpm_put); +EXPORT_SYMBOL_GPL(class_device_attr_link_power_management_policy); + static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 90df58a3edc9..0e6cf3a484dc 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -101,6 +101,8 @@ extern int sata_link_init_spd(struct ata_link *link); extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg); extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); extern struct ata_port *ata_port_alloc(struct ata_host *host); +extern void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy); +extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm); /* libata-acpi.c */ #ifdef CONFIG_ATA_ACPI diff --git a/include/linux/ata.h b/include/linux/ata.h index e21c002c3a4a..128dc7ad4901 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -236,6 +236,7 @@ enum { /* SETFEATURE Sector counts for SATA features */ SATA_AN = 0x05, /* Asynchronous Notification */ + SATA_DIPM = 0x03, /* Device Initiated Power Management */ /* ATAPI stuff */ ATAPI_PKT_DMA = (1 << 0), @@ -378,6 +379,26 @@ struct ata_taskfile { #define ata_id_cdb_intr(id) (((id)[0] & 0x60) == 0x20) +static inline bool ata_id_has_hipm(const u16 *id) +{ + u16 val = id[76]; + + if (val == 0 || val == 0xffff) + return false; + + return val & (1 << 9); +} + +static inline bool ata_id_has_dipm(const u16 *id) +{ + u16 val = id[78]; + + if (val == 0 || val == 0xffff) + return false; + + return val & (1 << 3); +} + static inline int ata_id_has_fua(const u16 *id) { if ((id[84] & 0xC000) != 0x4000) diff --git a/include/linux/libata.h b/include/linux/libata.h index 439d40f86c55..147ccc40c8af 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -133,6 +133,8 @@ enum { ATA_DFLAG_ACPI_PENDING = (1 << 5), /* ACPI resume action pending */ ATA_DFLAG_ACPI_FAILED = (1 << 6), /* ACPI on devcfg has failed */ ATA_DFLAG_AN = (1 << 7), /* AN configured */ + ATA_DFLAG_HIPM = (1 << 8), /* device supports HIPM */ + ATA_DFLAG_DIPM = (1 << 9), /* device supports DIPM */ ATA_DFLAG_CFG_MASK = (1 << 12) - 1, ATA_DFLAG_PIO = (1 << 12), /* device limited to PIO mode */ @@ -186,6 +188,7 @@ enum { ATA_FLAG_ACPI_SATA = (1 << 17), /* need native SATA ACPI layout */ ATA_FLAG_AN = (1 << 18), /* controller supports AN */ ATA_FLAG_PMP = (1 << 19), /* controller supports PMP */ + ATA_FLAG_IPM = (1 << 20), /* driver can handle IPM */ /* The following flag belongs to ap->pflags but is kept in * ap->flags because it's referenced in many LLDs and will be @@ -302,6 +305,7 @@ enum { ATA_EHI_RESUME_LINK = (1 << 1), /* resume link (reset modifier) */ ATA_EHI_NO_AUTOPSY = (1 << 2), /* no autopsy */ ATA_EHI_QUIET = (1 << 3), /* be quiet */ + ATA_EHI_LPM = (1 << 4), /* link power management action */ ATA_EHI_DID_SOFTRESET = (1 << 16), /* already soft-reset this port */ ATA_EHI_DID_HARDRESET = (1 << 17), /* already soft-reset this port */ @@ -333,6 +337,7 @@ enum { ATA_HORKAGE_BROKEN_HPA = (1 << 4), /* Broken HPA */ ATA_HORKAGE_SKIP_PM = (1 << 5), /* Skip PM operations */ ATA_HORKAGE_HPA_SIZE = (1 << 6), /* native size off by one */ + ATA_HORKAGE_IPM = (1 << 7), /* Link PM problems */ /* DMA mask for user DMA control: User visible values; DO NOT renumber */ @@ -378,6 +383,18 @@ typedef int (*ata_reset_fn_t)(struct ata_link *link, unsigned int *classes, unsigned long deadline); typedef void (*ata_postreset_fn_t)(struct ata_link *link, unsigned int *classes); +/* + * host pm policy: If you alter this, you also need to alter libata-scsi.c + * (for the ascii descriptions) + */ +enum link_pm { + NOT_AVAILABLE, + MIN_POWER, + MAX_PERFORMANCE, + MEDIUM_POWER, +}; +extern struct class_device_attribute class_device_attr_link_power_management_policy; + struct ata_ioports { void __iomem *cmd_addr; void __iomem *data_addr; @@ -624,6 +641,7 @@ struct ata_port { pm_message_t pm_mesg; int *pm_result; + enum link_pm pm_policy; struct timer_list fastdrain_timer; unsigned long fastdrain_cnt; @@ -691,7 +709,8 @@ struct ata_port_operations { int (*port_suspend) (struct ata_port *ap, pm_message_t mesg); int (*port_resume) (struct ata_port *ap); - + int (*enable_pm) (struct ata_port *ap, enum link_pm policy); + void (*disable_pm) (struct ata_port *ap); int (*port_start) (struct ata_port *ap); void (*port_stop) (struct ata_port *ap); -- cgit v1.2.3 From 73a2bcb0edb9ffb0b007b3546b430e2c6e415eee Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 29 Oct 2007 21:18:11 +0100 Subject: sched: keep utime/stime monotonic keep utime/stime monotonic. cpustats use utime/stime as a ratio against sum_exec_runtime, as a consequence it can happen - when the ratio changes faster than time accumulates - that either can be appear to go backwards. Signed-off-by: Peter Zijlstra Signed-off-by: Ingo Molnar --- fs/proc/array.c | 3 ++- include/linux/sched.h | 1 + kernel/fork.c | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/fs/proc/array.c b/fs/proc/array.c index 63c95afb561f..d80baaabf835 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -358,7 +358,8 @@ static cputime_t task_utime(struct task_struct *p) } utime = (clock_t)temp; - return clock_t_to_cputime(utime); + p->prev_utime = max(p->prev_utime, clock_t_to_cputime(utime)); + return p->prev_utime; } static cputime_t task_stime(struct task_struct *p) diff --git a/include/linux/sched.h b/include/linux/sched.h index 3c07d595979f..b0b1fe6e0b17 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1009,6 +1009,7 @@ struct task_struct { unsigned int rt_priority; cputime_t utime, stime, utimescaled, stimescaled; cputime_t gtime; + cputime_t prev_utime; unsigned long nvcsw, nivcsw; /* context switch counts */ struct timespec start_time; /* monotonic time */ struct timespec real_start_time; /* boot based time */ diff --git a/kernel/fork.c b/kernel/fork.c index ddafdfac9456..a65bfc47177c 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1056,6 +1056,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, p->gtime = cputime_zero; p->utimescaled = cputime_zero; p->stimescaled = cputime_zero; + p->prev_utime = cputime_zero; #ifdef CONFIG_TASK_XACCT p->rchar = 0; /* I/O counter: bytes read */ -- cgit v1.2.3 From 6a22c57b8d2a62dea7280a6b2ac807a539ef0716 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 29 Oct 2007 11:36:04 -0700 Subject: Revert "x86_64: allocate sparsemem memmap above 4G" This reverts commit 2e1c49db4c640b35df13889b86b9d62215ade4b6. First off, testing in Fedora has shown it to cause boot failures, bisected down by Martin Ebourne, and reported by Dave Jobes. So the commit will likely be reverted in the 2.6.23 stable kernels. Secondly, in the 2.6.24 model, x86-64 has now grown support for SPARSEMEM_VMEMMAP, which disables the relevant code anyway, so while the bug is not visible any more, it's become invisible due to the code just being irrelevant and no longer enabled on the only architecture that this ever affected. Reported-by: Dave Jones Tested-by: Martin Ebourne Cc: Zou Nan hai Cc: Suresh Siddha Cc: Andrew Morton Acked-by: Andy Whitcroft Signed-off-by: Linus Torvalds --- arch/x86/mm/init_64.c | 6 ------ include/linux/bootmem.h | 1 - mm/sparse.c | 11 ----------- 3 files changed, 18 deletions(-) (limited to 'include/linux') diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 1e3862e41065..a7308b2cd058 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -728,12 +728,6 @@ int in_gate_area_no_task(unsigned long addr) return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END); } -void * __init alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size) -{ - return __alloc_bootmem_core(pgdat->bdata, size, - SMP_CACHE_BYTES, (4UL*1024*1024*1024), 0); -} - const char *arch_vma_name(struct vm_area_struct *vma) { if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index c83534ee1e79..0365ec9fc0c9 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h @@ -59,7 +59,6 @@ extern void *__alloc_bootmem_core(struct bootmem_data *bdata, unsigned long align, unsigned long goal, unsigned long limit); -extern void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size); #ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE extern void reserve_bootmem(unsigned long addr, unsigned long size); diff --git a/mm/sparse.c b/mm/sparse.c index 08fb14f5eea3..e06f514fe04f 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -220,12 +220,6 @@ static int __meminit sparse_init_one_section(struct mem_section *ms, return 1; } -__attribute__((weak)) __init -void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size) -{ - return NULL; -} - static unsigned long usemap_size(void) { unsigned long size_bytes; @@ -267,11 +261,6 @@ struct page __init *sparse_mem_map_populate(unsigned long pnum, int nid) if (map) return map; - map = alloc_bootmem_high_node(NODE_DATA(nid), - sizeof(struct page) * PAGES_PER_SECTION); - if (map) - return map; - map = alloc_bootmem_node(NODE_DATA(nid), sizeof(struct page) * PAGES_PER_SECTION); return map; -- cgit v1.2.3 From 9301899be75b464ef097f0b5af7af6d9bd8f68a7 Mon Sep 17 00:00:00 2001 From: Balbir Singh Date: Tue, 30 Oct 2007 00:26:32 +0100 Subject: sched: fix /proc//stat stime/utime monotonicity, part 2 Extend Peter's patch to fix accounting issues, by keeping stime monotonic too. Signed-off-by: Balbir Singh Signed-off-by: Ingo Molnar Tested-by: Frans Pop --- fs/proc/array.c | 3 ++- include/linux/sched.h | 2 +- kernel/fork.c | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/fs/proc/array.c b/fs/proc/array.c index d80baaabf835..eba339ecba27 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -374,7 +374,8 @@ static cputime_t task_stime(struct task_struct *p) stime = nsec_to_clock_t(p->se.sum_exec_runtime) - cputime_to_clock_t(task_utime(p)); - return clock_t_to_cputime(stime); + p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime)); + return p->prev_stime; } #endif diff --git a/include/linux/sched.h b/include/linux/sched.h index b0b1fe6e0b17..155d7438f7ad 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1009,7 +1009,7 @@ struct task_struct { unsigned int rt_priority; cputime_t utime, stime, utimescaled, stimescaled; cputime_t gtime; - cputime_t prev_utime; + cputime_t prev_utime, prev_stime; unsigned long nvcsw, nivcsw; /* context switch counts */ struct timespec start_time; /* monotonic time */ struct timespec real_start_time; /* boot based time */ diff --git a/kernel/fork.c b/kernel/fork.c index a65bfc47177c..28a740151988 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1057,6 +1057,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, p->utimescaled = cputime_zero; p->stimescaled = cputime_zero; p->prev_utime = cputime_zero; + p->prev_stime = cputime_zero; #ifdef CONFIG_TASK_XACCT p->rchar = 0; /* I/O counter: bytes read */ -- cgit v1.2.3 From 502ef38da15d817f8e67acefc12dc2212f7f8aa1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 30 Oct 2007 01:19:19 -0700 Subject: [TIPC]: Add tipc_config.h to include/linux/Kbuild. Needed, as reported in: http://bugzilla.kernel.org/show_bug.cgi?id=9260 Signed-off-by: David S. Miller --- include/linux/Kbuild | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 6a65231bc785..bd33c22315c1 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -149,6 +149,7 @@ header-y += ticable.h header-y += times.h header-y += tiocl.h header-y += tipc.h +header-y += tipc_config.h header-y += toshiba.h header-y += ultrasound.h header-y += un.h -- cgit v1.2.3 From e027bd36c146582cef382364e5c826db93d4427b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 26 Oct 2007 16:19:26 +0900 Subject: libata: implement and use ATA_QCFLAG_QUIET Implement ATA_QCFLAG_QUIET which indicates that there's no need to report if the command fails with AC_ERR_DEV and set it for passthrough commands. Combined with previous changes, this now makes device errors for all direct commands reported directly to the issuer without going through EH actions and reporting. Note that EH is still invoked after non-IO device errors to determine the nature of the error and resume command execution (some controller requires special care after error to continue). It just performs default maintenance after error, examines what's going on, realizes that it's none of its business and reports the command failure without logging any error messages. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 4 +++- drivers/ata/libata-scsi.c | 4 ++-- include/linux/libata.h | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 3c6ad7d949c1..8d64f8fd8f1d 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1878,7 +1878,9 @@ static void ata_eh_link_report(struct ata_link *link) for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); - if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link) + if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link || + ((qc->flags & ATA_QCFLAG_QUIET) && + qc->err_mask == AC_ERR_DEV)) continue; if (qc->flags & ATA_QCFLAG_SENSE_VALID && !qc->err_mask) continue; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 6ef5ecb917ce..fc89590d3772 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2767,8 +2767,8 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) */ qc->nbytes = scsi_bufflen(scmd); - /* request result TF */ - qc->flags |= ATA_QCFLAG_RESULT_TF; + /* request result TF and be quiet about device error */ + qc->flags |= ATA_QCFLAG_RESULT_TF | ATA_QCFLAG_QUIET; return 0; diff --git a/include/linux/libata.h b/include/linux/libata.h index 147ccc40c8af..1e277852ba42 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -221,6 +221,7 @@ enum { ATA_QCFLAG_IO = (1 << 3), /* standard IO command */ ATA_QCFLAG_RESULT_TF = (1 << 4), /* result TF requested */ ATA_QCFLAG_CLEAR_EXCL = (1 << 5), /* clear excl_link on completion */ + ATA_QCFLAG_QUIET = (1 << 6), /* don't report device error */ ATA_QCFLAG_FAILED = (1 << 16), /* cmd failed and is owned by EH */ ATA_QCFLAG_SENSE_VALID = (1 << 17), /* sense data valid */ -- cgit v1.2.3 From 64e862a579015d229b8e40b6bc4ac3612e9656e1 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 29 Oct 2007 14:37:13 -0700 Subject: IPMI: fix comparison in demangle_device_id Coverity spotted some incorrect code in a recent change to the IPMI driver; this patch make sure the data is really long enough to pull the manufacturer id and product id out of a get device id message. Signed-off-by: Corey Minyard Cc: Adrian Bunk Cc: Stian Jordet Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/ipmi_smi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h index 56ae438ae510..6e8cec503380 100644 --- a/include/linux/ipmi_smi.h +++ b/include/linux/ipmi_smi.h @@ -173,7 +173,7 @@ static inline int ipmi_demangle_device_id(const unsigned char *data, id->firmware_revision_2 = data[3]; id->ipmi_version = data[4]; id->additional_device_support = data[5]; - if (data_len >= 6) { + if (data_len >= 11) { id->manufacturer_id = (data[6] | (data[7] << 8) | (data[8] << 16)); id->product_id = data[9] | (data[10] << 8); -- cgit v1.2.3 From 3077d78a74a62c5f531b005efdbcc01a3f2f09ca Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Mon, 29 Oct 2007 15:39:01 -0700 Subject: mv643xx_eth: Fix MV643XX_ETH offsets used by Pegasos 2 In the mv643xx_eth driver, we now use offsets from the ethernet register block within the chip, but the pegasos 2 platform still needs offsets from the full chip's register base address. Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- include/linux/mv643xx_eth.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mv643xx_eth.h b/include/linux/mv643xx_eth.h index 8df230a279a0..30e11aa3c1c9 100644 --- a/include/linux/mv643xx_eth.h +++ b/include/linux/mv643xx_eth.h @@ -8,9 +8,9 @@ #define MV643XX_ETH_NAME "mv643xx_eth" #define MV643XX_ETH_SHARED_REGS 0x2000 #define MV643XX_ETH_SHARED_REGS_SIZE 0x2000 -#define MV643XX_ETH_BAR_4 0x220 -#define MV643XX_ETH_SIZE_REG_4 0x224 -#define MV643XX_ETH_BASE_ADDR_ENABLE_REG 0x0290 +#define MV643XX_ETH_BAR_4 0x2220 +#define MV643XX_ETH_SIZE_REG_4 0x2224 +#define MV643XX_ETH_BASE_ADDR_ENABLE_REG 0x2290 struct mv643xx_eth_platform_data { int port_number; -- cgit v1.2.3 From 97ef1bb0c8e371b7988287f38bd107c4aa14d78d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 30 Oct 2007 21:44:00 -0700 Subject: [TIPC]: Fix headercheck wrt. tipc_config.h It wants string functions like memcpy() for inline routines, and these define userland interfaces. The only clean way to deal with this is to simply put linux/string.h into unifdef-y and have it include when not-__KERNEL__. Signed-off-by: David S. Miller --- include/linux/Kbuild | 1 + include/linux/string.h | 12 +++--------- 2 files changed, 4 insertions(+), 9 deletions(-) (limited to 'include/linux') diff --git a/include/linux/Kbuild b/include/linux/Kbuild index bd33c22315c1..37bfa19d8064 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -326,6 +326,7 @@ unifdef-y += sonypi.h unifdef-y += soundcard.h unifdef-y += stat.h unifdef-y += stddef.h +unifdef-y += string.h unifdef-y += synclink.h unifdef-y += sysctl.h unifdef-y += tcp.h diff --git a/include/linux/string.h b/include/linux/string.h index 836062b7582a..c5d3fcad7b57 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -3,16 +3,14 @@ /* We don't want strings.h stuff being user by user stuff by accident */ -#ifdef __KERNEL__ +#ifndef __KERNEL__ +#include +#else #include /* for inline */ #include /* for size_t */ #include /* for NULL */ -#ifdef __cplusplus -extern "C" { -#endif - extern char *strndup_user(const char __user *, long); /* @@ -111,9 +109,5 @@ extern void *kmemdup(const void *src, size_t len, gfp_t gfp); extern char **argv_split(gfp_t gfp, const char *str, int *argcp); extern void argv_free(char **argv); -#ifdef __cplusplus -} -#endif - #endif #endif /* _LINUX_STRING_H_ */ -- cgit v1.2.3 From fcd239d3d5575e5cc63aab5c33cf6dc66904f6d6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 17 Oct 2007 15:52:43 -0600 Subject: Driver core: remove class_device_*_bin_file These functions are not used by anyone, so remove them from the tree. The class_device code will be removed soon anyway, so no future users will ever be possible. Signed-off-by: Greg Kroah-Hartman --- drivers/base/class.c | 18 ------------------ include/linux/device.h | 4 ---- 2 files changed, 22 deletions(-) (limited to 'include/linux') diff --git a/drivers/base/class.c b/drivers/base/class.c index a863bb091e11..f6ebe6af3ef2 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -257,22 +257,6 @@ void class_device_remove_file(struct class_device * class_dev, sysfs_remove_file(&class_dev->kobj, &attr->attr); } -int class_device_create_bin_file(struct class_device *class_dev, - struct bin_attribute *attr) -{ - int error = -EINVAL; - if (class_dev) - error = sysfs_create_bin_file(&class_dev->kobj, attr); - return error; -} - -void class_device_remove_bin_file(struct class_device *class_dev, - struct bin_attribute *attr) -{ - if (class_dev) - sysfs_remove_bin_file(&class_dev->kobj, attr); -} - static ssize_t class_device_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) @@ -885,8 +869,6 @@ EXPORT_SYMBOL_GPL(class_device_create); EXPORT_SYMBOL_GPL(class_device_destroy); EXPORT_SYMBOL_GPL(class_device_create_file); EXPORT_SYMBOL_GPL(class_device_remove_file); -EXPORT_SYMBOL_GPL(class_device_create_bin_file); -EXPORT_SYMBOL_GPL(class_device_remove_bin_file); EXPORT_SYMBOL_GPL(class_interface_register); EXPORT_SYMBOL_GPL(class_interface_unregister); diff --git a/include/linux/device.h b/include/linux/device.h index 2e15822fe409..2c5e49d446b8 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -291,10 +291,6 @@ extern void class_device_put(struct class_device *); extern void class_device_remove_file(struct class_device *, const struct class_device_attribute *); -extern int __must_check class_device_create_bin_file(struct class_device *, - struct bin_attribute *); -extern void class_device_remove_bin_file(struct class_device *, - struct bin_attribute *); struct class_interface { struct list_head node; -- cgit v1.2.3 From d919fd433b5823d1cf9d0688eb2eec183de9b74c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 31 Oct 2007 12:51:29 -0700 Subject: Revert "Driver core: remove class_device_*_bin_file" This reverts commit fcd239d3d5575e5cc63aab5c33cf6dc66904f6d6. I messed up, ia64 still uses these files in the current tree, and now can not build the pci code, which all ia64 boxes seem to require :) This fixes that mistake. Signed-off-by: Greg Kroah-Hartman --- drivers/base/class.c | 18 ++++++++++++++++++ include/linux/device.h | 4 ++++ 2 files changed, 22 insertions(+) (limited to 'include/linux') diff --git a/drivers/base/class.c b/drivers/base/class.c index f6ebe6af3ef2..a863bb091e11 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -257,6 +257,22 @@ void class_device_remove_file(struct class_device * class_dev, sysfs_remove_file(&class_dev->kobj, &attr->attr); } +int class_device_create_bin_file(struct class_device *class_dev, + struct bin_attribute *attr) +{ + int error = -EINVAL; + if (class_dev) + error = sysfs_create_bin_file(&class_dev->kobj, attr); + return error; +} + +void class_device_remove_bin_file(struct class_device *class_dev, + struct bin_attribute *attr) +{ + if (class_dev) + sysfs_remove_bin_file(&class_dev->kobj, attr); +} + static ssize_t class_device_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) @@ -869,6 +885,8 @@ EXPORT_SYMBOL_GPL(class_device_create); EXPORT_SYMBOL_GPL(class_device_destroy); EXPORT_SYMBOL_GPL(class_device_create_file); EXPORT_SYMBOL_GPL(class_device_remove_file); +EXPORT_SYMBOL_GPL(class_device_create_bin_file); +EXPORT_SYMBOL_GPL(class_device_remove_bin_file); EXPORT_SYMBOL_GPL(class_interface_register); EXPORT_SYMBOL_GPL(class_interface_unregister); diff --git a/include/linux/device.h b/include/linux/device.h index 2c5e49d446b8..2e15822fe409 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -291,6 +291,10 @@ extern void class_device_put(struct class_device *); extern void class_device_remove_file(struct class_device *, const struct class_device_attribute *); +extern int __must_check class_device_create_bin_file(struct class_device *, + struct bin_attribute *); +extern void class_device_remove_bin_file(struct class_device *, + struct bin_attribute *); struct class_interface { struct list_head node; -- cgit v1.2.3 From 3b582cc14c50f71eabf1c3cada05acb8dc9f457c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 1 Nov 2007 02:21:47 -0700 Subject: [NET]: docbook fixes for netif_ functions Documentation updates for network interfaces. 1. Add doc for netif_napi_add 2. Remove doc for unused returns from netif_rx 3. Add doc for netif_receive_skb [ Incorporated minor mods from Randy Dunlap -DaveM ] Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/linux/netdevice.h | 10 ++++++++++ net/core/dev.c | 18 +++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 9b0c8f12373e..1e6af4f174b6 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -739,6 +739,16 @@ static inline void *netdev_priv(const struct net_device *dev) */ #define SET_NETDEV_DEV(net, pdev) ((net)->dev.parent = (pdev)) +/** + * netif_napi_add - initialize a napi context + * @dev: network device + * @napi: napi context + * @poll: polling function + * @weight: default weight + * + * netif_napi_add() must be used to initialize a napi context prior to calling + * *any* of the other napi related functions. + */ static inline void netif_napi_add(struct net_device *dev, struct napi_struct *napi, int (*poll)(struct napi_struct *, int), diff --git a/net/core/dev.c b/net/core/dev.c index 91ece48e127e..be6cedab5aa8 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1751,9 +1751,6 @@ DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, }; * * return values: * NET_RX_SUCCESS (no congestion) - * NET_RX_CN_LOW (low congestion) - * NET_RX_CN_MOD (moderate congestion) - * NET_RX_CN_HIGH (high congestion) * NET_RX_DROP (packet was dropped) * */ @@ -2001,6 +1998,21 @@ out: } #endif +/** + * netif_receive_skb - process receive buffer from network + * @skb: buffer to process + * + * netif_receive_skb() is the main receive data processing function. + * It always succeeds. The buffer may be dropped during processing + * for congestion control or by the protocol layers. + * + * This function may only be called from softirq context and interrupts + * should be enabled. + * + * Return values (usually ignored): + * NET_RX_SUCCESS: no congestion + * NET_RX_DROP: packet was dropped + */ int netif_receive_skb(struct sk_buff *skb) { struct packet_type *ptype, *pt_prev; -- cgit v1.2.3