From 9dfa52831e96194b8649613e3131baa2c109f7dc Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 16 Aug 2007 13:27:52 +0200 Subject: Merge blk_recount_segments into blk_recalc_rq_segments blk_recalc_rq_segments calls blk_recount_segments on each bio, then does some extra calculations to handle segments that overlap two bios. If we merge the code from blk_recount_segments into blk_recalc_rq_segments, we can process the whole request one bio_vec at a time, and not need the messy cross-bio calculations. Then blk_recount_segments can be implemented by calling blk_recalc_rq_segments, passing it a simple on-stack request which stores just the bio. Signed-off-by: Neil Brown diff .prev/block/ll_rw_blk.c ./block/ll_rw_blk.c Signed-off-by: Jens Axboe diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index ed39313..e35119a 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -42,6 +42,7 @@ static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io); static void init_request_from_bio(struct request *req, struct bio *bio); static int __make_request(struct request_queue *q, struct bio *bio); static struct io_context *current_io_context(gfp_t gfp_flags, int node); +static void blk_recalc_rq_segments(struct request *rq); /* * For the allocated request tables @@ -1220,16 +1221,42 @@ EXPORT_SYMBOL(blk_dump_rq_flags); void blk_recount_segments(struct request_queue *q, struct bio *bio) { + struct request rq; + struct bio *nxt = bio->bi_next; + rq.q = q; + rq.bio = rq.biotail = bio; + bio->bi_next = NULL; + blk_recalc_rq_segments(&rq); + bio->bi_next = nxt; + bio->bi_phys_segments = rq.nr_phys_segments; + bio->bi_hw_segments = rq.nr_hw_segments; + bio->bi_flags |= (1 << BIO_SEG_VALID); +} +EXPORT_SYMBOL(blk_recount_segments); + +static void blk_recalc_rq_segments(struct request *rq) +{ + int nr_phys_segs; + int nr_hw_segs; + unsigned int phys_size; + unsigned int hw_size; struct bio_vec *bv, *bvprv = NULL; - int i, nr_phys_segs, nr_hw_segs, seg_size, hw_seg_size, cluster; + int seg_size; + int hw_seg_size; + int cluster; + struct bio *bio; + int i; int high, highprv = 1; + struct request_queue *q = rq->q; - if (unlikely(!bio->bi_io_vec)) + if (!rq->bio) return; cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER); - hw_seg_size = seg_size = nr_phys_segs = nr_hw_segs = 0; - bio_for_each_segment(bv, bio, i) { + hw_seg_size = seg_size = 0; + phys_size = hw_size = nr_phys_segs = nr_hw_segs = 0; + rq_for_each_bio(bio, rq) + bio_for_each_segment(bv, bio, i) { /* * the trick here is making sure that a high page is never * considered part of another segment, since that might @@ -1255,12 +1282,13 @@ void blk_recount_segments(struct request_queue *q, struct bio *bio) } new_segment: if (BIOVEC_VIRT_MERGEABLE(bvprv, bv) && - !BIOVEC_VIRT_OVERSIZE(hw_seg_size + bv->bv_len)) { + !BIOVEC_VIRT_OVERSIZE(hw_seg_size + bv->bv_len)) hw_seg_size += bv->bv_len; - } else { + else { new_hw_segment: - if (hw_seg_size > bio->bi_hw_front_size) - bio->bi_hw_front_size = hw_seg_size; + if (nr_hw_segs == 1 && + hw_seg_size > rq->bio->bi_hw_front_size) + rq->bio->bi_hw_front_size = hw_seg_size; hw_seg_size = BIOVEC_VIRT_START_SIZE(bv) + bv->bv_len; nr_hw_segs++; } @@ -1270,15 +1298,15 @@ new_hw_segment: seg_size = bv->bv_len; highprv = high; } - if (hw_seg_size > bio->bi_hw_back_size) - bio->bi_hw_back_size = hw_seg_size; - if (nr_hw_segs == 1 && hw_seg_size > bio->bi_hw_front_size) - bio->bi_hw_front_size = hw_seg_size; - bio->bi_phys_segments = nr_phys_segs; - bio->bi_hw_segments = nr_hw_segs; - bio->bi_flags |= (1 << BIO_SEG_VALID); + + if (nr_hw_segs == 1 && + hw_seg_size > rq->bio->bi_hw_front_size) + rq->bio->bi_hw_front_size = hw_seg_size; + if (hw_seg_size > rq->biotail->bi_hw_back_size) + rq->biotail->bi_hw_back_size = hw_seg_size; + rq->nr_phys_segments = nr_phys_segs; + rq->nr_hw_segments = nr_hw_segs; } -EXPORT_SYMBOL(blk_recount_segments); static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio, struct bio *nxt) @@ -3329,48 +3357,6 @@ void submit_bio(int rw, struct bio *bio) EXPORT_SYMBOL(submit_bio); -static void blk_recalc_rq_segments(struct request *rq) -{ - struct bio *bio, *prevbio = NULL; - int nr_phys_segs, nr_hw_segs; - unsigned int phys_size, hw_size; - struct request_queue *q = rq->q; - - if (!rq->bio) - return; - - phys_size = hw_size = nr_phys_segs = nr_hw_segs = 0; - rq_for_each_bio(bio, rq) { - /* Force bio hw/phys segs to be recalculated. */ - bio->bi_flags &= ~(1 << BIO_SEG_VALID); - - nr_phys_segs += bio_phys_segments(q, bio); - nr_hw_segs += bio_hw_segments(q, bio); - if (prevbio) { - int pseg = phys_size + prevbio->bi_size + bio->bi_size; - int hseg = hw_size + prevbio->bi_size + bio->bi_size; - - if (blk_phys_contig_segment(q, prevbio, bio) && - pseg <= q->max_segment_size) { - nr_phys_segs--; - phys_size += prevbio->bi_size + bio->bi_size; - } else - phys_size = 0; - - if (blk_hw_contig_segment(q, prevbio, bio) && - hseg <= q->max_segment_size) { - nr_hw_segs--; - hw_size += prevbio->bi_size + bio->bi_size; - } else - hw_size = 0; - } - prevbio = bio; - } - - rq->nr_phys_segments = nr_phys_segs; - rq->nr_hw_segments = nr_hw_segs; -} - static void blk_recalc_rq_sectors(struct request *rq, int nsect) { if (blk_fs_request(rq)) { -- cgit v0.10.2 From 5705f7021748a69d84d6567e68e8851dab551464 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 25 Sep 2007 12:35:59 +0200 Subject: Introduce rq_for_each_segment replacing rq_for_each_bio Every usage of rq_for_each_bio wraps a usage of bio_for_each_segment, so these can be combined into rq_for_each_segment. We define "struct req_iterator" to hold the 'bio' and 'index' that are needed for the double iteration. Signed-off-by: Neil Brown Various compile fixes by me... Signed-off-by: Jens Axboe diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index 8af392f..dc3f49e 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt @@ -477,9 +477,9 @@ With this multipage bio design: the same bi_io_vec array, but with the index and size accordingly modified) - A linked list of bios is used as before for unrelated merges (*) - this avoids reallocs and makes independent completions easier to handle. -- Code that traverses the req list needs to make a distinction between - segments of a request (bio_for_each_segment) and the distinct completion - units/bios (rq_for_each_bio). +- Code that traverses the req list can find all the segments of a bio + by using rq_for_each_segment. This handles the fact that a request + has multiple bios, each of which can have multiple segments. - Drivers which can't process a large bio in one shot can use the bi_idx field to keep track of the next bio_vec entry to process. (e.g a 1MB bio_vec needs to be handled in max 128kB chunks for IDE) @@ -664,14 +664,14 @@ in lvm or md. 3.2.1 Traversing segments and completion units in a request -The macros bio_for_each_segment() and rq_for_each_bio() should be used for -traversing the bios in the request list (drivers should avoid directly -trying to do it themselves). Using these helpers should also make it easier -to cope with block changes in the future. +The macro rq_for_each_segment() should be used for traversing the bios +in the request list (drivers should avoid directly trying to do it +themselves). Using these helpers should also make it easier to cope +with block changes in the future. - rq_for_each_bio(bio, rq) - bio_for_each_segment(bio_vec, bio, i) - /* bio_vec is now current segment */ + struct req_iterator iter; + rq_for_each_segment(bio_vec, rq, iter) + /* bio_vec is now current segment */ I/O completion callbacks are per-bio rather than per-segment, so drivers that traverse bio chains on completion need to keep that in mind. Drivers diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index e35119a..094c0fa 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -1244,8 +1244,7 @@ static void blk_recalc_rq_segments(struct request *rq) int seg_size; int hw_seg_size; int cluster; - struct bio *bio; - int i; + struct req_iterator iter; int high, highprv = 1; struct request_queue *q = rq->q; @@ -1255,8 +1254,7 @@ static void blk_recalc_rq_segments(struct request *rq) cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER); hw_seg_size = seg_size = 0; phys_size = hw_size = nr_phys_segs = nr_hw_segs = 0; - rq_for_each_bio(bio, rq) - bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, rq, iter) { /* * the trick here is making sure that a high page is never * considered part of another segment, since that might @@ -1353,8 +1351,8 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq, struct scatterlist *sg) { struct bio_vec *bvec, *bvprv; - struct bio *bio; - int nsegs, i, cluster; + struct req_iterator iter; + int nsegs, cluster; nsegs = 0; cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER); @@ -1363,11 +1361,7 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq, * for each bio in rq */ bvprv = NULL; - rq_for_each_bio(bio, rq) { - /* - * for each segment in bio - */ - bio_for_each_segment(bvec, bio, i) { + rq_for_each_segment(bvec, rq, iter) { int nbytes = bvec->bv_len; if (bvprv && cluster) { @@ -1390,8 +1384,7 @@ new_segment: nsegs++; } bvprv = bvec; - } /* segments in bio */ - } /* bios in rq */ + } /* segments in rq */ return nsegs; } diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 085b779..f0a86e2 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -2437,22 +2437,19 @@ static void rw_interrupt(void) /* Compute maximal contiguous buffer size. */ static int buffer_chain_size(void) { - struct bio *bio; struct bio_vec *bv; - int size, i; + int size; + struct req_iterator iter; char *base; base = bio_data(current_req->bio); size = 0; - rq_for_each_bio(bio, current_req) { - bio_for_each_segment(bv, bio, i) { - if (page_address(bv->bv_page) + bv->bv_offset != - base + size) - break; + rq_for_each_segment(bv, current_req, iter) { + if (page_address(bv->bv_page) + bv->bv_offset != base + size) + break; - size += bv->bv_len; - } + size += bv->bv_len; } return size >> 9; @@ -2479,9 +2476,9 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) { int remaining; /* number of transferred 512-byte sectors */ struct bio_vec *bv; - struct bio *bio; char *buffer, *dma_buffer; - int size, i; + int size; + struct req_iterator iter; max_sector = transfer_size(ssize, min(max_sector, max_sector_2), @@ -2514,43 +2511,41 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) size = current_req->current_nr_sectors << 9; - rq_for_each_bio(bio, current_req) { - bio_for_each_segment(bv, bio, i) { - if (!remaining) - break; + rq_for_each_segment(bv, current_req, iter) { + if (!remaining) + break; - size = bv->bv_len; - SUPBOUND(size, remaining); + size = bv->bv_len; + SUPBOUND(size, remaining); - buffer = page_address(bv->bv_page) + bv->bv_offset; + buffer = page_address(bv->bv_page) + bv->bv_offset; #ifdef FLOPPY_SANITY_CHECK - if (dma_buffer + size > - floppy_track_buffer + (max_buffer_sectors << 10) || - dma_buffer < floppy_track_buffer) { - DPRINT("buffer overrun in copy buffer %d\n", - (int)((floppy_track_buffer - - dma_buffer) >> 9)); - printk("fsector_t=%d buffer_min=%d\n", - fsector_t, buffer_min); - printk("current_count_sectors=%ld\n", - current_count_sectors); - if (CT(COMMAND) == FD_READ) - printk("read\n"); - if (CT(COMMAND) == FD_WRITE) - printk("write\n"); - break; - } - if (((unsigned long)buffer) % 512) - DPRINT("%p buffer not aligned\n", buffer); -#endif + if (dma_buffer + size > + floppy_track_buffer + (max_buffer_sectors << 10) || + dma_buffer < floppy_track_buffer) { + DPRINT("buffer overrun in copy buffer %d\n", + (int)((floppy_track_buffer - + dma_buffer) >> 9)); + printk("fsector_t=%d buffer_min=%d\n", + fsector_t, buffer_min); + printk("current_count_sectors=%ld\n", + current_count_sectors); if (CT(COMMAND) == FD_READ) - memcpy(buffer, dma_buffer, size); - else - memcpy(dma_buffer, buffer, size); - - remaining -= size; - dma_buffer += size; + printk("read\n"); + if (CT(COMMAND) == FD_WRITE) + printk("write\n"); + break; } + if (((unsigned long)buffer) % 512) + DPRINT("%p buffer not aligned\n", buffer); +#endif + if (CT(COMMAND) == FD_READ) + memcpy(buffer, dma_buffer, size); + else + memcpy(dma_buffer, buffer, size); + + remaining -= size; + dma_buffer += size; } #ifdef FLOPPY_SANITY_CHECK if (remaining) { diff --git a/drivers/block/lguest_blk.c b/drivers/block/lguest_blk.c index 160cf14..1e838ae 100644 --- a/drivers/block/lguest_blk.c +++ b/drivers/block/lguest_blk.c @@ -142,12 +142,11 @@ static irqreturn_t lgb_irq(int irq, void *_bd) * return the total length. */ static unsigned int req_to_dma(struct request *req, struct lguest_dma *dma) { - unsigned int i = 0, idx, len = 0; - struct bio *bio; + unsigned int i = 0, len = 0; + struct req_iterator iter; + struct bio_vec *bvec; - rq_for_each_bio(bio, req) { - struct bio_vec *bvec; - bio_for_each_segment(bvec, bio, idx) { + rq_for_each_segment(bvec, req, iter) { /* We told the block layer not to give us too many. */ BUG_ON(i == LGUEST_MAX_DMA_SECTIONS); /* If we had a zero-length segment, it would look like @@ -160,7 +159,6 @@ static unsigned int req_to_dma(struct request *req, struct lguest_dma *dma) dma->len[i] = bvec->bv_len; len += bvec->bv_len; i++; - } } /* If the array isn't full, we mark the end with a 0 length */ if (i < LGUEST_MAX_DMA_SECTIONS) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index be92c65..228b2ff 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -180,7 +180,7 @@ static inline int sock_send_bvec(struct socket *sock, struct bio_vec *bvec, static int nbd_send_req(struct nbd_device *lo, struct request *req) { - int result, i, flags; + int result, flags; struct nbd_request request; unsigned long size = req->nr_sectors << 9; struct socket *sock = lo->sock; @@ -205,16 +205,15 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req) } if (nbd_cmd(req) == NBD_CMD_WRITE) { - struct bio *bio; + struct req_iterator iter; + struct bio_vec *bvec; /* * we are really probing at internals to determine * whether to set MSG_MORE or not... */ - rq_for_each_bio(bio, req) { - struct bio_vec *bvec; - bio_for_each_segment(bvec, bio, i) { + rq_for_each_segment(bvec, req, iter) { flags = 0; - if ((i < (bio->bi_vcnt - 1)) || bio->bi_next) + if (!rq_iter_last(req, iter)) flags = MSG_MORE; dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n", lo->disk->disk_name, req, @@ -226,7 +225,6 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req) result); goto error_out; } - } } } return 0; @@ -321,11 +319,10 @@ static struct request *nbd_read_stat(struct nbd_device *lo) dprintk(DBG_RX, "%s: request %p: got reply\n", lo->disk->disk_name, req); if (nbd_cmd(req) == NBD_CMD_READ) { - int i; - struct bio *bio; - rq_for_each_bio(bio, req) { - struct bio_vec *bvec; - bio_for_each_segment(bvec, bio, i) { + struct req_iterator iter; + struct bio_vec *bvec; + + rq_for_each_segment(bvec, req, iter) { result = sock_recv_bvec(sock, bvec); if (result <= 0) { printk(KERN_ERR "%s: Receive data failed (result %d)\n", @@ -336,7 +333,6 @@ static struct request *nbd_read_stat(struct nbd_device *lo) } dprintk(DBG_RX, "%s: request %p: got %d bytes data\n", lo->disk->disk_name, req, bvec->bv_len); - } } } return req; diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index aa8b890..8953e7c 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -91,30 +91,30 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev, struct request *req, int gather) { unsigned int offset = 0; - struct bio *bio; - sector_t sector; + struct req_iterator iter; struct bio_vec *bvec; - unsigned int i = 0, j; + unsigned int i = 0; size_t size; void *buf; - rq_for_each_bio(bio, req) { - sector = bio->bi_sector; + rq_for_each_segment(bvec, req, iter) { + unsigned long flags; dev_dbg(&dev->sbd.core, "%s:%u: bio %u: %u segs %u sectors from %lu\n", - __func__, __LINE__, i, bio_segments(bio), - bio_sectors(bio), sector); - bio_for_each_segment(bvec, bio, j) { + __func__, __LINE__, i, bio_segments(iter.bio), + bio_sectors(iter.bio), + (unsigned long)iter.bio->bi_sector); + size = bvec->bv_len; - buf = __bio_kmap_atomic(bio, j, KM_IRQ0); + buf = bvec_kmap_irq(bvec, &flags); if (gather) memcpy(dev->bounce_buf+offset, buf, size); else memcpy(buf, dev->bounce_buf+offset, size); offset += size; - flush_kernel_dcache_page(bio_iovec_idx(bio, j)->bv_page); - __bio_kunmap_atomic(bio, KM_IRQ0); - } + flush_kernel_dcache_page(bvec->bv_page); + bvec_kunmap_irq(bvec, &flags); + i++; } } @@ -130,12 +130,13 @@ static int ps3disk_submit_request_sg(struct ps3_storage_device *dev, #ifdef DEBUG unsigned int n = 0; - struct bio *bio; + struct bio_vec *bv; + struct req_iterator iter; - rq_for_each_bio(bio, req) + rq_for_each_segment(bv, req, iter) n++; dev_dbg(&dev->sbd.core, - "%s:%u: %s req has %u bios for %lu sectors %lu hard sectors\n", + "%s:%u: %s req has %u bvecs for %lu sectors %lu hard sectors\n", __func__, __LINE__, op, n, req->nr_sectors, req->hard_nr_sectors); #endif diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 964e516..6af2501 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -150,9 +150,8 @@ static int blkif_queue_request(struct request *req) struct blkfront_info *info = req->rq_disk->private_data; unsigned long buffer_mfn; struct blkif_request *ring_req; - struct bio *bio; + struct req_iterator iter; struct bio_vec *bvec; - int idx; unsigned long id; unsigned int fsect, lsect; int ref; @@ -186,8 +185,7 @@ static int blkif_queue_request(struct request *req) ring_req->operation = BLKIF_OP_WRITE_BARRIER; ring_req->nr_segments = 0; - rq_for_each_bio (bio, req) { - bio_for_each_segment (bvec, bio, idx) { + rq_for_each_segment(bvec, req, iter) { BUG_ON(ring_req->nr_segments == BLKIF_MAX_SEGMENTS_PER_REQUEST); buffer_mfn = pfn_to_mfn(page_to_pfn(bvec->bv_page)); @@ -213,7 +211,6 @@ static int blkif_queue_request(struct request *req) .last_sect = lsect }; ring_req->nr_segments++; - } } info->ring.req_prod_pvt++; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index ae8e1a6..a775450 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -606,13 +606,12 @@ static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, uns { struct request *rq = pc->rq; struct bio_vec *bvec; - struct bio *bio; + struct req_iterator iter; unsigned long flags; char *data; - int count, i, done = 0; + int count, done = 0; - rq_for_each_bio(bio, rq) { - bio_for_each_segment(bvec, bio, i) { + rq_for_each_segment(bvec, rq, iter) { if (!bcount) break; @@ -625,7 +624,6 @@ static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, uns bcount -= count; pc->b_count += count; done += count; - } } idefloppy_do_end_request(drive, 1, done >> 9); @@ -639,14 +637,13 @@ static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, uns static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount) { struct request *rq = pc->rq; - struct bio *bio; + struct req_iterator iter; struct bio_vec *bvec; unsigned long flags; - int count, i, done = 0; + int count, done = 0; char *data; - rq_for_each_bio(bio, rq) { - bio_for_each_segment(bvec, bio, i) { + rq_for_each_segment(bvec, rq, iter) { if (!bcount) break; @@ -659,7 +656,6 @@ static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, un bcount -= count; pc->b_count += count; done += count; - } } idefloppy_do_end_request(drive, 1, done >> 9); diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index d32c60d..6bb9676 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -472,14 +472,13 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) struct dasd_ccw_req *cqr; struct dasd_diag_req *dreq; struct dasd_diag_bio *dbio; - struct bio *bio; + struct req_iterator iter; struct bio_vec *bv; char *dst; unsigned int count, datasize; sector_t recid, first_rec, last_rec; unsigned int blksize, off; unsigned char rw_cmd; - int i; if (rq_data_dir(req) == READ) rw_cmd = MDSK_READ_REQ; @@ -493,13 +492,11 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) last_rec = (req->sector + req->nr_sectors - 1) >> device->s2b_shift; /* Check struct bio and count the number of blocks for the request. */ count = 0; - rq_for_each_bio(bio, req) { - bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { if (bv->bv_len & (blksize - 1)) /* Fba can only do full blocks. */ return ERR_PTR(-EINVAL); count += bv->bv_len >> (device->s2b_shift + 9); - } } /* Paranoia. */ if (count != last_rec - first_rec + 1) @@ -516,8 +513,7 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) dreq->block_count = count; dbio = dreq->bio; recid = first_rec; - rq_for_each_bio(bio, req) { - bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { dst = page_address(bv->bv_page) + bv->bv_offset; for (off = 0; off < bv->bv_len; off += blksize) { memset(dbio, 0, sizeof (struct dasd_diag_bio)); @@ -528,7 +524,6 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) dst += blksize; recid++; } - } } cqr->retries = DIAG_MAX_RETRIES; cqr->buildclk = get_clock(); diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index ea63ba7..36ba458 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1176,7 +1176,7 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) struct LO_eckd_data *LO_data; struct dasd_ccw_req *cqr; struct ccw1 *ccw; - struct bio *bio; + struct req_iterator iter; struct bio_vec *bv; char *dst; unsigned int blksize, blk_per_trk, off; @@ -1185,7 +1185,6 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) sector_t first_trk, last_trk; unsigned int first_offs, last_offs; unsigned char cmd, rcmd; - int i; private = (struct dasd_eckd_private *) device->private; if (rq_data_dir(req) == READ) @@ -1206,8 +1205,7 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) /* Check struct bio and count the number of blocks for the request. */ count = 0; cidaw = 0; - rq_for_each_bio(bio, req) { - bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { if (bv->bv_len & (blksize - 1)) /* Eckd can only do full blocks. */ return ERR_PTR(-EINVAL); @@ -1217,7 +1215,6 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) bv->bv_len)) cidaw += bv->bv_len >> (device->s2b_shift + 9); #endif - } } /* Paranoia. */ if (count != last_rec - first_rec + 1) @@ -1257,7 +1254,7 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) locate_record(ccw++, LO_data++, first_trk, first_offs + 1, last_rec - recid + 1, cmd, device, blksize); } - rq_for_each_bio(bio, req) bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { dst = page_address(bv->bv_page) + bv->bv_offset; if (dasd_page_cache) { char *copy = kmem_cache_alloc(dasd_page_cache, @@ -1328,12 +1325,12 @@ dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req) { struct dasd_eckd_private *private; struct ccw1 *ccw; - struct bio *bio; + struct req_iterator iter; struct bio_vec *bv; char *dst, *cda; unsigned int blksize, blk_per_trk, off; sector_t recid; - int i, status; + int status; if (!dasd_page_cache) goto out; @@ -1346,7 +1343,7 @@ dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req) ccw++; if (private->uses_cdl == 0 || recid > 2*blk_per_trk) ccw++; - rq_for_each_bio(bio, req) bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { dst = page_address(bv->bv_page) + bv->bv_offset; for (off = 0; off < bv->bv_len; off += blksize) { /* Skip locate record. */ diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index da16ead..119b8d2 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -234,14 +234,13 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req) struct LO_fba_data *LO_data; struct dasd_ccw_req *cqr; struct ccw1 *ccw; - struct bio *bio; + struct req_iterator iter; struct bio_vec *bv; char *dst; int count, cidaw, cplength, datasize; sector_t recid, first_rec, last_rec; unsigned int blksize, off; unsigned char cmd; - int i; private = (struct dasd_fba_private *) device->private; if (rq_data_dir(req) == READ) { @@ -257,8 +256,7 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req) /* Check struct bio and count the number of blocks for the request. */ count = 0; cidaw = 0; - rq_for_each_bio(bio, req) { - bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { if (bv->bv_len & (blksize - 1)) /* Fba can only do full blocks. */ return ERR_PTR(-EINVAL); @@ -268,7 +266,6 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req) bv->bv_len)) cidaw += bv->bv_len / blksize; #endif - } } /* Paranoia. */ if (count != last_rec - first_rec + 1) @@ -304,7 +301,7 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req) locate_record(ccw++, LO_data++, rq_data_dir(req), 0, count); } recid = first_rec; - rq_for_each_bio(bio, req) bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { dst = page_address(bv->bv_page) + bv->bv_offset; if (dasd_page_cache) { char *copy = kmem_cache_alloc(dasd_page_cache, @@ -359,11 +356,11 @@ dasd_fba_free_cp(struct dasd_ccw_req *cqr, struct request *req) { struct dasd_fba_private *private; struct ccw1 *ccw; - struct bio *bio; + struct req_iterator iter; struct bio_vec *bv; char *dst, *cda; unsigned int blksize, off; - int i, status; + int status; if (!dasd_page_cache) goto out; @@ -374,7 +371,7 @@ dasd_fba_free_cp(struct dasd_ccw_req *cqr, struct request *req) ccw++; if (private->rdc_data.mode.bits.data_chain != 0) ccw++; - rq_for_each_bio(bio, req) bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { dst = page_address(bv->bv_page) + bv->bv_offset; for (off = 0; off < bv->bv_len; off += blksize) { /* Skip locate record. */ diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index 80e7a53..ea3e6a3 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c @@ -1134,21 +1134,18 @@ tape_34xx_bread(struct tape_device *device, struct request *req) { struct tape_request *request; struct ccw1 *ccw; - int count = 0, i; + int count = 0; unsigned off; char *dst; struct bio_vec *bv; - struct bio *bio; + struct req_iterator iter; struct tape_34xx_block_id * start_block; DBF_EVENT(6, "xBREDid:"); /* Count the number of blocks for the request. */ - rq_for_each_bio(bio, req) { - bio_for_each_segment(bv, bio, i) { - count += bv->bv_len >> (TAPEBLOCK_HSEC_S2B + 9); - } - } + rq_for_each_segment(bv, req, iter) + count += bv->bv_len >> (TAPEBLOCK_HSEC_S2B + 9); /* Allocate the ccw request. */ request = tape_alloc_request(3+count+1, 8); @@ -1175,8 +1172,7 @@ tape_34xx_bread(struct tape_device *device, struct request *req) ccw = tape_ccw_cc(ccw, NOP, 0, NULL); ccw = tape_ccw_cc(ccw, NOP, 0, NULL); - rq_for_each_bio(bio, req) { - bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { dst = kmap(bv->bv_page) + bv->bv_offset; for (off = 0; off < bv->bv_len; off += TAPEBLOCK_HSEC_SIZE) { @@ -1187,7 +1183,6 @@ tape_34xx_bread(struct tape_device *device, struct request *req) ccw++; dst += TAPEBLOCK_HSEC_SIZE; } - } } ccw = tape_ccw_end(ccw, NOP, 0, NULL); diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 7e2b2ab..b16ad7a 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c @@ -623,21 +623,19 @@ tape_3590_bread(struct tape_device *device, struct request *req) { struct tape_request *request; struct ccw1 *ccw; - int count = 0, start_block, i; + int count = 0, start_block; unsigned off; char *dst; struct bio_vec *bv; - struct bio *bio; + struct req_iterator iter; DBF_EVENT(6, "xBREDid:"); start_block = req->sector >> TAPEBLOCK_HSEC_S2B; DBF_EVENT(6, "start_block = %i\n", start_block); - rq_for_each_bio(bio, req) { - bio_for_each_segment(bv, bio, i) { - count += bv->bv_len >> (TAPEBLOCK_HSEC_S2B + 9); - } - } + rq_for_each_segment(bv, req, iter) + count += bv->bv_len >> (TAPEBLOCK_HSEC_S2B + 9); + request = tape_alloc_request(2 + count + 1, 4); if (IS_ERR(request)) return request; @@ -653,8 +651,7 @@ tape_3590_bread(struct tape_device *device, struct request *req) */ ccw = tape_ccw_cc(ccw, NOP, 0, NULL); - rq_for_each_bio(bio, req) { - bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { dst = page_address(bv->bv_page) + bv->bv_offset; for (off = 0; off < bv->bv_len; off += TAPEBLOCK_HSEC_SIZE) { @@ -667,7 +664,6 @@ tape_3590_bread(struct tape_device *device, struct request *req) } if (off > bv->bv_len) BUG(); - } } ccw = tape_ccw_end(ccw, NOP, 0, NULL); DBF_EVENT(6, "xBREDccwg\n"); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index b126c6f..a4b13b8 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -637,10 +637,23 @@ static inline void blk_queue_bounce(struct request_queue *q, struct bio **bio) } #endif /* CONFIG_MMU */ -#define rq_for_each_bio(_bio, rq) \ +struct req_iterator { + int i; + struct bio *bio; +}; + +/* This should not be used directly - use rq_for_each_segment */ +#define __rq_for_each_bio(_bio, rq) \ if ((rq->bio)) \ for (_bio = (rq)->bio; _bio; _bio = _bio->bi_next) +#define rq_for_each_segment(bvl, _rq, _iter) \ + __rq_for_each_bio(_iter.bio, _rq) \ + bio_for_each_segment(bvl, _iter.bio, _iter.i) + +#define rq_iter_last(rq, _iter) \ + (_iter.bio->bi_next == NULL && _iter.i == _iter.bio->bi_vcnt-1) + extern int blk_register_queue(struct gendisk *disk); extern void blk_unregister_queue(struct gendisk *disk); extern void register_disk(struct gendisk *dev); -- cgit v0.10.2 From eea9befaccb8d43ce89585d612159761c978f056 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 16 Aug 2007 13:31:26 +0200 Subject: Fix various abuse of bio fields in umem.c umem.c: advances bi_idx and bi_sector to track where it is up to. But it is only ever doing this on one bio, so the updated fields can easily be kept elsewhere (current_*). updates bi_size, but never uses the updated values, so this isn't needed. reuses bi_phys_segments to count how many iovecs have been completely. As the completion happens sequentiually, we can store this information outside the bio too. Signed-off-by: Neil Brown diff .prev/drivers/block/umem.c ./drivers/block/umem.c Signed-off-by: Jens Axboe diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 6b7c02d..c378e28 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -113,6 +113,8 @@ struct cardinfo { * have been written */ struct bio *bio, *currentbio, **biotail; + int current_idx; + sector_t current_sector; struct request_queue *queue; @@ -121,6 +123,7 @@ struct cardinfo { struct mm_dma_desc *desc; int cnt, headcnt; struct bio *bio, **biotail; + int idx; } mm_pages[2]; #define DESC_PER_PAGE ((PAGE_SIZE*2)/sizeof(struct mm_dma_desc)) @@ -380,12 +383,16 @@ static int add_bio(struct cardinfo *card) dma_addr_t dma_handle; int offset; struct bio *bio; + struct bio_vec *vec; + int idx; int rw; int len; bio = card->currentbio; if (!bio && card->bio) { card->currentbio = card->bio; + card->current_idx = card->bio->bi_idx; + card->current_sector = card->bio->bi_sector; card->bio = card->bio->bi_next; if (card->bio == NULL) card->biotail = &card->bio; @@ -394,15 +401,17 @@ static int add_bio(struct cardinfo *card) } if (!bio) return 0; + idx = card->current_idx; rw = bio_rw(bio); if (card->mm_pages[card->Ready].cnt >= DESC_PER_PAGE) return 0; - len = bio_iovec(bio)->bv_len; - dma_handle = pci_map_page(card->dev, - bio_page(bio), - bio_offset(bio), + vec = bio_iovec_idx(bio, idx); + len = vec->bv_len; + dma_handle = pci_map_page(card->dev, + vec->bv_page, + vec->bv_offset, len, (rw==READ) ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); @@ -410,6 +419,8 @@ static int add_bio(struct cardinfo *card) p = &card->mm_pages[card->Ready]; desc = &p->desc[p->cnt]; p->cnt++; + if (p->bio == NULL) + p->idx = idx; if ((p->biotail) != &bio->bi_next) { *(p->biotail) = bio; p->biotail = &(bio->bi_next); @@ -419,7 +430,7 @@ static int add_bio(struct cardinfo *card) desc->data_dma_handle = dma_handle; desc->pci_addr = cpu_to_le64((u64)desc->data_dma_handle); - desc->local_addr= cpu_to_le64(bio->bi_sector << 9); + desc->local_addr = cpu_to_le64(card->current_sector << 9); desc->transfer_size = cpu_to_le32(len); offset = ( ((char*)&desc->sem_control_bits) - ((char*)p->desc)); desc->sem_addr = cpu_to_le64((u64)(p->page_dma+offset)); @@ -435,10 +446,10 @@ static int add_bio(struct cardinfo *card) desc->control_bits |= cpu_to_le32(DMASCR_TRANSFER_READ); desc->sem_control_bits = desc->control_bits; - bio->bi_sector += (len>>9); - bio->bi_size -= len; - bio->bi_idx++; - if (bio->bi_idx >= bio->bi_vcnt) + card->current_sector += (len >> 9); + idx++; + card->current_idx = idx; + if (idx >= bio->bi_vcnt) card->currentbio = NULL; return 1; @@ -474,10 +485,12 @@ static void process_page(unsigned long data) last=1; } page->headcnt++; - idx = bio->bi_phys_segments; - bio->bi_phys_segments++; - if (bio->bi_phys_segments >= bio->bi_vcnt) + idx = page->idx; + page->idx++; + if (page->idx >= bio->bi_vcnt) { page->bio = bio->bi_next; + page->idx = page->bio->bi_idx; + } pci_unmap_page(card->dev, desc->data_dma_handle, bio_iovec_idx(bio,idx)->bv_len, @@ -547,7 +560,6 @@ static int mm_make_request(struct request_queue *q, struct bio *bio) pr_debug("mm_make_request %llu %u\n", (unsigned long long)bio->bi_sector, bio->bi_size); - bio->bi_phys_segments = bio->bi_idx; /* count of completed segments*/ spin_lock_irq(&card->lock); *card->biotail = bio; bio->bi_next = NULL; -- cgit v0.10.2 From 3001ca77128273cc5634d79f5306ce2e5a14ec41 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 16 Aug 2007 13:31:27 +0200 Subject: New function blk_req_append_bio ll_back_merge_fn is currently exported to SCSI where is it used, together with blk_rq_bio_prep, in exactly the same way these functions are used in __blk_rq_map_user. So move the common code into a new function (blk_rq_append_bio), and don't export ll_back_merge_fn any longer. Signed-off-by: Neil Brown diff .prev/block/ll_rw_blk.c ./block/ll_rw_blk.c Signed-off-by: Jens Axboe diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 094c0fa..2de9bad 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -1441,7 +1441,8 @@ static inline int ll_new_hw_segment(struct request_queue *q, return 1; } -int ll_back_merge_fn(struct request_queue *q, struct request *req, struct bio *bio) +static int ll_back_merge_fn(struct request_queue *q, struct request *req, + struct bio *bio) { unsigned short max_sectors; int len; @@ -1477,7 +1478,6 @@ int ll_back_merge_fn(struct request_queue *q, struct request *req, struct bio *b return ll_new_hw_segment(q, req, bio); } -EXPORT_SYMBOL(ll_back_merge_fn); static int ll_front_merge_fn(struct request_queue *q, struct request *req, struct bio *bio) @@ -2367,6 +2367,23 @@ static int __blk_rq_unmap_user(struct bio *bio) return ret; } +int blk_rq_append_bio(struct request_queue *q, struct request *rq, + struct bio *bio) +{ + if (!rq->bio) + blk_rq_bio_prep(q, rq, bio); + else if (!ll_back_merge_fn(q, rq, bio)) + return -EINVAL; + else { + rq->biotail->bi_next = bio; + rq->biotail = bio; + + rq->data_len += bio->bi_size; + } + return 0; +} +EXPORT_SYMBOL(blk_rq_append_bio); + static int __blk_rq_map_user(struct request_queue *q, struct request *rq, void __user *ubuf, unsigned int len) { @@ -2398,21 +2415,10 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, */ bio_get(bio); - if (!rq->bio) - blk_rq_bio_prep(q, rq, bio); - else if (!ll_back_merge_fn(q, rq, bio)) { - ret = -EINVAL; - goto unmap_bio; - } else { - rq->biotail->bi_next = bio; - rq->biotail = bio; - - rq->data_len += bio->bi_size; - } - - return bio->bi_size; + ret = blk_rq_append_bio(q, rq, bio); + if (!ret) + return bio->bi_size; -unmap_bio: /* if it was boucned we must call the end io function */ bio_endio(bio, bio->bi_size, 0); __blk_rq_unmap_user(orig_bio); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index a417a6ff..59b3985 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -263,16 +263,7 @@ static int scsi_merge_bio(struct request *rq, struct bio *bio) bio->bi_rw |= (1 << BIO_RW); blk_queue_bounce(q, &bio); - if (!rq->bio) - blk_rq_bio_prep(q, rq, bio); - else if (!ll_back_merge_fn(q, rq, bio)) - return -EINVAL; - else { - rq->biotail->bi_next = bio; - rq->biotail = bio; - } - - return 0; + return blk_rq_append_bio(q, rq, bio); } static int scsi_bi_endio(struct bio *bio, unsigned int bytes_done, int error) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index a4b13b8..3021a5b 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -675,8 +675,8 @@ extern int sg_scsi_ioctl(struct file *, struct request_queue *, /* * Temporary export, until SCSI gets fixed up. */ -extern int ll_back_merge_fn(struct request_queue *, struct request *, - struct bio *); +extern int blk_rq_append_bio(struct request_queue *q, struct request *rq, + struct bio *bio); /* * A queue has just exitted congestion. Note this in the global counter of -- cgit v0.10.2 From 66846572bfb4ec62bcba260028cbbcbdb77bd636 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 16 Aug 2007 13:31:28 +0200 Subject: Stop exporting blk_rq_bio_prep blk_rq_bio_prep is exported for use in exactly one place. That place can benefit from using the new blk_rq_append_bio instead. So - change dm-emc to call blk_rq_append_bio - stop exporting blk_rq_bio_prep, and - initialise rq_disk in blk_rq_bio_prep, as dm-emc needs it. Signed-off-by: Neil Brown diff .prev/block/ll_rw_blk.c ./block/ll_rw_blk.c Signed-off-by: Jens Axboe diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 2de9bad..eb27b33 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -43,6 +43,8 @@ static void init_request_from_bio(struct request *req, struct bio *bio); static int __make_request(struct request_queue *q, struct bio *bio); static struct io_context *current_io_context(gfp_t gfp_flags, int node); static void blk_recalc_rq_segments(struct request *rq); +static void blk_rq_bio_prep(struct request_queue *q, struct request *rq, + struct bio *bio); /* * For the allocated request tables @@ -3665,8 +3667,8 @@ void end_request(struct request *req, int uptodate) EXPORT_SYMBOL(end_request); -void blk_rq_bio_prep(struct request_queue *q, struct request *rq, - struct bio *bio) +static void blk_rq_bio_prep(struct request_queue *q, struct request *rq, + struct bio *bio) { /* first two bits are identical in rq->cmd_flags and bio->bi_rw */ rq->cmd_flags |= (bio->bi_rw & 3); @@ -3680,9 +3682,10 @@ void blk_rq_bio_prep(struct request_queue *q, struct request *rq, rq->data_len = bio->bi_size; rq->bio = rq->biotail = bio; -} -EXPORT_SYMBOL(blk_rq_bio_prep); + if (bio->bi_bdev) + rq->rq_disk = bio->bi_bdev->bd_disk; +} int kblockd_schedule_work(struct work_struct *work) { diff --git a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c index 265c467..71cc858 100644 --- a/drivers/md/dm-emc.c +++ b/drivers/md/dm-emc.c @@ -109,15 +109,7 @@ static struct request *get_failover_req(struct emc_handler *h, return NULL; } - rq->bio = rq->biotail = bio; - blk_rq_bio_prep(q, rq, bio); - - rq->rq_disk = bdev->bd_contains->bd_disk; - - /* bio backed don't set data */ - rq->buffer = rq->data = NULL; - /* rq data_len used for pc cmd's request_bufflen */ - rq->data_len = bio->bi_size; + blk_rq_append_bio(q, rq, bio); rq->sense = h->sense; memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 3021a5b..492ac94 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -823,7 +823,6 @@ static inline struct request *blk_map_queue_find_tag(struct blk_queue_tag *bqt, return bqt->tag_index[tag]; } -extern void blk_rq_bio_prep(struct request_queue *, struct request *, struct bio *); extern int blkdev_issue_flush(struct block_device *, sector_t *); #define MAX_PHYS_SEGMENTS 128 -- cgit v0.10.2 From bc1c56fde6dd1c85e2047c276456c07bd4508b5c Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 16 Aug 2007 13:31:30 +0200 Subject: Share code between init_request_from_bio and blk_rq_bio_prep These have very similar functions and should share code where possible. Signed-off-by: Neil Brown diff .prev/block/ll_rw_blk.c ./block/ll_rw_blk.c Signed-off-by: Jens Axboe diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index eb27b33..e0608c4 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -2941,15 +2941,9 @@ static void init_request_from_bio(struct request *req, struct bio *bio) req->errors = 0; req->hard_sector = req->sector = bio->bi_sector; - req->hard_nr_sectors = req->nr_sectors = bio_sectors(bio); - req->current_nr_sectors = req->hard_cur_sectors = bio_cur_sectors(bio); - req->nr_phys_segments = bio_phys_segments(req->q, bio); - req->nr_hw_segments = bio_hw_segments(req->q, bio); - req->buffer = bio_data(bio); /* see ->buffer comment above */ - req->bio = req->biotail = bio; req->ioprio = bio_prio(bio); - req->rq_disk = bio->bi_bdev->bd_disk; req->start_time = jiffies; + blk_rq_bio_prep(req->q, req, bio); } static int __make_request(struct request_queue *q, struct bio *bio) -- cgit v0.10.2 From 6c92e699b56287da582ccb12a64b959b6d6109ba Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 16 Aug 2007 13:43:12 +0200 Subject: Fixup rq_for_each_segment() indentation Remove one level of nesting where appropriate. Signed-off-by: Jens Axboe diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index e0608c4..c6b2a47 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -1364,28 +1364,28 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq, */ bvprv = NULL; rq_for_each_segment(bvec, rq, iter) { - int nbytes = bvec->bv_len; + int nbytes = bvec->bv_len; - if (bvprv && cluster) { - if (sg[nsegs - 1].length + nbytes > q->max_segment_size) - goto new_segment; + if (bvprv && cluster) { + if (sg[nsegs - 1].length + nbytes > q->max_segment_size) + goto new_segment; - if (!BIOVEC_PHYS_MERGEABLE(bvprv, bvec)) - goto new_segment; - if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bvec)) - goto new_segment; + if (!BIOVEC_PHYS_MERGEABLE(bvprv, bvec)) + goto new_segment; + if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bvec)) + goto new_segment; - sg[nsegs - 1].length += nbytes; - } else { + sg[nsegs - 1].length += nbytes; + } else { new_segment: - memset(&sg[nsegs],0,sizeof(struct scatterlist)); - sg[nsegs].page = bvec->bv_page; - sg[nsegs].length = nbytes; - sg[nsegs].offset = bvec->bv_offset; + memset(&sg[nsegs],0,sizeof(struct scatterlist)); + sg[nsegs].page = bvec->bv_page; + sg[nsegs].length = nbytes; + sg[nsegs].offset = bvec->bv_offset; - nsegs++; - } - bvprv = bvec; + nsegs++; + } + bvprv = bvec; } /* segments in rq */ return nsegs; diff --git a/drivers/block/lguest_blk.c b/drivers/block/lguest_blk.c index 1e838ae..fa8e423 100644 --- a/drivers/block/lguest_blk.c +++ b/drivers/block/lguest_blk.c @@ -147,18 +147,18 @@ static unsigned int req_to_dma(struct request *req, struct lguest_dma *dma) struct bio_vec *bvec; rq_for_each_segment(bvec, req, iter) { - /* We told the block layer not to give us too many. */ - BUG_ON(i == LGUEST_MAX_DMA_SECTIONS); - /* If we had a zero-length segment, it would look like - * the end of the data referred to by the "struct - * lguest_dma", so make sure that doesn't happen. */ - BUG_ON(!bvec->bv_len); - /* Convert page & offset to a physical address */ - dma->addr[i] = page_to_phys(bvec->bv_page) - + bvec->bv_offset; - dma->len[i] = bvec->bv_len; - len += bvec->bv_len; - i++; + /* We told the block layer not to give us too many. */ + BUG_ON(i == LGUEST_MAX_DMA_SECTIONS); + /* If we had a zero-length segment, it would look like + * the end of the data referred to by the "struct + * lguest_dma", so make sure that doesn't happen. */ + BUG_ON(!bvec->bv_len); + /* Convert page & offset to a physical address */ + dma->addr[i] = page_to_phys(bvec->bv_page) + + bvec->bv_offset; + dma->len[i] = bvec->bv_len; + len += bvec->bv_len; + i++; } /* If the array isn't full, we mark the end with a 0 length */ if (i < LGUEST_MAX_DMA_SECTIONS) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 228b2ff..be5ec3a 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -212,19 +212,17 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req) * whether to set MSG_MORE or not... */ rq_for_each_segment(bvec, req, iter) { - flags = 0; - if (!rq_iter_last(req, iter)) - flags = MSG_MORE; - dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n", - lo->disk->disk_name, req, - bvec->bv_len); - result = sock_send_bvec(sock, bvec, flags); - if (result <= 0) { - printk(KERN_ERR "%s: Send data failed (result %d)\n", - lo->disk->disk_name, - result); - goto error_out; - } + flags = 0; + if (!rq_iter_last(req, iter)) + flags = MSG_MORE; + dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n", + lo->disk->disk_name, req, bvec->bv_len); + result = sock_send_bvec(sock, bvec, flags); + if (result <= 0) { + printk(KERN_ERR "%s: Send data failed (result %d)\n", + lo->disk->disk_name, result); + goto error_out; + } } } return 0; @@ -323,16 +321,15 @@ static struct request *nbd_read_stat(struct nbd_device *lo) struct bio_vec *bvec; rq_for_each_segment(bvec, req, iter) { - result = sock_recv_bvec(sock, bvec); - if (result <= 0) { - printk(KERN_ERR "%s: Receive data failed (result %d)\n", - lo->disk->disk_name, - result); - req->errors++; - return req; - } - dprintk(DBG_RX, "%s: request %p: got %d bytes data\n", - lo->disk->disk_name, req, bvec->bv_len); + result = sock_recv_bvec(sock, bvec); + if (result <= 0) { + printk(KERN_ERR "%s: Receive data failed (result %d)\n", + lo->disk->disk_name, result); + req->errors++; + return req; + } + dprintk(DBG_RX, "%s: request %p: got %d bytes data\n", + lo->disk->disk_name, req, bvec->bv_len); } } return req; diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index 8953e7c..06d0552 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -105,16 +105,15 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev, bio_sectors(iter.bio), (unsigned long)iter.bio->bi_sector); - size = bvec->bv_len; - buf = bvec_kmap_irq(bvec, &flags); - if (gather) - memcpy(dev->bounce_buf+offset, buf, size); - else - memcpy(buf, dev->bounce_buf+offset, size); - offset += size; - flush_kernel_dcache_page(bvec->bv_page); - bvec_kunmap_irq(bvec, &flags); - + size = bvec->bv_len; + buf = bvec_kmap_irq(bvec, &flags); + if (gather) + memcpy(dev->bounce_buf+offset, buf, size); + else + memcpy(buf, dev->bounce_buf+offset, size); + offset += size; + flush_kernel_dcache_page(bvec->bv_page); + bvec_kunmap_irq(bvec, &flags); i++; } } diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 6af2501..2bdebcb 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -186,31 +186,30 @@ static int blkif_queue_request(struct request *req) ring_req->nr_segments = 0; rq_for_each_segment(bvec, req, iter) { - BUG_ON(ring_req->nr_segments - == BLKIF_MAX_SEGMENTS_PER_REQUEST); - buffer_mfn = pfn_to_mfn(page_to_pfn(bvec->bv_page)); - fsect = bvec->bv_offset >> 9; - lsect = fsect + (bvec->bv_len >> 9) - 1; - /* install a grant reference. */ - ref = gnttab_claim_grant_reference(&gref_head); - BUG_ON(ref == -ENOSPC); - - gnttab_grant_foreign_access_ref( + BUG_ON(ring_req->nr_segments == BLKIF_MAX_SEGMENTS_PER_REQUEST); + buffer_mfn = pfn_to_mfn(page_to_pfn(bvec->bv_page)); + fsect = bvec->bv_offset >> 9; + lsect = fsect + (bvec->bv_len >> 9) - 1; + /* install a grant reference. */ + ref = gnttab_claim_grant_reference(&gref_head); + BUG_ON(ref == -ENOSPC); + + gnttab_grant_foreign_access_ref( ref, info->xbdev->otherend_id, buffer_mfn, rq_data_dir(req) ); - info->shadow[id].frame[ring_req->nr_segments] = + info->shadow[id].frame[ring_req->nr_segments] = mfn_to_pfn(buffer_mfn); - ring_req->seg[ring_req->nr_segments] = + ring_req->seg[ring_req->nr_segments] = (struct blkif_request_segment) { .gref = ref, .first_sect = fsect, .last_sect = lsect }; - ring_req->nr_segments++; + ring_req->nr_segments++; } info->ring.req_prod_pvt++; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index a775450..04a3578 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -612,18 +612,18 @@ static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, uns int count, done = 0; rq_for_each_segment(bvec, rq, iter) { - if (!bcount) - break; + if (!bcount) + break; - count = min(bvec->bv_len, bcount); + count = min(bvec->bv_len, bcount); - data = bvec_kmap_irq(bvec, &flags); - drive->hwif->atapi_input_bytes(drive, data, count); - bvec_kunmap_irq(data, &flags); + data = bvec_kmap_irq(bvec, &flags); + drive->hwif->atapi_input_bytes(drive, data, count); + bvec_kunmap_irq(data, &flags); - bcount -= count; - pc->b_count += count; - done += count; + bcount -= count; + pc->b_count += count; + done += count; } idefloppy_do_end_request(drive, 1, done >> 9); @@ -644,18 +644,18 @@ static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, un char *data; rq_for_each_segment(bvec, rq, iter) { - if (!bcount) - break; + if (!bcount) + break; - count = min(bvec->bv_len, bcount); + count = min(bvec->bv_len, bcount); - data = bvec_kmap_irq(bvec, &flags); - drive->hwif->atapi_output_bytes(drive, data, count); - bvec_kunmap_irq(data, &flags); + data = bvec_kmap_irq(bvec, &flags); + drive->hwif->atapi_output_bytes(drive, data, count); + bvec_kunmap_irq(data, &flags); - bcount -= count; - pc->b_count += count; - done += count; + bcount -= count; + pc->b_count += count; + done += count; } idefloppy_do_end_request(drive, 1, done >> 9); diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 6bb9676..571320ab 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -493,10 +493,10 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) /* Check struct bio and count the number of blocks for the request. */ count = 0; rq_for_each_segment(bv, req, iter) { - if (bv->bv_len & (blksize - 1)) - /* Fba can only do full blocks. */ - return ERR_PTR(-EINVAL); - count += bv->bv_len >> (device->s2b_shift + 9); + if (bv->bv_len & (blksize - 1)) + /* Fba can only do full blocks. */ + return ERR_PTR(-EINVAL); + count += bv->bv_len >> (device->s2b_shift + 9); } /* Paranoia. */ if (count != last_rec - first_rec + 1) @@ -514,16 +514,16 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) dbio = dreq->bio; recid = first_rec; rq_for_each_segment(bv, req, iter) { - dst = page_address(bv->bv_page) + bv->bv_offset; - for (off = 0; off < bv->bv_len; off += blksize) { - memset(dbio, 0, sizeof (struct dasd_diag_bio)); - dbio->type = rw_cmd; - dbio->block_number = recid + 1; - dbio->buffer = dst; - dbio++; - dst += blksize; - recid++; - } + dst = page_address(bv->bv_page) + bv->bv_offset; + for (off = 0; off < bv->bv_len; off += blksize) { + memset(dbio, 0, sizeof (struct dasd_diag_bio)); + dbio->type = rw_cmd; + dbio->block_number = recid + 1; + dbio->buffer = dst; + dbio++; + dst += blksize; + recid++; + } } cqr->retries = DIAG_MAX_RETRIES; cqr->buildclk = get_clock(); diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 36ba458..44adf84 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1206,14 +1206,13 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) count = 0; cidaw = 0; rq_for_each_segment(bv, req, iter) { - if (bv->bv_len & (blksize - 1)) - /* Eckd can only do full blocks. */ - return ERR_PTR(-EINVAL); - count += bv->bv_len >> (device->s2b_shift + 9); + if (bv->bv_len & (blksize - 1)) + /* Eckd can only do full blocks. */ + return ERR_PTR(-EINVAL); + count += bv->bv_len >> (device->s2b_shift + 9); #if defined(CONFIG_64BIT) - if (idal_is_needed (page_address(bv->bv_page), - bv->bv_len)) - cidaw += bv->bv_len >> (device->s2b_shift + 9); + if (idal_is_needed (page_address(bv->bv_page), bv->bv_len)) + cidaw += bv->bv_len >> (device->s2b_shift + 9); #endif } /* Paranoia. */ diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index 119b8d2..1d95822 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -257,14 +257,13 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req) count = 0; cidaw = 0; rq_for_each_segment(bv, req, iter) { - if (bv->bv_len & (blksize - 1)) - /* Fba can only do full blocks. */ - return ERR_PTR(-EINVAL); - count += bv->bv_len >> (device->s2b_shift + 9); + if (bv->bv_len & (blksize - 1)) + /* Fba can only do full blocks. */ + return ERR_PTR(-EINVAL); + count += bv->bv_len >> (device->s2b_shift + 9); #if defined(CONFIG_64BIT) - if (idal_is_needed (page_address(bv->bv_page), - bv->bv_len)) - cidaw += bv->bv_len / blksize; + if (idal_is_needed (page_address(bv->bv_page), bv->bv_len)) + cidaw += bv->bv_len / blksize; #endif } /* Paranoia. */ diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index ea3e6a3..5b47e9c 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c @@ -1173,16 +1173,15 @@ tape_34xx_bread(struct tape_device *device, struct request *req) ccw = tape_ccw_cc(ccw, NOP, 0, NULL); rq_for_each_segment(bv, req, iter) { - dst = kmap(bv->bv_page) + bv->bv_offset; - for (off = 0; off < bv->bv_len; - off += TAPEBLOCK_HSEC_SIZE) { - ccw->flags = CCW_FLAG_CC; - ccw->cmd_code = READ_FORWARD; - ccw->count = TAPEBLOCK_HSEC_SIZE; - set_normalized_cda(ccw, (void*) __pa(dst)); - ccw++; - dst += TAPEBLOCK_HSEC_SIZE; - } + dst = kmap(bv->bv_page) + bv->bv_offset; + for (off = 0; off < bv->bv_len; off += TAPEBLOCK_HSEC_SIZE) { + ccw->flags = CCW_FLAG_CC; + ccw->cmd_code = READ_FORWARD; + ccw->count = TAPEBLOCK_HSEC_SIZE; + set_normalized_cda(ccw, (void*) __pa(dst)); + ccw++; + dst += TAPEBLOCK_HSEC_SIZE; + } } ccw = tape_ccw_end(ccw, NOP, 0, NULL); diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index b16ad7a..9f244c5 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c @@ -652,18 +652,17 @@ tape_3590_bread(struct tape_device *device, struct request *req) ccw = tape_ccw_cc(ccw, NOP, 0, NULL); rq_for_each_segment(bv, req, iter) { - dst = page_address(bv->bv_page) + bv->bv_offset; - for (off = 0; off < bv->bv_len; - off += TAPEBLOCK_HSEC_SIZE) { - ccw->flags = CCW_FLAG_CC; - ccw->cmd_code = READ_FORWARD; - ccw->count = TAPEBLOCK_HSEC_SIZE; - set_normalized_cda(ccw, (void *) __pa(dst)); - ccw++; - dst += TAPEBLOCK_HSEC_SIZE; - } - if (off > bv->bv_len) - BUG(); + dst = page_address(bv->bv_page) + bv->bv_offset; + for (off = 0; off < bv->bv_len; off += TAPEBLOCK_HSEC_SIZE) { + ccw->flags = CCW_FLAG_CC; + ccw->cmd_code = READ_FORWARD; + ccw->count = TAPEBLOCK_HSEC_SIZE; + set_normalized_cda(ccw, (void *) __pa(dst)); + ccw++; + dst += TAPEBLOCK_HSEC_SIZE; + } + if (off > bv->bv_len) + BUG(); } ccw = tape_ccw_end(ccw, NOP, 0, NULL); DBF_EVENT(6, "xBREDccwg\n"); -- cgit v0.10.2 From db47d475371bc85dd122112e957669cbbcc70dee Mon Sep 17 00:00:00 2001 From: Satyam Sharma Date: Thu, 23 Aug 2007 09:29:40 +0200 Subject: ll_rw_blk: blk_cpu_notifier should be __cpuinitdata blk_cpu_notifier is marked as __devinitdata, but __devinitdata need not be __init even if HOTPLUG_CPU=n, which wastes space. It should be marked __cpuinitdata, and the callback itself as __cpuinit. Signed-off-by: Satyam Sharma Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index c6b2a47..3b2eff4 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -3555,7 +3555,7 @@ static void blk_done_softirq(struct softirq_action *h) } } -static int blk_cpu_notify(struct notifier_block *self, unsigned long action, +static int __cpuinit blk_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { /* @@ -3576,7 +3576,7 @@ static int blk_cpu_notify(struct notifier_block *self, unsigned long action, } -static struct notifier_block __devinitdata blk_cpu_notifier = { +static struct notifier_block blk_cpu_notifier __cpuinitdata = { .notifier_call = blk_cpu_notify, }; -- cgit v0.10.2 From 3317fedba9446465082bcc6ce1232451ad1d51ce Mon Sep 17 00:00:00 2001 From: Dhaval Giani Date: Thu, 23 Aug 2007 10:43:07 +0200 Subject: Corrections in Documentation/block/ioprio.txt The newer glibc does not allow system calls to be made via _syscallN() wrapper. They have to be made through syscall(). The ionice code used the older interface. Correcting it to use syscall. Signed-off-by: Dhaval Giani Signed-off-by: Jens Axboe diff --git a/Documentation/block/ioprio.txt b/Documentation/block/ioprio.txt index 1b930ef..35e516b 100644 --- a/Documentation/block/ioprio.txt +++ b/Documentation/block/ioprio.txt @@ -86,8 +86,15 @@ extern int sys_ioprio_get(int, int); #error "Unsupported arch" #endif -_syscall3(int, ioprio_set, int, which, int, who, int, ioprio); -_syscall2(int, ioprio_get, int, which, int, who); +static inline int ioprio_set(int which, int who, int ioprio) +{ + return syscall(__NR_ioprio_set, which, who, ioprio); +} + +static inline int ioprio_get(int which, int who) +{ + return syscall(__NR_ioprio_get, which, who); +} enum { IOPRIO_CLASS_NONE, -- cgit v0.10.2 From f5ff8422bbdd59f8c1f699df248e1b7a11073027 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 21 Sep 2007 09:19:54 +0200 Subject: Fix warnings with !CONFIG_BLOCK Hide everything in blkdev.h with CONFIG_BLOCK isn't set, and fixup the (few) files that fail to build because they were relying on blkdev.h pulling in extra includes for them. Signed-off-by: Jens Axboe diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index a4b142a..8d23b0b 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 492ac94..a0a9981 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1,6 +1,8 @@ #ifndef _LINUX_BLKDEV_H #define _LINUX_BLKDEV_H +#ifdef CONFIG_BLOCK + #include #include #include @@ -32,8 +34,6 @@ ) #endif -#ifdef CONFIG_BLOCK - struct scsi_ioctl_command; struct request_queue; diff --git a/include/linux/writeback.h b/include/linux/writeback.h index b4af6bc..c7c3337 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -5,6 +5,7 @@ #define WRITEBACK_H #include +#include struct backing_dev_info; diff --git a/kernel/sched.c b/kernel/sched.c index 6107a0c..6c10fa7 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -61,6 +61,7 @@ #include #include #include +#include #include diff --git a/mm/readahead.c b/mm/readahead.c index 39bf45d..be20c9d 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -15,6 +15,7 @@ #include #include #include +#include void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) { -- cgit v0.10.2 From d24517d793f21edab1a411da95f2c45cb88a84aa Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 27 Sep 2007 12:46:11 +0200 Subject: Remove flush_dry_bio_endio The entire function of flush_dry_bio_endio is to undo the effects of bio_endio (when called on a barrier request). So remove the function and the call to bio_endio. This allows us to remove "bi_size" from "struct request_queue". Signed-off-by: Neil Brown ### Diffstat output ./block/ll_rw_blk.c | 39 ++------------------------------------- ./include/linux/blkdev.h | 1 - 2 files changed, 2 insertions(+), 38 deletions(-) diff .prev/block/ll_rw_blk.c ./block/ll_rw_blk.c Signed-off-by: Jens Axboe diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 3b2eff4..dfe0948 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -431,7 +431,6 @@ static void queue_flush(struct request_queue *q, unsigned which) static inline struct request *start_ordered(struct request_queue *q, struct request *rq) { - q->bi_size = 0; q->orderr = 0; q->ordered = q->next_ordered; q->ordseq |= QUEUE_ORDSEQ_STARTED; @@ -528,55 +527,21 @@ int blk_do_ordered(struct request_queue *q, struct request **rqp) return 1; } -static int flush_dry_bio_endio(struct bio *bio, unsigned int bytes, int error) -{ - struct request_queue *q = bio->bi_private; - - /* - * This is dry run, restore bio_sector and size. We'll finish - * this request again with the original bi_end_io after an - * error occurs or post flush is complete. - */ - q->bi_size += bytes; - - if (bio->bi_size) - return 1; - - /* Reset bio */ - set_bit(BIO_UPTODATE, &bio->bi_flags); - bio->bi_size = q->bi_size; - bio->bi_sector -= (q->bi_size >> 9); - q->bi_size = 0; - - return 0; -} - static int ordered_bio_endio(struct request *rq, struct bio *bio, unsigned int nbytes, int error) { struct request_queue *q = rq->q; - bio_end_io_t *endio; - void *private; if (&q->bar_rq != rq) return 0; /* - * Okay, this is the barrier request in progress, dry finish it. + * Okay, this is the barrier request in progress, just + * record the error; */ if (error && !q->orderr) q->orderr = error; - endio = bio->bi_end_io; - private = bio->bi_private; - bio->bi_end_io = flush_dry_bio_endio; - bio->bi_private = q; - - bio_endio(bio, nbytes, error); - - bio->bi_end_io = endio; - bio->bi_private = private; - return 1; } diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index a0a9981..95be0ac 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -471,7 +471,6 @@ struct request_queue int orderr, ordcolor; struct request pre_flush_rq, bar_rq, post_flush_rq; struct request *orig_bar_rq; - unsigned int bi_size; struct mutex sysfs_lock; -- cgit v0.10.2 From 9cc54d40b8ca01fcefc9151044b6996565061d90 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 27 Sep 2007 12:46:12 +0200 Subject: Only call bi_end_io once for any bio Currently bi_end_io can be called multiple times as sub-requests complete. However no ->bi_end_io function wants to know about that. So only call when the bio is complete. Signed-off-by: Neil Brown ### Diffstat output ./fs/bio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff .prev/fs/bio.c ./fs/bio.c Signed-off-by: Jens Axboe diff --git a/fs/bio.c b/fs/bio.c index 29a44c1..5720b94 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1018,6 +1018,8 @@ void bio_endio(struct bio *bio, unsigned int bytes_done, int error) { if (error) clear_bit(BIO_UPTODATE, &bio->bi_flags); + else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) + error = -EIO; if (unlikely(bytes_done > bio->bi_size)) { printk("%s: want %u bytes done, only %u left\n", __FUNCTION__, @@ -1028,7 +1030,7 @@ void bio_endio(struct bio *bio, unsigned int bytes_done, int error) bio->bi_size -= bytes_done; bio->bi_sector += (bytes_done >> 9); - if (bio->bi_end_io) + if (bio->bi_size && bio->bi_end_io) bio->bi_end_io(bio, bytes_done, error); } -- cgit v0.10.2 From 5bb23a688b2de23d7765a1dd439d89c038378978 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 27 Sep 2007 12:46:13 +0200 Subject: Don't decrement bi_size in bio_endio The only caller of bio_endio that does not pass the full bi_size is end_that_request_first. Also, no ->bi_end_io method is really interested in bi_size being decremented. So move the decrement and related code into ll_rw_blk and merge it with order_bio_endio to form req_bio_endio which does endio functionality specific to request completion. As some ->bi_end_io methods do check bi_size of 0, we set it thus for now, but that will go in the next patch. Signed-off-by: Neil Brown ### Diffstat output ./block/ll_rw_blk.c | 42 +++++++++++++++++++++++++++--------------- ./fs/bio.c | 23 +++++++++++------------ 2 files changed, 38 insertions(+), 27 deletions(-) diff .prev/block/ll_rw_blk.c ./block/ll_rw_blk.c Signed-off-by: Jens Axboe diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index dfe0948..b55ed0d 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -527,22 +527,36 @@ int blk_do_ordered(struct request_queue *q, struct request **rqp) return 1; } -static int ordered_bio_endio(struct request *rq, struct bio *bio, - unsigned int nbytes, int error) +static void req_bio_endio(struct request *rq, struct bio *bio, + unsigned int nbytes, int error) { struct request_queue *q = rq->q; - if (&q->bar_rq != rq) - return 0; + if (&q->bar_rq != rq) { + if (error) + clear_bit(BIO_UPTODATE, &bio->bi_flags); + else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) + error = -EIO; - /* - * Okay, this is the barrier request in progress, just - * record the error; - */ - if (error && !q->orderr) - q->orderr = error; + if (unlikely(nbytes > bio->bi_size)) { + printk("%s: want %u bytes done, only %u left\n", + __FUNCTION__, nbytes, bio->bi_size); + nbytes = bio->bi_size; + } - return 1; + bio->bi_size -= nbytes; + bio->bi_sector += (nbytes >> 9); + if (bio->bi_size == 0) + bio_endio(bio, bio->bi_size, error); + } else { + + /* + * Okay, this is the barrier request in progress, just + * record the error; + */ + if (error && !q->orderr) + q->orderr = error; + } } /** @@ -3388,8 +3402,7 @@ static int __end_that_request_first(struct request *req, int uptodate, if (nr_bytes >= bio->bi_size) { req->bio = bio->bi_next; nbytes = bio->bi_size; - if (!ordered_bio_endio(req, bio, nbytes, error)) - bio_endio(bio, nbytes, error); + req_bio_endio(req, bio, nbytes, error); next_idx = 0; bio_nbytes = 0; } else { @@ -3444,8 +3457,7 @@ static int __end_that_request_first(struct request *req, int uptodate, * if the request wasn't completed, update state */ if (bio_nbytes) { - if (!ordered_bio_endio(req, bio, bio_nbytes, error)) - bio_endio(bio, bio_nbytes, error); + req_bio_endio(req, bio, bio_nbytes, error); bio->bi_idx += next_idx; bio_iovec(bio)->bv_offset += nr_bytes; bio_iovec(bio)->bv_len -= nr_bytes; diff --git a/fs/bio.c b/fs/bio.c index 5720b94..3adecd6 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1006,13 +1006,14 @@ void bio_check_pages_dirty(struct bio *bio) * @error: error, if any * * Description: - * bio_endio() will end I/O on @bytes_done number of bytes. This may be - * just a partial part of the bio, or it may be the whole bio. bio_endio() - * is the preferred way to end I/O on a bio, it takes care of decrementing - * bi_size and clearing BIO_UPTODATE on error. @error is 0 on success, and - * and one of the established -Exxxx (-EIO, for instance) error values in - * case something went wrong. Noone should call bi_end_io() directly on - * a bio unless they own it and thus know that it has an end_io function. + * bio_endio() will end I/O on @bytes_done number of bytes. This + * must always be the whole (remaining) bio. bio_endio() is the + * preferred way to end I/O on a bio, it takes care of clearing + * BIO_UPTODATE on error. @error is 0 on success, and and one of the + * established -Exxxx (-EIO, for instance) error values in case + * something went wrong. Noone should call bi_end_io() directly on a + * bio unless they own it and thus know that it has an end_io + * function. **/ void bio_endio(struct bio *bio, unsigned int bytes_done, int error) { @@ -1021,16 +1022,14 @@ void bio_endio(struct bio *bio, unsigned int bytes_done, int error) else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) error = -EIO; - if (unlikely(bytes_done > bio->bi_size)) { + if (unlikely(bytes_done != bio->bi_size)) { printk("%s: want %u bytes done, only %u left\n", __FUNCTION__, bytes_done, bio->bi_size); bytes_done = bio->bi_size; } - bio->bi_size -= bytes_done; - bio->bi_sector += (bytes_done >> 9); - - if (bio->bi_size && bio->bi_end_io) + bio->bi_size = 0; /* expected by some callees - will be removed */ + if (bio->bi_end_io) bio->bi_end_io(bio, bytes_done, error); } -- cgit v0.10.2 From 6712ecf8f648118c3363c142196418f89a510b90 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 27 Sep 2007 12:47:43 +0200 Subject: Drop 'size' argument from bio_endio and bi_end_io As bi_end_io is only called once when the reqeust is complete, the 'size' argument is now redundant. Remove it. Now there is no need for bio_endio to subtract the size completed from bi_size. So don't do that either. While we are at it, change bi_end_io to return void. Signed-off-by: Neil Brown Signed-off-by: Jens Axboe diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index b55ed0d..cd9d2c5 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -547,7 +547,7 @@ static void req_bio_endio(struct request *rq, struct bio *bio, bio->bi_size -= nbytes; bio->bi_sector += (nbytes >> 9); if (bio->bi_size == 0) - bio_endio(bio, bio->bi_size, error); + bio_endio(bio, error); } else { /* @@ -2401,7 +2401,7 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, return bio->bi_size; /* if it was boucned we must call the end io function */ - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); __blk_rq_unmap_user(orig_bio); bio_put(bio); return ret; @@ -2510,7 +2510,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, return PTR_ERR(bio); if (bio->bi_size != len) { - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); bio_unmap_user(bio); return -EINVAL; } @@ -3040,7 +3040,7 @@ out: return 0; end_io: - bio_endio(bio, nr_sectors << 9, err); + bio_endio(bio, err); return 0; } @@ -3187,7 +3187,7 @@ static inline void __generic_make_request(struct bio *bio) bdevname(bio->bi_bdev, b), (long long) bio->bi_sector); end_io: - bio_endio(bio, bio->bi_size, -EIO); + bio_endio(bio, -EIO); break; } diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 007faaf..b1d00ef 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -138,7 +138,7 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio) buf = mempool_alloc(d->bufpool, GFP_NOIO); if (buf == NULL) { printk(KERN_INFO "aoe: buf allocation failure\n"); - bio_endio(bio, bio->bi_size, -ENOMEM); + bio_endio(bio, -ENOMEM); return 0; } memset(buf, 0, sizeof(*buf)); @@ -159,7 +159,7 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio) d->aoemajor, d->aoeminor); spin_unlock_irqrestore(&d->lock, flags); mempool_free(buf, d->bufpool); - bio_endio(bio, bio->bi_size, -ENXIO); + bio_endio(bio, -ENXIO); return 0; } diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 01fbdd3..5abae34 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -652,7 +652,7 @@ aoecmd_ata_rsp(struct sk_buff *skb) disk_stat_add(disk, sectors[rw], n_sect); disk_stat_add(disk, io_ticks, duration); n = (buf->flags & BUFFL_FAIL) ? -EIO : 0; - bio_endio(buf->bio, buf->bio->bi_size, n); + bio_endio(buf->bio, n); mempool_free(buf, d->bufpool); } } diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 05a9719..51f5071 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -119,7 +119,7 @@ aoedev_downdev(struct aoedev *d) bio = buf->bio; if (--buf->nframesout == 0) { mempool_free(buf, d->bufpool); - bio_endio(bio, bio->bi_size, -EIO); + bio_endio(bio, -EIO); } skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0; } @@ -130,7 +130,7 @@ aoedev_downdev(struct aoedev *d) list_del(d->bufq.next); bio = buf->bio; mempool_free(buf, d->bufpool); - bio_endio(bio, bio->bi_size, -EIO); + bio_endio(bio, -EIO); } if (d->gd) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 084358a..28d1457 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -1194,7 +1194,7 @@ static inline void complete_buffers(struct bio *bio, int status) int nr_sectors = bio_sectors(bio); bio->bi_next = NULL; - bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO); + bio_endio(bio, status ? 0 : -EIO); bio = xbh; } } diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index eb9799a..3853c9a 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -987,7 +987,7 @@ static inline void complete_buffers(struct bio *bio, int ok) xbh = bio->bi_next; bio->bi_next = NULL; - bio_endio(bio, nr_sectors << 9, ok ? 0 : -EIO); + bio_endio(bio, ok ? 0 : -EIO); bio = xbh; } diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index f0a86e2..80483aa 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3810,14 +3810,10 @@ static int check_floppy_change(struct gendisk *disk) * a disk in the drive, and whether that disk is writable. */ -static int floppy_rb0_complete(struct bio *bio, unsigned int bytes_done, +static void floppy_rb0_complete(struct bio *bio, int err) { - if (bio->bi_size) - return 1; - complete((struct completion *)bio->bi_private); - return 0; } static int __floppy_read_block_0(struct block_device *bdev) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 9f015fc..b9233a0 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -551,7 +551,7 @@ static int loop_make_request(struct request_queue *q, struct bio *old_bio) out: spin_unlock_irq(&lo->lo_lock); - bio_io_error(old_bio, old_bio->bi_size); + bio_io_error(old_bio); return 0; } @@ -580,7 +580,7 @@ static inline void loop_handle_bio(struct loop_device *lo, struct bio *bio) bio_put(bio); } else { int ret = do_bio_filebacked(lo, bio); - bio_endio(bio, bio->bi_size, ret); + bio_endio(bio, ret); } } diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index fadbfd8..540bf36 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -1058,15 +1058,12 @@ static void pkt_make_local_copy(struct packet_data *pkt, struct bio_vec *bvec) } } -static int pkt_end_io_read(struct bio *bio, unsigned int bytes_done, int err) +static void pkt_end_io_read(struct bio *bio, int err) { struct packet_data *pkt = bio->bi_private; struct pktcdvd_device *pd = pkt->pd; BUG_ON(!pd); - if (bio->bi_size) - return 1; - VPRINTK("pkt_end_io_read: bio=%p sec0=%llx sec=%llx err=%d\n", bio, (unsigned long long)pkt->sector, (unsigned long long)bio->bi_sector, err); @@ -1077,19 +1074,14 @@ static int pkt_end_io_read(struct bio *bio, unsigned int bytes_done, int err) wake_up(&pd->wqueue); } pkt_bio_finished(pd); - - return 0; } -static int pkt_end_io_packet_write(struct bio *bio, unsigned int bytes_done, int err) +static void pkt_end_io_packet_write(struct bio *bio, int err) { struct packet_data *pkt = bio->bi_private; struct pktcdvd_device *pd = pkt->pd; BUG_ON(!pd); - if (bio->bi_size) - return 1; - VPRINTK("pkt_end_io_packet_write: id=%d, err=%d\n", pkt->id, err); pd->stats.pkt_ended++; @@ -1098,7 +1090,6 @@ static int pkt_end_io_packet_write(struct bio *bio, unsigned int bytes_done, int atomic_dec(&pkt->io_wait); atomic_inc(&pkt->run_sm); wake_up(&pd->wqueue); - return 0; } /* @@ -1470,7 +1461,7 @@ static void pkt_finish_packet(struct packet_data *pkt, int uptodate) while (bio) { next = bio->bi_next; bio->bi_next = NULL; - bio_endio(bio, bio->bi_size, uptodate ? 0 : -EIO); + bio_endio(bio, uptodate ? 0 : -EIO); bio = next; } pkt->orig_bios = pkt->orig_bios_tail = NULL; @@ -2462,19 +2453,15 @@ static int pkt_close(struct inode *inode, struct file *file) } -static int pkt_end_io_read_cloned(struct bio *bio, unsigned int bytes_done, int err) +static void pkt_end_io_read_cloned(struct bio *bio, int err) { struct packet_stacked_data *psd = bio->bi_private; struct pktcdvd_device *pd = psd->pd; - if (bio->bi_size) - return 1; - bio_put(bio); - bio_endio(psd->bio, psd->bio->bi_size, err); + bio_endio(psd->bio, err); mempool_free(psd, psd_pool); pkt_bio_finished(pd); - return 0; } static int pkt_make_request(struct request_queue *q, struct bio *bio) @@ -2620,7 +2607,7 @@ static int pkt_make_request(struct request_queue *q, struct bio *bio) } return 0; end_io: - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 65150b5..701ea77 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -287,10 +287,10 @@ static int rd_make_request(struct request_queue *q, struct bio *bio) if (ret) goto fail; - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); return 0; fail: - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } diff --git a/drivers/block/umem.c b/drivers/block/umem.c index c378e28..be7fac8 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -545,7 +545,7 @@ static void process_page(unsigned long data) return_bio = bio->bi_next; bio->bi_next = NULL; - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); } } diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index bdc52d6..8216a6f 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -489,7 +489,7 @@ static void dec_pending(struct dm_crypt_io *io, int error) if (!atomic_dec_and_test(&io->pending)) return; - bio_endio(io->base_bio, io->base_bio->bi_size, io->error); + bio_endio(io->base_bio, io->error); mempool_free(io, cc->io_pool); } @@ -509,25 +509,19 @@ static void kcryptd_queue_io(struct dm_crypt_io *io) queue_work(_kcryptd_workqueue, &io->work); } -static int crypt_endio(struct bio *clone, unsigned int done, int error) +static void crypt_endio(struct bio *clone, int error) { struct dm_crypt_io *io = clone->bi_private; struct crypt_config *cc = io->target->private; unsigned read_io = bio_data_dir(clone) == READ; /* - * free the processed pages, even if - * it's only a partially completed write + * free the processed pages */ - if (!read_io) - crypt_free_buffer_pages(cc, clone, done); - - /* keep going - not finished yet */ - if (unlikely(clone->bi_size)) - return 1; - - if (!read_io) + if (!read_io) { + crypt_free_buffer_pages(cc, clone, clone->bi_size); goto out; + } if (unlikely(!bio_flagged(clone, BIO_UPTODATE))) { error = -EIO; @@ -537,12 +531,11 @@ static int crypt_endio(struct bio *clone, unsigned int done, int error) bio_put(clone); io->post_process = 1; kcryptd_queue_io(io); - return 0; + return; out: bio_put(clone); dec_pending(io, error); - return error; } static void clone_init(struct dm_crypt_io *io, struct bio *clone) diff --git a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c index 71cc858..a2191a4 100644 --- a/drivers/md/dm-emc.c +++ b/drivers/md/dm-emc.c @@ -38,13 +38,10 @@ static inline void free_bio(struct bio *bio) bio_put(bio); } -static int emc_endio(struct bio *bio, unsigned int bytes_done, int error) +static void emc_endio(struct bio *bio, int error) { struct dm_path *path = bio->bi_private; - if (bio->bi_size) - return 1; - /* We also need to look at the sense keys here whether or not to * switch to the next PG etc. * diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index f3a7724..b8e342f 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -124,15 +124,11 @@ static void dec_count(struct io *io, unsigned int region, int error) } } -static int endio(struct bio *bio, unsigned int done, int error) +static void endio(struct bio *bio, int error) { struct io *io; unsigned region; - /* keep going until we've finished */ - if (bio->bi_size) - return 1; - if (error && bio_data_dir(bio) == READ) zero_fill_bio(bio); @@ -146,8 +142,6 @@ static int endio(struct bio *bio, unsigned int done, int error) bio_put(bio); dec_count(io, region, error); - - return 0; } /*----------------------------------------------------------------- diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index d6ca9d0..31056ab 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -390,11 +390,11 @@ static void dispatch_queued_ios(struct multipath *m) r = map_io(m, bio, mpio, 1); if (r < 0) - bio_endio(bio, bio->bi_size, r); + bio_endio(bio, r); else if (r == DM_MAPIO_REMAPPED) generic_make_request(bio); else if (r == DM_MAPIO_REQUEUE) - bio_endio(bio, bio->bi_size, -EIO); + bio_endio(bio, -EIO); bio = next; } diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 144071e..d09ff15 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -820,7 +820,7 @@ static void write_callback(unsigned long error, void *context) break; } } - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); } static void do_write(struct mirror_set *ms, struct bio *bio) @@ -900,7 +900,7 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes) */ if (unlikely(ms->log_failure)) while ((bio = bio_list_pop(&sync))) - bio_endio(bio, bio->bi_size, -EIO); + bio_endio(bio, -EIO); else while ((bio = bio_list_pop(&sync))) do_write(ms, bio); diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 83ddbfe..98a633f 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -636,7 +636,7 @@ static void error_bios(struct bio *bio) while (bio) { n = bio->bi_next; bio->bi_next = NULL; - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); bio = n; } } diff --git a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c index f314d7d..bdec206 100644 --- a/drivers/md/dm-zero.c +++ b/drivers/md/dm-zero.c @@ -43,7 +43,7 @@ static int zero_map(struct dm_target *ti, struct bio *bio, break; } - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); /* accepted bio, don't make new request */ return DM_MAPIO_SUBMITTED; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 2120155..167765c 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -484,23 +484,20 @@ static void dec_pending(struct dm_io *io, int error) blk_add_trace_bio(io->md->queue, io->bio, BLK_TA_COMPLETE); - bio_endio(io->bio, io->bio->bi_size, io->error); + bio_endio(io->bio, io->error); } free_io(io->md, io); } } -static int clone_endio(struct bio *bio, unsigned int done, int error) +static void clone_endio(struct bio *bio, int error) { int r = 0; struct dm_target_io *tio = bio->bi_private; struct mapped_device *md = tio->io->md; dm_endio_fn endio = tio->ti->type->end_io; - if (bio->bi_size) - return 1; - if (!bio_flagged(bio, BIO_UPTODATE) && !error) error = -EIO; @@ -514,7 +511,7 @@ static int clone_endio(struct bio *bio, unsigned int done, int error) error = r; else if (r == DM_ENDIO_INCOMPLETE) /* The target will handle the io */ - return 1; + return; else if (r) { DMWARN("unimplemented target endio return value: %d", r); BUG(); @@ -530,7 +527,6 @@ static int clone_endio(struct bio *bio, unsigned int done, int error) bio_put(bio); free_tio(md, tio); - return r; } static sector_t max_io_len(struct mapped_device *md, @@ -761,7 +757,7 @@ static void __split_bio(struct mapped_device *md, struct bio *bio) ci.map = dm_get_table(md); if (!ci.map) { - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return; } @@ -803,7 +799,7 @@ static int dm_request(struct request_queue *q, struct bio *bio) * guarantee it is (or can be) handled by the targets correctly. */ if (unlikely(bio_barrier(bio))) { - bio_endio(bio, bio->bi_size, -EOPNOTSUPP); + bio_endio(bio, -EOPNOTSUPP); return 0; } @@ -820,13 +816,13 @@ static int dm_request(struct request_queue *q, struct bio *bio) up_read(&md->io_lock); if (bio_rw(bio) == READA) { - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } r = queue_io(md, bio); if (r < 0) { - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } else if (r == 0) diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c index cb059cf..cf2ddce 100644 --- a/drivers/md/faulty.c +++ b/drivers/md/faulty.c @@ -65,18 +65,16 @@ #include -static int faulty_fail(struct bio *bio, unsigned int bytes_done, int error) +static void faulty_fail(struct bio *bio, int error) { struct bio *b = bio->bi_private; b->bi_size = bio->bi_size; b->bi_sector = bio->bi_sector; - if (bio->bi_size == 0) - bio_put(bio); + bio_put(bio); - clear_bit(BIO_UPTODATE, &b->bi_flags); - return (b->bi_end_io)(b, bytes_done, -EIO); + bio_io_error(b); } typedef struct faulty_conf { @@ -179,7 +177,7 @@ static int make_request(struct request_queue *q, struct bio *bio) /* special case - don't decrement, don't generic_make_request, * just fail immediately */ - bio_endio(bio, bio->bi_size, -EIO); + bio_endio(bio, -EIO); return 0; } diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 17f795c..5501487 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -338,7 +338,7 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) sector_t block; if (unlikely(bio_barrier(bio))) { - bio_endio(bio, bio->bi_size, -EOPNOTSUPP); + bio_endio(bio, -EOPNOTSUPP); return 0; } @@ -358,7 +358,7 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) bdevname(tmp_dev->rdev->bdev, b), (unsigned long long)tmp_dev->size, (unsigned long long)tmp_dev->offset); - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } if (unlikely(bio->bi_sector + (bio->bi_size >> 9) > diff --git a/drivers/md/md.c b/drivers/md/md.c index f883b7e..e8f102e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -213,7 +213,7 @@ static DEFINE_SPINLOCK(all_mddevs_lock); static int md_fail_request (struct request_queue *q, struct bio *bio) { - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } @@ -384,12 +384,10 @@ static void free_disk_sb(mdk_rdev_t * rdev) } -static int super_written(struct bio *bio, unsigned int bytes_done, int error) +static void super_written(struct bio *bio, int error) { mdk_rdev_t *rdev = bio->bi_private; mddev_t *mddev = rdev->mddev; - if (bio->bi_size) - return 1; if (error || !test_bit(BIO_UPTODATE, &bio->bi_flags)) { printk("md: super_written gets error=%d, uptodate=%d\n", @@ -401,16 +399,13 @@ static int super_written(struct bio *bio, unsigned int bytes_done, int error) if (atomic_dec_and_test(&mddev->pending_writes)) wake_up(&mddev->sb_wait); bio_put(bio); - return 0; } -static int super_written_barrier(struct bio *bio, unsigned int bytes_done, int error) +static void super_written_barrier(struct bio *bio, int error) { struct bio *bio2 = bio->bi_private; mdk_rdev_t *rdev = bio2->bi_private; mddev_t *mddev = rdev->mddev; - if (bio->bi_size) - return 1; if (!test_bit(BIO_UPTODATE, &bio->bi_flags) && error == -EOPNOTSUPP) { @@ -424,11 +419,11 @@ static int super_written_barrier(struct bio *bio, unsigned int bytes_done, int e spin_unlock_irqrestore(&mddev->write_lock, flags); wake_up(&mddev->sb_wait); bio_put(bio); - return 0; + } else { + bio_put(bio2); + bio->bi_private = rdev; + super_written(bio, error); } - bio_put(bio2); - bio->bi_private = rdev; - return super_written(bio, bytes_done, error); } void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, @@ -489,13 +484,9 @@ void md_super_wait(mddev_t *mddev) finish_wait(&mddev->sb_wait, &wq); } -static int bi_complete(struct bio *bio, unsigned int bytes_done, int error) +static void bi_complete(struct bio *bio, int error) { - if (bio->bi_size) - return 1; - complete((struct completion*)bio->bi_private); - return 0; } int sync_page_io(struct block_device *bdev, sector_t sector, int size, diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 1e2af43..f2a63f3 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -82,21 +82,17 @@ static void multipath_end_bh_io (struct multipath_bh *mp_bh, int err) struct bio *bio = mp_bh->master_bio; multipath_conf_t *conf = mddev_to_conf(mp_bh->mddev); - bio_endio(bio, bio->bi_size, err); + bio_endio(bio, err); mempool_free(mp_bh, conf->pool); } -static int multipath_end_request(struct bio *bio, unsigned int bytes_done, - int error) +static void multipath_end_request(struct bio *bio, int error) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); struct multipath_bh * mp_bh = (struct multipath_bh *)(bio->bi_private); multipath_conf_t *conf = mddev_to_conf(mp_bh->mddev); mdk_rdev_t *rdev = conf->multipaths[mp_bh->path].rdev; - if (bio->bi_size) - return 1; - if (uptodate) multipath_end_bh_io(mp_bh, 0); else if (!bio_rw_ahead(bio)) { @@ -112,7 +108,6 @@ static int multipath_end_request(struct bio *bio, unsigned int bytes_done, } else multipath_end_bh_io(mp_bh, error); rdev_dec_pending(rdev, conf->mddev); - return 0; } static void unplug_slaves(mddev_t *mddev) @@ -155,7 +150,7 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio) const int rw = bio_data_dir(bio); if (unlikely(bio_barrier(bio))) { - bio_endio(bio, bio->bi_size, -EOPNOTSUPP); + bio_endio(bio, -EOPNOTSUPP); return 0; } @@ -169,7 +164,7 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio) mp_bh->path = multipath_map(conf); if (mp_bh->path < 0) { - bio_endio(bio, bio->bi_size, -EIO); + bio_endio(bio, -EIO); mempool_free(mp_bh, conf->pool); return 0; } diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index b8216bc..ef0da2d 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -420,7 +420,7 @@ static int raid0_make_request (struct request_queue *q, struct bio *bio) const int rw = bio_data_dir(bio); if (unlikely(bio_barrier(bio))) { - bio_endio(bio, bio->bi_size, -EOPNOTSUPP); + bio_endio(bio, -EOPNOTSUPP); return 0; } @@ -490,7 +490,7 @@ bad_map: " or bigger than %dk %llu %d\n", chunk_size, (unsigned long long)bio->bi_sector, bio->bi_size >> 10); - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index f33a729..6d03bea 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -238,7 +238,7 @@ static void raid_end_bio_io(r1bio_t *r1_bio) (unsigned long long) bio->bi_sector + (bio->bi_size >> 9) - 1); - bio_endio(bio, bio->bi_size, + bio_endio(bio, test_bit(R1BIO_Uptodate, &r1_bio->state) ? 0 : -EIO); } free_r1bio(r1_bio); @@ -255,16 +255,13 @@ static inline void update_head_pos(int disk, r1bio_t *r1_bio) r1_bio->sector + (r1_bio->sectors); } -static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int error) +static void raid1_end_read_request(struct bio *bio, int error) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); int mirror; conf_t *conf = mddev_to_conf(r1_bio->mddev); - if (bio->bi_size) - return 1; - mirror = r1_bio->read_disk; /* * this branch is our 'one mirror IO has finished' event handler: @@ -301,10 +298,9 @@ static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int } rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev); - return 0; } -static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int error) +static void raid1_end_write_request(struct bio *bio, int error) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); @@ -312,8 +308,6 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int conf_t *conf = mddev_to_conf(r1_bio->mddev); struct bio *to_put = NULL; - if (bio->bi_size) - return 1; for (mirror = 0; mirror < conf->raid_disks; mirror++) if (r1_bio->bios[mirror] == bio) @@ -366,7 +360,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int (unsigned long long) mbio->bi_sector, (unsigned long long) mbio->bi_sector + (mbio->bi_size >> 9) - 1); - bio_endio(mbio, mbio->bi_size, 0); + bio_endio(mbio, 0); } } } @@ -400,8 +394,6 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int if (to_put) bio_put(to_put); - - return 0; } @@ -796,7 +788,7 @@ static int make_request(struct request_queue *q, struct bio * bio) if (unlikely(!mddev->barriers_work && bio_barrier(bio))) { if (rw == WRITE) md_write_end(mddev); - bio_endio(bio, bio->bi_size, -EOPNOTSUPP); + bio_endio(bio, -EOPNOTSUPP); return 0; } @@ -1137,14 +1129,11 @@ abort: } -static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) +static void end_sync_read(struct bio *bio, int error) { r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); int i; - if (bio->bi_size) - return 1; - for (i=r1_bio->mddev->raid_disks; i--; ) if (r1_bio->bios[i] == bio) break; @@ -1160,10 +1149,9 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) if (atomic_dec_and_test(&r1_bio->remaining)) reschedule_retry(r1_bio); - return 0; } -static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error) +static void end_sync_write(struct bio *bio, int error) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); @@ -1172,9 +1160,6 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error) int i; int mirror=0; - if (bio->bi_size) - return 1; - for (i = 0; i < conf->raid_disks; i++) if (r1_bio->bios[i] == bio) { mirror = i; @@ -1200,7 +1185,6 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error) md_done_sync(mddev, r1_bio->sectors, uptodate); put_buf(r1_bio); } - return 0; } static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 4e53792..25a96c4 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -227,7 +227,7 @@ static void raid_end_bio_io(r10bio_t *r10_bio) { struct bio *bio = r10_bio->master_bio; - bio_endio(bio, bio->bi_size, + bio_endio(bio, test_bit(R10BIO_Uptodate, &r10_bio->state) ? 0 : -EIO); free_r10bio(r10_bio); } @@ -243,15 +243,13 @@ static inline void update_head_pos(int slot, r10bio_t *r10_bio) r10_bio->devs[slot].addr + (r10_bio->sectors); } -static int raid10_end_read_request(struct bio *bio, unsigned int bytes_done, int error) +static void raid10_end_read_request(struct bio *bio, int error) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private); int slot, dev; conf_t *conf = mddev_to_conf(r10_bio->mddev); - if (bio->bi_size) - return 1; slot = r10_bio->read_slot; dev = r10_bio->devs[slot].devnum; @@ -284,19 +282,15 @@ static int raid10_end_read_request(struct bio *bio, unsigned int bytes_done, int } rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev); - return 0; } -static int raid10_end_write_request(struct bio *bio, unsigned int bytes_done, int error) +static void raid10_end_write_request(struct bio *bio, int error) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private); int slot, dev; conf_t *conf = mddev_to_conf(r10_bio->mddev); - if (bio->bi_size) - return 1; - for (slot = 0; slot < conf->copies; slot++) if (r10_bio->devs[slot].bio == bio) break; @@ -339,7 +333,6 @@ static int raid10_end_write_request(struct bio *bio, unsigned int bytes_done, in } rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev); - return 0; } @@ -787,7 +780,7 @@ static int make_request(struct request_queue *q, struct bio * bio) unsigned long flags; if (unlikely(bio_barrier(bio))) { - bio_endio(bio, bio->bi_size, -EOPNOTSUPP); + bio_endio(bio, -EOPNOTSUPP); return 0; } @@ -819,7 +812,7 @@ static int make_request(struct request_queue *q, struct bio * bio) " or bigger than %dk %llu %d\n", chunk_sects/2, (unsigned long long)bio->bi_sector, bio->bi_size >> 10); - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } @@ -1155,15 +1148,12 @@ abort: } -static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) +static void end_sync_read(struct bio *bio, int error) { r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private); conf_t *conf = mddev_to_conf(r10_bio->mddev); int i,d; - if (bio->bi_size) - return 1; - for (i=0; icopies; i++) if (r10_bio->devs[i].bio == bio) break; @@ -1192,10 +1182,9 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) reschedule_retry(r10_bio); } rdev_dec_pending(conf->mirrors[d].rdev, conf->mddev); - return 0; } -static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error) +static void end_sync_write(struct bio *bio, int error) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private); @@ -1203,9 +1192,6 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error) conf_t *conf = mddev_to_conf(mddev); int i,d; - if (bio->bi_size) - return 1; - for (i = 0; i < conf->copies; i++) if (r10_bio->devs[i].bio == bio) break; @@ -1228,7 +1214,6 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error) } } rdev_dec_pending(conf->mirrors[d].rdev, mddev); - return 0; } /* @@ -1374,7 +1359,7 @@ static void recovery_request_write(mddev_t *mddev, r10bio_t *r10_bio) if (test_bit(R10BIO_Uptodate, &r10_bio->state)) generic_make_request(wbio); else - bio_endio(wbio, wbio->bi_size, -EIO); + bio_endio(wbio, -EIO); } diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index f96dea9..caaca9e 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -108,12 +108,11 @@ static void return_io(struct bio *return_bi) { struct bio *bi = return_bi; while (bi) { - int bytes = bi->bi_size; return_bi = bi->bi_next; bi->bi_next = NULL; bi->bi_size = 0; - bi->bi_end_io(bi, bytes, + bi->bi_end_io(bi, test_bit(BIO_UPTODATE, &bi->bi_flags) ? 0 : -EIO); bi = return_bi; @@ -382,10 +381,10 @@ static unsigned long get_stripe_work(struct stripe_head *sh) return pending; } -static int -raid5_end_read_request(struct bio *bi, unsigned int bytes_done, int error); -static int -raid5_end_write_request (struct bio *bi, unsigned int bytes_done, int error); +static void +raid5_end_read_request(struct bio *bi, int error); +static void +raid5_end_write_request(struct bio *bi, int error); static void ops_run_io(struct stripe_head *sh) { @@ -1110,8 +1109,7 @@ static void shrink_stripes(raid5_conf_t *conf) conf->slab_cache = NULL; } -static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, - int error) +static void raid5_end_read_request(struct bio * bi, int error) { struct stripe_head *sh = bi->bi_private; raid5_conf_t *conf = sh->raid_conf; @@ -1120,8 +1118,6 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, char b[BDEVNAME_SIZE]; mdk_rdev_t *rdev; - if (bi->bi_size) - return 1; for (i=0 ; idev[i].req) @@ -1132,7 +1128,7 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, uptodate); if (i == disks) { BUG(); - return 0; + return; } if (uptodate) { @@ -1185,20 +1181,15 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, clear_bit(R5_LOCKED, &sh->dev[i].flags); set_bit(STRIPE_HANDLE, &sh->state); release_stripe(sh); - return 0; } -static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done, - int error) +static void raid5_end_write_request (struct bio *bi, int error) { struct stripe_head *sh = bi->bi_private; raid5_conf_t *conf = sh->raid_conf; int disks = sh->disks, i; int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); - if (bi->bi_size) - return 1; - for (i=0 ; idev[i].req) break; @@ -1208,7 +1199,7 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done, uptodate); if (i == disks) { BUG(); - return 0; + return; } if (!uptodate) @@ -1219,7 +1210,6 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done, clear_bit(R5_LOCKED, &sh->dev[i].flags); set_bit(STRIPE_HANDLE, &sh->state); release_stripe(sh); - return 0; } @@ -3340,7 +3330,7 @@ static struct bio *remove_bio_from_retry(raid5_conf_t *conf) * first). * If the read failed.. */ -static int raid5_align_endio(struct bio *bi, unsigned int bytes, int error) +static void raid5_align_endio(struct bio *bi, int error) { struct bio* raid_bi = bi->bi_private; mddev_t *mddev; @@ -3348,8 +3338,6 @@ static int raid5_align_endio(struct bio *bi, unsigned int bytes, int error) int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); mdk_rdev_t *rdev; - if (bi->bi_size) - return 1; bio_put(bi); mddev = raid_bi->bi_bdev->bd_disk->queue->queuedata; @@ -3360,17 +3348,16 @@ static int raid5_align_endio(struct bio *bi, unsigned int bytes, int error) rdev_dec_pending(rdev, conf->mddev); if (!error && uptodate) { - bio_endio(raid_bi, bytes, 0); + bio_endio(raid_bi, 0); if (atomic_dec_and_test(&conf->active_aligned_reads)) wake_up(&conf->wait_for_stripe); - return 0; + return; } pr_debug("raid5_align_endio : io error...handing IO for a retry\n"); add_bio_to_retry(raid_bi, conf); - return 0; } static int bio_fits_rdev(struct bio *bi) @@ -3476,7 +3463,7 @@ static int make_request(struct request_queue *q, struct bio * bi) int remaining; if (unlikely(bio_barrier(bi))) { - bio_endio(bi, bi->bi_size, -EOPNOTSUPP); + bio_endio(bi, -EOPNOTSUPP); return 0; } @@ -3592,12 +3579,11 @@ static int make_request(struct request_queue *q, struct bio * bi) remaining = --bi->bi_phys_segments; spin_unlock_irq(&conf->device_lock); if (remaining == 0) { - int bytes = bi->bi_size; if ( rw == WRITE ) md_write_end(mddev); - bi->bi_size = 0; - bi->bi_end_io(bi, bytes, + + bi->bi_end_io(bi, test_bit(BIO_UPTODATE, &bi->bi_flags) ? 0 : -EIO); } @@ -3875,10 +3861,8 @@ static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio) remaining = --raid_bio->bi_phys_segments; spin_unlock_irq(&conf->device_lock); if (remaining == 0) { - int bytes = raid_bio->bi_size; - raid_bio->bi_size = 0; - raid_bio->bi_end_io(raid_bio, bytes, + raid_bio->bi_end_io(raid_bio, test_bit(BIO_UPTODATE, &raid_bio->bi_flags) ? 0 : -EIO); } diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 4d8798b..859f870 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -674,10 +674,10 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio) } bytes_done += bvec->bv_len; } - bio_endio(bio, bytes_done, 0); + bio_endio(bio, 0); return 0; fail: - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index 354a060..0fbacc8 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c @@ -230,12 +230,10 @@ static int xpram_make_request(struct request_queue *q, struct bio *bio) } } set_bit(BIO_UPTODATE, &bio->bi_flags); - bytes = bio->bi_size; - bio->bi_size = 0; - bio->bi_end_io(bio, bytes, 0); + bio_end_io(bio, 0); return 0; fail: - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 59b3985..604f4d7 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -266,13 +266,9 @@ static int scsi_merge_bio(struct request *rq, struct bio *bio) return blk_rq_append_bio(q, rq, bio); } -static int scsi_bi_endio(struct bio *bio, unsigned int bytes_done, int error) +static void scsi_bi_endio(struct bio *bio, int error) { - if (bio->bi_size) - return 1; - bio_put(bio); - return 0; } /** @@ -328,7 +324,7 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl, if (bio->bi_vcnt >= nr_vecs) { err = scsi_merge_bio(rq, bio); if (err) { - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); goto free_bios; } bio = NULL; @@ -350,7 +346,7 @@ free_bios: /* * call endio instead of bio_put incase it was bounced */ - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); } return err; diff --git a/fs/bio.c b/fs/bio.c index 3adecd6..5f604f2 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -798,13 +798,9 @@ void bio_unmap_user(struct bio *bio) bio_put(bio); } -static int bio_map_kern_endio(struct bio *bio, unsigned int bytes_done, int err) +static void bio_map_kern_endio(struct bio *bio, int err) { - if (bio->bi_size) - return 1; - bio_put(bio); - return 0; } @@ -1002,12 +998,10 @@ void bio_check_pages_dirty(struct bio *bio) /** * bio_endio - end I/O on a bio * @bio: bio - * @bytes_done: number of bytes completed * @error: error, if any * * Description: - * bio_endio() will end I/O on @bytes_done number of bytes. This - * must always be the whole (remaining) bio. bio_endio() is the + * bio_endio() will end I/O on the whole bio. bio_endio() is the * preferred way to end I/O on a bio, it takes care of clearing * BIO_UPTODATE on error. @error is 0 on success, and and one of the * established -Exxxx (-EIO, for instance) error values in case @@ -1015,22 +1009,15 @@ void bio_check_pages_dirty(struct bio *bio) * bio unless they own it and thus know that it has an end_io * function. **/ -void bio_endio(struct bio *bio, unsigned int bytes_done, int error) +void bio_endio(struct bio *bio, int error) { if (error) clear_bit(BIO_UPTODATE, &bio->bi_flags); else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) error = -EIO; - if (unlikely(bytes_done != bio->bi_size)) { - printk("%s: want %u bytes done, only %u left\n", __FUNCTION__, - bytes_done, bio->bi_size); - bytes_done = bio->bi_size; - } - - bio->bi_size = 0; /* expected by some callees - will be removed */ if (bio->bi_end_io) - bio->bi_end_io(bio, bytes_done, error); + bio->bi_end_io(bio, error); } void bio_pair_release(struct bio_pair *bp) @@ -1038,37 +1025,29 @@ void bio_pair_release(struct bio_pair *bp) if (atomic_dec_and_test(&bp->cnt)) { struct bio *master = bp->bio1.bi_private; - bio_endio(master, master->bi_size, bp->error); + bio_endio(master, bp->error); mempool_free(bp, bp->bio2.bi_private); } } -static int bio_pair_end_1(struct bio * bi, unsigned int done, int err) +static void bio_pair_end_1(struct bio *bi, int err) { struct bio_pair *bp = container_of(bi, struct bio_pair, bio1); if (err) bp->error = err; - if (bi->bi_size) - return 1; - bio_pair_release(bp); - return 0; } -static int bio_pair_end_2(struct bio * bi, unsigned int done, int err) +static void bio_pair_end_2(struct bio *bi, int err) { struct bio_pair *bp = container_of(bi, struct bio_pair, bio2); if (err) bp->error = err; - if (bi->bi_size) - return 1; - bio_pair_release(bp); - return 0; } /* diff --git a/fs/block_dev.c b/fs/block_dev.c index 2980eab..6339a30 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -172,7 +172,7 @@ blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, } #if 0 -static int blk_end_aio(struct bio *bio, unsigned int bytes_done, int error) +static void blk_end_aio(struct bio *bio, int error) { struct kiocb *iocb = bio->bi_private; atomic_t *bio_count = &iocb->ki_bio_count; diff --git a/fs/buffer.c b/fs/buffer.c index 0e5ec37..75b51df 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2634,13 +2634,10 @@ sector_t generic_block_bmap(struct address_space *mapping, sector_t block, return tmp.b_blocknr; } -static int end_bio_bh_io_sync(struct bio *bio, unsigned int bytes_done, int err) +static void end_bio_bh_io_sync(struct bio *bio, int err) { struct buffer_head *bh = bio->bi_private; - if (bio->bi_size) - return 1; - if (err == -EOPNOTSUPP) { set_bit(BIO_EOPNOTSUPP, &bio->bi_flags); set_bit(BH_Eopnotsupp, &bh->b_state); @@ -2648,7 +2645,6 @@ static int end_bio_bh_io_sync(struct bio *bio, unsigned int bytes_done, int err) bh->b_end_io(bh, test_bit(BIO_UPTODATE, &bio->bi_flags)); bio_put(bio); - return 0; } int submit_bh(int rw, struct buffer_head * bh) diff --git a/fs/direct-io.c b/fs/direct-io.c index 901dc55..b5928a7 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -264,15 +264,12 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio); /* * Asynchronous IO callback. */ -static int dio_bio_end_aio(struct bio *bio, unsigned int bytes_done, int error) +static void dio_bio_end_aio(struct bio *bio, int error) { struct dio *dio = bio->bi_private; unsigned long remaining; unsigned long flags; - if (bio->bi_size) - return 1; - /* cleanup the bio */ dio_bio_complete(dio, bio); @@ -287,8 +284,6 @@ static int dio_bio_end_aio(struct bio *bio, unsigned int bytes_done, int error) aio_complete(dio->iocb, ret, 0); kfree(dio); } - - return 0; } /* @@ -298,21 +293,17 @@ static int dio_bio_end_aio(struct bio *bio, unsigned int bytes_done, int error) * During I/O bi_private points at the dio. After I/O, bi_private is used to * implement a singly-linked list of completed BIOs, at dio->bio_list. */ -static int dio_bio_end_io(struct bio *bio, unsigned int bytes_done, int error) +static void dio_bio_end_io(struct bio *bio, int error) { struct dio *dio = bio->bi_private; unsigned long flags; - if (bio->bi_size) - return 1; - spin_lock_irqsave(&dio->bio_lock, flags); bio->bi_private = dio->bio_list; dio->bio_list = bio; if (--dio->refcount == 1 && dio->waiter) wake_up_process(dio->waiter); spin_unlock_irqrestore(&dio->bio_lock, flags); - return 0; } static int diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index f916b97..2473e2a 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -160,11 +160,9 @@ int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent) } -static int end_bio_io_page(struct bio *bio, unsigned int bytes_done, int error) +static void end_bio_io_page(struct bio *bio, int error) { struct page *page = bio->bi_private; - if (bio->bi_size) - return 1; if (!error) SetPageUptodate(page); diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index de3e4a5..57c3b8a 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -2200,16 +2200,13 @@ static int lbmIOWait(struct lbuf * bp, int flag) * * executed at INTIODONE level */ -static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error) +static void lbmIODone(struct bio *bio, int error) { struct lbuf *bp = bio->bi_private; struct lbuf *nextbp, *tail; struct jfs_log *log; unsigned long flags; - if (bio->bi_size) - return 1; - /* * get back jfs buffer bound to the i/o buffer */ diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 62e96be..1332adc 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -280,14 +280,10 @@ static void last_read_complete(struct page *page) unlock_page(page); } -static int metapage_read_end_io(struct bio *bio, unsigned int bytes_done, - int err) +static void metapage_read_end_io(struct bio *bio, int err) { struct page *page = bio->bi_private; - if (bio->bi_size) - return 1; - if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) { printk(KERN_ERR "metapage_read_end_io: I/O error\n"); SetPageError(page); @@ -341,16 +337,12 @@ static void last_write_complete(struct page *page) end_page_writeback(page); } -static int metapage_write_end_io(struct bio *bio, unsigned int bytes_done, - int err) +static void metapage_write_end_io(struct bio *bio, int err) { struct page *page = bio->bi_private; BUG_ON(!PagePrivate(page)); - if (bio->bi_size) - return 1; - if (! test_bit(BIO_UPTODATE, &bio->bi_flags)) { printk(KERN_ERR "metapage_write_end_io: I/O error\n"); SetPageError(page); diff --git a/fs/mpage.c b/fs/mpage.c index c1698f2..b1c3e58 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -39,14 +39,11 @@ * status of that page is hard. See end_buffer_async_read() for the details. * There is no point in duplicating all that complexity. */ -static int mpage_end_io_read(struct bio *bio, unsigned int bytes_done, int err) +static void mpage_end_io_read(struct bio *bio, int err) { const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; - if (bio->bi_size) - return 1; - do { struct page *page = bvec->bv_page; @@ -62,17 +59,13 @@ static int mpage_end_io_read(struct bio *bio, unsigned int bytes_done, int err) unlock_page(page); } while (bvec >= bio->bi_io_vec); bio_put(bio); - return 0; } -static int mpage_end_io_write(struct bio *bio, unsigned int bytes_done, int err) +static void mpage_end_io_write(struct bio *bio, int err) { const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; - if (bio->bi_size) - return 1; - do { struct page *page = bvec->bv_page; @@ -87,7 +80,6 @@ static int mpage_end_io_write(struct bio *bio, unsigned int bytes_done, int err) end_page_writeback(page); } while (bvec >= bio->bi_io_vec); bio_put(bio); - return 0; } static struct bio *mpage_bio_submit(int rw, struct bio *bio) diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 2bd7f78..da2c2b4 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -217,7 +217,6 @@ static void o2hb_wait_on_io(struct o2hb_region *reg, } static int o2hb_bio_end_io(struct bio *bio, - unsigned int bytes_done, int error) { struct o2hb_bio_wait_ctxt *wc = bio->bi_private; @@ -227,9 +226,6 @@ static int o2hb_bio_end_io(struct bio *bio, wc->wc_error = error; } - if (bio->bi_size) - return 1; - o2hb_bio_wait_dec(wc, 1); bio_put(bio); return 0; diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 5f152f6..3f13519 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -326,14 +326,10 @@ xfs_iomap_valid( STATIC int xfs_end_bio( struct bio *bio, - unsigned int bytes_done, int error) { xfs_ioend_t *ioend = bio->bi_private; - if (bio->bi_size) - return 1; - ASSERT(atomic_read(&bio->bi_cnt) >= 1); ioend->io_error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : error; diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index b0f0e58..6a75f4d 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -1106,16 +1106,12 @@ _xfs_buf_ioend( STATIC int xfs_buf_bio_end_io( struct bio *bio, - unsigned int bytes_done, int error) { xfs_buf_t *bp = (xfs_buf_t *)bio->bi_private; unsigned int blocksize = bp->b_target->bt_bsize; struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; - if (bio->bi_size) - return 1; - if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) bp->b_error = EIO; diff --git a/include/linux/bio.h b/include/linux/bio.h index 1ddef34..089a8bc 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -64,7 +64,7 @@ struct bio_vec { struct bio_set; struct bio; -typedef int (bio_end_io_t) (struct bio *, unsigned int, int); +typedef void (bio_end_io_t) (struct bio *, int); typedef void (bio_destructor_t) (struct bio *); /* @@ -226,7 +226,7 @@ struct bio { #define BIO_SEG_BOUNDARY(q, b1, b2) \ BIOVEC_SEG_BOUNDARY((q), __BVEC_END((b1)), __BVEC_START((b2))) -#define bio_io_error(bio, bytes) bio_endio((bio), (bytes), -EIO) +#define bio_io_error(bio) bio_endio((bio), -EIO) /* * drivers should not use the __ version unless they _really_ want to @@ -286,7 +286,7 @@ extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *); extern void bio_put(struct bio *); extern void bio_free(struct bio *, struct bio_set *); -extern void bio_endio(struct bio *, unsigned int, int); +extern void bio_endio(struct bio *, int); struct request_queue; extern int bio_phys_segments(struct request_queue *, struct bio *); extern int bio_hw_segments(struct request_queue *, struct bio *); diff --git a/include/linux/swap.h b/include/linux/swap.h index 665f85f..edf681a 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -221,7 +221,7 @@ extern void swap_unplug_io_fn(struct backing_dev_info *, struct page *); /* linux/mm/page_io.c */ extern int swap_readpage(struct file *, struct page *); extern int swap_writepage(struct page *page, struct writeback_control *wbc); -extern int end_swap_bio_read(struct bio *bio, unsigned int bytes_done, int err); +extern void end_swap_bio_read(struct bio *bio, int err); /* linux/mm/swap_state.c */ extern struct address_space swapper_space; diff --git a/mm/bounce.c b/mm/bounce.c index 179fe38..3b549bf 100644 --- a/mm/bounce.c +++ b/mm/bounce.c @@ -140,26 +140,19 @@ static void bounce_end_io(struct bio *bio, mempool_t *pool, int err) mempool_free(bvec->bv_page, pool); } - bio_endio(bio_orig, bio_orig->bi_size, err); + bio_endio(bio_orig, err); bio_put(bio); } -static int bounce_end_io_write(struct bio *bio, unsigned int bytes_done, int err) +static void bounce_end_io_write(struct bio *bio, int err) { - if (bio->bi_size) - return 1; - bounce_end_io(bio, page_pool, err); - return 0; } -static int bounce_end_io_write_isa(struct bio *bio, unsigned int bytes_done, int err) +static void bounce_end_io_write_isa(struct bio *bio, int err) { - if (bio->bi_size) - return 1; bounce_end_io(bio, isa_page_pool, err); - return 0; } static void __bounce_end_io_read(struct bio *bio, mempool_t *pool, int err) @@ -172,22 +165,14 @@ static void __bounce_end_io_read(struct bio *bio, mempool_t *pool, int err) bounce_end_io(bio, pool, err); } -static int bounce_end_io_read(struct bio *bio, unsigned int bytes_done, int err) +static void bounce_end_io_read(struct bio *bio, int err) { - if (bio->bi_size) - return 1; - __bounce_end_io_read(bio, page_pool, err); - return 0; } -static int bounce_end_io_read_isa(struct bio *bio, unsigned int bytes_done, int err) +static void bounce_end_io_read_isa(struct bio *bio, int err) { - if (bio->bi_size) - return 1; - __bounce_end_io_read(bio, isa_page_pool, err); - return 0; } static void __blk_queue_bounce(struct request_queue *q, struct bio **bio_orig, diff --git a/mm/page_io.c b/mm/page_io.c index dbffec0..3b97f68 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -44,14 +44,11 @@ static struct bio *get_swap_bio(gfp_t gfp_flags, pgoff_t index, return bio; } -static int end_swap_bio_write(struct bio *bio, unsigned int bytes_done, int err) +static void end_swap_bio_write(struct bio *bio, int err) { const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); struct page *page = bio->bi_io_vec[0].bv_page; - if (bio->bi_size) - return 1; - if (!uptodate) { SetPageError(page); /* @@ -71,17 +68,13 @@ static int end_swap_bio_write(struct bio *bio, unsigned int bytes_done, int err) } end_page_writeback(page); bio_put(bio); - return 0; } -int end_swap_bio_read(struct bio *bio, unsigned int bytes_done, int err) +void end_swap_bio_read(struct bio *bio, int err) { const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); struct page *page = bio->bi_io_vec[0].bv_page; - if (bio->bi_size) - return 1; - if (!uptodate) { SetPageError(page); ClearPageUptodate(page); @@ -94,7 +87,6 @@ int end_swap_bio_read(struct bio *bio, unsigned int bytes_done, int err) } unlock_page(page); bio_put(bio); - return 0; } /* -- cgit v0.10.2 From c9d3d8ecf672c513435691a886876aee5ab11001 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 1 Oct 2007 16:33:51 +0200 Subject: Add Xilinx SystemACE entry to maintainers I'm the author of the SystemACE driver Signed-off-by: Grant Likely Signed-off-by: Jens Axboe diff --git a/MAINTAINERS b/MAINTAINERS index 9a91d9e..53144f4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4176,6 +4176,13 @@ W: http://oss.sgi.com/projects/xfs T: git git://oss.sgi.com:8090/xfs/xfs-2.6.git S: Supported +XILINX SYSTEMACE DRIVER +P: Grant Likely +M: grant.likely@secretlab.ca +W: http://www.secretlab.ca/ +L: linux-kernel@vger.kernel.org +S: Maintained + XILINX UARTLITE SERIAL DRIVER P: Peter Korsgaard M: jacmet@sunsite.dk -- cgit v0.10.2 From edec49616c7b4ad7ceb3b936a8d95b10652ee677 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 1 Oct 2007 16:33:52 +0200 Subject: Sysace: Use the established platform bus api SystemACE uses the platform bus binding, but it doesn't use the platform bus API. Move to using the correct API for consistency sake and future proofing against platform bus changes. Signed-off-by: Grant Likely Signed-off-by: Jens Axboe diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 3ede0b6..b104476 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -1060,13 +1060,12 @@ static void __devexit ace_teardown(struct ace_device *ace) * Platform Bus Support */ -static int __devinit ace_probe(struct device *device) +static int __devinit ace_probe(struct platform_device *dev) { - struct platform_device *dev = to_platform_device(device); struct ace_device *ace; int i; - dev_dbg(device, "ace_probe(%p)\n", device); + dev_dbg(&dev->dev, "ace_probe(%p)\n", dev); /* * Allocate the ace device structure @@ -1075,7 +1074,7 @@ static int __devinit ace_probe(struct device *device) if (!ace) goto err_alloc; - ace->dev = device; + ace->dev = &dev->dev; ace->id = dev->id; ace->irq = NO_IRQ; @@ -1089,7 +1088,7 @@ static int __devinit ace_probe(struct device *device) /* FIXME: Should get bus_width from the platform_device struct */ ace->bus_width = 1; - dev_set_drvdata(&dev->dev, ace); + platform_set_drvdata(dev, ace); /* Call the bus-independant setup code */ if (ace_setup(ace) != 0) @@ -1098,7 +1097,7 @@ static int __devinit ace_probe(struct device *device) return 0; err_setup: - dev_set_drvdata(&dev->dev, NULL); + platform_set_drvdata(dev, NULL); kfree(ace); err_alloc: printk(KERN_ERR "xsysace: could not initialize device\n"); @@ -1108,25 +1107,27 @@ static int __devinit ace_probe(struct device *device) /* * Platform bus remove() method */ -static int __devexit ace_remove(struct device *device) +static int __devexit ace_remove(struct platform_device *dev) { - struct ace_device *ace = dev_get_drvdata(device); - - dev_dbg(device, "ace_remove(%p)\n", device); + struct ace_device *ace = platform_get_drvdata(dev); + dev_dbg(&dev->dev, "ace_remove(%p)\n", dev); if (ace) { ace_teardown(ace); + platform_set_drvdata(dev, NULL); kfree(ace); } return 0; } -static struct device_driver ace_driver = { - .name = "xsysace", - .bus = &platform_bus_type, +static struct platform_driver ace_platform_driver = { .probe = ace_probe, .remove = __devexit_p(ace_remove), + .driver = { + .owner = THIS_MODULE, + .name = "xsysace", + }, }; /* --------------------------------------------------------------------- @@ -1134,20 +1135,31 @@ static struct device_driver ace_driver = { */ static int __init ace_init(void) { + int rc; + ace_major = register_blkdev(ace_major, "xsysace"); if (ace_major <= 0) { - printk(KERN_WARNING "xsysace: register_blkdev() failed\n"); - return ace_major; + rc = -ENOMEM; + goto err_blk; } - pr_debug("Registering Xilinx SystemACE driver, major=%i\n", ace_major); - return driver_register(&ace_driver); + if ((rc = platform_driver_register(&ace_platform_driver)) != 0) + goto err_plat; + + pr_info("Xilinx SystemACE device driver, major=%i\n", ace_major); + return 0; + + err_plat: + unregister_blkdev(ace_major, "xsysace"); + err_blk: + printk(KERN_ERR "xsysace: registration failed; err=%i\n", rc); + return rc; } static void __exit ace_exit(void) { pr_debug("Unregistering Xilinx SystemACE driver\n"); - driver_unregister(&ace_driver); + platform_driver_unregister(&ace_platform_driver); unregister_blkdev(ace_major, "xsysace"); } -- cgit v0.10.2 From 1b455466549f46bab0a75a7a296a9331a38fd6fa Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 1 Oct 2007 16:33:53 +0200 Subject: Sysace: Move structure allocation from bus binding into common code Split the determination of device registers/irqs/etc from the actual allocation and initialization of the device structure. This cleans up the code a bit in preparation to add an of_platform bus binding Signed-off-by: Grant Likely Signed-off-by: Jens Axboe diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index b104476..555939b 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -1033,7 +1033,7 @@ static int __devinit ace_setup(struct ace_device *ace) if (ace->irq != NO_IRQ) free_irq(ace->irq, ace); err_ioremap: - printk(KERN_INFO "xsysace: error initializing device at 0x%lx\n", + dev_info(ace->dev, "xsysace: error initializing device at 0x%lx\n", ace->physaddr); return -ENOMEM; } @@ -1056,68 +1056,91 @@ static void __devexit ace_teardown(struct ace_device *ace) iounmap(ace->baseaddr); } -/* --------------------------------------------------------------------- - * Platform Bus Support - */ - -static int __devinit ace_probe(struct platform_device *dev) +static int __devinit +ace_alloc(struct device *dev, int id, unsigned long physaddr, + int irq, int bus_width) { struct ace_device *ace; - int i; + int rc; + dev_dbg(dev, "ace_alloc(%p)\n", dev); - dev_dbg(&dev->dev, "ace_probe(%p)\n", dev); + if (!physaddr) { + rc = -ENODEV; + goto err_noreg; + } - /* - * Allocate the ace device structure - */ + /* Allocate and initialize the ace device structure */ ace = kzalloc(sizeof(struct ace_device), GFP_KERNEL); - if (!ace) + if (!ace) { + rc = -ENOMEM; goto err_alloc; - - ace->dev = &dev->dev; - ace->id = dev->id; - ace->irq = NO_IRQ; - - for (i = 0; i < dev->num_resources; i++) { - if (dev->resource[i].flags & IORESOURCE_MEM) - ace->physaddr = dev->resource[i].start; - if (dev->resource[i].flags & IORESOURCE_IRQ) - ace->irq = dev->resource[i].start; } - /* FIXME: Should get bus_width from the platform_device struct */ - ace->bus_width = 1; - - platform_set_drvdata(dev, ace); + ace->dev = dev; + ace->id = id; + ace->physaddr = physaddr; + ace->irq = irq; + ace->bus_width = bus_width; - /* Call the bus-independant setup code */ - if (ace_setup(ace) != 0) + /* Call the setup code */ + if ((rc = ace_setup(ace)) != 0) goto err_setup; + dev_set_drvdata(dev, ace); return 0; err_setup: - platform_set_drvdata(dev, NULL); + dev_set_drvdata(dev, NULL); kfree(ace); err_alloc: - printk(KERN_ERR "xsysace: could not initialize device\n"); - return -ENOMEM; + err_noreg: + dev_err(dev, "could not initialize device, err=%i\n", rc); + return rc; } -/* - * Platform bus remove() method - */ -static int __devexit ace_remove(struct platform_device *dev) +static void __devexit ace_free(struct device *dev) { - struct ace_device *ace = platform_get_drvdata(dev); - dev_dbg(&dev->dev, "ace_remove(%p)\n", dev); + struct ace_device *ace = dev_get_drvdata(dev); + dev_dbg(dev, "ace_free(%p)\n", dev); if (ace) { ace_teardown(ace); - platform_set_drvdata(dev, NULL); + dev_set_drvdata(dev, NULL); kfree(ace); } +} + +/* --------------------------------------------------------------------- + * Platform Bus Support + */ + +static int __devinit ace_probe(struct platform_device *dev) +{ + unsigned long physaddr = 0; + int bus_width = 1; /* FIXME: should not be hard coded */ + int id = dev->id; + int irq = NO_IRQ; + int i; + + dev_dbg(&dev->dev, "ace_probe(%p)\n", dev); + + for (i = 0; i < dev->num_resources; i++) { + if (dev->resource[i].flags & IORESOURCE_MEM) + physaddr = dev->resource[i].start; + if (dev->resource[i].flags & IORESOURCE_IRQ) + irq = dev->resource[i].start; + } + + /* Call the bus-independant setup code */ + return ace_alloc(&dev->dev, id, physaddr, irq, bus_width); +} +/* + * Platform bus remove() method + */ +static int __devexit ace_remove(struct platform_device *dev) +{ + ace_free(&dev->dev); return 0; } -- cgit v0.10.2 From 4a24d8610df542b6599a65b100d438df144574de Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 1 Oct 2007 16:33:54 +0200 Subject: Sysace: minor rework and cleanup changes Miscellanious rework to the sysace driver; Not critical, but makes the subsequent addition of the of_platform bus binding a wee bit cleaner Signed-off-by: Grant Likely Signed-off-by: Jens Axboe diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 555939b..10bb4e5 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -158,6 +158,9 @@ MODULE_LICENSE("GPL"); #define ACE_FIFO_SIZE (32) #define ACE_BUF_PER_SECTOR (ACE_SECTOR_SIZE / ACE_FIFO_SIZE) +#define ACE_BUS_WIDTH_8 0 +#define ACE_BUS_WIDTH_16 1 + struct ace_reg_ops; struct ace_device { @@ -931,9 +934,11 @@ static int __devinit ace_setup(struct ace_device *ace) { u16 version; u16 val; - int rc; + dev_dbg(ace->dev, "ace_setup(ace=0x%p)\n", ace); + dev_dbg(ace->dev, "physaddr=0x%lx irq=%i\n", ace->physaddr, ace->irq); + spin_lock_init(&ace->lock); init_completion(&ace->id_completion); @@ -982,7 +987,7 @@ static int __devinit ace_setup(struct ace_device *ace) snprintf(ace->gd->disk_name, 32, "xs%c", ace->id + 'a'); /* set bus width */ - if (ace->bus_width == 1) { + if (ace->bus_width == ACE_BUS_WIDTH_16) { /* 0x0101 should work regardless of endianess */ ace_out_le16(ace, ACE_BUSMODE, 0x0101); @@ -1117,7 +1122,7 @@ static void __devexit ace_free(struct device *dev) static int __devinit ace_probe(struct platform_device *dev) { unsigned long physaddr = 0; - int bus_width = 1; /* FIXME: should not be hard coded */ + int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */ int id = dev->id; int irq = NO_IRQ; int i; @@ -1166,6 +1171,7 @@ static int __init ace_init(void) goto err_blk; } + pr_debug("xsysace: registering platform binding\n"); if ((rc = platform_driver_register(&ace_platform_driver)) != 0) goto err_plat; -- cgit v0.10.2 From 32f6fff47df65d25d3dedbd2953508c05225b726 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 1 Oct 2007 16:33:54 +0200 Subject: Sysace: Move IRQ handler registration to occur after FSM is initialized The FSM needs to be initialized before it is safe to call the ISR Signed-off-by: Grant Likely Signed-off-by: Jens Axboe diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 10bb4e5..296d567 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -949,15 +949,6 @@ static int __devinit ace_setup(struct ace_device *ace) if (!ace->baseaddr) goto err_ioremap; - if (ace->irq != NO_IRQ) { - rc = request_irq(ace->irq, ace_interrupt, 0, "systemace", ace); - if (rc) { - /* Failure - fall back to polled mode */ - dev_err(ace->dev, "request_irq failed\n"); - ace->irq = NO_IRQ; - } - } - /* * Initialize the state machine tasklet and stall timer */ @@ -1015,6 +1006,16 @@ static int __devinit ace_setup(struct ace_device *ace) val |= ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ; ace_out(ace, ACE_CTRL, val); + /* Now we can hook up the irq handler */ + if (ace->irq != NO_IRQ) { + rc = request_irq(ace->irq, ace_interrupt, 0, "systemace", ace); + if (rc) { + /* Failure - fall back to polled mode */ + dev_err(ace->dev, "request_irq failed\n"); + ace->irq = NO_IRQ; + } + } + /* Print the identification */ dev_info(ace->dev, "Xilinx SystemACE revision %i.%i.%i\n", (version >> 12) & 0xf, (version >> 8) & 0x0f, version & 0xff); @@ -1035,8 +1036,6 @@ static int __devinit ace_setup(struct ace_device *ace) blk_cleanup_queue(ace->queue); err_blk_initq: iounmap(ace->baseaddr); - if (ace->irq != NO_IRQ) - free_irq(ace->irq, ace); err_ioremap: dev_info(ace->dev, "xsysace: error initializing device at 0x%lx\n", ace->physaddr); -- cgit v0.10.2 From 95e896c35f3c3157159b89682b60281640b5d148 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 1 Oct 2007 16:33:55 +0200 Subject: Sysace: Add of_platform_bus binding The of_platform bus binding is needed to make the device driver usable under arch/powerpc. Signed-off-by: Grant Likely Signed-off-by: Jens Axboe diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 296d567..56c4af3 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -91,6 +91,10 @@ #include #include #include +#if defined(CONFIG_OF) +#include +#include +#endif MODULE_AUTHOR("Grant Likely "); MODULE_DESCRIPTION("Xilinx SystemACE device driver"); @@ -1158,6 +1162,85 @@ static struct platform_driver ace_platform_driver = { }; /* --------------------------------------------------------------------- + * OF_Platform Bus Support + */ + +#if defined(CONFIG_OF) +static int __devinit +ace_of_probe(struct of_device *op, const struct of_device_id *match) +{ + struct resource res; + unsigned long physaddr; + const u32 *id; + int irq, bus_width, rc; + + dev_dbg(&op->dev, "ace_of_probe(%p, %p)\n", op, match); + + /* device id */ + id = of_get_property(op->node, "port-number", NULL); + + /* physaddr */ + rc = of_address_to_resource(op->node, 0, &res); + if (rc) { + dev_err(&op->dev, "invalid address\n"); + return rc; + } + physaddr = res.start; + + /* irq */ + irq = irq_of_parse_and_map(op->node, 0); + + /* bus width */ + bus_width = ACE_BUS_WIDTH_16; + if (of_find_property(op->node, "8-bit", NULL)) + bus_width = ACE_BUS_WIDTH_8; + + /* Call the bus-independant setup code */ + return ace_alloc(&op->dev, id ? *id : 0, physaddr, irq, bus_width); +} + +static int __devexit ace_of_remove(struct of_device *op) +{ + ace_free(&op->dev); + return 0; +} + +/* Match table for of_platform binding */ +static struct of_device_id __devinit ace_of_match[] = { + { .compatible = "xilinx,xsysace", }, + {}, +}; +MODULE_DEVICE_TABLE(of, ace_of_match); + +static struct of_platform_driver ace_of_driver = { + .owner = THIS_MODULE, + .name = "xsysace", + .match_table = ace_of_match, + .probe = ace_of_probe, + .remove = __devexit_p(ace_of_remove), + .driver = { + .name = "xsysace", + }, +}; + +/* Registration helpers to keep the number of #ifdefs to a minimum */ +static inline int __init ace_of_register(void) +{ + pr_debug("xsysace: registering OF binding\n"); + return of_register_platform_driver(&ace_of_driver); +} + +static inline void __exit ace_of_unregister(void) +{ + of_unregister_platform_driver(&ace_of_driver); +} +#else /* CONFIG_OF */ +/* CONFIG_OF not enabled; do nothing helpers */ +static inline int __init ace_of_register(void) { return 0; } +static inline void __exit ace_of_unregister(void) { } +#endif /* CONFIG_OF */ + +/* --------------------------------------------------------------------- * Module init/exit routines */ static int __init ace_init(void) @@ -1170,6 +1253,9 @@ static int __init ace_init(void) goto err_blk; } + if ((rc = ace_of_register()) != 0) + goto err_of; + pr_debug("xsysace: registering platform binding\n"); if ((rc = platform_driver_register(&ace_platform_driver)) != 0) goto err_plat; @@ -1178,6 +1264,8 @@ static int __init ace_init(void) return 0; err_plat: + ace_of_unregister(); + err_of: unregister_blkdev(ace_major, "xsysace"); err_blk: printk(KERN_ERR "xsysace: registration failed; err=%i\n", rc); @@ -1188,6 +1276,7 @@ static void __exit ace_exit(void) { pr_debug("Unregistering Xilinx SystemACE driver\n"); platform_driver_unregister(&ace_platform_driver); + ace_of_unregister(); unregister_blkdev(ace_major, "xsysace"); } -- cgit v0.10.2 From ed155a95a4eb7d8dae61b64ab394314c5195e414 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 1 Oct 2007 16:33:56 +0200 Subject: Sysace: Labels in C code should not be indented. Remove the indentation on labels Signed-off-by: Grant Likely Signed-off-by: Jens Axboe diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 56c4af3..3ea172b 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -1034,13 +1034,13 @@ static int __devinit ace_setup(struct ace_device *ace) return 0; - err_read: +err_read: put_disk(ace->gd); - err_alloc_disk: +err_alloc_disk: blk_cleanup_queue(ace->queue); - err_blk_initq: +err_blk_initq: iounmap(ace->baseaddr); - err_ioremap: +err_ioremap: dev_info(ace->dev, "xsysace: error initializing device at 0x%lx\n", ace->physaddr); return -ENOMEM; @@ -1097,11 +1097,11 @@ ace_alloc(struct device *dev, int id, unsigned long physaddr, dev_set_drvdata(dev, ace); return 0; - err_setup: +err_setup: dev_set_drvdata(dev, NULL); kfree(ace); - err_alloc: - err_noreg: +err_alloc: +err_noreg: dev_err(dev, "could not initialize device, err=%i\n", rc); return rc; } @@ -1263,11 +1263,11 @@ static int __init ace_init(void) pr_info("Xilinx SystemACE device driver, major=%i\n", ace_major); return 0; - err_plat: +err_plat: ace_of_unregister(); - err_of: +err_of: unregister_blkdev(ace_major, "xsysace"); - err_blk: +err_blk: printk(KERN_ERR "xsysace: registration failed; err=%i\n", rc); return rc; } -- cgit v0.10.2 From 3084f0c6105a71e43225c36b4d97c1407988a242 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 27 Sep 2007 06:25:06 -0400 Subject: drivers/block/umem: move private include away from include/linux Move include/linux/umem.h to drivers/block, as umem.c is the only user, and its not an exported header. Move the PCI_{VENDOR,DEVICE}_ID_* constants to include/linux/pci_ids.h. Signed-off-by: Jeff Garzik diff --git a/drivers/block/umem.c b/drivers/block/umem.c index be7fac8..33ef766 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -52,7 +52,7 @@ #include /* O_ACCMODE */ #include /* HDIO_GETGEO */ -#include +#include "umem.h" #include #include diff --git a/drivers/block/umem.h b/drivers/block/umem.h new file mode 100644 index 0000000..3a3819a --- /dev/null +++ b/drivers/block/umem.h @@ -0,0 +1,133 @@ + +/* + * This file contains defines for the + * Micro Memory MM5415 + * family PCI Memory Module with Battery Backup. + * + * Copyright Micro Memory INC 2001. All rights reserved. + * Release under the terms of the GNU GENERAL PUBLIC LICENSE version 2. + * See the file COPYING. + */ + +#ifndef _DRIVERS_BLOCK_MM_H +#define _DRIVERS_BLOCK_MM_H + + +#define IRQ_TIMEOUT (1 * HZ) + +/* CSR register definition */ +#define MEMCTRLSTATUS_MAGIC 0x00 +#define MM_MAGIC_VALUE (unsigned char)0x59 + +#define MEMCTRLSTATUS_BATTERY 0x04 +#define BATTERY_1_DISABLED 0x01 +#define BATTERY_1_FAILURE 0x02 +#define BATTERY_2_DISABLED 0x04 +#define BATTERY_2_FAILURE 0x08 + +#define MEMCTRLSTATUS_MEMORY 0x07 +#define MEM_128_MB 0xfe +#define MEM_256_MB 0xfc +#define MEM_512_MB 0xf8 +#define MEM_1_GB 0xf0 +#define MEM_2_GB 0xe0 + +#define MEMCTRLCMD_LEDCTRL 0x08 +#define LED_REMOVE 2 +#define LED_FAULT 4 +#define LED_POWER 6 +#define LED_FLIP 255 +#define LED_OFF 0x00 +#define LED_ON 0x01 +#define LED_FLASH_3_5 0x02 +#define LED_FLASH_7_0 0x03 +#define LED_POWER_ON 0x00 +#define LED_POWER_OFF 0x01 +#define USER_BIT1 0x01 +#define USER_BIT2 0x02 + +#define MEMORY_INITIALIZED USER_BIT1 + +#define MEMCTRLCMD_ERRCTRL 0x0C +#define EDC_NONE_DEFAULT 0x00 +#define EDC_NONE 0x01 +#define EDC_STORE_READ 0x02 +#define EDC_STORE_CORRECT 0x03 + +#define MEMCTRLCMD_ERRCNT 0x0D +#define MEMCTRLCMD_ERRSTATUS 0x0E + +#define ERROR_DATA_LOG 0x20 +#define ERROR_ADDR_LOG 0x28 +#define ERROR_COUNT 0x3D +#define ERROR_SYNDROME 0x3E +#define ERROR_CHECK 0x3F + +#define DMA_PCI_ADDR 0x40 +#define DMA_LOCAL_ADDR 0x48 +#define DMA_TRANSFER_SIZE 0x50 +#define DMA_DESCRIPTOR_ADDR 0x58 +#define DMA_SEMAPHORE_ADDR 0x60 +#define DMA_STATUS_CTRL 0x68 +#define DMASCR_GO 0x00001 +#define DMASCR_TRANSFER_READ 0x00002 +#define DMASCR_CHAIN_EN 0x00004 +#define DMASCR_SEM_EN 0x00010 +#define DMASCR_DMA_COMP_EN 0x00020 +#define DMASCR_CHAIN_COMP_EN 0x00040 +#define DMASCR_ERR_INT_EN 0x00080 +#define DMASCR_PARITY_INT_EN 0x00100 +#define DMASCR_ANY_ERR 0x00800 +#define DMASCR_MBE_ERR 0x01000 +#define DMASCR_PARITY_ERR_REP 0x02000 +#define DMASCR_PARITY_ERR_DET 0x04000 +#define DMASCR_SYSTEM_ERR_SIG 0x08000 +#define DMASCR_TARGET_ABT 0x10000 +#define DMASCR_MASTER_ABT 0x20000 +#define DMASCR_DMA_COMPLETE 0x40000 +#define DMASCR_CHAIN_COMPLETE 0x80000 + +/* +3.SOME PCs HAVE HOST BRIDGES WHICH APPARENTLY DO NOT CORRECTLY HANDLE +READ-LINE (0xE) OR READ-MULTIPLE (0xC) PCI COMMAND CODES DURING DMA +TRANSFERS. IN OTHER SYSTEMS THESE COMMAND CODES WILL CAUSE THE HOST BRIDGE +TO ALLOW LONGER BURSTS DURING DMA READ OPERATIONS. THE UPPER FOUR BITS +(31..28) OF THE DMA CSR HAVE BEEN MADE PROGRAMMABLE, SO THAT EITHER A 0x6, +AN 0xE OR A 0xC CAN BE WRITTEN TO THEM TO SET THE COMMAND CODE USED DURING +DMA READ OPERATIONS. +*/ +#define DMASCR_READ 0x60000000 +#define DMASCR_READLINE 0xE0000000 +#define DMASCR_READMULTI 0xC0000000 + + +#define DMASCR_ERROR_MASK (DMASCR_MASTER_ABT | DMASCR_TARGET_ABT | DMASCR_SYSTEM_ERR_SIG | DMASCR_PARITY_ERR_DET | DMASCR_MBE_ERR | DMASCR_ANY_ERR) +#define DMASCR_HARD_ERROR (DMASCR_MASTER_ABT | DMASCR_TARGET_ABT | DMASCR_SYSTEM_ERR_SIG | DMASCR_PARITY_ERR_DET | DMASCR_MBE_ERR) + +#define WINDOWMAP_WINNUM 0x7B + +#define DMA_READ_FROM_HOST 0 +#define DMA_WRITE_TO_HOST 1 + +struct mm_dma_desc { + __le64 pci_addr; + __le64 local_addr; + __le32 transfer_size; + u32 zero1; + __le64 next_desc_addr; + __le64 sem_addr; + __le32 control_bits; + u32 zero2; + + dma_addr_t data_dma_handle; + + /* Copy of the bits */ + __le64 sem_control_bits; +} __attribute__((aligned(8))); + +/* bits for card->flags */ +#define UM_FLAG_DMA_IN_REGS 1 +#define UM_FLAG_NO_BYTE_STATUS 2 +#define UM_FLAG_NO_BATTREG 4 +#define UM_FLAG_NO_BATT 8 +#endif diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 55f307f..506b9ae 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1736,6 +1736,11 @@ #define PCI_VENDOR_ID_RADISYS 0x1331 +#define PCI_VENDOR_ID_MICRO_MEMORY 0x1332 +#define PCI_DEVICE_ID_MICRO_MEMORY_5415CN 0x5415 +#define PCI_DEVICE_ID_MICRO_MEMORY_5425CN 0x5425 +#define PCI_DEVICE_ID_MICRO_MEMORY_6155 0x6155 + #define PCI_VENDOR_ID_DOMEX 0x134a #define PCI_DEVICE_ID_DOMEX_DMX3191D 0x0001 diff --git a/include/linux/umem.h b/include/linux/umem.h deleted file mode 100644 index f36ebfc..0000000 --- a/include/linux/umem.h +++ /dev/null @@ -1,138 +0,0 @@ - -/* - * This file contains defines for the - * Micro Memory MM5415 - * family PCI Memory Module with Battery Backup. - * - * Copyright Micro Memory INC 2001. All rights reserved. - * Release under the terms of the GNU GENERAL PUBLIC LICENSE version 2. - * See the file COPYING. - */ - -#ifndef _DRIVERS_BLOCK_MM_H -#define _DRIVERS_BLOCK_MM_H - - -#define IRQ_TIMEOUT (1 * HZ) - -/* CSR register definition */ -#define MEMCTRLSTATUS_MAGIC 0x00 -#define MM_MAGIC_VALUE (unsigned char)0x59 - -#define MEMCTRLSTATUS_BATTERY 0x04 -#define BATTERY_1_DISABLED 0x01 -#define BATTERY_1_FAILURE 0x02 -#define BATTERY_2_DISABLED 0x04 -#define BATTERY_2_FAILURE 0x08 - -#define MEMCTRLSTATUS_MEMORY 0x07 -#define MEM_128_MB 0xfe -#define MEM_256_MB 0xfc -#define MEM_512_MB 0xf8 -#define MEM_1_GB 0xf0 -#define MEM_2_GB 0xe0 - -#define MEMCTRLCMD_LEDCTRL 0x08 -#define LED_REMOVE 2 -#define LED_FAULT 4 -#define LED_POWER 6 -#define LED_FLIP 255 -#define LED_OFF 0x00 -#define LED_ON 0x01 -#define LED_FLASH_3_5 0x02 -#define LED_FLASH_7_0 0x03 -#define LED_POWER_ON 0x00 -#define LED_POWER_OFF 0x01 -#define USER_BIT1 0x01 -#define USER_BIT2 0x02 - -#define MEMORY_INITIALIZED USER_BIT1 - -#define MEMCTRLCMD_ERRCTRL 0x0C -#define EDC_NONE_DEFAULT 0x00 -#define EDC_NONE 0x01 -#define EDC_STORE_READ 0x02 -#define EDC_STORE_CORRECT 0x03 - -#define MEMCTRLCMD_ERRCNT 0x0D -#define MEMCTRLCMD_ERRSTATUS 0x0E - -#define ERROR_DATA_LOG 0x20 -#define ERROR_ADDR_LOG 0x28 -#define ERROR_COUNT 0x3D -#define ERROR_SYNDROME 0x3E -#define ERROR_CHECK 0x3F - -#define DMA_PCI_ADDR 0x40 -#define DMA_LOCAL_ADDR 0x48 -#define DMA_TRANSFER_SIZE 0x50 -#define DMA_DESCRIPTOR_ADDR 0x58 -#define DMA_SEMAPHORE_ADDR 0x60 -#define DMA_STATUS_CTRL 0x68 -#define DMASCR_GO 0x00001 -#define DMASCR_TRANSFER_READ 0x00002 -#define DMASCR_CHAIN_EN 0x00004 -#define DMASCR_SEM_EN 0x00010 -#define DMASCR_DMA_COMP_EN 0x00020 -#define DMASCR_CHAIN_COMP_EN 0x00040 -#define DMASCR_ERR_INT_EN 0x00080 -#define DMASCR_PARITY_INT_EN 0x00100 -#define DMASCR_ANY_ERR 0x00800 -#define DMASCR_MBE_ERR 0x01000 -#define DMASCR_PARITY_ERR_REP 0x02000 -#define DMASCR_PARITY_ERR_DET 0x04000 -#define DMASCR_SYSTEM_ERR_SIG 0x08000 -#define DMASCR_TARGET_ABT 0x10000 -#define DMASCR_MASTER_ABT 0x20000 -#define DMASCR_DMA_COMPLETE 0x40000 -#define DMASCR_CHAIN_COMPLETE 0x80000 - -/* -3.SOME PCs HAVE HOST BRIDGES WHICH APPARENTLY DO NOT CORRECTLY HANDLE -READ-LINE (0xE) OR READ-MULTIPLE (0xC) PCI COMMAND CODES DURING DMA -TRANSFERS. IN OTHER SYSTEMS THESE COMMAND CODES WILL CAUSE THE HOST BRIDGE -TO ALLOW LONGER BURSTS DURING DMA READ OPERATIONS. THE UPPER FOUR BITS -(31..28) OF THE DMA CSR HAVE BEEN MADE PROGRAMMABLE, SO THAT EITHER A 0x6, -AN 0xE OR A 0xC CAN BE WRITTEN TO THEM TO SET THE COMMAND CODE USED DURING -DMA READ OPERATIONS. -*/ -#define DMASCR_READ 0x60000000 -#define DMASCR_READLINE 0xE0000000 -#define DMASCR_READMULTI 0xC0000000 - - -#define DMASCR_ERROR_MASK (DMASCR_MASTER_ABT | DMASCR_TARGET_ABT | DMASCR_SYSTEM_ERR_SIG | DMASCR_PARITY_ERR_DET | DMASCR_MBE_ERR | DMASCR_ANY_ERR) -#define DMASCR_HARD_ERROR (DMASCR_MASTER_ABT | DMASCR_TARGET_ABT | DMASCR_SYSTEM_ERR_SIG | DMASCR_PARITY_ERR_DET | DMASCR_MBE_ERR) - -#define WINDOWMAP_WINNUM 0x7B - -#define DMA_READ_FROM_HOST 0 -#define DMA_WRITE_TO_HOST 1 - -struct mm_dma_desc { - __le64 pci_addr; - __le64 local_addr; - __le32 transfer_size; - u32 zero1; - __le64 next_desc_addr; - __le64 sem_addr; - __le32 control_bits; - u32 zero2; - - dma_addr_t data_dma_handle; - - /* Copy of the bits */ - __le64 sem_control_bits; -} __attribute__((aligned(8))); - -#define PCI_VENDOR_ID_MICRO_MEMORY 0x1332 -#define PCI_DEVICE_ID_MICRO_MEMORY_5415CN 0x5415 -#define PCI_DEVICE_ID_MICRO_MEMORY_5425CN 0x5425 -#define PCI_DEVICE_ID_MICRO_MEMORY_6155 0x6155 - -/* bits for card->flags */ -#define UM_FLAG_DMA_IN_REGS 1 -#define UM_FLAG_NO_BYTE_STATUS 2 -#define UM_FLAG_NO_BATTREG 4 -#define UM_FLAG_NO_BATT 8 -#endif -- cgit v0.10.2 From 4e0af881afee2b399854b1cdfdbe37e6ab6a09ca Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 27 Sep 2007 06:41:25 -0400 Subject: drivers/block/umem: use dev_printk() dev_printk() gives us a consistent prefix (driver name + PCI bus id), which allows us to eliminate the hand-rolled one. Also allows us to eliminate card->card_number, which was used solely in printk() calls. Signed-off-by: Jeff Garzik diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 33ef766..32060b8 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -97,7 +97,6 @@ static int major_nr; #include struct cardinfo { - int card_number; struct pci_dev *dev; int irq; @@ -236,7 +235,7 @@ static void dump_regs(struct cardinfo *card) */ static void dump_dmastat(struct cardinfo *card, unsigned int dmastat) { - printk(KERN_DEBUG "MM%d*: DMAstat - ", card->card_number); + dev_printk(KERN_DEBUG, &card->dev->dev, "DMAstat - "); if (dmastat & DMASCR_ANY_ERR) printk("ANY_ERR "); if (dmastat & DMASCR_MBE_ERR) @@ -499,17 +498,17 @@ static void process_page(unsigned long data) if (control & DMASCR_HARD_ERROR) { /* error */ clear_bit(BIO_UPTODATE, &bio->bi_flags); - printk(KERN_WARNING "MM%d: I/O error on sector %d/%d\n", - card->card_number, - le32_to_cpu(desc->local_addr)>>9, - le32_to_cpu(desc->transfer_size)); + dev_printk(KERN_WARNING, &card->dev->dev, + "I/O error on sector %d/%d\n", + le32_to_cpu(desc->local_addr)>>9, + le32_to_cpu(desc->transfer_size)); dump_dmastat(card, control); } else if (test_bit(BIO_RW, &bio->bi_rw) && le32_to_cpu(desc->local_addr)>>9 == card->init_size) { card->init_size += le32_to_cpu(desc->transfer_size)>>9; if (card->init_size>>1 >= card->mm_size) { - printk(KERN_INFO "MM%d: memory now initialised\n", - card->card_number); + dev_printk(KERN_INFO, &card->dev->dev, + "memory now initialised\n"); set_userbit(card, MEMORY_INITIALIZED, 1); } } @@ -618,46 +617,51 @@ HW_TRACE(0x30); dump_dmastat(card, dma_status); if (stat & 0x01) - printk(KERN_ERR "MM%d*: Memory access error detected (err count %d)\n", - card->card_number, count); + dev_printk(KERN_ERR, &card->dev->dev, + "Memory access error detected (err count %d)\n", + count); if (stat & 0x02) - printk(KERN_ERR "MM%d*: Multi-bit EDC error\n", - card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, + "Multi-bit EDC error\n"); - printk(KERN_ERR "MM%d*: Fault Address 0x%02x%08x, Fault Data 0x%08x%08x\n", - card->card_number, addr_log2, addr_log1, data_log2, data_log1); - printk(KERN_ERR "MM%d*: Fault Check 0x%02x, Fault Syndrome 0x%02x\n", - card->card_number, check, syndrome); + dev_printk(KERN_ERR, &card->dev->dev, + "Fault Address 0x%02x%08x, Fault Data 0x%08x%08x\n", + addr_log2, addr_log1, data_log2, data_log1); + dev_printk(KERN_ERR, &card->dev->dev, + "Fault Check 0x%02x, Fault Syndrome 0x%02x\n", + check, syndrome); writeb(0, card->csr_remap + ERROR_COUNT); } if (dma_status & DMASCR_PARITY_ERR_REP) { - printk(KERN_ERR "MM%d*: PARITY ERROR REPORTED\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, + "PARITY ERROR REPORTED\n"); pci_read_config_word(card->dev, PCI_STATUS, &cfg_status); pci_write_config_word(card->dev, PCI_STATUS, cfg_status); } if (dma_status & DMASCR_PARITY_ERR_DET) { - printk(KERN_ERR "MM%d*: PARITY ERROR DETECTED\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, + "PARITY ERROR DETECTED\n"); pci_read_config_word(card->dev, PCI_STATUS, &cfg_status); pci_write_config_word(card->dev, PCI_STATUS, cfg_status); } if (dma_status & DMASCR_SYSTEM_ERR_SIG) { - printk(KERN_ERR "MM%d*: SYSTEM ERROR\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, "SYSTEM ERROR\n"); pci_read_config_word(card->dev, PCI_STATUS, &cfg_status); pci_write_config_word(card->dev, PCI_STATUS, cfg_status); } if (dma_status & DMASCR_TARGET_ABT) { - printk(KERN_ERR "MM%d*: TARGET ABORT\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, "TARGET ABORT\n"); pci_read_config_word(card->dev, PCI_STATUS, &cfg_status); pci_write_config_word(card->dev, PCI_STATUS, cfg_status); } if (dma_status & DMASCR_MASTER_ABT) { - printk(KERN_ERR "MM%d*: MASTER ABORT\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, "MASTER ABORT\n"); pci_read_config_word(card->dev, PCI_STATUS, &cfg_status); pci_write_config_word(card->dev, PCI_STATUS, cfg_status); } @@ -708,20 +712,20 @@ static int check_battery(struct cardinfo *card, int battery, int status) card->battery[battery].last_change = jiffies; if (card->battery[battery].good) { - printk(KERN_ERR "MM%d: Battery %d now good\n", - card->card_number, battery + 1); + dev_printk(KERN_ERR, &card->dev->dev, + "Battery %d now good\n", battery + 1); card->battery[battery].warned = 0; } else - printk(KERN_ERR "MM%d: Battery %d now FAILED\n", - card->card_number, battery + 1); + dev_printk(KERN_ERR, &card->dev->dev, + "Battery %d now FAILED\n", battery + 1); return 1; } else if (!card->battery[battery].good && !card->battery[battery].warned && time_after_eq(jiffies, card->battery[battery].last_change + (HZ * 60 * 60 * 5))) { - printk(KERN_ERR "MM%d: Battery %d still FAILED after 5 hours\n", - card->card_number, battery + 1); + dev_printk(KERN_ERR, &card->dev->dev, + "Battery %d still FAILED after 5 hours\n", battery + 1); card->battery[battery].warned = 1; return 1; @@ -745,8 +749,8 @@ static void check_batteries(struct cardinfo *card) status = readb(card->csr_remap + MEMCTRLSTATUS_BATTERY); if (debug & DEBUG_BATTERY_POLLING) - printk(KERN_DEBUG "MM%d: checking battery status, 1 = %s, 2 = %s\n", - card->card_number, + dev_printk(KERN_DEBUG, &card->dev->dev, + "checking battery status, 1 = %s, 2 = %s\n", (status & BATTERY_1_FAILURE) ? "FAILURE" : "OK", (status & BATTERY_2_FAILURE) ? "FAILURE" : "OK"); @@ -866,6 +870,10 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i unsigned char batt_status; unsigned int saved_bar, data; int magic_number; + static int printed_version; + + if (!printed_version++) + printk(KERN_INFO DRIVER_VERSION " : " DRIVER_DESC "\n"); if (pci_enable_device(dev) < 0) return -ENODEV; @@ -874,21 +882,21 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i pci_set_master(dev); card->dev = dev; - card->card_number = num_cards; card->csr_base = pci_resource_start(dev, 0); card->csr_len = pci_resource_len(dev, 0); - printk(KERN_INFO "Micro Memory(tm) controller #%d found at %02x:%02x (PCI Mem Module (Battery Backup))\n", - card->card_number, dev->bus->number, dev->devfn); + dev_printk(KERN_INFO, &dev->dev, + "Micro Memory(tm) controller found (PCI Mem Module (Battery Backup))\n"); if (pci_set_dma_mask(dev, DMA_64BIT_MASK) && pci_set_dma_mask(dev, DMA_32BIT_MASK)) { - printk(KERN_WARNING "MM%d: NO suitable DMA found\n",num_cards); + dev_printk(KERN_WARNING, &dev->dev, "NO suitable DMA found\n"); return -ENOMEM; } if (!request_mem_region(card->csr_base, card->csr_len, "Micro Memory")) { - printk(KERN_ERR "MM%d: Unable to request memory region\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, + "Unable to request memory region\n"); ret = -ENOMEM; goto failed_req_csr; @@ -896,13 +904,15 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i card->csr_remap = ioremap_nocache(card->csr_base, card->csr_len); if (!card->csr_remap) { - printk(KERN_ERR "MM%d: Unable to remap memory region\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, + "Unable to remap memory region\n"); ret = -ENOMEM; goto failed_remap_csr; } - printk(KERN_INFO "MM%d: CSR 0x%08lx -> 0x%p (0x%lx)\n", card->card_number, + dev_printk(KERN_INFO, &card->dev->dev, + "CSR 0x%08lx -> 0x%p (0x%lx)\n", card->csr_base, card->csr_remap, card->csr_len); switch(card->dev->device) { @@ -927,7 +937,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i } if (readb(card->csr_remap + MEMCTRLSTATUS_MAGIC) != magic_number) { - printk(KERN_ERR "MM%d: Magic number invalid\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, "Magic number invalid\n"); ret = -ENOMEM; goto failed_magic; } @@ -940,7 +950,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i &card->mm_pages[1].page_dma); if (card->mm_pages[0].desc == NULL || card->mm_pages[1].desc == NULL) { - printk(KERN_ERR "MM%d: alloc failed\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, "alloc failed\n"); goto failed_alloc; } reset_page(&card->mm_pages[0]); @@ -995,11 +1005,12 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i card->battery[0].last_change = card->battery[1].last_change = jiffies; if (card->flags & UM_FLAG_NO_BATT) - printk(KERN_INFO "MM%d: Size %d KB\n", - card->card_number, card->mm_size); + dev_printk(KERN_INFO, &card->dev->dev, + "Size %d KB\n", card->mm_size); else { - printk(KERN_INFO "MM%d: Size %d KB, Battery 1 %s (%s), Battery 2 %s (%s)\n", - card->card_number, card->mm_size, + dev_printk(KERN_INFO, &card->dev->dev, + "Size %d KB, Battery 1 %s (%s), Battery 2 %s (%s)\n", + card->mm_size, (batt_status & BATTERY_1_DISABLED ? "Disabled" : "Enabled"), card->battery[0].good ? "OK" : "FAILURE", (batt_status & BATTERY_2_DISABLED ? "Disabled" : "Enabled"), @@ -1021,14 +1032,16 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i if (request_irq(dev->irq, mm_interrupt, IRQF_SHARED, "pci-umem", card)) { - printk(KERN_ERR "MM%d: Unable to allocate IRQ\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, + "Unable to allocate IRQ\n"); ret = -ENODEV; goto failed_req_irq; } card->irq = dev->irq; - printk(KERN_INFO "MM%d: Window size %d bytes, IRQ %d\n", card->card_number, + dev_printk(KERN_INFO, &card->dev->dev, + "Window size %d bytes, IRQ %d\n", card->win_size, card->irq); spin_lock_init(&card->lock); @@ -1049,10 +1062,12 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i num_cards++; if (!get_userbit(card, MEMORY_INITIALIZED)) { - printk(KERN_INFO "MM%d: memory NOT initialized. Consider over-writing whole device.\n", card->card_number); + dev_printk(KERN_INFO, &card->dev->dev, + "memory NOT initialized. Consider over-writing whole device.\n"); card->init_size = 0; } else { - printk(KERN_INFO "MM%d: memory already initialized\n", card->card_number); + dev_printk(KERN_INFO, &card->dev->dev, + "memory already initialized\n"); card->init_size = card->mm_size; } @@ -1137,8 +1152,6 @@ static int __init mm_init(void) int retval, i; int err; - printk(KERN_INFO DRIVER_VERSION " : " DRIVER_DESC "\n"); - retval = pci_register_driver(&mm_pci_driver); if (retval) return -ENOMEM; @@ -1169,7 +1182,7 @@ static int __init mm_init(void) } init_battery_timer(); - printk("MM: desc_per_page = %ld\n", DESC_PER_PAGE); + printk(KERN_INFO "MM: desc_per_page = %ld\n", DESC_PER_PAGE); /* printk("mm_init: Done. 10-19-01 9:00\n"); */ return 0; -- cgit v0.10.2 From ee4a7b6874469244ed0e3b8fde20028e0bb52642 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 27 Sep 2007 07:40:33 -0400 Subject: drivers/block/umem: minor cleanups * tab-align DRIVER_*, pci_driver entries * reduced wasted memory by killing unused struct cardinfo members * move free_irq() call above resource unmap, to fix tiny window where irq handler may access recently-unmapped memory * propagate pci_enable_device() return value * use pci_request_regions, pci_release_regions() for resource reservation * call pci_disable_device() in pci_driver::remove() Signed-off-by: Jeff Garzik diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 32060b8..97c5dc9 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -67,9 +67,10 @@ * Version Information */ -#define DRIVER_VERSION "v2.3" -#define DRIVER_AUTHOR "San Mehat, Johannes Erdfelt, NeilBrown" -#define DRIVER_DESC "Micro Memory(tm) PCI memory board block driver" +#define DRIVER_NAME "umem" +#define DRIVER_VERSION "v2.3" +#define DRIVER_AUTHOR "San Mehat, Johannes Erdfelt, NeilBrown" +#define DRIVER_DESC "Micro Memory(tm) PCI memory board block driver" static int debug; /* #define HW_TRACE(x) writeb(x,cards[0].csr_remap + MEMCTRLSTATUS_MAGIC) */ @@ -99,12 +100,7 @@ static int major_nr; struct cardinfo { struct pci_dev *dev; - int irq; - - unsigned long csr_base; unsigned char __iomem *csr_remap; - unsigned long csr_len; - unsigned int win_size; /* PCI window size */ unsigned int mm_size; /* size in kbytes */ unsigned int init_size; /* initial segment, in sectors, @@ -869,22 +865,27 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i unsigned char mem_present; unsigned char batt_status; unsigned int saved_bar, data; + unsigned long csr_base; + unsigned long csr_len; int magic_number; static int printed_version; if (!printed_version++) printk(KERN_INFO DRIVER_VERSION " : " DRIVER_DESC "\n"); - if (pci_enable_device(dev) < 0) - return -ENODEV; + ret = pci_enable_device(dev); + if (ret) + return ret; pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF8); pci_set_master(dev); card->dev = dev; - card->csr_base = pci_resource_start(dev, 0); - card->csr_len = pci_resource_len(dev, 0); + csr_base = pci_resource_start(dev, 0); + csr_len = pci_resource_len(dev, 0); + if (!csr_base || !csr_len) + return -ENODEV; dev_printk(KERN_INFO, &dev->dev, "Micro Memory(tm) controller found (PCI Mem Module (Battery Backup))\n"); @@ -894,15 +895,15 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i dev_printk(KERN_WARNING, &dev->dev, "NO suitable DMA found\n"); return -ENOMEM; } - if (!request_mem_region(card->csr_base, card->csr_len, "Micro Memory")) { + + ret = pci_request_regions(dev, DRIVER_NAME); + if (ret) { dev_printk(KERN_ERR, &card->dev->dev, "Unable to request memory region\n"); - ret = -ENOMEM; - goto failed_req_csr; } - card->csr_remap = ioremap_nocache(card->csr_base, card->csr_len); + card->csr_remap = ioremap_nocache(csr_base, csr_len); if (!card->csr_remap) { dev_printk(KERN_ERR, &card->dev->dev, "Unable to remap memory region\n"); @@ -913,7 +914,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i dev_printk(KERN_INFO, &card->dev->dev, "CSR 0x%08lx -> 0x%p (0x%lx)\n", - card->csr_base, card->csr_remap, card->csr_len); + csr_base, card->csr_remap, csr_len); switch(card->dev->device) { case 0x5415: @@ -1028,9 +1029,6 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i data = ~data; data += 1; - card->win_size = data; - - if (request_irq(dev->irq, mm_interrupt, IRQF_SHARED, "pci-umem", card)) { dev_printk(KERN_ERR, &card->dev->dev, "Unable to allocate IRQ\n"); @@ -1039,10 +1037,8 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i goto failed_req_irq; } - card->irq = dev->irq; dev_printk(KERN_INFO, &card->dev->dev, - "Window size %d bytes, IRQ %d\n", - card->win_size, card->irq); + "Window size %d bytes, IRQ %d\n", data, dev->irq); spin_lock_init(&card->lock); @@ -1089,7 +1085,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i failed_magic: iounmap(card->csr_remap); failed_remap_csr: - release_mem_region(card->csr_base, card->csr_len); + pci_release_regions(dev); failed_req_csr: return ret; @@ -1104,9 +1100,8 @@ static void mm_pci_remove(struct pci_dev *dev) struct cardinfo *card = pci_get_drvdata(dev); tasklet_kill(&card->tasklet); + free_irq(dev->irq, card); iounmap(card->csr_remap); - release_mem_region(card->csr_base, card->csr_len); - free_irq(card->irq, card); if (card->mm_pages[0].desc) pci_free_consistent(card->dev, PAGE_SIZE*2, @@ -1117,6 +1112,9 @@ static void mm_pci_remove(struct pci_dev *dev) card->mm_pages[1].desc, card->mm_pages[1].page_dma); blk_cleanup_queue(card->queue); + + pci_release_regions(dev); + pci_disable_device(dev); } static const struct pci_device_id mm_pci_ids[] = { @@ -1136,11 +1134,12 @@ static const struct pci_device_id mm_pci_ids[] = { MODULE_DEVICE_TABLE(pci, mm_pci_ids); static struct pci_driver mm_pci_driver = { - .name = "umem", - .id_table = mm_pci_ids, - .probe = mm_pci_probe, - .remove = mm_pci_remove, + .name = DRIVER_NAME, + .id_table = mm_pci_ids, + .probe = mm_pci_probe, + .remove = mm_pci_remove, }; + /* ----------------------------------------------------------------------------------- -- mm_init -- cgit v0.10.2 From 4e953a216265f8646360fa909bdc87ea4bf446b3 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 27 Sep 2007 07:41:50 -0400 Subject: drivers/block/umem: trim trailing whitespace Signed-off-by: Jeff Garzik diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 97c5dc9..2510417 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -293,7 +293,7 @@ static void mm_start_io(struct cardinfo *card) desc->control_bits &= ~cpu_to_le32(DMASCR_CHAIN_EN); desc->sem_control_bits = desc->control_bits; - + if (debug & DEBUG_LED_ON_TRANSFER) set_led(card, LED_REMOVE, LED_ON); @@ -327,7 +327,7 @@ static int add_bio(struct cardinfo *card); static void activate(struct cardinfo *card) { - /* if No page is Active, and Ready is + /* if No page is Active, and Ready is * not empty, then switch Ready page * to active and start IO. * Then add any bh's that are available to Ready @@ -366,7 +366,7 @@ static void mm_unplug_device(struct request_queue *q) spin_unlock_irqrestore(&card->lock, flags); } -/* +/* * If there is room on Ready page, take * one bh off list and add it. * return 1 if there was room, else 0. @@ -467,7 +467,7 @@ static void process_page(unsigned long data) if (card->Active < 0) goto out_unlock; page = &card->mm_pages[card->Active]; - + while (page->headcnt < page->cnt) { struct bio *bio = page->bio; struct mm_dma_desc *desc = &page->desc[page->headcnt]; @@ -477,7 +477,7 @@ static void process_page(unsigned long data) if (!(control & DMASCR_DMA_COMPLETE)) { control = dma_status; - last=1; + last=1; } page->headcnt++; idx = page->idx; @@ -487,7 +487,7 @@ static void process_page(unsigned long data) page->idx = page->bio->bi_idx; } - pci_unmap_page(card->dev, desc->data_dma_handle, + pci_unmap_page(card->dev, desc->data_dma_handle, bio_iovec_idx(bio,idx)->bv_len, (control& DMASCR_TRANSFER_READ) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); @@ -592,7 +592,7 @@ HW_TRACE(0x30); else writeb((DMASCR_DMA_COMPLETE|DMASCR_CHAIN_COMPLETE) >> 16, card->csr_remap+ DMA_STATUS_CTRL + 2); - + /* log errors and clear interrupt status */ if (dma_status & DMASCR_ANY_ERR) { unsigned int data_log1, data_log2; @@ -668,7 +668,7 @@ HW_TRACE(0x30); HW_TRACE(0x36); - return IRQ_HANDLED; + return IRQ_HANDLED; } /* ----------------------------------------------------------------------------------- @@ -761,7 +761,7 @@ static void check_all_batteries(unsigned long ptr) { int i; - for (i = 0; i < num_cards; i++) + for (i = 0; i < num_cards; i++) if (!(cards[i].flags & UM_FLAG_NO_BATT)) { struct cardinfo *card = &cards[i]; spin_lock_bh(&card->lock); @@ -972,7 +972,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i tasklet_init(&card->tasklet, process_page, (unsigned long)card); card->check_batteries = 0; - + mem_present = readb(card->csr_remap + MEMCTRLSTATUS_MEMORY); switch (mem_present) { case MEM_128_MB: @@ -1005,7 +1005,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i card->battery[1].good = !(batt_status & BATTERY_2_FAILURE); card->battery[0].last_change = card->battery[1].last_change = jiffies; - if (card->flags & UM_FLAG_NO_BATT) + if (card->flags & UM_FLAG_NO_BATT) dev_printk(KERN_INFO, &card->dev->dev, "Size %d KB\n", card->mm_size); else { diff --git a/drivers/block/umem.h b/drivers/block/umem.h index 3a3819a..375c689 100644 --- a/drivers/block/umem.h +++ b/drivers/block/umem.h @@ -87,13 +87,13 @@ #define DMASCR_DMA_COMPLETE 0x40000 #define DMASCR_CHAIN_COMPLETE 0x80000 -/* -3.SOME PCs HAVE HOST BRIDGES WHICH APPARENTLY DO NOT CORRECTLY HANDLE -READ-LINE (0xE) OR READ-MULTIPLE (0xC) PCI COMMAND CODES DURING DMA -TRANSFERS. IN OTHER SYSTEMS THESE COMMAND CODES WILL CAUSE THE HOST BRIDGE -TO ALLOW LONGER BURSTS DURING DMA READ OPERATIONS. THE UPPER FOUR BITS -(31..28) OF THE DMA CSR HAVE BEEN MADE PROGRAMMABLE, SO THAT EITHER A 0x6, -AN 0xE OR A 0xC CAN BE WRITTEN TO THEM TO SET THE COMMAND CODE USED DURING +/* +3.SOME PCs HAVE HOST BRIDGES WHICH APPARENTLY DO NOT CORRECTLY HANDLE +READ-LINE (0xE) OR READ-MULTIPLE (0xC) PCI COMMAND CODES DURING DMA +TRANSFERS. IN OTHER SYSTEMS THESE COMMAND CODES WILL CAUSE THE HOST BRIDGE +TO ALLOW LONGER BURSTS DURING DMA READ OPERATIONS. THE UPPER FOUR BITS +(31..28) OF THE DMA CSR HAVE BEEN MADE PROGRAMMABLE, SO THAT EITHER A 0x6, +AN 0xE OR A 0xC CAN BE WRITTEN TO THEM TO SET THE COMMAND CODE USED DURING DMA READ OPERATIONS. */ #define DMASCR_READ 0x60000000 -- cgit v0.10.2 From cb3503ca54dc34e8dc3b823a6bd52c0807c102f4 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 27 Sep 2007 07:49:39 -0400 Subject: drivers/block/umem: use DRIVER_NAME where appropriate Signed-off-by: Jeff Garzik diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 2510417..99806f9 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -1029,7 +1029,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i data = ~data; data += 1; - if (request_irq(dev->irq, mm_interrupt, IRQF_SHARED, "pci-umem", card)) { + if (request_irq(dev->irq, mm_interrupt, IRQF_SHARED, DRIVER_NAME, card)) { dev_printk(KERN_ERR, &card->dev->dev, "Unable to allocate IRQ\n"); ret = -ENODEV; @@ -1155,7 +1155,7 @@ static int __init mm_init(void) if (retval) return -ENOMEM; - err = major_nr = register_blkdev(0, "umem"); + err = major_nr = register_blkdev(0, DRIVER_NAME); if (err < 0) { pci_unregister_driver(&mm_pci_driver); return -EIO; @@ -1187,7 +1187,7 @@ static int __init mm_init(void) out: pci_unregister_driver(&mm_pci_driver); - unregister_blkdev(major_nr, "umem"); + unregister_blkdev(major_nr, DRIVER_NAME); while (i--) put_disk(mm_gendisk[i]); return -ENOMEM; @@ -1210,7 +1210,7 @@ static void __exit mm_cleanup(void) pci_unregister_driver(&mm_pci_driver); - unregister_blkdev(major_nr, "umem"); + unregister_blkdev(major_nr, DRIVER_NAME); } module_init(mm_init); -- cgit v0.10.2 From 34e1b83413d91999416443f31c276095f9937aa6 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 4 Oct 2007 08:52:38 +0200 Subject: Sysace: Minor coding convention fixup Put function call and return code test on separate lines. Signed-off-by: Grant Likely Signed-off-by: Jens Axboe diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 3ea172b..3847464 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -1091,7 +1091,8 @@ ace_alloc(struct device *dev, int id, unsigned long physaddr, ace->bus_width = bus_width; /* Call the setup code */ - if ((rc = ace_setup(ace)) != 0) + rc = ace_setup(ace); + if (rc) goto err_setup; dev_set_drvdata(dev, ace); @@ -1253,11 +1254,13 @@ static int __init ace_init(void) goto err_blk; } - if ((rc = ace_of_register()) != 0) + rc = ace_of_register(); + if (rc) goto err_of; pr_debug("xsysace: registering platform binding\n"); - if ((rc = platform_driver_register(&ace_platform_driver)) != 0) + rc = platform_driver_register(&ace_platform_driver); + if (rc) goto err_plat; pr_info("Xilinx SystemACE device driver, major=%i\n", ace_major); -- cgit v0.10.2 From b5515d86f2efd4dd3516c16c17c1a611a5800b19 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 4 Oct 2007 08:52:39 +0200 Subject: Sysace: sparse fixes Signed-off-by: Grant Likely Signed-off-by: Jens Axboe diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 3847464..5b73471 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -195,7 +195,7 @@ struct ace_device { /* Details of hardware device */ unsigned long physaddr; - void *baseaddr; + void __iomem *baseaddr; int irq; int bus_width; /* 0 := 8 bit; 1 := 16 bit */ struct ace_reg_ops *reg_ops; @@ -227,20 +227,20 @@ struct ace_reg_ops { /* 8 Bit bus width */ static u16 ace_in_8(struct ace_device *ace, int reg) { - void *r = ace->baseaddr + reg; + void __iomem *r = ace->baseaddr + reg; return in_8(r) | (in_8(r + 1) << 8); } static void ace_out_8(struct ace_device *ace, int reg, u16 val) { - void *r = ace->baseaddr + reg; + void __iomem *r = ace->baseaddr + reg; out_8(r, val); out_8(r + 1, val >> 8); } static void ace_datain_8(struct ace_device *ace) { - void *r = ace->baseaddr + 0x40; + void __iomem *r = ace->baseaddr + 0x40; u8 *dst = ace->data_ptr; int i = ACE_FIFO_SIZE; while (i--) @@ -250,7 +250,7 @@ static void ace_datain_8(struct ace_device *ace) static void ace_dataout_8(struct ace_device *ace) { - void *r = ace->baseaddr + 0x40; + void __iomem *r = ace->baseaddr + 0x40; u8 *src = ace->data_ptr; int i = ACE_FIFO_SIZE; while (i--) -- cgit v0.10.2 From d2bbf3da3759d04cd5836955cc59c8ae96092831 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 4 Oct 2007 08:52:40 +0200 Subject: Sysace: Don't enable IRQ until after interrupt handler is registered The previous patch to move the interrupt handler registration moved it below enabling interrupts which could be a problem if the device is on a shared interrupt line. This patch fixes the order. Signed-off-by: Grant Likely Signed-off-by: Jens Axboe diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 5b73471..9e7652d 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -1005,11 +1005,6 @@ static int __devinit ace_setup(struct ace_device *ace) ace_out(ace, ACE_CTRL, ACE_CTRL_FORCECFGMODE | ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ); - /* Enable interrupts */ - val = ace_in(ace, ACE_CTRL); - val |= ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ; - ace_out(ace, ACE_CTRL, val); - /* Now we can hook up the irq handler */ if (ace->irq != NO_IRQ) { rc = request_irq(ace->irq, ace_interrupt, 0, "systemace", ace); @@ -1020,6 +1015,11 @@ static int __devinit ace_setup(struct ace_device *ace) } } + /* Enable interrupts */ + val = ace_in(ace, ACE_CTRL); + val |= ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ; + ace_out(ace, ACE_CTRL, val); + /* Print the identification */ dev_info(ace->dev, "Xilinx SystemACE revision %i.%i.%i\n", (version >> 12) & 0xf, (version >> 8) & 0x0f, version & 0xff); -- cgit v0.10.2 From f58c4c0a17e500e767473598b3deafaa1d64051d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 9 Oct 2007 13:23:51 +0200 Subject: compat_ioctl: move common block ioctls to compat_blkdev_ioctl Make compat_blkdev_ioctl and blkdev_ioctl reflect the respective native versions. This is somewhat more efficient and makes it easier to keep the two in sync. Also get rid of the bogus handling for broken_blkgetsize and the duplicate entry for BLKRASET. Signed-off-by: Arnd Bergmann Signed-off-by: Jens Axboe diff --git a/block/Makefile b/block/Makefile index 959feeb..3cfe7ce 100644 --- a/block/Makefile +++ b/block/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o +obj-$(CONFIG_COMPAT) += compat_ioctl.o diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c new file mode 100644 index 0000000..d20fdb4 --- /dev/null +++ b/block/compat_ioctl.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int compat_put_ushort(unsigned long arg, unsigned short val) +{ + return put_user(val, (unsigned short __user *)compat_ptr(arg)); +} + +static int compat_put_int(unsigned long arg, int val) +{ + return put_user(val, (compat_int_t __user *)compat_ptr(arg)); +} + +static int compat_put_long(unsigned long arg, long val) +{ + return put_user(val, (compat_long_t __user *)compat_ptr(arg)); +} + +static int compat_put_ulong(unsigned long arg, compat_ulong_t val) +{ + return put_user(val, (compat_ulong_t __user *)compat_ptr(arg)); +} + +static int compat_put_u64(unsigned long arg, u64 val) +{ + return put_user(val, (compat_u64 __user *)compat_ptr(arg)); +} + +#define BLKBSZGET_32 _IOR(0x12, 112, int) +#define BLKBSZSET_32 _IOW(0x12, 113, int) +#define BLKGETSIZE64_32 _IOR(0x12, 114, int) + +static int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file, + struct block_device *bdev, + unsigned cmd, unsigned long arg) +{ + struct backing_dev_info *bdi; + + switch (cmd) { + case BLKRAGET: + case BLKFRAGET: + if (!arg) + return -EINVAL; + bdi = blk_get_backing_dev_info(bdev); + if (bdi == NULL) + return -ENOTTY; + return compat_put_long(arg, + (bdi->ra_pages * PAGE_CACHE_SIZE) / 512); + case BLKROGET: /* compatible */ + return compat_put_int(arg, bdev_read_only(bdev) != 0); + case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */ + return compat_put_int(arg, block_size(bdev)); + case BLKSSZGET: /* get block device hardware sector size */ + return compat_put_int(arg, bdev_hardsect_size(bdev)); + case BLKSECTGET: + return compat_put_ushort(arg, + bdev_get_queue(bdev)->max_sectors); + case BLKRASET: /* compatible, but no compat_ptr (!) */ + case BLKFRASET: + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + bdi = blk_get_backing_dev_info(bdev); + if (bdi == NULL) + return -ENOTTY; + bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; + return 0; + case BLKGETSIZE: + if ((bdev->bd_inode->i_size >> 9) > ~0UL) + return -EFBIG; + return compat_put_ulong(arg, bdev->bd_inode->i_size >> 9); + + case BLKGETSIZE64_32: + return compat_put_u64(arg, bdev->bd_inode->i_size); + } + return -ENOIOCTLCMD; +} + +/* Most of the generic ioctls are handled in the normal fallback path. + This assumes the blkdev's low level compat_ioctl always returns + ENOIOCTLCMD for unknown ioctls. */ +long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) +{ + int ret = -ENOIOCTLCMD; + struct inode *inode = file->f_mapping->host; + struct block_device *bdev = inode->i_bdev; + struct gendisk *disk = bdev->bd_disk; + + switch (cmd) { + case BLKFLSBUF: + case BLKROSET: + /* + * the ones below are implemented in blkdev_locked_ioctl, + * but we call blkdev_ioctl, which gets the lock for us + */ + case BLKRRPART: + return blkdev_ioctl(inode, file, cmd, + (unsigned long)compat_ptr(arg)); + case BLKBSZSET_32: + return blkdev_ioctl(inode, file, BLKBSZSET, + (unsigned long)compat_ptr(arg)); + } + + lock_kernel(); + ret = compat_blkdev_locked_ioctl(inode, file, bdev, cmd, arg); + /* FIXME: why do we assume -> compat_ioctl needs the BKL? */ + if (ret == -ENOIOCTLCMD && disk->fops->compat_ioctl) + ret = disk->fops->compat_ioctl(file, cmd, arg); + unlock_kernel(); + + return ret; +} diff --git a/block/ioctl.c b/block/ioctl.c index f7e3e8a..52d6385 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -217,6 +217,10 @@ int blkdev_driver_ioctl(struct inode *inode, struct file *file, } EXPORT_SYMBOL_GPL(blkdev_driver_ioctl); +/* + * always keep this in sync with compat_blkdev_ioctl() and + * compat_blkdev_locked_ioctl() + */ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, unsigned long arg) { @@ -284,21 +288,4 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, return blkdev_driver_ioctl(inode, file, disk, cmd, arg); } - -/* Most of the generic ioctls are handled in the normal fallback path. - This assumes the blkdev's low level compat_ioctl always returns - ENOIOCTLCMD for unknown ioctls. */ -long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) -{ - struct block_device *bdev = file->f_path.dentry->d_inode->i_bdev; - struct gendisk *disk = bdev->bd_disk; - int ret = -ENOIOCTLCMD; - if (disk->fops->compat_ioctl) { - lock_kernel(); - ret = disk->fops->compat_ioctl(file, cmd, arg); - unlock_kernel(); - } - return ret; -} - EXPORT_SYMBOL_GPL(blkdev_ioctl); diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 37310b0..6be1218 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -1537,12 +1537,6 @@ ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg) } #ifdef CONFIG_BLOCK -static int broken_blkgetsize(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - /* The mkswap binary hard codes it to Intel value :-((( */ - return w_long(fd, BLKGETSIZE, arg); -} - struct blkpg_ioctl_arg32 { compat_int_t op; compat_int_t flags; @@ -1578,29 +1572,6 @@ static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); } -#ifdef CONFIG_BLOCK -/* Fix sizeof(sizeof()) breakage */ -#define BLKBSZGET_32 _IOR(0x12,112,int) -#define BLKBSZSET_32 _IOW(0x12,113,int) -#define BLKGETSIZE64_32 _IOR(0x12,114,int) - -static int do_blkbszget(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - return sys_ioctl(fd, BLKBSZGET, (unsigned long)compat_ptr(arg)); -} - -static int do_blkbszset(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - return sys_ioctl(fd, BLKBSZSET, (unsigned long)compat_ptr(arg)); -} - -static int do_blkgetsize64(unsigned int fd, unsigned int cmd, - unsigned long arg) -{ - return sys_ioctl(fd, BLKGETSIZE64, (unsigned long)compat_ptr(arg)); -} -#endif - /* Bluetooth ioctls */ #define HCIUARTSETPROTO _IOW('U', 200, int) #define HCIUARTGETPROTO _IOR('U', 201, int) @@ -2546,19 +2517,11 @@ COMPATIBLE_IOCTL(FDFMTTRK) COMPATIBLE_IOCTL(FDRAWCMD) /* 0x12 */ #ifdef CONFIG_BLOCK -COMPATIBLE_IOCTL(BLKRASET) -COMPATIBLE_IOCTL(BLKROSET) -COMPATIBLE_IOCTL(BLKROGET) -COMPATIBLE_IOCTL(BLKRRPART) -COMPATIBLE_IOCTL(BLKFLSBUF) COMPATIBLE_IOCTL(BLKSECTSET) -COMPATIBLE_IOCTL(BLKSSZGET) COMPATIBLE_IOCTL(BLKTRACESTART) COMPATIBLE_IOCTL(BLKTRACESTOP) COMPATIBLE_IOCTL(BLKTRACESETUP) COMPATIBLE_IOCTL(BLKTRACETEARDOWN) -ULONG_IOCTL(BLKRASET) -ULONG_IOCTL(BLKFRASET) #endif /* RAID */ COMPATIBLE_IOCTL(RAID_VERSION) @@ -3337,11 +3300,6 @@ HANDLE_IOCTL(SIOCGSTAMPNS, do_siocgstampns) #endif #ifdef CONFIG_BLOCK HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo) -HANDLE_IOCTL(BLKRAGET, w_long) -HANDLE_IOCTL(BLKGETSIZE, w_long) -HANDLE_IOCTL(0x1260, broken_blkgetsize) -HANDLE_IOCTL(BLKFRAGET, w_long) -HANDLE_IOCTL(BLKSECTGET, w_long) HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans) HANDLE_IOCTL(HDIO_GET_MULTCOUNT, hdio_ioctl_trans) @@ -3415,9 +3373,6 @@ HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl) HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl) /* block stuff */ #ifdef CONFIG_BLOCK -HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget) -HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset) -HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64) /* Raw devices */ HANDLE_IOCTL(RAW_SETBIND, raw_ioctl) HANDLE_IOCTL(RAW_GETBIND, raw_ioctl) -- cgit v0.10.2 From 7199d4cdd8485f802df3e1bc131245c69009b9a4 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 9 Oct 2007 13:23:52 +0200 Subject: compat_ioctl: add compat_blkdev_driver_ioctl() Handle those blockdev ioctl calls that are compatible directly from the compat_blkdev_ioctl() function, instead of having to go through the compat_ioctl hash lookup. Signed-off-by: Arnd Bergmann Signed-off-by: Jens Axboe diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index d20fdb4..500cc9e 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -40,6 +40,122 @@ static int compat_put_u64(unsigned long arg, u64 val) #define BLKBSZSET_32 _IOW(0x12, 113, int) #define BLKGETSIZE64_32 _IOR(0x12, 114, int) +static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, + struct gendisk *disk, unsigned cmd, unsigned long arg) +{ + int ret; + + switch (arg) { + /* + * No handler required for the ones below, we just need to + * convert arg to a 64 bit pointer. + */ + case BLKSECTSET: + /* + * 0x03 -- HD/IDE ioctl's used by hdparm and friends. + * Some need translations, these do not. + */ + case HDIO_GET_IDENTITY: + case HDIO_DRIVE_TASK: + case HDIO_DRIVE_CMD: + case HDIO_SCAN_HWIF: + /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */ + case 0x330: + /* 0x02 -- Floppy ioctls */ + case FDMSGON: + case FDMSGOFF: + case FDSETEMSGTRESH: + case FDFLUSH: + case FDWERRORCLR: + case FDSETMAXERRS: + case FDGETMAXERRS: + case FDGETDRVTYP: + case FDEJECT: + case FDCLRPRM: + case FDFMTBEG: + case FDFMTEND: + case FDRESET: + case FDTWADDLE: + case FDFMTTRK: + case FDRAWCMD: + /* CDROM stuff */ + case CDROMPAUSE: + case CDROMRESUME: + case CDROMPLAYMSF: + case CDROMPLAYTRKIND: + case CDROMREADTOCHDR: + case CDROMREADTOCENTRY: + case CDROMSTOP: + case CDROMSTART: + case CDROMEJECT: + case CDROMVOLCTRL: + case CDROMSUBCHNL: + case CDROMMULTISESSION: + case CDROM_GET_MCN: + case CDROMRESET: + case CDROMVOLREAD: + case CDROMSEEK: + case CDROMPLAYBLK: + case CDROMCLOSETRAY: + case CDROM_DISC_STATUS: + case CDROM_CHANGER_NSLOTS: + case CDROM_GET_CAPABILITY: + /* Ignore cdrom.h about these next 5 ioctls, they absolutely do + * not take a struct cdrom_read, instead they take a struct cdrom_msf + * which is compatible. + */ + case CDROMREADMODE2: + case CDROMREADMODE1: + case CDROMREADRAW: + case CDROMREADCOOKED: + case CDROMREADALL: + /* DVD ioctls */ + case DVD_READ_STRUCT: + case DVD_WRITE_STRUCT: + case DVD_AUTH: + arg = (unsigned long)compat_ptr(arg); + /* These intepret arg as an unsigned long, not as a pointer, + * so we must not do compat_ptr() conversion. */ + case HDIO_SET_MULTCOUNT: + case HDIO_SET_UNMASKINTR: + case HDIO_SET_KEEPSETTINGS: + case HDIO_SET_32BIT: + case HDIO_SET_NOWERR: + case HDIO_SET_DMA: + case HDIO_SET_PIO_MODE: + case HDIO_SET_NICE: + case HDIO_SET_WCACHE: + case HDIO_SET_ACOUSTIC: + case HDIO_SET_BUSSTATE: + case HDIO_SET_ADDRESS: + case CDROMEJECT_SW: + case CDROM_SET_OPTIONS: + case CDROM_CLEAR_OPTIONS: + case CDROM_SELECT_SPEED: + case CDROM_SELECT_DISC: + case CDROM_MEDIA_CHANGED: + case CDROM_DRIVE_STATUS: + case CDROM_LOCKDOOR: + case CDROM_DEBUG: + break; + default: + /* unknown ioctl number */ + return -ENOIOCTLCMD; + } + + if (disk->fops->unlocked_ioctl) + return disk->fops->unlocked_ioctl(file, cmd, arg); + + if (disk->fops->ioctl) { + lock_kernel(); + ret = disk->fops->ioctl(inode, file, cmd, arg); + unlock_kernel(); + return ret; + } + + return -ENOTTY; +} + static int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file, struct block_device *bdev, unsigned cmd, unsigned long arg) @@ -117,5 +233,8 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) ret = disk->fops->compat_ioctl(file, cmd, arg); unlock_kernel(); - return ret; + if (ret != -ENOIOCTLCMD) + return ret; + + return compat_blkdev_driver_ioctl(inode, file, disk, cmd, arg); } diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 6be1218..16d681c 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -2477,47 +2477,8 @@ COMPATIBLE_IOCTL(FIONREAD) /* This is also TIOCINQ */ /* 0x00 */ COMPATIBLE_IOCTL(FIBMAP) COMPATIBLE_IOCTL(FIGETBSZ) -/* 0x03 -- HD/IDE ioctl's used by hdparm and friends. - * Some need translations, these do not. - */ -COMPATIBLE_IOCTL(HDIO_GET_IDENTITY) -COMPATIBLE_IOCTL(HDIO_DRIVE_TASK) -COMPATIBLE_IOCTL(HDIO_DRIVE_CMD) -ULONG_IOCTL(HDIO_SET_MULTCOUNT) -ULONG_IOCTL(HDIO_SET_UNMASKINTR) -ULONG_IOCTL(HDIO_SET_KEEPSETTINGS) -ULONG_IOCTL(HDIO_SET_32BIT) -ULONG_IOCTL(HDIO_SET_NOWERR) -ULONG_IOCTL(HDIO_SET_DMA) -ULONG_IOCTL(HDIO_SET_PIO_MODE) -ULONG_IOCTL(HDIO_SET_NICE) -ULONG_IOCTL(HDIO_SET_WCACHE) -ULONG_IOCTL(HDIO_SET_ACOUSTIC) -ULONG_IOCTL(HDIO_SET_BUSSTATE) -ULONG_IOCTL(HDIO_SET_ADDRESS) -COMPATIBLE_IOCTL(HDIO_SCAN_HWIF) -/* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */ -COMPATIBLE_IOCTL(0x330) -/* 0x02 -- Floppy ioctls */ -COMPATIBLE_IOCTL(FDMSGON) -COMPATIBLE_IOCTL(FDMSGOFF) -COMPATIBLE_IOCTL(FDSETEMSGTRESH) -COMPATIBLE_IOCTL(FDFLUSH) -COMPATIBLE_IOCTL(FDWERRORCLR) -COMPATIBLE_IOCTL(FDSETMAXERRS) -COMPATIBLE_IOCTL(FDGETMAXERRS) -COMPATIBLE_IOCTL(FDGETDRVTYP) -COMPATIBLE_IOCTL(FDEJECT) -COMPATIBLE_IOCTL(FDCLRPRM) -COMPATIBLE_IOCTL(FDFMTBEG) -COMPATIBLE_IOCTL(FDFMTEND) -COMPATIBLE_IOCTL(FDRESET) -COMPATIBLE_IOCTL(FDTWADDLE) -COMPATIBLE_IOCTL(FDFMTTRK) -COMPATIBLE_IOCTL(FDRAWCMD) /* 0x12 */ #ifdef CONFIG_BLOCK -COMPATIBLE_IOCTL(BLKSECTSET) COMPATIBLE_IOCTL(BLKTRACESTART) COMPATIBLE_IOCTL(BLKTRACESTOP) COMPATIBLE_IOCTL(BLKTRACESETUP) @@ -2770,50 +2731,6 @@ COMPATIBLE_IOCTL(PPGETMODE) COMPATIBLE_IOCTL(PPGETPHASE) COMPATIBLE_IOCTL(PPGETFLAGS) COMPATIBLE_IOCTL(PPSETFLAGS) -/* CDROM stuff */ -COMPATIBLE_IOCTL(CDROMPAUSE) -COMPATIBLE_IOCTL(CDROMRESUME) -COMPATIBLE_IOCTL(CDROMPLAYMSF) -COMPATIBLE_IOCTL(CDROMPLAYTRKIND) -COMPATIBLE_IOCTL(CDROMREADTOCHDR) -COMPATIBLE_IOCTL(CDROMREADTOCENTRY) -COMPATIBLE_IOCTL(CDROMSTOP) -COMPATIBLE_IOCTL(CDROMSTART) -COMPATIBLE_IOCTL(CDROMEJECT) -COMPATIBLE_IOCTL(CDROMVOLCTRL) -COMPATIBLE_IOCTL(CDROMSUBCHNL) -ULONG_IOCTL(CDROMEJECT_SW) -COMPATIBLE_IOCTL(CDROMMULTISESSION) -COMPATIBLE_IOCTL(CDROM_GET_MCN) -COMPATIBLE_IOCTL(CDROMRESET) -COMPATIBLE_IOCTL(CDROMVOLREAD) -COMPATIBLE_IOCTL(CDROMSEEK) -COMPATIBLE_IOCTL(CDROMPLAYBLK) -COMPATIBLE_IOCTL(CDROMCLOSETRAY) -ULONG_IOCTL(CDROM_SET_OPTIONS) -ULONG_IOCTL(CDROM_CLEAR_OPTIONS) -ULONG_IOCTL(CDROM_SELECT_SPEED) -ULONG_IOCTL(CDROM_SELECT_DISC) -ULONG_IOCTL(CDROM_MEDIA_CHANGED) -ULONG_IOCTL(CDROM_DRIVE_STATUS) -COMPATIBLE_IOCTL(CDROM_DISC_STATUS) -COMPATIBLE_IOCTL(CDROM_CHANGER_NSLOTS) -ULONG_IOCTL(CDROM_LOCKDOOR) -ULONG_IOCTL(CDROM_DEBUG) -COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY) -/* Ignore cdrom.h about these next 5 ioctls, they absolutely do - * not take a struct cdrom_read, instead they take a struct cdrom_msf - * which is compatible. - */ -COMPATIBLE_IOCTL(CDROMREADMODE2) -COMPATIBLE_IOCTL(CDROMREADMODE1) -COMPATIBLE_IOCTL(CDROMREADRAW) -COMPATIBLE_IOCTL(CDROMREADCOOKED) -COMPATIBLE_IOCTL(CDROMREADALL) -/* DVD ioctls */ -COMPATIBLE_IOCTL(DVD_READ_STRUCT) -COMPATIBLE_IOCTL(DVD_WRITE_STRUCT) -COMPATIBLE_IOCTL(DVD_AUTH) /* pktcdvd */ COMPATIBLE_IOCTL(PACKET_CTRL_CMD) /* Big A */ -- cgit v0.10.2 From 171044d449611c6e5040b37210ff6aba47f33ee4 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 9 Oct 2007 13:23:53 +0200 Subject: compat_ioctl: handle blk_trace ioctls blk_trace_setup is broken on x86_64 compat systems, this makes the code work correctly on all 64 bit architectures in compat mode. Signed-off-by: Arnd Bergmann Signed-off-by: Jens Axboe diff --git a/block/blktrace.c b/block/blktrace.c index 20fa034..775471e 100644 --- a/block/blktrace.c +++ b/block/blktrace.c @@ -312,33 +312,26 @@ static struct rchan_callbacks blk_relay_callbacks = { /* * Setup everything required to start tracing */ -static int blk_trace_setup(struct request_queue *q, struct block_device *bdev, - char __user *arg) +int do_blk_trace_setup(struct request_queue *q, struct block_device *bdev, + struct blk_user_trace_setup *buts) { - struct blk_user_trace_setup buts; struct blk_trace *old_bt, *bt = NULL; struct dentry *dir = NULL; char b[BDEVNAME_SIZE]; int ret, i; - if (copy_from_user(&buts, arg, sizeof(buts))) - return -EFAULT; - - if (!buts.buf_size || !buts.buf_nr) + if (!buts->buf_size || !buts->buf_nr) return -EINVAL; - strcpy(buts.name, bdevname(bdev, b)); + strcpy(buts->name, bdevname(bdev, b)); /* * some device names have larger paths - convert the slashes * to underscores for this to work as expected */ - for (i = 0; i < strlen(buts.name); i++) - if (buts.name[i] == '/') - buts.name[i] = '_'; - - if (copy_to_user(arg, &buts, sizeof(buts))) - return -EFAULT; + for (i = 0; i < strlen(buts->name); i++) + if (buts->name[i] == '/') + buts->name[i] = '_'; ret = -ENOMEM; bt = kzalloc(sizeof(*bt), GFP_KERNEL); @@ -350,7 +343,7 @@ static int blk_trace_setup(struct request_queue *q, struct block_device *bdev, goto err; ret = -ENOENT; - dir = blk_create_tree(buts.name); + dir = blk_create_tree(buts->name); if (!dir) goto err; @@ -363,20 +356,21 @@ static int blk_trace_setup(struct request_queue *q, struct block_device *bdev, if (!bt->dropped_file) goto err; - bt->rchan = relay_open("trace", dir, buts.buf_size, buts.buf_nr, &blk_relay_callbacks, bt); + bt->rchan = relay_open("trace", dir, buts->buf_size, + buts->buf_nr, &blk_relay_callbacks, bt); if (!bt->rchan) goto err; - bt->act_mask = buts.act_mask; + bt->act_mask = buts->act_mask; if (!bt->act_mask) bt->act_mask = (u16) -1; - bt->start_lba = buts.start_lba; - bt->end_lba = buts.end_lba; + bt->start_lba = buts->start_lba; + bt->end_lba = buts->end_lba; if (!bt->end_lba) bt->end_lba = -1ULL; - bt->pid = buts.pid; + bt->pid = buts->pid; bt->trace_state = Blktrace_setup; ret = -EBUSY; @@ -401,6 +395,26 @@ err: return ret; } +static int blk_trace_setup(struct request_queue *q, struct block_device *bdev, + char __user *arg) +{ + struct blk_user_trace_setup buts; + int ret; + + ret = copy_from_user(&buts, arg, sizeof(buts)); + if (ret) + return -EFAULT; + + ret = do_blk_trace_setup(q, bdev, &buts); + if (ret) + return ret; + + if (copy_to_user(arg, &buts, sizeof(buts))) + return -EFAULT; + + return 0; +} + static int blk_trace_startstop(struct request_queue *q, int start) { struct blk_trace *bt; diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 500cc9e..219b7e7 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -40,6 +40,53 @@ static int compat_put_u64(unsigned long arg, u64 val) #define BLKBSZSET_32 _IOW(0x12, 113, int) #define BLKGETSIZE64_32 _IOR(0x12, 114, int) +struct compat_blk_user_trace_setup { + char name[32]; + u16 act_mask; + u32 buf_size; + u32 buf_nr; + compat_u64 start_lba; + compat_u64 end_lba; + u32 pid; +}; +#define BLKTRACESETUP32 _IOWR(0x12, 115, struct compat_blk_user_trace_setup) + +static int compat_blk_trace_setup(struct block_device *bdev, char __user *arg) +{ + struct blk_user_trace_setup buts; + struct compat_blk_user_trace_setup cbuts; + struct request_queue *q; + int ret; + + q = bdev_get_queue(bdev); + if (!q) + return -ENXIO; + + if (copy_from_user(&cbuts, arg, sizeof(cbuts))) + return -EFAULT; + + buts = (struct blk_user_trace_setup) { + .act_mask = cbuts.act_mask, + .buf_size = cbuts.buf_size, + .buf_nr = cbuts.buf_nr, + .start_lba = cbuts.start_lba, + .end_lba = cbuts.end_lba, + .pid = cbuts.pid, + }; + memcpy(&buts.name, &cbuts.name, 32); + + mutex_lock(&bdev->bd_mutex); + ret = do_blk_trace_setup(q, bdev, &buts); + mutex_unlock(&bdev->bd_mutex); + if (ret) + return ret; + + if (copy_to_user(arg, &buts.name, 32)) + return -EFAULT; + + return 0; +} + static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, struct gendisk *disk, unsigned cmd, unsigned long arg) { @@ -197,6 +244,13 @@ static int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file, case BLKGETSIZE64_32: return compat_put_u64(arg, bdev->bd_inode->i_size); + + case BLKTRACESETUP32: + return compat_blk_trace_setup(bdev, compat_ptr(arg)); + case BLKTRACESTART: /* compatible */ + case BLKTRACESTOP: /* compatible */ + case BLKTRACETEARDOWN: /* compatible */ + return blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); } return -ENOIOCTLCMD; } diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 16d681c..7106560 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -62,7 +62,6 @@ #include #include #include -#include #include #include @@ -2477,13 +2476,6 @@ COMPATIBLE_IOCTL(FIONREAD) /* This is also TIOCINQ */ /* 0x00 */ COMPATIBLE_IOCTL(FIBMAP) COMPATIBLE_IOCTL(FIGETBSZ) -/* 0x12 */ -#ifdef CONFIG_BLOCK -COMPATIBLE_IOCTL(BLKTRACESTART) -COMPATIBLE_IOCTL(BLKTRACESTOP) -COMPATIBLE_IOCTL(BLKTRACESETUP) -COMPATIBLE_IOCTL(BLKTRACETEARDOWN) -#endif /* RAID */ COMPATIBLE_IOCTL(RAID_VERSION) COMPATIBLE_IOCTL(GET_ARRAY_INFO) diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index 7b5d56b..972093b 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h @@ -142,10 +142,14 @@ struct blk_user_trace_setup { u32 pid; }; +#ifdef __KERNEL__ #if defined(CONFIG_BLK_DEV_IO_TRACE) extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *); extern void blk_trace_shutdown(struct request_queue *); extern void __blk_add_trace(struct blk_trace *, sector_t, int, int, u32, int, int, void *); +extern int do_blk_trace_setup(struct request_queue *q, + struct block_device *bdev, struct blk_user_trace_setup *buts); + /** * blk_add_trace_rq - Add a trace for a request oriented action @@ -286,6 +290,7 @@ static inline void blk_add_trace_remap(struct request_queue *q, struct bio *bio, #define blk_add_trace_generic(q, rq, rw, what) do { } while (0) #define blk_add_trace_pdu_int(q, what, bio, pdu) do { } while (0) #define blk_add_trace_remap(q, bio, dev, f, t) do {} while (0) +#define do_blk_trace_setup(q, bdev, buts) do {} while (0) #endif /* CONFIG_BLK_DEV_IO_TRACE */ - +#endif /* __KERNEL__ */ #endif -- cgit v0.10.2 From 9617db085c119879cd371e3212806a15596e121a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 9 Oct 2007 13:23:55 +0200 Subject: compat_ioctl: move hdio calls to block/compat_ioctl.c These are common to multiple block drivers, so they should be handled by the block layer. Signed-off-by: Arnd Bergmann Signed-off-by: Jens Axboe diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 219b7e7..5c6dafa 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -36,6 +36,62 @@ static int compat_put_u64(unsigned long arg, u64 val) return put_user(val, (compat_u64 __user *)compat_ptr(arg)); } +struct compat_hd_geometry { + unsigned char heads; + unsigned char sectors; + unsigned short cylinders; + u32 start; +}; + +static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev, + struct compat_hd_geometry __user *ugeo) +{ + struct hd_geometry geo; + int ret; + + if (!ugeo) + return -EINVAL; + if (!disk->fops->getgeo) + return -ENOTTY; + + /* + * We need to set the startsect first, the driver may + * want to override it. + */ + geo.start = get_start_sect(bdev); + ret = disk->fops->getgeo(bdev, &geo); + if (ret) + return ret; + + ret = copy_to_user(ugeo, &geo, 4); + ret |= __put_user(geo.start, &ugeo->start); + if (ret) + ret = -EFAULT; + + return ret; +} + +static int compat_hdio_ioctl(struct inode *inode, struct file *file, + struct gendisk *disk, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + unsigned long kval; + unsigned int __user *uvp; + int error; + + set_fs(KERNEL_DS); + error = blkdev_driver_ioctl(inode, file, disk, + cmd, (unsigned long)(&kval)); + set_fs(old_fs); + + if (error == 0) { + uvp = compat_ptr(arg); + if (put_user(kval, uvp)) + error = -EFAULT; + } + return error; +} + #define BLKBSZGET_32 _IOR(0x12, 112, int) #define BLKBSZSET_32 _IOW(0x12, 113, int) #define BLKGETSIZE64_32 _IOR(0x12, 114, int) @@ -93,6 +149,18 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, int ret; switch (arg) { + case HDIO_GET_UNMASKINTR: + case HDIO_GET_MULTCOUNT: + case HDIO_GET_KEEPSETTINGS: + case HDIO_GET_32BIT: + case HDIO_GET_NOWERR: + case HDIO_GET_DMA: + case HDIO_GET_NICE: + case HDIO_GET_WCACHE: + case HDIO_GET_ACOUSTIC: + case HDIO_GET_ADDRESS: + case HDIO_GET_BUSSTATE: + return compat_hdio_ioctl(inode, file, disk, cmd, arg); /* * No handler required for the ones below, we just need to * convert arg to a 64 bit pointer. @@ -266,6 +334,8 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) struct gendisk *disk = bdev->bd_disk; switch (cmd) { + case HDIO_GETGEO: + return compat_hdio_getgeo(disk, bdev, compat_ptr(arg)); case BLKFLSBUF: case BLKROSET: /* diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 7106560..e6a9471 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -667,53 +666,6 @@ out: #endif #ifdef CONFIG_BLOCK -struct hd_geometry32 { - unsigned char heads; - unsigned char sectors; - unsigned short cylinders; - u32 start; -}; - -static int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct hd_geometry geo; - struct hd_geometry32 __user *ugeo; - int err; - - set_fs (KERNEL_DS); - err = sys_ioctl(fd, HDIO_GETGEO, (unsigned long)&geo); - set_fs (old_fs); - ugeo = compat_ptr(arg); - if (!err) { - err = copy_to_user (ugeo, &geo, 4); - err |= __put_user (geo.start, &ugeo->start); - if (err) - err = -EFAULT; - } - return err; -} - -static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - unsigned long kval; - unsigned int __user *uvp; - int error; - - set_fs(KERNEL_DS); - error = sys_ioctl(fd, cmd, (long)&kval); - set_fs(old_fs); - - if(error == 0) { - uvp = compat_ptr(arg); - if(put_user(kval, uvp)) - error = -EFAULT; - } - return error; -} - - typedef struct sg_io_hdr32 { compat_int_t interface_id; /* [i] 'S' for SCSI generic (required) */ compat_int_t dxfer_direction; /* [i] data transfer direction */ @@ -3208,19 +3160,7 @@ HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp) HANDLE_IOCTL(SIOCGSTAMPNS, do_siocgstampns) #endif #ifdef CONFIG_BLOCK -HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo) HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_MULTCOUNT, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_32BIT, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_NOWERR, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_DMA, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_NICE, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_WCACHE, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_ACOUSTIC, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_ADDRESS, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_BUSSTATE, hdio_ioctl_trans) HANDLE_IOCTL(FDSETPRM32, fd_ioctl_trans) HANDLE_IOCTL(FDDEFPRM32, fd_ioctl_trans) HANDLE_IOCTL(FDGETPRM32, fd_ioctl_trans) -- cgit v0.10.2 From 18cf7f8723d913ce02bea43e468bebdd07bc880c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 9 Oct 2007 13:23:56 +0200 Subject: compat_ioctl: move BLKPG handling to block/compat_ioctl.c BLKPG is common to all block devices, so it should be handled by common code. Signed-off-by: Arnd Bergmann Signed-off-by: Jens Axboe diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 5c6dafa..44807d3 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -92,6 +92,35 @@ static int compat_hdio_ioctl(struct inode *inode, struct file *file, return error; } +struct compat_blkpg_ioctl_arg { + compat_int_t op; + compat_int_t flags; + compat_int_t datalen; + compat_caddr_t data; +}; + +static int compat_blkpg_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32) +{ + struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a)); + compat_caddr_t udata; + compat_int_t n; + int err; + + err = get_user(n, &ua32->op); + err |= put_user(n, &a->op); + err |= get_user(n, &ua32->flags); + err |= put_user(n, &a->flags); + err |= get_user(n, &ua32->datalen); + err |= put_user(n, &a->datalen); + err |= get_user(udata, &ua32->data); + err |= put_user(compat_ptr(udata), &a->data); + if (err) + return err; + + return blkdev_ioctl(inode, file, cmd, (unsigned long)a); +} + #define BLKBSZGET_32 _IOR(0x12, 112, int) #define BLKBSZSET_32 _IOW(0x12, 113, int) #define BLKGETSIZE64_32 _IOR(0x12, 114, int) @@ -348,6 +377,8 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) case BLKBSZSET_32: return blkdev_ioctl(inode, file, BLKBSZSET, (unsigned long)compat_ptr(arg)); + case BLKPG: + return compat_blkpg_ioctl(inode, file, cmd, compat_ptr(arg)); } lock_kernel(); diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index e6a9471..3baa90d 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include @@ -1487,37 +1486,6 @@ ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg) return -EINVAL; } -#ifdef CONFIG_BLOCK -struct blkpg_ioctl_arg32 { - compat_int_t op; - compat_int_t flags; - compat_int_t datalen; - compat_caddr_t data; -}; - -static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct blkpg_ioctl_arg32 __user *ua32 = compat_ptr(arg); - struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a)); - compat_caddr_t udata; - compat_int_t n; - int err; - - err = get_user(n, &ua32->op); - err |= put_user(n, &a->op); - err |= get_user(n, &ua32->flags); - err |= put_user(n, &a->flags); - err |= get_user(n, &ua32->datalen); - err |= put_user(n, &a->datalen); - err |= get_user(udata, &ua32->data); - err |= put_user(compat_ptr(udata), &a->data); - if (err) - return err; - - return sys_ioctl(fd, cmd, (unsigned long)a); -} -#endif - static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) { return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); @@ -3160,7 +3128,6 @@ HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp) HANDLE_IOCTL(SIOCGSTAMPNS, do_siocgstampns) #endif #ifdef CONFIG_BLOCK -HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) HANDLE_IOCTL(FDSETPRM32, fd_ioctl_trans) HANDLE_IOCTL(FDDEFPRM32, fd_ioctl_trans) HANDLE_IOCTL(FDGETPRM32, fd_ioctl_trans) -- cgit v0.10.2 From b3087cc4f31a66c8c7b63419e913ed9d34145f10 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 9 Oct 2007 13:23:56 +0200 Subject: compat_ioctl: move cdrom handlers to block/compat_ioctl.c These are shared by all cd-rom drivers and should have common handlers. Do slight cosmetic cleanups in the process. Signed-off-by: Arnd Bergmann Signed-off-by: Jens Axboe diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 44807d3..92b3e8d 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -92,6 +92,84 @@ static int compat_hdio_ioctl(struct inode *inode, struct file *file, return error; } +struct compat_cdrom_read_audio { + union cdrom_addr addr; + u8 addr_format; + compat_int_t nframes; + compat_caddr_t buf; +}; + +struct compat_cdrom_generic_command { + unsigned char cmd[CDROM_PACKET_SIZE]; + compat_caddr_t buffer; + compat_uint_t buflen; + compat_int_t stat; + compat_caddr_t sense; + unsigned char data_direction; + compat_int_t quiet; + compat_int_t timeout; + compat_caddr_t reserved[1]; +}; + +static int compat_cdrom_read_audio(struct inode *inode, struct file *file, + struct gendisk *disk, unsigned int cmd, unsigned long arg) +{ + struct cdrom_read_audio __user *cdread_audio; + struct compat_cdrom_read_audio __user *cdread_audio32; + __u32 data; + void __user *datap; + + cdread_audio = compat_alloc_user_space(sizeof(*cdread_audio)); + cdread_audio32 = compat_ptr(arg); + + if (copy_in_user(&cdread_audio->addr, + &cdread_audio32->addr, + (sizeof(*cdread_audio32) - + sizeof(compat_caddr_t)))) + return -EFAULT; + + if (get_user(data, &cdread_audio32->buf)) + return -EFAULT; + datap = compat_ptr(data); + if (put_user(datap, &cdread_audio->buf)) + return -EFAULT; + + return blkdev_driver_ioctl(inode, file, disk, cmd, + (unsigned long)cdread_audio); +} + +static int compat_cdrom_generic_command(struct inode *inode, struct file *file, + struct gendisk *disk, unsigned int cmd, unsigned long arg) +{ + struct cdrom_generic_command __user *cgc; + struct compat_cdrom_generic_command __user *cgc32; + u32 data; + unsigned char dir; + int itmp; + + cgc = compat_alloc_user_space(sizeof(*cgc)); + cgc32 = compat_ptr(arg); + + if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) || + get_user(data, &cgc32->buffer) || + put_user(compat_ptr(data), &cgc->buffer) || + copy_in_user(&cgc->buflen, &cgc32->buflen, + (sizeof(unsigned int) + sizeof(int))) || + get_user(data, &cgc32->sense) || + put_user(compat_ptr(data), &cgc->sense) || + get_user(dir, &cgc32->data_direction) || + put_user(dir, &cgc->data_direction) || + get_user(itmp, &cgc32->quiet) || + put_user(itmp, &cgc->quiet) || + get_user(itmp, &cgc32->timeout) || + put_user(itmp, &cgc->timeout) || + get_user(data, &cgc32->reserved[0]) || + put_user(compat_ptr(data), &cgc->reserved[0])) + return -EFAULT; + + return blkdev_driver_ioctl(inode, file, disk, cmd, (unsigned long)cgc); +} + struct compat_blkpg_ioctl_arg { compat_int_t op; compat_int_t flags; @@ -190,6 +268,11 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, case HDIO_GET_ADDRESS: case HDIO_GET_BUSSTATE: return compat_hdio_ioctl(inode, file, disk, cmd, arg); + case CDROMREADAUDIO: + return compat_cdrom_read_audio(inode, file, disk, cmd, arg); + case CDROM_SEND_PACKET: + return compat_cdrom_generic_command(inode, file, disk, cmd, arg); + /* * No handler required for the ones below, we just need to * convert arg to a 64 bit pointer. diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 3baa90d..24c7435 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -1039,108 +1038,6 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) return err ? -EFAULT: 0; } -struct cdrom_read_audio32 { - union cdrom_addr addr; - u8 addr_format; - compat_int_t nframes; - compat_caddr_t buf; -}; - -struct cdrom_generic_command32 { - unsigned char cmd[CDROM_PACKET_SIZE]; - compat_caddr_t buffer; - compat_uint_t buflen; - compat_int_t stat; - compat_caddr_t sense; - unsigned char data_direction; - compat_int_t quiet; - compat_int_t timeout; - compat_caddr_t reserved[1]; -}; - -static int cdrom_do_read_audio(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct cdrom_read_audio __user *cdread_audio; - struct cdrom_read_audio32 __user *cdread_audio32; - __u32 data; - void __user *datap; - - cdread_audio = compat_alloc_user_space(sizeof(*cdread_audio)); - cdread_audio32 = compat_ptr(arg); - - if (copy_in_user(&cdread_audio->addr, - &cdread_audio32->addr, - (sizeof(*cdread_audio32) - - sizeof(compat_caddr_t)))) - return -EFAULT; - - if (get_user(data, &cdread_audio32->buf)) - return -EFAULT; - datap = compat_ptr(data); - if (put_user(datap, &cdread_audio->buf)) - return -EFAULT; - - return sys_ioctl(fd, cmd, (unsigned long) cdread_audio); -} - -static int cdrom_do_generic_command(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct cdrom_generic_command __user *cgc; - struct cdrom_generic_command32 __user *cgc32; - u32 data; - unsigned char dir; - int itmp; - - cgc = compat_alloc_user_space(sizeof(*cgc)); - cgc32 = compat_ptr(arg); - - if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) || - get_user(data, &cgc32->buffer) || - put_user(compat_ptr(data), &cgc->buffer) || - copy_in_user(&cgc->buflen, &cgc32->buflen, - (sizeof(unsigned int) + sizeof(int))) || - get_user(data, &cgc32->sense) || - put_user(compat_ptr(data), &cgc->sense) || - get_user(dir, &cgc32->data_direction) || - put_user(dir, &cgc->data_direction) || - get_user(itmp, &cgc32->quiet) || - put_user(itmp, &cgc->quiet) || - get_user(itmp, &cgc32->timeout) || - put_user(itmp, &cgc->timeout) || - get_user(data, &cgc32->reserved[0]) || - put_user(compat_ptr(data), &cgc->reserved[0])) - return -EFAULT; - - return sys_ioctl(fd, cmd, (unsigned long) cgc); -} - -static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - int err; - - switch(cmd) { - case CDROMREADAUDIO: - err = cdrom_do_read_audio(fd, cmd, arg); - break; - - case CDROM_SEND_PACKET: - err = cdrom_do_generic_command(fd, cmd, arg); - break; - - default: - do { - static int count; - if (++count <= 20) - printk("cdrom_ioctl: Unknown cmd fd(%d) " - "cmd(%08x) arg(%08x)\n", - (int)fd, (unsigned int)cmd, (unsigned int)arg); - } while(0); - err = -EINVAL; - break; - }; - - return err; -} #endif /* CONFIG_BLOCK */ #ifdef CONFIG_VT @@ -3147,8 +3044,6 @@ HANDLE_IOCTL(PPPIOCSACTIVE32, ppp_sock_fprog_ioctl_trans) #ifdef CONFIG_BLOCK HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans) HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans) -HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans) -HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans) #endif #define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int) HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout) -- cgit v0.10.2 From 1ca91cd0336b05b91c51b403c9ed9d297813533f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 9 Oct 2007 13:23:57 +0200 Subject: compat_ioctl: move floppy handlers to block/compat_ioctl.c The floppy ioctls are used by multiple drivers, so they should be handled in a shared location. Also, add minor cleanups. Signed-off-by: Arnd Bergmann Signed-off-by: Jens Axboe diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 92b3e8d..f84093b 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -203,6 +203,332 @@ static int compat_blkpg_ioctl(struct inode *inode, struct file *file, #define BLKBSZSET_32 _IOW(0x12, 113, int) #define BLKGETSIZE64_32 _IOR(0x12, 114, int) +struct compat_floppy_struct { + compat_uint_t size; + compat_uint_t sect; + compat_uint_t head; + compat_uint_t track; + compat_uint_t stretch; + unsigned char gap; + unsigned char rate; + unsigned char spec1; + unsigned char fmt_gap; + const compat_caddr_t name; +}; + +struct compat_floppy_drive_params { + char cmos; + compat_ulong_t max_dtr; + compat_ulong_t hlt; + compat_ulong_t hut; + compat_ulong_t srt; + compat_ulong_t spinup; + compat_ulong_t spindown; + unsigned char spindown_offset; + unsigned char select_delay; + unsigned char rps; + unsigned char tracks; + compat_ulong_t timeout; + unsigned char interleave_sect; + struct floppy_max_errors max_errors; + char flags; + char read_track; + short autodetect[8]; + compat_int_t checkfreq; + compat_int_t native_format; +}; + +struct compat_floppy_drive_struct { + signed char flags; + compat_ulong_t spinup_date; + compat_ulong_t select_date; + compat_ulong_t first_read_date; + short probed_format; + short track; + short maxblock; + short maxtrack; + compat_int_t generation; + compat_int_t keep_data; + compat_int_t fd_ref; + compat_int_t fd_device; + compat_int_t last_checked; + compat_caddr_t dmabuf; + compat_int_t bufblocks; +}; + +struct compat_floppy_fdc_state { + compat_int_t spec1; + compat_int_t spec2; + compat_int_t dtr; + unsigned char version; + unsigned char dor; + compat_ulong_t address; + unsigned int rawcmd:2; + unsigned int reset:1; + unsigned int need_configure:1; + unsigned int perp_mode:2; + unsigned int has_fifo:1; + unsigned int driver_version; + unsigned char track[4]; +}; + +struct compat_floppy_write_errors { + unsigned int write_errors; + compat_ulong_t first_error_sector; + compat_int_t first_error_generation; + compat_ulong_t last_error_sector; + compat_int_t last_error_generation; + compat_uint_t badness; +}; + +#define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct) +#define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct) +#define FDGETPRM32 _IOR(2, 0x04, struct compat_floppy_struct) +#define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params) +#define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params) +#define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct) +#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct) +#define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state) +#define FDWERRORGET32 _IOR(2, 0x17, struct compat_floppy_write_errors) + +static struct { + unsigned int cmd32; + unsigned int cmd; +} fd_ioctl_trans_table[] = { + { FDSETPRM32, FDSETPRM }, + { FDDEFPRM32, FDDEFPRM }, + { FDGETPRM32, FDGETPRM }, + { FDSETDRVPRM32, FDSETDRVPRM }, + { FDGETDRVPRM32, FDGETDRVPRM }, + { FDGETDRVSTAT32, FDGETDRVSTAT }, + { FDPOLLDRVSTAT32, FDPOLLDRVSTAT }, + { FDGETFDCSTAT32, FDGETFDCSTAT }, + { FDWERRORGET32, FDWERRORGET } +}; + +#define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table) + +static int compat_fd_ioctl(struct inode *inode, struct file *file, + struct gendisk *disk, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + void *karg = NULL; + unsigned int kcmd = 0; + int i, err; + + for (i = 0; i < NR_FD_IOCTL_TRANS; i++) + if (cmd == fd_ioctl_trans_table[i].cmd32) { + kcmd = fd_ioctl_trans_table[i].cmd; + break; + } + if (!kcmd) + return -EINVAL; + + switch (cmd) { + case FDSETPRM32: + case FDDEFPRM32: + case FDGETPRM32: + { + compat_uptr_t name; + struct compat_floppy_struct __user *uf; + struct floppy_struct *f; + + uf = compat_ptr(arg); + f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL); + if (!karg) + return -ENOMEM; + if (cmd == FDGETPRM32) + break; + err = __get_user(f->size, &uf->size); + err |= __get_user(f->sect, &uf->sect); + err |= __get_user(f->head, &uf->head); + err |= __get_user(f->track, &uf->track); + err |= __get_user(f->stretch, &uf->stretch); + err |= __get_user(f->gap, &uf->gap); + err |= __get_user(f->rate, &uf->rate); + err |= __get_user(f->spec1, &uf->spec1); + err |= __get_user(f->fmt_gap, &uf->fmt_gap); + err |= __get_user(name, &uf->name); + f->name = compat_ptr(name); + if (err) { + err = -EFAULT; + goto out; + } + break; + } + case FDSETDRVPRM32: + case FDGETDRVPRM32: + { + struct compat_floppy_drive_params __user *uf; + struct floppy_drive_params *f; + + uf = compat_ptr(arg); + f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL); + if (!karg) + return -ENOMEM; + if (cmd == FDGETDRVPRM32) + break; + err = __get_user(f->cmos, &uf->cmos); + err |= __get_user(f->max_dtr, &uf->max_dtr); + err |= __get_user(f->hlt, &uf->hlt); + err |= __get_user(f->hut, &uf->hut); + err |= __get_user(f->srt, &uf->srt); + err |= __get_user(f->spinup, &uf->spinup); + err |= __get_user(f->spindown, &uf->spindown); + err |= __get_user(f->spindown_offset, &uf->spindown_offset); + err |= __get_user(f->select_delay, &uf->select_delay); + err |= __get_user(f->rps, &uf->rps); + err |= __get_user(f->tracks, &uf->tracks); + err |= __get_user(f->timeout, &uf->timeout); + err |= __get_user(f->interleave_sect, &uf->interleave_sect); + err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors)); + err |= __get_user(f->flags, &uf->flags); + err |= __get_user(f->read_track, &uf->read_track); + err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect)); + err |= __get_user(f->checkfreq, &uf->checkfreq); + err |= __get_user(f->native_format, &uf->native_format); + if (err) { + err = -EFAULT; + goto out; + } + break; + } + case FDGETDRVSTAT32: + case FDPOLLDRVSTAT32: + karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL); + if (!karg) + return -ENOMEM; + break; + case FDGETFDCSTAT32: + karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL); + if (!karg) + return -ENOMEM; + break; + case FDWERRORGET32: + karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL); + if (!karg) + return -ENOMEM; + break; + default: + return -EINVAL; + } + set_fs(KERNEL_DS); + err = blkdev_driver_ioctl(inode, file, disk, kcmd, (unsigned long)karg); + set_fs(old_fs); + if (err) + goto out; + switch (cmd) { + case FDGETPRM32: + { + struct floppy_struct *f = karg; + struct compat_floppy_struct __user *uf = compat_ptr(arg); + + err = __put_user(f->size, &uf->size); + err |= __put_user(f->sect, &uf->sect); + err |= __put_user(f->head, &uf->head); + err |= __put_user(f->track, &uf->track); + err |= __put_user(f->stretch, &uf->stretch); + err |= __put_user(f->gap, &uf->gap); + err |= __put_user(f->rate, &uf->rate); + err |= __put_user(f->spec1, &uf->spec1); + err |= __put_user(f->fmt_gap, &uf->fmt_gap); + err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name); + break; + } + case FDGETDRVPRM32: + { + struct compat_floppy_drive_params __user *uf; + struct floppy_drive_params *f = karg; + + uf = compat_ptr(arg); + err = __put_user(f->cmos, &uf->cmos); + err |= __put_user(f->max_dtr, &uf->max_dtr); + err |= __put_user(f->hlt, &uf->hlt); + err |= __put_user(f->hut, &uf->hut); + err |= __put_user(f->srt, &uf->srt); + err |= __put_user(f->spinup, &uf->spinup); + err |= __put_user(f->spindown, &uf->spindown); + err |= __put_user(f->spindown_offset, &uf->spindown_offset); + err |= __put_user(f->select_delay, &uf->select_delay); + err |= __put_user(f->rps, &uf->rps); + err |= __put_user(f->tracks, &uf->tracks); + err |= __put_user(f->timeout, &uf->timeout); + err |= __put_user(f->interleave_sect, &uf->interleave_sect); + err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors)); + err |= __put_user(f->flags, &uf->flags); + err |= __put_user(f->read_track, &uf->read_track); + err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect)); + err |= __put_user(f->checkfreq, &uf->checkfreq); + err |= __put_user(f->native_format, &uf->native_format); + break; + } + case FDGETDRVSTAT32: + case FDPOLLDRVSTAT32: + { + struct compat_floppy_drive_struct __user *uf; + struct floppy_drive_struct *f = karg; + + uf = compat_ptr(arg); + err = __put_user(f->flags, &uf->flags); + err |= __put_user(f->spinup_date, &uf->spinup_date); + err |= __put_user(f->select_date, &uf->select_date); + err |= __put_user(f->first_read_date, &uf->first_read_date); + err |= __put_user(f->probed_format, &uf->probed_format); + err |= __put_user(f->track, &uf->track); + err |= __put_user(f->maxblock, &uf->maxblock); + err |= __put_user(f->maxtrack, &uf->maxtrack); + err |= __put_user(f->generation, &uf->generation); + err |= __put_user(f->keep_data, &uf->keep_data); + err |= __put_user(f->fd_ref, &uf->fd_ref); + err |= __put_user(f->fd_device, &uf->fd_device); + err |= __put_user(f->last_checked, &uf->last_checked); + err |= __put_user((u64)f->dmabuf, &uf->dmabuf); + err |= __put_user((u64)f->bufblocks, &uf->bufblocks); + break; + } + case FDGETFDCSTAT32: + { + struct compat_floppy_fdc_state __user *uf; + struct floppy_fdc_state *f = karg; + + uf = compat_ptr(arg); + err = __put_user(f->spec1, &uf->spec1); + err |= __put_user(f->spec2, &uf->spec2); + err |= __put_user(f->dtr, &uf->dtr); + err |= __put_user(f->version, &uf->version); + err |= __put_user(f->dor, &uf->dor); + err |= __put_user(f->address, &uf->address); + err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address), + (char *)&f->address + sizeof(f->address), sizeof(int)); + err |= __put_user(f->driver_version, &uf->driver_version); + err |= __copy_to_user(uf->track, f->track, sizeof(f->track)); + break; + } + case FDWERRORGET32: + { + struct compat_floppy_write_errors __user *uf; + struct floppy_write_errors *f = karg; + + uf = compat_ptr(arg); + err = __put_user(f->write_errors, &uf->write_errors); + err |= __put_user(f->first_error_sector, &uf->first_error_sector); + err |= __put_user(f->first_error_generation, &uf->first_error_generation); + err |= __put_user(f->last_error_sector, &uf->last_error_sector); + err |= __put_user(f->last_error_generation, &uf->last_error_generation); + err |= __put_user(f->badness, &uf->badness); + break; + } + default: + break; + } + if (err) + err = -EFAULT; + +out: + kfree(karg); + return err; +} + struct compat_blk_user_trace_setup { char name[32]; u16 act_mask; @@ -268,6 +594,16 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, case HDIO_GET_ADDRESS: case HDIO_GET_BUSSTATE: return compat_hdio_ioctl(inode, file, disk, cmd, arg); + case FDSETPRM32: + case FDDEFPRM32: + case FDGETPRM32: + case FDSETDRVPRM32: + case FDGETDRVPRM32: + case FDGETDRVSTAT32: + case FDPOLLDRVSTAT32: + case FDGETFDCSTAT32: + case FDWERRORGET32: + return compat_fd_ioctl(inode, file, disk, cmd, arg); case CDROMREADAUDIO: return compat_cdrom_read_audio(inode, file, disk, cmd, arg); case CDROM_SEND_PACKET: diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 24c7435..b9e3357 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -1407,333 +1406,6 @@ static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) #define HIDPGETCONNLIST _IOR('H', 210, int) #define HIDPGETCONNINFO _IOR('H', 211, int) -#ifdef CONFIG_BLOCK -struct floppy_struct32 { - compat_uint_t size; - compat_uint_t sect; - compat_uint_t head; - compat_uint_t track; - compat_uint_t stretch; - unsigned char gap; - unsigned char rate; - unsigned char spec1; - unsigned char fmt_gap; - const compat_caddr_t name; -}; - -struct floppy_drive_params32 { - char cmos; - compat_ulong_t max_dtr; - compat_ulong_t hlt; - compat_ulong_t hut; - compat_ulong_t srt; - compat_ulong_t spinup; - compat_ulong_t spindown; - unsigned char spindown_offset; - unsigned char select_delay; - unsigned char rps; - unsigned char tracks; - compat_ulong_t timeout; - unsigned char interleave_sect; - struct floppy_max_errors max_errors; - char flags; - char read_track; - short autodetect[8]; - compat_int_t checkfreq; - compat_int_t native_format; -}; - -struct floppy_drive_struct32 { - signed char flags; - compat_ulong_t spinup_date; - compat_ulong_t select_date; - compat_ulong_t first_read_date; - short probed_format; - short track; - short maxblock; - short maxtrack; - compat_int_t generation; - compat_int_t keep_data; - compat_int_t fd_ref; - compat_int_t fd_device; - compat_int_t last_checked; - compat_caddr_t dmabuf; - compat_int_t bufblocks; -}; - -struct floppy_fdc_state32 { - compat_int_t spec1; - compat_int_t spec2; - compat_int_t dtr; - unsigned char version; - unsigned char dor; - compat_ulong_t address; - unsigned int rawcmd:2; - unsigned int reset:1; - unsigned int need_configure:1; - unsigned int perp_mode:2; - unsigned int has_fifo:1; - unsigned int driver_version; - unsigned char track[4]; -}; - -struct floppy_write_errors32 { - unsigned int write_errors; - compat_ulong_t first_error_sector; - compat_int_t first_error_generation; - compat_ulong_t last_error_sector; - compat_int_t last_error_generation; - compat_uint_t badness; -}; - -#define FDSETPRM32 _IOW(2, 0x42, struct floppy_struct32) -#define FDDEFPRM32 _IOW(2, 0x43, struct floppy_struct32) -#define FDGETPRM32 _IOR(2, 0x04, struct floppy_struct32) -#define FDSETDRVPRM32 _IOW(2, 0x90, struct floppy_drive_params32) -#define FDGETDRVPRM32 _IOR(2, 0x11, struct floppy_drive_params32) -#define FDGETDRVSTAT32 _IOR(2, 0x12, struct floppy_drive_struct32) -#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct floppy_drive_struct32) -#define FDGETFDCSTAT32 _IOR(2, 0x15, struct floppy_fdc_state32) -#define FDWERRORGET32 _IOR(2, 0x17, struct floppy_write_errors32) - -static struct { - unsigned int cmd32; - unsigned int cmd; -} fd_ioctl_trans_table[] = { - { FDSETPRM32, FDSETPRM }, - { FDDEFPRM32, FDDEFPRM }, - { FDGETPRM32, FDGETPRM }, - { FDSETDRVPRM32, FDSETDRVPRM }, - { FDGETDRVPRM32, FDGETDRVPRM }, - { FDGETDRVSTAT32, FDGETDRVSTAT }, - { FDPOLLDRVSTAT32, FDPOLLDRVSTAT }, - { FDGETFDCSTAT32, FDGETFDCSTAT }, - { FDWERRORGET32, FDWERRORGET } -}; - -#define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table) - -static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - void *karg = NULL; - unsigned int kcmd = 0; - int i, err; - - for (i = 0; i < NR_FD_IOCTL_TRANS; i++) - if (cmd == fd_ioctl_trans_table[i].cmd32) { - kcmd = fd_ioctl_trans_table[i].cmd; - break; - } - if (!kcmd) - return -EINVAL; - - switch (cmd) { - case FDSETPRM32: - case FDDEFPRM32: - case FDGETPRM32: - { - compat_uptr_t name; - struct floppy_struct32 __user *uf; - struct floppy_struct *f; - - uf = compat_ptr(arg); - f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL); - if (!karg) - return -ENOMEM; - if (cmd == FDGETPRM32) - break; - err = __get_user(f->size, &uf->size); - err |= __get_user(f->sect, &uf->sect); - err |= __get_user(f->head, &uf->head); - err |= __get_user(f->track, &uf->track); - err |= __get_user(f->stretch, &uf->stretch); - err |= __get_user(f->gap, &uf->gap); - err |= __get_user(f->rate, &uf->rate); - err |= __get_user(f->spec1, &uf->spec1); - err |= __get_user(f->fmt_gap, &uf->fmt_gap); - err |= __get_user(name, &uf->name); - f->name = compat_ptr(name); - if (err) { - err = -EFAULT; - goto out; - } - break; - } - case FDSETDRVPRM32: - case FDGETDRVPRM32: - { - struct floppy_drive_params32 __user *uf; - struct floppy_drive_params *f; - - uf = compat_ptr(arg); - f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL); - if (!karg) - return -ENOMEM; - if (cmd == FDGETDRVPRM32) - break; - err = __get_user(f->cmos, &uf->cmos); - err |= __get_user(f->max_dtr, &uf->max_dtr); - err |= __get_user(f->hlt, &uf->hlt); - err |= __get_user(f->hut, &uf->hut); - err |= __get_user(f->srt, &uf->srt); - err |= __get_user(f->spinup, &uf->spinup); - err |= __get_user(f->spindown, &uf->spindown); - err |= __get_user(f->spindown_offset, &uf->spindown_offset); - err |= __get_user(f->select_delay, &uf->select_delay); - err |= __get_user(f->rps, &uf->rps); - err |= __get_user(f->tracks, &uf->tracks); - err |= __get_user(f->timeout, &uf->timeout); - err |= __get_user(f->interleave_sect, &uf->interleave_sect); - err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors)); - err |= __get_user(f->flags, &uf->flags); - err |= __get_user(f->read_track, &uf->read_track); - err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect)); - err |= __get_user(f->checkfreq, &uf->checkfreq); - err |= __get_user(f->native_format, &uf->native_format); - if (err) { - err = -EFAULT; - goto out; - } - break; - } - case FDGETDRVSTAT32: - case FDPOLLDRVSTAT32: - karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL); - if (!karg) - return -ENOMEM; - break; - case FDGETFDCSTAT32: - karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL); - if (!karg) - return -ENOMEM; - break; - case FDWERRORGET32: - karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL); - if (!karg) - return -ENOMEM; - break; - default: - return -EINVAL; - } - set_fs (KERNEL_DS); - err = sys_ioctl (fd, kcmd, (unsigned long)karg); - set_fs (old_fs); - if (err) - goto out; - switch (cmd) { - case FDGETPRM32: - { - struct floppy_struct *f = karg; - struct floppy_struct32 __user *uf = compat_ptr(arg); - - err = __put_user(f->size, &uf->size); - err |= __put_user(f->sect, &uf->sect); - err |= __put_user(f->head, &uf->head); - err |= __put_user(f->track, &uf->track); - err |= __put_user(f->stretch, &uf->stretch); - err |= __put_user(f->gap, &uf->gap); - err |= __put_user(f->rate, &uf->rate); - err |= __put_user(f->spec1, &uf->spec1); - err |= __put_user(f->fmt_gap, &uf->fmt_gap); - err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name); - break; - } - case FDGETDRVPRM32: - { - struct floppy_drive_params32 __user *uf; - struct floppy_drive_params *f = karg; - - uf = compat_ptr(arg); - err = __put_user(f->cmos, &uf->cmos); - err |= __put_user(f->max_dtr, &uf->max_dtr); - err |= __put_user(f->hlt, &uf->hlt); - err |= __put_user(f->hut, &uf->hut); - err |= __put_user(f->srt, &uf->srt); - err |= __put_user(f->spinup, &uf->spinup); - err |= __put_user(f->spindown, &uf->spindown); - err |= __put_user(f->spindown_offset, &uf->spindown_offset); - err |= __put_user(f->select_delay, &uf->select_delay); - err |= __put_user(f->rps, &uf->rps); - err |= __put_user(f->tracks, &uf->tracks); - err |= __put_user(f->timeout, &uf->timeout); - err |= __put_user(f->interleave_sect, &uf->interleave_sect); - err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors)); - err |= __put_user(f->flags, &uf->flags); - err |= __put_user(f->read_track, &uf->read_track); - err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect)); - err |= __put_user(f->checkfreq, &uf->checkfreq); - err |= __put_user(f->native_format, &uf->native_format); - break; - } - case FDGETDRVSTAT32: - case FDPOLLDRVSTAT32: - { - struct floppy_drive_struct32 __user *uf; - struct floppy_drive_struct *f = karg; - - uf = compat_ptr(arg); - err = __put_user(f->flags, &uf->flags); - err |= __put_user(f->spinup_date, &uf->spinup_date); - err |= __put_user(f->select_date, &uf->select_date); - err |= __put_user(f->first_read_date, &uf->first_read_date); - err |= __put_user(f->probed_format, &uf->probed_format); - err |= __put_user(f->track, &uf->track); - err |= __put_user(f->maxblock, &uf->maxblock); - err |= __put_user(f->maxtrack, &uf->maxtrack); - err |= __put_user(f->generation, &uf->generation); - err |= __put_user(f->keep_data, &uf->keep_data); - err |= __put_user(f->fd_ref, &uf->fd_ref); - err |= __put_user(f->fd_device, &uf->fd_device); - err |= __put_user(f->last_checked, &uf->last_checked); - err |= __put_user((u64)f->dmabuf, &uf->dmabuf); - err |= __put_user((u64)f->bufblocks, &uf->bufblocks); - break; - } - case FDGETFDCSTAT32: - { - struct floppy_fdc_state32 __user *uf; - struct floppy_fdc_state *f = karg; - - uf = compat_ptr(arg); - err = __put_user(f->spec1, &uf->spec1); - err |= __put_user(f->spec2, &uf->spec2); - err |= __put_user(f->dtr, &uf->dtr); - err |= __put_user(f->version, &uf->version); - err |= __put_user(f->dor, &uf->dor); - err |= __put_user(f->address, &uf->address); - err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address), - (char *)&f->address + sizeof(f->address), sizeof(int)); - err |= __put_user(f->driver_version, &uf->driver_version); - err |= __copy_to_user(uf->track, f->track, sizeof(f->track)); - break; - } - case FDWERRORGET32: - { - struct floppy_write_errors32 __user *uf; - struct floppy_write_errors *f = karg; - - uf = compat_ptr(arg); - err = __put_user(f->write_errors, &uf->write_errors); - err |= __put_user(f->first_error_sector, &uf->first_error_sector); - err |= __put_user(f->first_error_generation, &uf->first_error_generation); - err |= __put_user(f->last_error_sector, &uf->last_error_sector); - err |= __put_user(f->last_error_generation, &uf->last_error_generation); - err |= __put_user(f->badness, &uf->badness); - break; - } - default: - break; - } - if (err) - err = -EFAULT; - -out: - kfree(karg); - return err; -} -#endif - struct mtd_oob_buf32 { u_int32_t start; u_int32_t length; @@ -3025,15 +2697,6 @@ HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp) HANDLE_IOCTL(SIOCGSTAMPNS, do_siocgstampns) #endif #ifdef CONFIG_BLOCK -HANDLE_IOCTL(FDSETPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDDEFPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDGETPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDSETDRVPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDGETDRVPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDGETDRVSTAT32, fd_ioctl_trans) -HANDLE_IOCTL(FDPOLLDRVSTAT32, fd_ioctl_trans) -HANDLE_IOCTL(FDGETFDCSTAT32, fd_ioctl_trans) -HANDLE_IOCTL(FDWERRORGET32, fd_ioctl_trans) HANDLE_IOCTL(SG_IO,sg_ioctl_trans) HANDLE_IOCTL(SG_GET_REQUEST_TABLE, sg_grt_trans) #endif -- cgit v0.10.2 From 780513ecb80ea0934fc6833efc4f5ed9ab4ff9bb Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Thu, 11 Oct 2007 21:26:08 +0200 Subject: [BLOCK] Fix failing compile with BLK_DEV_IO_TRACE=n I get a compilation error in sglist-arch branch with BLK_DEV_IO_TRACE=n: CC block/compat_ioctl.o /usr0/export/dev/bharrosh/git/pub/linux-2.6-block/block/compat_ioctl.c: In function ?compat_blk_trace_setup?: /usr0/export/dev/bharrosh/git/pub/linux-2.6-block/block/compat_ioctl.c:568: error: expected expression before ?do? make[2]: *** [block/compat_ioctl.o] Error 1 Signed-off-by: Jens Axboe diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index 972093b..2e105a1 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h @@ -290,7 +290,12 @@ static inline void blk_add_trace_remap(struct request_queue *q, struct bio *bio, #define blk_add_trace_generic(q, rq, rw, what) do { } while (0) #define blk_add_trace_pdu_int(q, what, bio, pdu) do { } while (0) #define blk_add_trace_remap(q, bio, dev, f, t) do {} while (0) -#define do_blk_trace_setup(q, bdev, buts) do {} while (0) +static inline int do_blk_trace_setup(struct request_queue *q, + struct block_device *bdev, + struct blk_user_trace_setup *buts) +{ + return 0; +} #endif /* CONFIG_BLK_DEV_IO_TRACE */ #endif /* __KERNEL__ */ #endif -- cgit v0.10.2