Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 110062
b: refs/heads/master
c: 18d6522
h: refs/heads/master
v: v3
  • Loading branch information
Atsuo Igarashi authored and Jason Wessel committed Sep 26, 2008
1 parent cbde488 commit 1745753
Show file tree
Hide file tree
Showing 22 changed files with 336 additions and 157 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 66120005e65eed8a05b14a36ab448bdec42f0d6b
refs/heads/master: 18d6522b86d21a04c8ac1ea79747e2e434a956d9
78 changes: 78 additions & 0 deletions trunk/arch/arm/include/asm/cnt32_to_63.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* include/asm/cnt32_to_63.h -- extend a 32-bit counter to 63 bits
*
* Author: Nicolas Pitre
* Created: December 3, 2006
* Copyright: MontaVista Software, Inc.
*
* 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.
*/

#ifndef __INCLUDE_CNT32_TO_63_H__
#define __INCLUDE_CNT32_TO_63_H__

#include <linux/compiler.h>
#include <asm/types.h>
#include <asm/byteorder.h>

/*
* Prototype: u64 cnt32_to_63(u32 cnt)
* Many hardware clock counters are only 32 bits wide and therefore have
* a relatively short period making wrap-arounds rather frequent. This
* is a problem when implementing sched_clock() for example, where a 64-bit
* non-wrapping monotonic value is expected to be returned.
*
* To overcome that limitation, let's extend a 32-bit counter to 63 bits
* in a completely lock free fashion. Bits 0 to 31 of the clock are provided
* by the hardware while bits 32 to 62 are stored in memory. The top bit in
* memory is used to synchronize with the hardware clock half-period. When
* the top bit of both counters (hardware and in memory) differ then the
* memory is updated with a new value, incrementing it when the hardware
* counter wraps around.
*
* Because a word store in memory is atomic then the incremented value will
* always be in synch with the top bit indicating to any potential concurrent
* reader if the value in memory is up to date or not with regards to the
* needed increment. And any race in updating the value in memory is harmless
* as the same value would simply be stored more than once.
*
* The only restriction for the algorithm to work properly is that this
* code must be executed at least once per each half period of the 32-bit
* counter to properly update the state bit in memory. This is usually not a
* problem in practice, but if it is then a kernel timer could be scheduled
* to manage for this code to be executed often enough.
*
* Note that the top bit (bit 63) in the returned value should be considered
* as garbage. It is not cleared here because callers are likely to use a
* multiplier on the returned value which can get rid of the top bit
* implicitly by making the multiplier even, therefore saving on a runtime
* clear-bit instruction. Otherwise caller must remember to clear the top
* bit explicitly.
*/

/* this is used only to give gcc a clue about good code generation */
typedef union {
struct {
#if defined(__LITTLE_ENDIAN)
u32 lo, hi;
#elif defined(__BIG_ENDIAN)
u32 hi, lo;
#endif
};
u64 val;
} cnt32_to_63_t;

#define cnt32_to_63(cnt_lo) \
({ \
static volatile u32 __m_cnt_hi = 0; \
cnt32_to_63_t __x; \
__x.hi = __m_cnt_hi; \
__x.lo = (cnt_lo); \
if (unlikely((s32)(__x.hi ^ __x.lo) < 0)) \
__m_cnt_hi = __x.hi = (__x.hi ^ 0x80000000) + (__x.hi >> 31); \
__x.val; \
})

#endif
46 changes: 6 additions & 40 deletions trunk/drivers/ata/sata_nv.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,6 @@ static void nv_nf2_freeze(struct ata_port *ap);
static void nv_nf2_thaw(struct ata_port *ap);
static void nv_ck804_freeze(struct ata_port *ap);
static void nv_ck804_thaw(struct ata_port *ap);
static int nv_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
static int nv_adma_slave_config(struct scsi_device *sdev);
static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc);
static void nv_adma_qc_prep(struct ata_queued_cmd *qc);
Expand Down Expand Up @@ -405,45 +403,28 @@ static struct scsi_host_template nv_swncq_sht = {
.slave_configure = nv_swncq_slave_config,
};

/* OSDL bz3352 reports that some nv controllers can't determine device
* signature reliably and nv_hardreset is implemented to work around
* the problem. This was reported on nf3 and it's unclear whether any
* other controllers are affected. However, the workaround has been
* applied to all variants and there isn't much to gain by trying to
* find out exactly which ones are affected at this point especially
* because NV has moved over to ahci for newer controllers.
*/
static struct ata_port_operations nv_common_ops = {
static struct ata_port_operations nv_generic_ops = {
.inherits = &ata_bmdma_port_ops,
.hardreset = nv_hardreset,
.hardreset = ATA_OP_NULL,
.scr_read = nv_scr_read,
.scr_write = nv_scr_write,
};

/* OSDL bz11195 reports that link doesn't come online after hardreset
* on generic nv's and there have been several other similar reports
* on linux-ide. Disable hardreset for generic nv's.
*/
static struct ata_port_operations nv_generic_ops = {
.inherits = &nv_common_ops,
.hardreset = ATA_OP_NULL,
};

static struct ata_port_operations nv_nf2_ops = {
.inherits = &nv_common_ops,
.inherits = &nv_generic_ops,
.freeze = nv_nf2_freeze,
.thaw = nv_nf2_thaw,
};

static struct ata_port_operations nv_ck804_ops = {
.inherits = &nv_common_ops,
.inherits = &nv_generic_ops,
.freeze = nv_ck804_freeze,
.thaw = nv_ck804_thaw,
.host_stop = nv_ck804_host_stop,
};

static struct ata_port_operations nv_adma_ops = {
.inherits = &nv_common_ops,
.inherits = &nv_generic_ops,

.check_atapi_dma = nv_adma_check_atapi_dma,
.sff_tf_read = nv_adma_tf_read,
Expand All @@ -467,7 +448,7 @@ static struct ata_port_operations nv_adma_ops = {
};

static struct ata_port_operations nv_swncq_ops = {
.inherits = &nv_common_ops,
.inherits = &nv_generic_ops,

.qc_defer = ata_std_qc_defer,
.qc_prep = nv_swncq_qc_prep,
Expand Down Expand Up @@ -1605,21 +1586,6 @@ static void nv_mcp55_thaw(struct ata_port *ap)
ata_sff_thaw(ap);
}

static int nv_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline)
{
int rc;

/* SATA hardreset fails to retrieve proper device signature on
* some controllers. Request follow up SRST. For more info,
* see http://bugzilla.kernel.org/show_bug.cgi?id=3352
*/
rc = sata_sff_hardreset(link, class, deadline);
if (rc)
return rc;
return -EAGAIN;
}

static void nv_adma_error_handler(struct ata_port *ap)
{
struct nv_adma_port_priv *pp = ap->private_data;
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/scsi/qla2xxx/qla_isr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1834,6 +1834,7 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_HOST_INT);
}
spin_unlock_irq(&ha->hardware_lock);
ha->isp_ops->enable_intrs(ha);

fail:
return ret;
Expand Down
2 changes: 0 additions & 2 deletions trunk/drivers/scsi/qla2xxx/qla_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -1740,8 +1740,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
goto probe_failed;

ha->isp_ops->enable_intrs(ha);

scsi_scan_host(host);

qla2x00_alloc_sysfs_attr(ha);
Expand Down
1 change: 0 additions & 1 deletion trunk/drivers/scsi/qlogicpti.c
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,6 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd,
ds[i].d_count = sg_dma_len(s);
}
sg_count -= n;
sg = s;
}
} else {
cmd->dataseg[0].d_base = 0;
Expand Down
3 changes: 1 addition & 2 deletions trunk/drivers/scsi/scsi_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,7 @@ static void scsi_end_bidi_request(struct scsi_cmnd *cmd)
void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
{
int result = cmd->result;
int this_count;
int this_count = scsi_bufflen(cmd);
struct request_queue *q = cmd->device->request_queue;
struct request *req = cmd->request;
int error = 0;
Expand Down Expand Up @@ -908,7 +908,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
*/
if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL)
return;
this_count = blk_rq_bytes(req);

/* good_bytes = 0, or (inclusive) there were leftovers and
* result = 0, so scsi_end_request couldn't retry.
Expand Down
10 changes: 4 additions & 6 deletions trunk/fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1395,10 +1395,6 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)
if (dentry->d_parent != parent)
goto next;

/* non-existing due to RCU? */
if (d_unhashed(dentry))
goto next;

/*
* It is safe to compare names since d_move() cannot
* change the qstr (protected by d_lock).
Expand All @@ -1414,8 +1410,10 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)
goto next;
}

atomic_inc(&dentry->d_count);
found = dentry;
if (!d_unhashed(dentry)) {
atomic_inc(&dentry->d_count);
found = dentry;
}
spin_unlock(&dentry->d_lock);
break;
next:
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/ubifs/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ void dbg_dump_node(const struct ubifs_info *c, const void *node)
printk(KERN_DEBUG "\t%d orphan inode numbers:\n", n);
for (i = 0; i < n; i++)
printk(KERN_DEBUG "\t ino %llu\n",
(unsigned long long)le64_to_cpu(orph->inos[i]));
le64_to_cpu(orph->inos[i]));
break;
}
default:
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/ubifs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir)

while (1) {
dbg_gen("feed '%s', ino %llu, new f_pos %#x",
dent->name, (unsigned long long)le64_to_cpu(dent->inum),
dent->name, le64_to_cpu(dent->inum),
key_hash_flash(c, &dent->key));
ubifs_assert(dent->ch.sqnum > ubifs_inode(dir)->creat_sqnum);

Expand Down
1 change: 1 addition & 0 deletions trunk/fs/ubifs/find.c
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,7 @@ int ubifs_find_free_space(struct ubifs_info *c, int min_space, int *free,
rsvd_idx_lebs = 0;
lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt -
c->lst.taken_empty_lebs;
ubifs_assert(lebs + c->lst.idx_lebs >= c->min_idx_lebs);
if (rsvd_idx_lebs < lebs)
/*
* OK to allocate an empty LEB, but we still don't want to go
Expand Down
14 changes: 3 additions & 11 deletions trunk/fs/ubifs/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,15 +334,15 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp)

err = move_nodes(c, sleb);
if (err)
goto out_inc_seq;
goto out;

err = gc_sync_wbufs(c);
if (err)
goto out_inc_seq;
goto out;

err = ubifs_change_one_lp(c, lnum, c->leb_size, 0, 0, 0, 0);
if (err)
goto out_inc_seq;
goto out;

/* Allow for races with TNC */
c->gced_lnum = lnum;
Expand All @@ -369,14 +369,6 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp)
out:
ubifs_scan_destroy(sleb);
return err;

out_inc_seq:
/* We may have moved at least some nodes so allow for races with TNC */
c->gced_lnum = lnum;
smp_wmb();
c->gc_seq += 1;
smp_wmb();
goto out;
}

/**
Expand Down
3 changes: 2 additions & 1 deletion trunk/fs/ubifs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1024,13 +1024,14 @@ static int mount_ubifs(struct ubifs_info *c)
goto out_dereg;
}

sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id);
if (!mounted_read_only) {
err = alloc_wbufs(c);
if (err)
goto out_cbuf;

/* Create background thread */
sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num,
c->vi.vol_id);
c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name);
if (!c->bgt)
c->bgt = ERR_PTR(-EINVAL);
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/ubifs/tnc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1476,7 +1476,7 @@ int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key,
}

err = fallible_read_node(c, key, &zbr, node);
if (err <= 0 || maybe_leb_gced(c, zbr.lnum, gc_seq1)) {
if (maybe_leb_gced(c, zbr.lnum, gc_seq1)) {
/*
* The node may have been GC'ed out from under us so try again
* while keeping the TNC mutex locked.
Expand Down
Loading

0 comments on commit 1745753

Please sign in to comment.