Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 253788
b: refs/heads/master
c: de505e7
h: refs/heads/master
v: v3
  • Loading branch information
Linus Torvalds committed Jun 19, 2011
1 parent e71ba8a commit c288c09
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 37 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: b1e698db0939b04602ded2a2196ff69c92b49378
refs/heads/master: de505e709ffb09a7382ca8e0d8c7dbb171ba5830
8 changes: 5 additions & 3 deletions trunk/drivers/cpufreq/cpufreq_stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,11 +298,13 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
old_index = stat->last_index;
new_index = freq_table_get_index(stat, freq->new);

cpufreq_stats_update(freq->cpu);
if (old_index == new_index)
/* We can't do stat->time_in_state[-1]= .. */
if (old_index == -1 || new_index == -1)
return 0;

if (old_index == -1 || new_index == -1)
cpufreq_stats_update(freq->cpu);

if (old_index == new_index)
return 0;

spin_lock(&cpufreq_stats_lock);
Expand Down
6 changes: 5 additions & 1 deletion trunk/drivers/cpufreq/powernow-k8.c
Original file line number Diff line number Diff line change
Expand Up @@ -1079,6 +1079,9 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data,
}

res = transition_fid_vid(data, fid, vid);
if (res)
return res;

freqs.new = find_khz_freq_from_fid(data->currfid);

for_each_cpu(i, data->available_cores) {
Expand All @@ -1101,7 +1104,8 @@ static int transition_frequency_pstate(struct powernow_k8_data *data,
/* get MSR index for hardware pstate transition */
pstate = index & HW_PSTATE_MASK;
if (pstate > data->max_hw_pstate)
return 0;
return -EINVAL;

freqs.old = find_khz_freq_from_pstate(data->powernow_table,
data->currpstate);
freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate);
Expand Down
10 changes: 10 additions & 0 deletions trunk/drivers/gpu/drm/i915/i915_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -1740,6 +1740,16 @@ void ironlake_irq_preinstall(struct drm_device *dev)
INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work);

I915_WRITE(HWSTAM, 0xeffe);
if (IS_GEN6(dev)) {
/* Workaround stalls observed on Sandy Bridge GPUs by
* making the blitter command streamer generate a
* write to the Hardware Status Page for
* MI_USER_INTERRUPT. This appears to serialize the
* previous seqno write out before the interrupt
* happens.
*/
I915_WRITE(GEN6_BLITTER_HWSTAM, ~GEN6_BLITTER_USER_INTERRUPT);
}

/* XXX hotplug from PCH */

Expand Down
3 changes: 2 additions & 1 deletion trunk/fs/isofs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
out_no_read:
printk(KERN_WARNING "%s: bread failed, dev=%s, iso_blknum=%d, block=%d\n",
__func__, s->s_id, iso_blknum, block);
goto out_freesbi;
goto out_freebh;
out_bad_zone_size:
printk(KERN_WARNING "ISOFS: Bad logical zone size %ld\n",
sbi->s_log_zone_size);
Expand All @@ -989,6 +989,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)

out_freebh:
brelse(bh);
brelse(pri_bh);
out_freesbi:
kfree(opt.iocharset);
kfree(sbi);
Expand Down
106 changes: 75 additions & 31 deletions trunk/mm/rmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ static inline void anon_vma_free(struct anon_vma *anon_vma)
kmem_cache_free(anon_vma_cachep, anon_vma);
}

static inline struct anon_vma_chain *anon_vma_chain_alloc(void)
static inline struct anon_vma_chain *anon_vma_chain_alloc(gfp_t gfp)
{
return kmem_cache_alloc(anon_vma_chain_cachep, GFP_KERNEL);
return kmem_cache_alloc(anon_vma_chain_cachep, gfp);
}

static void anon_vma_chain_free(struct anon_vma_chain *anon_vma_chain)
Expand Down Expand Up @@ -159,7 +159,7 @@ int anon_vma_prepare(struct vm_area_struct *vma)
struct mm_struct *mm = vma->vm_mm;
struct anon_vma *allocated;

avc = anon_vma_chain_alloc();
avc = anon_vma_chain_alloc(GFP_KERNEL);
if (!avc)
goto out_enomem;

Expand Down Expand Up @@ -200,6 +200,32 @@ int anon_vma_prepare(struct vm_area_struct *vma)
return -ENOMEM;
}

/*
* This is a useful helper function for locking the anon_vma root as
* we traverse the vma->anon_vma_chain, looping over anon_vma's that
* have the same vma.
*
* Such anon_vma's should have the same root, so you'd expect to see
* just a single mutex_lock for the whole traversal.
*/
static inline struct anon_vma *lock_anon_vma_root(struct anon_vma *root, struct anon_vma *anon_vma)
{
struct anon_vma *new_root = anon_vma->root;
if (new_root != root) {
if (WARN_ON_ONCE(root))
mutex_unlock(&root->mutex);
root = new_root;
mutex_lock(&root->mutex);
}
return root;
}

