diff options
author | Jack Steiner <steiner@sgi.com> | 2009-12-15 19:48:08 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 10:20:15 -0500 |
commit | 7f2251b1bcdd3d2971b2fde3008b270ea11b8780 (patch) | |
tree | 5fc3a2fc089188a6a61e16374a5b715db280aca7 /drivers/misc/sgi-gru/grumain.c | |
parent | 6c9620c64be3920487c0533e0ab6724dad565d59 (diff) |
gru: handle failures to mmu_notifier_register
Under some conditions, mmu_notifier_register() will fail to register a
mmu_notifier. Fix the GRU driver to correctly handle these failures.
Signed-off-by: Jack Steiner <steiner@sgi.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/misc/sgi-gru/grumain.c')
-rw-r--r-- | drivers/misc/sgi-gru/grumain.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c index 9ec54bde4472..944028871884 100644 --- a/drivers/misc/sgi-gru/grumain.c +++ b/drivers/misc/sgi-gru/grumain.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
28 | #include <linux/device.h> | 28 | #include <linux/device.h> |
29 | #include <linux/list.h> | 29 | #include <linux/list.h> |
30 | #include <linux/err.h> | ||
30 | #include <asm/uv/uv_hub.h> | 31 | #include <asm/uv/uv_hub.h> |
31 | #include "gru.h" | 32 | #include "gru.h" |
32 | #include "grutables.h" | 33 | #include "grutables.h" |
@@ -286,7 +287,8 @@ static void gru_unload_mm_tracker(struct gru_state *gru, | |||
286 | void gts_drop(struct gru_thread_state *gts) | 287 | void gts_drop(struct gru_thread_state *gts) |
287 | { | 288 | { |
288 | if (gts && atomic_dec_return(>s->ts_refcnt) == 0) { | 289 | if (gts && atomic_dec_return(>s->ts_refcnt) == 0) { |
289 | gru_drop_mmu_notifier(gts->ts_gms); | 290 | if (gts->ts_gms) |
291 | gru_drop_mmu_notifier(gts->ts_gms); | ||
290 | kfree(gts); | 292 | kfree(gts); |
291 | STAT(gts_free); | 293 | STAT(gts_free); |
292 | } | 294 | } |
@@ -313,13 +315,14 @@ struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma, | |||
313 | int cbr_au_count, int dsr_au_count, int options, int tsid) | 315 | int cbr_au_count, int dsr_au_count, int options, int tsid) |
314 | { | 316 | { |
315 | struct gru_thread_state *gts; | 317 | struct gru_thread_state *gts; |
318 | struct gru_mm_struct *gms; | ||
316 | int bytes; | 319 | int bytes; |
317 | 320 | ||
318 | bytes = DSR_BYTES(dsr_au_count) + CBR_BYTES(cbr_au_count); | 321 | bytes = DSR_BYTES(dsr_au_count) + CBR_BYTES(cbr_au_count); |
319 | bytes += sizeof(struct gru_thread_state); | 322 | bytes += sizeof(struct gru_thread_state); |
320 | gts = kmalloc(bytes, GFP_KERNEL); | 323 | gts = kmalloc(bytes, GFP_KERNEL); |
321 | if (!gts) | 324 | if (!gts) |
322 | return NULL; | 325 | return ERR_PTR(-ENOMEM); |
323 | 326 | ||
324 | STAT(gts_alloc); | 327 | STAT(gts_alloc); |
325 | memset(gts, 0, sizeof(struct gru_thread_state)); /* zero out header */ | 328 | memset(gts, 0, sizeof(struct gru_thread_state)); /* zero out header */ |
@@ -338,9 +341,10 @@ struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma, | |||
338 | if (vma) { | 341 | if (vma) { |
339 | gts->ts_mm = current->mm; | 342 | gts->ts_mm = current->mm; |
340 | gts->ts_vma = vma; | 343 | gts->ts_vma = vma; |
341 | gts->ts_gms = gru_register_mmu_notifier(); | 344 | gms = gru_register_mmu_notifier(); |
342 | if (!gts->ts_gms) | 345 | if (IS_ERR(gms)) |
343 | goto err; | 346 | goto err; |
347 | gts->ts_gms = gms; | ||
344 | } | 348 | } |
345 | 349 | ||
346 | gru_dbg(grudev, "alloc gts %p\n", gts); | 350 | gru_dbg(grudev, "alloc gts %p\n", gts); |
@@ -348,7 +352,7 @@ struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma, | |||
348 | 352 | ||
349 | err: | 353 | err: |
350 | gts_drop(gts); | 354 | gts_drop(gts); |
351 | return NULL; | 355 | return ERR_CAST(gms); |
352 | } | 356 | } |
353 | 357 | ||
354 | /* | 358 | /* |
@@ -396,8 +400,8 @@ struct gru_thread_state *gru_alloc_thread_state(struct vm_area_struct *vma, | |||
396 | 400 | ||
397 | gts = gru_alloc_gts(vma, vdata->vd_cbr_au_count, vdata->vd_dsr_au_count, | 401 | gts = gru_alloc_gts(vma, vdata->vd_cbr_au_count, vdata->vd_dsr_au_count, |
398 | vdata->vd_user_options, tsid); | 402 | vdata->vd_user_options, tsid); |
399 | if (!gts) | 403 | if (IS_ERR(gts)) |
400 | return NULL; | 404 | return gts; |
401 | 405 | ||
402 | spin_lock(&vdata->vd_lock); | 406 | spin_lock(&vdata->vd_lock); |
403 | ngts = gru_find_current_gts_nolock(vdata, tsid); | 407 | ngts = gru_find_current_gts_nolock(vdata, tsid); |