diff options
author | Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> | 2009-06-10 00:38:41 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-06-15 02:47:22 -0400 |
commit | fb89e89d0ff6142f0616eb8260ea89d6fd924982 (patch) | |
tree | 75a8457c238807871a48be213abb719765901061 /drivers/block/ps3vram.c | |
parent | 13685a1654b65357fb34066a98ef40445f7820fc (diff) |
ps3vram: Replace mutex by spinlock + bio_list
Remove the mutex serializing access to the cache.
Instead, queue up new requests on a bio_list if the driver is busy.
This improves sequential write performance by ca. 2%.
Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Cc: Jim Paris <jim@jtan.com>
Cc: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'drivers/block/ps3vram.c')
-rw-r--r-- | drivers/block/ps3vram.c | 51 |
1 files changed, 36 insertions, 15 deletions
diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c index 2c2ea9cb207b..7d1c742d6d66 100644 --- a/drivers/block/ps3vram.c +++ b/drivers/block/ps3vram.c | |||
@@ -81,8 +81,8 @@ struct ps3vram_priv { | |||
81 | 81 | ||
82 | struct ps3vram_cache cache; | 82 | struct ps3vram_cache cache; |
83 | 83 | ||
84 | /* Used to serialize cache/DMA operations */ | 84 | spinlock_t lock; /* protecting list of bios */ |
85 | struct mutex lock; | 85 | struct bio_list list; |
86 | }; | 86 | }; |
87 | 87 | ||
88 | 88 | ||
@@ -443,8 +443,6 @@ static int ps3vram_read(struct ps3_system_bus_device *dev, loff_t from, | |||
443 | offset = (unsigned int) (from & (priv->cache.page_size - 1)); | 443 | offset = (unsigned int) (from & (priv->cache.page_size - 1)); |
444 | avail = priv->cache.page_size - offset; | 444 | avail = priv->cache.page_size - offset; |
445 | 445 | ||
446 | mutex_lock(&priv->lock); | ||
447 | |||
448 | entry = ps3vram_cache_match(dev, from); | 446 | entry = ps3vram_cache_match(dev, from); |
449 | cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; | 447 | cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; |
450 | 448 | ||
@@ -456,8 +454,6 @@ static int ps3vram_read(struct ps3_system_bus_device *dev, loff_t from, | |||
456 | avail = count; | 454 | avail = count; |
457 | memcpy(buf, priv->xdr_buf + cached, avail); | 455 | memcpy(buf, priv->xdr_buf + cached, avail); |
458 | 456 | ||
459 | mutex_unlock(&priv->lock); | ||
460 | |||
461 | buf += avail; | 457 | buf += avail; |
462 | count -= avail; | 458 | count -= avail; |
463 | from += avail; | 459 | from += avail; |
@@ -488,8 +484,6 @@ static int ps3vram_write(struct ps3_system_bus_device *dev, loff_t to, | |||
488 | offset = (unsigned int) (to & (priv->cache.page_size - 1)); | 484 | offset = (unsigned int) (to & (priv->cache.page_size - 1)); |
489 | avail = priv->cache.page_size - offset; | 485 | avail = priv->cache.page_size - offset; |
490 | 486 | ||
491 | mutex_lock(&priv->lock); | ||
492 | |||
493 | entry = ps3vram_cache_match(dev, to); | 487 | entry = ps3vram_cache_match(dev, to); |
494 | cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; | 488 | cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; |
495 | 489 | ||
@@ -503,8 +497,6 @@ static int ps3vram_write(struct ps3_system_bus_device *dev, loff_t to, | |||
503 | 497 | ||
504 | priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY; | 498 | priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY; |
505 | 499 | ||
506 | mutex_unlock(&priv->lock); | ||
507 | |||
508 | buf += avail; | 500 | buf += avail; |
509 | count -= avail; | 501 | count -= avail; |
510 | to += avail; | 502 | to += avail; |
@@ -546,17 +538,17 @@ static void __devinit ps3vram_proc_init(struct ps3_system_bus_device *dev) | |||
546 | dev_warn(&dev->core, "failed to create /proc entry\n"); | 538 | dev_warn(&dev->core, "failed to create /proc entry\n"); |
547 | } | 539 | } |
548 | 540 | ||
549 | static int ps3vram_make_request(struct request_queue *q, struct bio *bio) | 541 | static struct bio *ps3vram_do_bio(struct ps3_system_bus_device *dev, |
542 | struct bio *bio) | ||
550 | { | 543 | { |
551 | struct ps3_system_bus_device *dev = q->queuedata; | 544 | struct ps3vram_priv *priv = dev->core.driver_data; |
552 | int write = bio_data_dir(bio) == WRITE; | 545 | int write = bio_data_dir(bio) == WRITE; |
553 | const char *op = write ? "write" : "read"; | 546 | const char *op = write ? "write" : "read"; |
554 | loff_t offset = bio->bi_sector << 9; | 547 | loff_t offset = bio->bi_sector << 9; |
555 | int error = 0; | 548 | int error = 0; |
556 | struct bio_vec *bvec; | 549 | struct bio_vec *bvec; |
557 | unsigned int i; | 550 | unsigned int i; |
558 | 551 | struct bio *next; | |
559 | dev_dbg(&dev->core, "%s\n", __func__); | ||
560 | 552 | ||
561 | bio_for_each_segment(bvec, bio, i) { | 553 | bio_for_each_segment(bvec, bio, i) { |
562 | /* PS3 is ppc64, so we don't handle highmem */ | 554 | /* PS3 is ppc64, so we don't handle highmem */ |
@@ -587,7 +579,35 @@ static int ps3vram_make_request(struct request_queue *q, struct bio *bio) | |||
587 | dev_dbg(&dev->core, "%s completed\n", op); | 579 | dev_dbg(&dev->core, "%s completed\n", op); |
588 | 580 | ||
589 | out: | 581 | out: |
582 | spin_lock_irq(&priv->lock); | ||
583 | bio_list_pop(&priv->list); | ||
584 | next = bio_list_peek(&priv->list); | ||
585 | spin_unlock_irq(&priv->lock); | ||
586 | |||
590 | bio_endio(bio, error); | 587 | bio_endio(bio, error); |
588 | return next; | ||
589 | } | ||
590 | |||
591 | static int ps3vram_make_request(struct request_queue *q, struct bio *bio) | ||
592 | { | ||
593 | struct ps3_system_bus_device *dev = q->queuedata; | ||
594 | struct ps3vram_priv *priv = dev->core.driver_data; | ||
595 | int busy; | ||
596 | |||
597 | dev_dbg(&dev->core, "%s\n", __func__); | ||
598 | |||
599 | spin_lock_irq(&priv->lock); | ||
600 | busy = !bio_list_empty(&priv->list); | ||
601 | bio_list_add(&priv->list, bio); | ||
602 | spin_unlock_irq(&priv->lock); | ||
603 | |||
604 | if (busy) | ||
605 | return 0; | ||
606 | |||
607 | do { | ||
608 | bio = ps3vram_do_bio(dev, bio); | ||
609 | } while (bio); | ||
610 | |||
591 | return 0; | 611 | return 0; |
592 | } | 612 | } |
593 | 613 | ||
@@ -607,7 +627,8 @@ static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev) | |||
607 | goto fail; | 627 | goto fail; |
608 | } | 628 | } |
609 | 629 | ||
610 | mutex_init(&priv->lock); | 630 | spin_lock_init(&priv->lock); |
631 | bio_list_init(&priv->list); | ||
611 | dev->core.driver_data = priv; | 632 | dev->core.driver_data = priv; |
612 | 633 | ||
613 | priv = dev->core.driver_data; | 634 | priv = dev->core.driver_data; |