aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/ps3vram.c
diff options
context:
space:
mode:
authorGeert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>2009-06-10 00:38:41 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-06-15 02:47:22 -0400
commitfb89e89d0ff6142f0616eb8260ea89d6fd924982 (patch)
tree75a8457c238807871a48be213abb719765901061 /drivers/block/ps3vram.c
parent13685a1654b65357fb34066a98ef40445f7820fc (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.c51
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
549static int ps3vram_make_request(struct request_queue *q, struct bio *bio) 541static 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
589out: 581out:
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
591static 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;