Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
[safe/jmp/linux-2.6] / drivers / block / pktcdvd.c
index edda7b6..ddf1942 100644 (file)
@@ -57,6 +57,7 @@
 #include <linux/miscdevice.h>
 #include <linux/freezer.h>
 #include <linux/mutex.h>
+#include <linux/slab.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_ioctl.h>
 #include <scsi/scsi.h>
@@ -92,7 +93,7 @@ static struct mutex ctl_mutex;        /* Serialize open/close/setup/teardown */
 static mempool_t *psd_pool;
 
 static struct class    *class_pktcdvd = NULL;    /* /sys/class/pktcdvd */
-static struct dentry   *pkt_debugfs_root = NULL; /* /debug/pktcdvd */
+static struct dentry   *pkt_debugfs_root = NULL; /* /sys/kernel/debug/pktcdvd */
 
 /* forward declaration */
 static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev);
@@ -284,7 +285,7 @@ static ssize_t kobj_pkt_store(struct kobject *kobj,
        return len;
 }
 
-static struct sysfs_ops kobj_pkt_ops = {
+static const struct sysfs_ops kobj_pkt_ops = {
        .show = kobj_pkt_show,
        .store = kobj_pkt_store
 };
@@ -302,7 +303,7 @@ static struct kobj_type kobj_pkt_type_wqueue = {
 static void pkt_sysfs_dev_new(struct pktcdvd_device *pd)
 {
        if (class_pktcdvd) {
-               pd->dev = device_create(class_pktcdvd, NULL, pd->pkt_dev, NULL,
+               pd->dev = device_create(class_pktcdvd, NULL, MKDEV(0, 0), NULL,
                                        "%s", pd->name);
                if (IS_ERR(pd->dev))
                        pd->dev = NULL;
@@ -322,7 +323,7 @@ static void pkt_sysfs_dev_remove(struct pktcdvd_device *pd)
        pkt_kobj_remove(pd->kobj_stat);
        pkt_kobj_remove(pd->kobj_wqueue);
        if (class_pktcdvd)
-               device_destroy(class_pktcdvd, pd->pkt_dev);
+               device_unregister(pd->dev);
 }
 
 
@@ -337,7 +338,9 @@ static void class_pktcdvd_release(struct class *cls)
 {
        kfree(cls);
 }
-static ssize_t class_pktcdvd_show_map(struct class *c, char *data)
+static ssize_t class_pktcdvd_show_map(struct class *c,
+                                       struct class_attribute *attr,
+                                       char *data)
 {
        int n = 0;
        int idx;
@@ -356,7 +359,9 @@ static ssize_t class_pktcdvd_show_map(struct class *c, char *data)
        return n;
 }
 
-static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf,
+static ssize_t class_pktcdvd_store_add(struct class *c,
+                                       struct class_attribute *attr,
+                                       const char *buf,
                                        size_t count)
 {
        unsigned int major, minor;
@@ -376,7 +381,9 @@ static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf,
        return -EINVAL;
 }
 
-static ssize_t class_pktcdvd_store_remove(struct class *c, const char *buf,
+static ssize_t class_pktcdvd_store_remove(struct class *c,
+                                         struct class_attribute *attr,
+                                         const char *buf,
                                        size_t count)
 {
        unsigned int major, minor;
@@ -430,7 +437,7 @@ static void pkt_sysfs_cleanup(void)
 /********************************************************************
   entries in debugfs
 
-  /debugfs/pktcdvd[0-7]/
+  /sys/kernel/debug/pktcdvd[0-7]/
                        info
 
  *******************************************************************/
@@ -569,6 +576,7 @@ static struct packet_data *pkt_alloc_packet_data(int frames)
        }
 
        spin_lock_init(&pkt->lock);
+       bio_list_init(&pkt->orig_bios);
 
        for (i = 0; i < frames; i++) {
                struct bio *bio = pkt_bio_alloc(1);
@@ -721,43 +729,6 @@ static void pkt_rbtree_insert(struct pktcdvd_device *pd, struct pkt_rb_node *nod
 }
 
 /*
- * Add a bio to a single linked list defined by its head and tail pointers.
- */
-static void pkt_add_list_last(struct bio *bio, struct bio **list_head, struct bio **list_tail)
-{
-       bio->bi_next = NULL;
-       if (*list_tail) {
-               BUG_ON((*list_head) == NULL);
-               (*list_tail)->bi_next = bio;
-               (*list_tail) = bio;
-       } else {
-               BUG_ON((*list_head) != NULL);
-               (*list_head) = bio;
-               (*list_tail) = bio;
-       }
-}
-
-/*
- * Remove and return the first bio from a single linked list defined by its
- * head and tail pointers.
- */
-static inline struct bio *pkt_get_list_first(struct bio **list_head, struct bio **list_tail)
-{
-       struct bio *bio;
-
-       if (*list_head == NULL)
-               return NULL;
-
-       bio = *list_head;
-       *list_head = bio->bi_next;
-       if (*list_head == NULL)
-               *list_tail = NULL;
-
-       bio->bi_next = NULL;
-       return bio;
-}
-
-/*
  * Send a packet_command to the underlying block device and
  * wait for completion.
  */
@@ -876,13 +847,10 @@ static noinline_for_stack int pkt_set_speed(struct pktcdvd_device *pd,
 static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio)
 {
        spin_lock(&pd->iosched.lock);
-       if (bio_data_dir(bio) == READ) {
-               pkt_add_list_last(bio, &pd->iosched.read_queue,
-                                 &pd->iosched.read_queue_tail);
-       } else {
-               pkt_add_list_last(bio, &pd->iosched.write_queue,
-                                 &pd->iosched.write_queue_tail);
-       }
+       if (bio_data_dir(bio) == READ)
+               bio_list_add(&pd->iosched.read_queue, bio);
+       else
+               bio_list_add(&pd->iosched.write_queue, bio);
        spin_unlock(&pd->iosched.lock);
 
        atomic_set(&pd->iosched.attention, 1);
@@ -917,8 +885,8 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
                int reads_queued, writes_queued;
 
                spin_lock(&pd->iosched.lock);
-               reads_queued = (pd->iosched.read_queue != NULL);
-               writes_queued = (pd->iosched.write_queue != NULL);
+               reads_queued = !bio_list_empty(&pd->iosched.read_queue);
+               writes_queued = !bio_list_empty(&pd->iosched.write_queue);
                spin_unlock(&pd->iosched.lock);
 
                if (!reads_queued && !writes_queued)
@@ -927,7 +895,7 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
                if (pd->iosched.writing) {
                        int need_write_seek = 1;
                        spin_lock(&pd->iosched.lock);
-                       bio = pd->iosched.write_queue;
+                       bio = bio_list_peek(&pd->iosched.write_queue);
                        spin_unlock(&pd->iosched.lock);
                        if (bio && (bio->bi_sector == pd->iosched.last_write))
                                need_write_seek = 0;
@@ -950,13 +918,10 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
                }
 
                spin_lock(&pd->iosched.lock);
-               if (pd->iosched.writing) {
-                       bio = pkt_get_list_first(&pd->iosched.write_queue,
-                                                &pd->iosched.write_queue_tail);
-               } else {
-                       bio = pkt_get_list_first(&pd->iosched.read_queue,
-                                                &pd->iosched.read_queue_tail);
-               }
+               if (pd->iosched.writing)
+                       bio = bio_list_pop(&pd->iosched.write_queue);
+               else
+                       bio = bio_list_pop(&pd->iosched.read_queue);
                spin_unlock(&pd->iosched.lock);
 
                if (!bio)
@@ -991,13 +956,15 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
  */
 static int pkt_set_segment_merging(struct pktcdvd_device *pd, struct request_queue *q)
 {
-       if ((pd->settings.size << 9) / CD_FRAMESIZE <= q->max_phys_segments) {
+       if ((pd->settings.size << 9) / CD_FRAMESIZE
+           <= queue_max_segments(q)) {
                /*
                 * The cdrom device can handle one segment/frame
                 */
                clear_bit(PACKET_MERGE_SEGS, &pd->flags);
                return 0;
-       } else if ((pd->settings.size << 9) / PAGE_SIZE <= q->max_phys_segments) {
+       } else if ((pd->settings.size << 9) / PAGE_SIZE
+                  <= queue_max_segments(q)) {
                /*
                 * We can handle this case at the expense of some extra memory
                 * copies during write operations
@@ -1112,7 +1079,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
        int f;
        char written[PACKET_MAX_SIZE];
 
-       BUG_ON(!pkt->orig_bios);
+       BUG_ON(bio_list_empty(&pkt->orig_bios));
 
        atomic_set(&pkt->io_wait, 0);
        atomic_set(&pkt->io_errors, 0);
@@ -1122,7 +1089,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
         */
        memset(written, 0, sizeof(written));
        spin_lock(&pkt->lock);
-       for (bio = pkt->orig_bios; bio; bio = bio->bi_next) {
+       bio_list_for_each(bio, &pkt->orig_bios) {
                int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9);
                int num_frames = bio->bi_size / CD_FRAMESIZE;
                pd->stats.secs_w += num_frames * (CD_FRAMESIZE >> 9);
@@ -1361,7 +1328,7 @@ try_next_bio:
                        break;
                pkt_rbtree_erase(pd, node);
                spin_lock(&pkt->lock);
-               pkt_add_list_last(bio, &pkt->orig_bios, &pkt->orig_bios_tail);
+               bio_list_add(&pkt->orig_bios, bio);
                pkt->write_size += bio->bi_size / CD_FRAMESIZE;
                spin_unlock(&pkt->lock);
        }
@@ -1370,8 +1337,10 @@ try_next_bio:
        wakeup = (pd->write_congestion_on > 0
                        && pd->bio_queue_size <= pd->write_congestion_off);
        spin_unlock(&pd->lock);
-       if (wakeup)
-               clear_bdi_congested(&pd->disk->queue->backing_dev_info, WRITE);
+       if (wakeup) {
+               clear_bdi_congested(&pd->disk->queue->backing_dev_info,
+                                       BLK_RW_ASYNC);
+       }
 
        pkt->sleep_time = max(PACKET_WAIT_TIME, 1);
        pkt_set_state(pkt, PACKET_WAITING_STATE);
@@ -1405,7 +1374,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
         */
        frames_write = 0;
        spin_lock(&pkt->lock);
-       for (bio = pkt->orig_bios; bio; bio = bio->bi_next) {
+       bio_list_for_each(bio, &pkt->orig_bios) {
                int segment = bio->bi_idx;
                int src_offs = 0;
                int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9);
@@ -1468,20 +1437,14 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
 
 static void pkt_finish_packet(struct packet_data *pkt, int uptodate)
 {
-       struct bio *bio, *next;
+       struct bio *bio;
 
        if (!uptodate)
                pkt->cache_valid = 0;
 
        /* Finish all bios corresponding to this packet */
-       bio = pkt->orig_bios;
-       while (bio) {
-               next = bio->bi_next;
-               bio->bi_next = NULL;
+       while ((bio = bio_list_pop(&pkt->orig_bios)))
                bio_endio(bio, uptodate ? 0 : -EIO);
-               bio = next;
-       }
-       pkt->orig_bios = pkt->orig_bios_tail = NULL;
 }
 
 static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data *pkt)
@@ -2356,7 +2319,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
                 * even if the size is a multiple of the packet size.
                 */
                spin_lock_irq(q->queue_lock);
-               blk_queue_max_sectors(q, pd->settings.size);
+               blk_queue_max_hw_sectors(q, pd->settings.size);
                spin_unlock_irq(q->queue_lock);
                set_bit(PACKET_WRITABLE, &pd->flags);
        } else {
@@ -2563,8 +2526,7 @@ static int pkt_make_request(struct request_queue *q, struct bio *bio)
                        spin_lock(&pkt->lock);
                        if ((pkt->state == PACKET_WAITING_STATE) ||
                            (pkt->state == PACKET_READ_WAIT_STATE)) {
-                               pkt_add_list_last(bio, &pkt->orig_bios,
-                                                 &pkt->orig_bios_tail);
+                               bio_list_add(&pkt->orig_bios, bio);
                                pkt->write_size += bio->bi_size / CD_FRAMESIZE;
                                if ((pkt->write_size >= pkt->frames) &&
                                    (pkt->state == PACKET_WAITING_STATE)) {
@@ -2590,10 +2552,10 @@ static int pkt_make_request(struct request_queue *q, struct bio *bio)
        spin_lock(&pd->lock);
        if (pd->write_congestion_on > 0
            && pd->bio_queue_size >= pd->write_congestion_on) {
-               set_bdi_congested(&q->backing_dev_info, WRITE);
+               set_bdi_congested(&q->backing_dev_info, BLK_RW_ASYNC);
                do {
                        spin_unlock(&pd->lock);
-                       congestion_wait(WRITE, HZ);
+                       congestion_wait(BLK_RW_ASYNC, HZ);
                        spin_lock(&pd->lock);
                } while(pd->bio_queue_size > pd->write_congestion_off);
        }
@@ -2657,8 +2619,8 @@ static void pkt_init_queue(struct pktcdvd_device *pd)
        struct request_queue *q = pd->disk->queue;
 
        blk_queue_make_request(q, pkt_make_request);
-       blk_queue_hardsect_size(q, CD_FRAMESIZE);
-       blk_queue_max_sectors(q, PACKET_MAX_SECTORS);
+       blk_queue_logical_block_size(q, CD_FRAMESIZE);
+       blk_queue_max_hw_sectors(q, PACKET_MAX_SECTORS);
        blk_queue_merge_bvec(q, pkt_merge_bvec);
        q->queuedata = pd;
 }
@@ -2845,7 +2807,7 @@ static int pkt_media_changed(struct gendisk *disk)
        return attached_disk->fops->media_changed(attached_disk);
 }
 
-static struct block_device_operations pktcdvd_ops = {
+static const struct block_device_operations pktcdvd_ops = {
        .owner =                THIS_MODULE,
        .open =                 pkt_open,
        .release =              pkt_close,
@@ -2853,6 +2815,11 @@ static struct block_device_operations pktcdvd_ops = {
        .media_changed =        pkt_media_changed,
 };
 
+static char *pktcdvd_devnode(struct gendisk *gd, mode_t *mode)
+{
+       return kasprintf(GFP_KERNEL, "pktcdvd/%s", gd->disk_name);
+}
+
 /*
  * Set up mapping from pktcdvd device to CD-ROM device.
  */
@@ -2889,6 +2856,8 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)
 
        spin_lock_init(&pd->lock);
        spin_lock_init(&pd->iosched.lock);
+       bio_list_init(&pd->iosched.read_queue);
+       bio_list_init(&pd->iosched.write_queue);
        sprintf(pd->name, DRIVER_NAME"%d", idx);
        init_waitqueue_head(&pd->wqueue);
        pd->bio_queue = RB_ROOT;
@@ -2905,6 +2874,7 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)
        disk->fops = &pktcdvd_ops;
        disk->flags = GENHD_FL_REMOVABLE;
        strcpy(disk->disk_name, pd->name);
+       disk->devnode = pktcdvd_devnode;
        disk->private_data = pd;
        disk->queue = blk_alloc_queue(GFP_KERNEL);
        if (!disk->queue)
@@ -3060,6 +3030,7 @@ static const struct file_operations pkt_ctl_fops = {
 static struct miscdevice pkt_misc = {
        .minor          = MISC_DYNAMIC_MINOR,
        .name           = DRIVER_NAME,
+       .nodename       = "pktcdvd/control",
        .fops           = &pkt_ctl_fops
 };