Commit fb89e89d authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Benjamin Herrenschmidt

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: default avatarGeert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Cc: Jim Paris <jim@jtan.com>
Cc: Jens Axboe <axboe@kernel.dk>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 13685a16
...@@ -81,8 +81,8 @@ struct ps3vram_priv { ...@@ -81,8 +81,8 @@ struct ps3vram_priv {
struct ps3vram_cache cache; struct ps3vram_cache cache;
/* Used to serialize cache/DMA operations */ spinlock_t lock; /* protecting list of bios */
struct mutex lock; struct bio_list list;
}; };
...@@ -443,8 +443,6 @@ static int ps3vram_read(struct ps3_system_bus_device *dev, loff_t from, ...@@ -443,8 +443,6 @@ static int ps3vram_read(struct ps3_system_bus_device *dev, loff_t from,
offset = (unsigned int) (from & (priv->cache.page_size - 1)); offset = (unsigned int) (from & (priv->cache.page_size - 1));
avail = priv->cache.page_size - offset; avail = priv->cache.page_size - offset;
mutex_lock(&priv->lock);
entry = ps3vram_cache_match(dev, from); entry = ps3vram_cache_match(dev, from);
cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; cached = CACHE_OFFSET + entry * priv->cache.page_size + offset;
...@@ -456,8 +454,6 @@ static int ps3vram_read(struct ps3_system_bus_device *dev, loff_t from, ...@@ -456,8 +454,6 @@ static int ps3vram_read(struct ps3_system_bus_device *dev, loff_t from,
avail = count; avail = count;
memcpy(buf, priv->xdr_buf + cached, avail); memcpy(buf, priv->xdr_buf + cached, avail);
mutex_unlock(&priv->lock);
buf += avail; buf += avail;
count -= avail; count -= avail;
from += avail; from += avail;
...@@ -488,8 +484,6 @@ static int ps3vram_write(struct ps3_system_bus_device *dev, loff_t to, ...@@ -488,8 +484,6 @@ static int ps3vram_write(struct ps3_system_bus_device *dev, loff_t to,
offset = (unsigned int) (to & (priv->cache.page_size - 1)); offset = (unsigned int) (to & (priv->cache.page_size - 1));
avail = priv->cache.page_size - offset; avail = priv->cache.page_size - offset;
mutex_lock(&priv->lock);
entry = ps3vram_cache_match(dev, to); entry = ps3vram_cache_match(dev, to);
cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; cached = CACHE_OFFSET + entry * priv->cache.page_size + offset;
...@@ -503,8 +497,6 @@ static int ps3vram_write(struct ps3_system_bus_device *dev, loff_t to, ...@@ -503,8 +497,6 @@ static int ps3vram_write(struct ps3_system_bus_device *dev, loff_t to,
priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY; priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY;
mutex_unlock(&priv->lock);
buf += avail; buf += avail;
count -= avail; count -= avail;
to += avail; to += avail;
...@@ -546,17 +538,17 @@ static void __devinit ps3vram_proc_init(struct ps3_system_bus_device *dev) ...@@ -546,17 +538,17 @@ static void __devinit ps3vram_proc_init(struct ps3_system_bus_device *dev)
dev_warn(&dev->core, "failed to create /proc entry\n"); dev_warn(&dev->core, "failed to create /proc entry\n");
} }
static int ps3vram_make_request(struct request_queue *q, struct bio *bio) static struct bio *ps3vram_do_bio(struct ps3_system_bus_device *dev,
struct bio *bio)
{ {
struct ps3_system_bus_device *dev = q->queuedata; struct ps3vram_priv *priv = dev->core.driver_data;
int write = bio_data_dir(bio) == WRITE; int write = bio_data_dir(bio) == WRITE;
const char *op = write ? "write" : "read"; const char *op = write ? "write" : "read";
loff_t offset = bio->bi_sector << 9; loff_t offset = bio->bi_sector << 9;
int error = 0; int error = 0;
struct bio_vec *bvec; struct bio_vec *bvec;
unsigned int i; unsigned int i;
struct bio *next;
dev_dbg(&dev->core, "%s\n", __func__);
bio_for_each_segment(bvec, bio, i) { bio_for_each_segment(bvec, bio, i) {
/* PS3 is ppc64, so we don't handle highmem */ /* 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,7 +579,35 @@ static int ps3vram_make_request(struct request_queue *q, struct bio *bio)
dev_dbg(&dev->core, "%s completed\n", op); dev_dbg(&dev->core, "%s completed\n", op);
out: out:
spin_lock_irq(&priv->lock);
bio_list_pop(&priv->list);
next = bio_list_peek(&priv->list);
spin_unlock_irq(&priv->lock);
bio_endio(bio, error); bio_endio(bio, error);
return next;
}
static int ps3vram_make_request(struct request_queue *q, struct bio *bio)
{
struct ps3_system_bus_device *dev = q->queuedata;
struct ps3vram_priv *priv = dev->core.driver_data;
int busy;
dev_dbg(&dev->core, "%s\n", __func__);
spin_lock_irq(&priv->lock);
busy = !bio_list_empty(&priv->list);
bio_list_add(&priv->list, bio);
spin_unlock_irq(&priv->lock);
if (busy)
return 0;
do {
bio = ps3vram_do_bio(dev, bio);
} while (bio);
return 0; return 0;
} }
...@@ -607,7 +627,8 @@ static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev) ...@@ -607,7 +627,8 @@ static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev)
goto fail; goto fail;
} }
mutex_init(&priv->lock); spin_lock_init(&priv->lock);
bio_list_init(&priv->list);
dev->core.driver_data = priv; dev->core.driver_data = priv;
priv = dev->core.driver_data; priv = dev->core.driver_data;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment