Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
Browse files Browse the repository at this point in the history
* 'for-linus' of git://git.kernel.dk/linux-2.6-block:
  loop: mutex already unlocked in loop_clr_fd()
  cfq-iosched: don't let idling interfere with plugging
  block: remove unused REQ_UNPLUG
  cfq-iosched: kill two unused cfqq flags
  cfq-iosched: change dispatch logic to deal with single requests at the time
  mflash: initial support
  cciss: change to discover first memory BAR
  cciss: kernel scan thread for MSA2012
  cciss: fix residual count for block pc requests
  block: fix inconsistency in I/O stat accounting code
  block: elevator quiescing helpers
  • Loading branch information
Linus Torvalds committed Apr 7, 2009
2 parents aeeae86 + ffcd7dc commit 6a5d263
Show file tree
Hide file tree
Showing 18 changed files with 1,624 additions and 149 deletions.
2 changes: 2 additions & 0 deletions Documentation/blockdev/00-INDEX
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ cpqarray.txt
- info on using Compaq's SMART2 Intelligent Disk Array Controllers.
floppy.txt
- notes and driver options for the floppy disk driver.
mflash.txt
- info on mGine m(g)flash driver for linux.
nbd.txt
- info on a TCP implementation of a network block device.
paride.txt
Expand Down
84 changes: 84 additions & 0 deletions Documentation/blockdev/mflash.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
This document describes m[g]flash support in linux.

Contents
1. Overview
2. Reserved area configuration
3. Example of mflash platform driver registration

1. Overview

Mflash and gflash are embedded flash drive. The only difference is mflash is
MCP(Multi Chip Package) device. These two device operate exactly same way.
So the rest mflash repersents mflash and gflash altogether.

Internally, mflash has nand flash and other hardware logics and supports
2 different operation (ATA, IO) modes. ATA mode doesn't need any new
driver and currently works well under standard IDE subsystem. Actually it's
one chip SSD. IO mode is ATA-like custom mode for the host that doesn't have
IDE interface.

Followings are brief descriptions about IO mode.
A. IO mode based on ATA protocol and uses some custom command. (read confirm,
write confirm)
B. IO mode uses SRAM bus interface.
C. IO mode supports 4kB boot area, so host can boot from mflash.

2. Reserved area configuration
If host boot from mflash, usually needs raw area for boot loader image. All of
the mflash's block device operation will be taken this value as start offset.
Note that boot loader's size of reserved area and kernel configuration value
must be same.

3. Example of mflash platform driver registration
Working mflash is very straight forward. Adding platform device stuff to board
configuration file is all. Here is some pseudo example.

static struct mg_drv_data mflash_drv_data = {
/* If you want to polling driver set to 1 */
.use_polling = 0,
/* device attribution */
.dev_attr = MG_BOOT_DEV
};

static struct resource mg_mflash_rsc[] = {
/* Base address of mflash */
[0] = {
.start = 0x08000000,
.end = 0x08000000 + SZ_64K - 1,
.flags = IORESOURCE_MEM
},
/* mflash interrupt pin */
[1] = {
.start = IRQ_GPIO(84),
.end = IRQ_GPIO(84),
.flags = IORESOURCE_IRQ
},
/* mflash reset pin */
[2] = {
.start = 43,
.end = 43,
.name = MG_RST_PIN,
.flags = IORESOURCE_IO
},
/* mflash reset-out pin
* If you use mflash as storage device (i.e. other than MG_BOOT_DEV),
* should assign this */
[3] = {
.start = 51,
.end = 51,
.name = MG_RSTOUT_PIN,
.flags = IORESOURCE_IO
}
};

static struct platform_device mflash_dev = {
.name = MG_DEV_NAME,
.id = -1,
.dev = {
.platform_data = &mflash_drv_data,
},
.num_resources = ARRAY_SIZE(mg_mflash_rsc),
.resource = mg_mflash_rsc
};

platform_device_register(&mflash_dev);
15 changes: 4 additions & 11 deletions block/blk-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,11 @@ static struct workqueue_struct *kblockd_workqueue;

static void drive_stat_acct(struct request *rq, int new_io)
{
struct gendisk *disk = rq->rq_disk;
struct hd_struct *part;
int rw = rq_data_dir(rq);
int cpu;

if (!blk_fs_request(rq) || !disk || !blk_do_io_stat(disk->queue))
if (!blk_fs_request(rq) || !blk_do_io_stat(rq))
return;

cpu = part_stat_lock();
Expand Down Expand Up @@ -1124,8 +1123,6 @@ void init_request_from_bio(struct request *req, struct bio *bio)

if (bio_sync(bio))
req->cmd_flags |= REQ_RW_SYNC;
if (bio_unplug(bio))
req->cmd_flags |= REQ_UNPLUG;
if (bio_rw_meta(bio))
req->cmd_flags |= REQ_RW_META;
if (bio_noidle(bio))
Expand Down Expand Up @@ -1675,9 +1672,7 @@ EXPORT_SYMBOL(blkdev_dequeue_request);

static void blk_account_io_completion(struct request *req, unsigned int bytes)
{
struct gendisk *disk = req->rq_disk;

if (!disk || !blk_do_io_stat(disk->queue))
if (!blk_do_io_stat(req))
return;

if (blk_fs_request(req)) {
Expand All @@ -1694,9 +1689,7 @@ static void blk_account_io_completion(struct request *req, unsigned int bytes)

static void blk_account_io_done(struct request *req)
{
struct gendisk *disk = req->rq_disk;

if (!disk || !blk_do_io_stat(disk->queue))
if (!blk_do_io_stat(req))
return;

/*
Expand All @@ -1711,7 +1704,7 @@ static void blk_account_io_done(struct request *req)
int cpu;

cpu = part_stat_lock();
part = disk_map_sector_rcu(disk, req->sector);
part = disk_map_sector_rcu(req->rq_disk, req->sector);

part_stat_inc(cpu, part, ios[rw]);
part_stat_add(cpu, part, ticks[rw], duration);
Expand Down
29 changes: 17 additions & 12 deletions block/blk-merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,22 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req,
return 1;
}

static void blk_account_io_merge(struct request *req)
{
if (blk_do_io_stat(req)) {
struct hd_struct *part;
int cpu;

cpu = part_stat_lock();
part = disk_map_sector_rcu(req->rq_disk, req->sector);

part_round_stats(cpu, part);
part_dec_in_flight(part);

part_stat_unlock();
}
}

/*
* Has to be called with the request spinlock acquired
*/
Expand Down Expand Up @@ -386,18 +402,7 @@ static int attempt_merge(struct request_queue *q, struct request *req,

elv_merge_requests(q, req, next);

if (req->rq_disk) {
struct hd_struct *part;
int cpu;

cpu = part_stat_lock();
part = disk_map_sector_rcu(req->rq_disk, req->sector);

part_round_stats(cpu, part);
part_dec_in_flight(part);

part_stat_unlock();
}
blk_account_io_merge(req);

req->ioprio = ioprio_best(req->ioprio, next->ioprio);
if (blk_rq_cpu_valid(next))
Expand Down
4 changes: 4 additions & 0 deletions block/blk-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,14 @@ static ssize_t queue_iostats_store(struct request_queue *q, const char *page,
ssize_t ret = queue_var_store(&stats, page, count);

spin_lock_irq(q->queue_lock);
elv_quisce_start(q);

if (stats)
queue_flag_set(QUEUE_FLAG_IO_STAT, q);
else
queue_flag_clear(QUEUE_FLAG_IO_STAT, q);

elv_quisce_end(q);
spin_unlock_irq(q->queue_lock);

return ret;
Expand Down
14 changes: 10 additions & 4 deletions block/blk.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ void blk_queue_congestion_threshold(struct request_queue *q);

int blk_dev_init(void);

void elv_quisce_start(struct request_queue *q);
void elv_quisce_end(struct request_queue *q);


/*
* Return the threshold (number of used requests) at which the queue is
* considered to be congested. It include a little hysteresis to keep the
Expand Down Expand Up @@ -108,12 +112,14 @@ static inline int blk_cpu_to_group(int cpu)
#endif
}

static inline int blk_do_io_stat(struct request_queue *q)
static inline int blk_do_io_stat(struct request *rq)
{
if (q)
return blk_queue_io_stat(q);
struct gendisk *disk = rq->rq_disk;

return 0;
if (!disk || !disk->queue)
return 0;

return blk_queue_io_stat(disk->queue) && (rq->cmd_flags & REQ_ELVPRIV);
}

#endif
Loading

0 comments on commit 6a5d263

Please sign in to comment.