static inline void unlock_anon_vma_root(struct anon_vma *root)
{
if (root)
mutex_unlock(&root->mutex);
}

static void anon_vma_chain_link(struct vm_area_struct *vma,
struct anon_vma_chain *avc,
struct anon_vma *anon_vma)
Expand All @@ -208,13 +234,11 @@ static void anon_vma_chain_link(struct vm_area_struct *vma,
avc->anon_vma = anon_vma;
list_add(&avc->same_vma, &vma->anon_vma_chain);

anon_vma_lock(anon_vma);
/*
* It's critical to add new vmas to the tail of the anon_vma,
* see comment in huge_memory.c:__split_huge_page().
*/
list_add_tail(&avc->same_anon_vma, &anon_vma->head);
anon_vma_unlock(anon_vma);
}

/*
Expand All @@ -224,13 +248,24 @@ static void anon_vma_chain_link(struct vm_area_struct *vma,
int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
{
struct anon_vma_chain *avc, *pavc;
struct anon_vma *root = NULL;

list_for_each_entry_reverse(pavc, &src->anon_vma_chain, same_vma) {
avc = anon_vma_chain_alloc();
if (!avc)
goto enomem_failure;
anon_vma_chain_link(dst, avc, pavc->anon_vma);
struct anon_vma *anon_vma;

avc = anon_vma_chain_alloc(GFP_NOWAIT | __GFP_NOWARN);
if (unlikely(!avc)) {
unlock_anon_vma_root(root);
root = NULL;
avc = anon_vma_chain_alloc(GFP_KERNEL);
if (!avc)
goto enomem_failure;
}
anon_vma = pavc->anon_vma;
root = lock_anon_vma_root(root, anon_vma);
anon_vma_chain_link(dst, avc, anon_vma);
}
unlock_anon_vma_root(root);
return 0;

enomem_failure:
Expand Down Expand Up @@ -263,7 +298,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
anon_vma = anon_vma_alloc();
if (!anon_vma)
goto out_error;
avc = anon_vma_chain_alloc();
avc = anon_vma_chain_alloc(GFP_KERNEL);
if (!avc)
goto out_error_free_anon_vma;

Expand All @@ -280,7 +315,9 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
get_anon_vma(anon_vma->root);
/* Mark this anon_vma as the one where our new (COWed) pages go. */
vma->anon_vma = anon_vma;
anon_vma_lock(anon_vma);
anon_vma_chain_link(vma, avc, anon_vma);
anon_vma_unlock(anon_vma);

return 0;

Expand All @@ -291,36 +328,43 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
return -ENOMEM;
}

static void anon_vma_unlink(struct anon_vma_chain *anon_vma_chain)
{
struct anon_vma *anon_vma = anon_vma_chain->anon_vma;
int empty;

/* If anon_vma_fork fails, we can get an empty anon_vma_chain. */
if (!anon_vma)
return;

anon_vma_lock(anon_vma);
list_del(&anon_vma_chain->same_anon_vma);

/* We must garbage collect the anon_vma if it's empty */
empty = list_empty(&anon_vma->head);
anon_vma_unlock(anon_vma);

if (empty)
put_anon_vma(anon_vma);
}

void unlink_anon_vmas(struct vm_area_struct *vma)
{
struct anon_vma_chain *avc, *next;
struct anon_vma *root = NULL;

/*
* Unlink each anon_vma chained to the VMA. This list is ordered
* from newest to oldest, ensuring the root anon_vma gets freed last.
*/
list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) {
anon_vma_unlink(avc);
struct anon_vma *anon_vma = avc->anon_vma;

root = lock_anon_vma_root(root, anon_vma);
list_del(&avc->same_anon_vma);

/*
* Leave empty anon_vmas on the list - we'll need
* to free them outside the lock.
*/
if (list_empty(&anon_vma->head))
continue;

list_del(&avc->same_vma);
anon_vma_chain_free(avc);
}
unlock_anon_vma_root(root);

/*
* Iterate the list once more, it now only contains empty and unlinked
* anon_vmas, destroy them. Could not do before due to __put_anon_vma()
* needing to acquire the anon_vma->root->mutex.
*/
list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) {
struct anon_vma *anon_vma = avc->anon_vma;

put_anon_vma(anon_vma);

list_del(&avc->same_vma);
anon_vma_chain_free(avc);
}
Expand Down

0 comments on commit c288c09

Please sign in to comment.