int card_init_queue(struct card_queue *cq, struct memory_card *card, spinlock_t * lock) { struct card_host *host = card->host; u64 limit = BLK_BOUNCE_HIGH; int ret=0; if (host->parent->dma_mask && *host->parent->dma_mask) limit = *host->parent->dma_mask; cq->card = card; cq->queue = blk_init_queue(card_request, lock); if (!cq->queue) return -ENOMEM; blk_queue_prep_rq(cq->queue, card_prep_request); card_init_bounce_buf(cq, card); if(!cq->bounce_buf){ blk_queue_bounce_limit(cq->queue, limit); blk_queue_max_hw_sectors(cq->queue, host->max_sectors); //blk_queue_max_hw_phys_segments(cq->queue, host->max_phys_segs); blk_queue_max_segments(cq->queue, host->max_hw_segs); blk_queue_max_segment_size(cq->queue, host->max_seg_size); cq->queue->queuedata = cq; cq->req = NULL; cq->sg = kmalloc(sizeof(struct scatterlist) * host->max_phys_segs, GFP_KERNEL); if (!cq->sg) { ret = -ENOMEM; blk_cleanup_queue(cq->queue); return ret; } } /*change card io scheduler from cfq to deadline*/ cq->queue->queuedata = cq; elevator_exit(cq->queue->elevator); cq->queue->elevator = NULL; ret = elevator_init(cq->queue, "deadline"); if (ret) { printk("[card_init_queue] elevator_init deadline fail\n"); blk_cleanup_queue(cq->queue); return ret; } init_MUTEX(&cq->thread_sem); cq->thread = kthread_run(card_queue_thread, cq, "%s_queue", card->name); if (IS_ERR(cq->thread)) { ret = PTR_ERR(cq->thread); //goto free_bounce_sg; } cq->nb.notifier_call = card_reboot_notifier; register_reboot_notifier(&cq->nb); return ret; }
static int __init virtualblockdevice_init(void) { int ret; elevator_t *oldelev; printk(KERN_ALERT "VirtualBlockDevice: Entry virtualblockdevice_init !\n"); ret = register_blkdev( virtualblockdevice_major, VIRTUALBLOCKDEVICE_NAME ); if( 0 > ret ) { printk(KERN_ALERT "VirtualBlockDevice: Failure to register block device: virtualblockdevice ! Major: %d\tErrno: %d !\n", virtualblockdevice_major, ret); goto failure_register_blkdev; } virtualblockdevice_major = ret; printk(KERN_ALERT "VirtualBlockDevice: Success to register block device: virtualblockdevice ! Major: %d !\n", virtualblockdevice_major); // get request_queue virtualblockdevice_queue = blk_init_queue( virtualblockdevice_do_request, NULL ); if( !virtualblockdevice_queue ) { printk(KERN_ALERT "VirtualBlockDevice: Failure to init request_queue !\n"); ret = -ENOMEM; goto failure_init_queue; } printk(KERN_ALERT "VirtualBlockDevice: Success to init request_queue !\n"); // switch elevator oldelev = virtualblockdevice_queue->elevator; if( IS_ERR_VALUE( elevator_init( virtualblockdevice_queue, "noop" ) ) ) { printk(KERN_ALERT "VirtualBlockDevice: Failure to switch elevator to noop, continue to use old one !\n"); } else { printk(KERN_ALERT "VirtualBlockDevice: Success to switch elevator to noop !\n"); elevator_exit( oldelev ); } // get gendisk virtualblockdevice_disk = alloc_disk( 1 ); if( !virtualblockdevice_disk ) { printk(KERN_ALERT "VirtualBlockDevice: Failure to allocate gendisk !\n"); ret = -ENOMEM; goto failure_alloc_disk; } printk(KERN_ALERT "VirtualBlockDevice: Success to allocate gendisk !\n"); // initialize gendisk strcpy( virtualblockdevice_disk->disk_name, VIRTUALBLOCKDEVICE_NAME ); virtualblockdevice_disk->major = virtualblockdevice_major; virtualblockdevice_disk->first_minor = virtualblockdevice_minor; virtualblockdevice_disk->fops = &virtualblockdevice_fops; virtualblockdevice_disk->queue = virtualblockdevice_queue; set_capacity( virtualblockdevice_disk, ( VIRTUALBLOCKDEVICE_DISK_CAPACITY >> 9 ) ); // add gendisk to kernel add_disk( virtualblockdevice_disk ); return 0; failure_alloc_disk: blk_cleanup_queue( virtualblockdevice_queue ); failure_init_queue: unregister_blkdev( virtualblockdevice_major, VIRTUALBLOCKDEVICE_NAME ); failure_register_blkdev: return ret; }