static void card_blk_remove(struct memory_card *card) { struct card_blk_data *card_data = card_get_drvdata(card); if (card_data) { int devidx; del_gendisk(card_data->disk); /* * I think this is needed. */ queue_flag_set_unlocked(QUEUE_FLAG_DEAD, card_data->queue.queue); queue_flag_set_unlocked(QUEUE_FLAG_STOPPED, card_data->queue.queue); card_data->queue.queue->queuedata = NULL; card_cleanup_queue(&card_data->queue); //card_data->disk->queue = NULL; devidx = card_data->disk->first_minor >> CARD_SHIFT; __clear_bit(devidx, dev_use); card_blk_put(card_data); } card_set_drvdata(card, NULL); }
/** * blk_queue_init_tags - initialize the queue tag info * @q: the request queue for the device * @depth: the maximum queue depth supported * @tags: the tag to use * * Queue lock must be held here if the function is called to resize an * existing map. **/ int blk_queue_init_tags(struct request_queue *q, int depth, struct blk_queue_tag *tags) { int rc; BUG_ON(tags && q->queue_tags && tags != q->queue_tags); if (!tags && !q->queue_tags) { tags = __blk_queue_init_tags(q, depth); if (!tags) goto fail; } else if (q->queue_tags) { rc = blk_queue_resize_tags(q, depth); if (rc) return rc; queue_flag_set(QUEUE_FLAG_QUEUED, q); return 0; } else atomic_inc(&tags->refcnt); /* * assign it, all done */ q->queue_tags = tags; queue_flag_set_unlocked(QUEUE_FLAG_QUEUED, q); INIT_LIST_HEAD(&q->tag_busy_list); return 0; fail: kfree(tags); return -ENOMEM; }
static ssize_t tier_attr_discard_store(struct tier_device *dev, const char *buf, size_t s) { if ('0' != buf[0] && '1' != buf[0]) return s; #if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) return -EOPNOTSUPP; #endif if ('0' == buf[0]) { if (dev->discard) { dev->discard = 0; pr_info("discard_to_devices is disabled\n"); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) if (dev->discard) { queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, dev->rqueue); } #endif } } else { if (!dev->discard) { dev->discard = 1; pr_info("discard is enabled\n"); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) if (dev->discard) { queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, dev->rqueue); } #endif } } return s; }
static void mmc_queue_setup_discard(struct request_queue *q, struct mmc_card *card) { unsigned max_discard; max_discard = mmc_calc_max_discard(card); if (!max_discard) return; queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); blk_queue_max_discard_sectors(q, max_discard); q->limits.discard_granularity = card->pref_erase << 9; /* granularity must not be greater than max. discard */ if (card->pref_erase > max_discard) q->limits.discard_granularity = 0; if (mmc_can_secure_erase_trim(card)) queue_flag_set_unlocked(QUEUE_FLAG_SECERASE, q); }
int blk_register_queue(struct gendisk *disk) { add_my_disk(disk); int ret; struct device *dev = disk_to_dev(disk); struct request_queue *q = disk->queue; if (WARN_ON(!q)) return -ENXIO; /* * SCSI probing may synchronously create and destroy a lot of * request_queues for non-existent devices. Shutting down a fully * functional queue takes measureable wallclock time as RCU grace * periods are involved. To avoid excessive latency in these * cases, a request_queue starts out in a degraded mode which is * faster to shut down and is made fully functional here as * request_queues for non-existent devices never get registered. */ if (!blk_queue_init_done(q)) { queue_flag_set_unlocked(QUEUE_FLAG_INIT_DONE, q); blk_queue_bypass_end(q); if (q->mq_ops) blk_mq_finish_init(q); } ret = blk_trace_init_sysfs(dev); if (ret) return ret; ret = kobject_add(&q->kobj, kobject_get(&dev->kobj), "%s", "queue"); if (ret < 0) { blk_trace_remove_sysfs(dev); return ret; } kobject_uevent(&q->kobj, KOBJ_ADD); if (q->mq_ops) blk_mq_register_disk(disk); if (!q->request_fn) return 0; ret = elv_register_queue(q); if (ret) { kobject_uevent(&q->kobj, KOBJ_REMOVE); kobject_del(&q->kobj); blk_trace_remove_sysfs(dev); kobject_put(&dev->kobj); return ret; } return 0; }
static void mmc_queue_setup_discard(struct request_queue *q, struct mmc_card *card) { unsigned max_discard; max_discard = mmc_calc_max_discard(card); if (!max_discard) return; queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); q->limits.max_discard_sectors = max_discard; if (card->erased_byte == 0) q->limits.discard_zeroes_data = 1; q->limits.discard_granularity = card->pref_erase << 9; /* granularity must not be greater than max. discard */ if (card->pref_erase > max_discard) q->limits.discard_granularity = 0; if (mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card)) queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, q); }
/** * Support discard. */ void walb_discard_support(struct walb_dev *wdev) { struct request_queue *q = wdev->queue; LOGn("Supports REQ_DISCARD.\n"); q->limits.discard_granularity = wdev->physical_bs; /* Should be stored in u16 variable and aligned. */ q->limits.max_discard_sectors = 1 << 15; q->limits.discard_zeroes_data = 0; queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); wdev->support_discard = true; }
static int card_queue_thread(void *d) { struct card_queue *cq = d; struct request_queue *q = cq->queue; // unsigned char rewait; /* * Set iothread to ensure that we aren't put to sleep by * the process freezing. We handle suspension ourselves. */ current->flags |= PF_MEMALLOC; down(&cq->thread_sem); do { struct request *req = NULL; /*wait sdio handle irq & xfer data*/ //for(rewait=3;(!sdio_irq_handled)&&(rewait--);) // schedule(); spin_lock_irq(q->queue_lock); set_current_state(TASK_INTERRUPTIBLE); q = cq->queue; if (!blk_queue_plugged(q)) { req = blk_fetch_request(q); } cq->req = req; spin_unlock_irq(q->queue_lock); if (!req) { if (kthread_should_stop()) { set_current_state(TASK_RUNNING); break; } up(&cq->thread_sem); schedule(); down(&cq->thread_sem); continue; } set_current_state(TASK_RUNNING); cq->issue_fn(cq, req); cond_resched(); } while (1); /*Stop queue*/ spin_lock_irq(q->queue_lock); queue_flag_set_unlocked(QUEUE_FLAG_STOPPED, cq->queue); spin_unlock_irq(q->queue_lock); up(&cq->thread_sem); cq->thread = NULL; return 0; }
/* * Initializes the block layer interfaces. */ static int sd_init_blk_dev(struct sd_host *host) { struct gendisk *disk; struct request_queue *queue; int channel; int retval; channel = to_channel(exi_get_exi_channel(host->exi_device)); /* queue */ retval = -ENOMEM; spin_lock_init(&host->queue_lock); queue = blk_init_queue(sd_request_func, &host->queue_lock); if (!queue) { sd_printk(KERN_ERR, "error initializing queue\n"); goto err_blk_init_queue; } blk_queue_dma_alignment(queue, EXI_DMA_ALIGN); blk_queue_max_phys_segments(queue, 1); blk_queue_max_hw_segments(queue, 1); blk_queue_max_sectors(queue, 8); queue_flag_set_unlocked(QUEUE_FLAG_NONROT, queue); queue->queuedata = host; host->queue = queue; /* disk */ disk = alloc_disk(1 << MMC_SHIFT); if (!disk) { sd_printk(KERN_ERR, "error allocating disk\n"); goto err_alloc_disk; } disk->major = SD_MAJOR; disk->first_minor = channel << MMC_SHIFT; disk->fops = &sd_fops; sprintf(disk->disk_name, "%s%c", SD_NAME, 'a' + channel); disk->private_data = host; disk->queue = host->queue; host->disk = disk; retval = 0; goto out; err_alloc_disk: blk_cleanup_queue(host->queue); host->queue = NULL; err_blk_init_queue: out: return retval; }
int blk_register_queue(struct gendisk *disk) { int ret; struct device *dev = disk_to_dev(disk); struct request_queue *q = disk->queue; if (WARN_ON(!q)) return -ENXIO; /* * Initialization must be complete by now. Finish the initial * bypass from queue allocation. */ blk_queue_bypass_end(q); queue_flag_set_unlocked(QUEUE_FLAG_INIT_DONE, q); ret = blk_trace_init_sysfs(dev); if (ret) return ret; ret = kobject_add(&q->kobj, kobject_get(&dev->kobj), "%s", "queue"); if (ret < 0) { blk_trace_remove_sysfs(dev); return ret; } kobject_uevent(&q->kobj, KOBJ_ADD); if (q->mq_ops) blk_mq_register_disk(disk); if (!q->request_fn) return 0; ret = elv_register_queue(q); if (ret) { kobject_uevent(&q->kobj, KOBJ_REMOVE); kobject_del(&q->kobj); blk_trace_remove_sysfs(dev); kobject_put(&dev->kobj); return ret; } return 0; }
/** * bsg_setup_queue - Create and add the bsg hooks so we can receive requests * @dev: device to attach bsg device to * @q: request queue setup by caller * @name: device to give bsg device * * The caller should have setup the reuqest queue with bsg_request_fn * as the request_fn. */ int bsg_setup_queue(struct device *dev, struct request_queue *q, char *name) { int ret; q->queuedata = dev; queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q); blk_queue_softirq_done(q, bsg_softirq_done); blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT); ret = bsg_register_queue(q, dev, name, NULL); if (ret) { printk(KERN_ERR "%s: bsg interface failed to " "initialize - register queue\n", dev->kobj.name); return ret; } return 0; }
static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) { struct request_queue *q = sdkp->disk->queue; unsigned int logical_block_size = sdkp->device->sector_size; unsigned int max_blocks = 0; q->limits.discard_zeroes_data = sdkp->lbprz; q->limits.discard_alignment = sdkp->unmap_alignment * logical_block_size; q->limits.discard_granularity = max(sdkp->physical_block_size, sdkp->unmap_granularity * logical_block_size); sdkp->provisioning_mode = mode; switch (mode) { case SD_LBP_DISABLE: q->limits.max_discard_sectors = 0; queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q); return; case SD_LBP_UNMAP: max_blocks = min_not_zero(sdkp->max_unmap_blocks, 0xffffffff); break; case SD_LBP_WS16: max_blocks = min_not_zero(sdkp->max_ws_blocks, 0xffffffff); break; case SD_LBP_WS10: max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff); break; case SD_LBP_ZERO: max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff); q->limits.discard_zeroes_data = 1; break; } q->limits.max_discard_sectors = max_blocks * (logical_block_size >> 9); queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); }
static void mmc_setup_queue(struct mmc_queue *mq, struct mmc_card *card) { struct mmc_host *host = card->host; u64 limit = BLK_BOUNCE_HIGH; if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT; queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue); queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, mq->queue); if (mmc_can_erase(card)) mmc_queue_setup_discard(mq->queue, card); blk_queue_bounce_limit(mq->queue, limit); blk_queue_max_hw_sectors(mq->queue, min(host->max_blk_count, host->max_req_size / 512)); blk_queue_max_segments(mq->queue, host->max_segs); blk_queue_max_segment_size(mq->queue, host->max_seg_size); /* Initialize thread_sem even if it is not used */ sema_init(&mq->thread_sem, 1); }
static int pmem_attach_disk(struct device *dev, struct nd_namespace_common *ndns, struct pmem_device *pmem) { struct gendisk *disk; pmem->pmem_queue = blk_alloc_queue(GFP_KERNEL); if (!pmem->pmem_queue) return -ENOMEM; blk_queue_make_request(pmem->pmem_queue, pmem_make_request); blk_queue_physical_block_size(pmem->pmem_queue, PAGE_SIZE); blk_queue_max_hw_sectors(pmem->pmem_queue, UINT_MAX); blk_queue_bounce_limit(pmem->pmem_queue, BLK_BOUNCE_ANY); queue_flag_set_unlocked(QUEUE_FLAG_NONROT, pmem->pmem_queue); disk = alloc_disk(0); if (!disk) { blk_cleanup_queue(pmem->pmem_queue); return -ENOMEM; } disk->major = pmem_major; disk->first_minor = 0; disk->fops = &pmem_fops; disk->private_data = pmem; disk->queue = pmem->pmem_queue; disk->flags = GENHD_FL_EXT_DEVT; nvdimm_namespace_disk_name(ndns, disk->disk_name); disk->driverfs_dev = dev; set_capacity(disk, (pmem->size - pmem->data_offset) / 512); pmem->pmem_disk = disk; add_disk(disk); revalidate_disk(disk); return 0; }
/** * mmc_init_queue - initialise a queue structure. * @mq: mmc queue * @card: mmc card to attach this queue * @lock: queue lock * @subname: partition subname * * Initialise a MMC card request queue. */ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock, const char *subname) { struct mmc_host *host = card->host; u64 limit = BLK_BOUNCE_HIGH; int ret; struct mmc_queue_req *mqrq_cur = &mq->mqrq[0]; struct mmc_queue_req *mqrq_prev = &mq->mqrq[1]; if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) limit = *mmc_dev(host)->dma_mask; mq->card = card; mq->queue = blk_init_queue(mmc_request, lock); if (!mq->queue) return -ENOMEM; memset(&mq->mqrq_cur, 0, sizeof(mq->mqrq_cur)); memset(&mq->mqrq_prev, 0, sizeof(mq->mqrq_prev)); mq->mqrq_cur = mqrq_cur; mq->mqrq_prev = mqrq_prev; mq->queue->queuedata = mq; blk_queue_prep_rq(mq->queue, mmc_prep_request); queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue); if (mmc_can_erase(card)) mmc_queue_setup_discard(mq->queue, card); #ifdef CONFIG_MMC_BLOCK_BOUNCE if (host->max_segs == 1) { unsigned int bouncesz; if(!mmc_card_sd(card)) bouncesz = MMC_QUEUE_BOUNCESZ; else bouncesz = MMC_QUEUE_SD_BOUNCESZ; if (bouncesz > host->max_req_size) bouncesz = host->max_req_size; if (bouncesz > host->max_seg_size) bouncesz = host->max_seg_size; if (bouncesz > (host->max_blk_count * 512)) bouncesz = host->max_blk_count * 512; if (bouncesz > 512) { if(!mmc_card_sd(card)) mqrq_cur->bounce_buf = kmalloc(bouncesz, GFP_KERNEL); else mqrq_cur->bounce_buf = mmc_queue_cur_bounce_buf; if (!mqrq_cur->bounce_buf) { printk(KERN_WARNING "%s: unable to " "allocate bounce cur buffer\n", mmc_card_name(card)); } if(!mmc_card_sd(card)) mqrq_prev->bounce_buf = kmalloc(bouncesz, GFP_KERNEL); else mqrq_prev->bounce_buf = mmc_queue_prev_bounce_buf; if (!mqrq_prev->bounce_buf) { printk(KERN_WARNING "%s: unable to " "allocate bounce prev buffer\n", mmc_card_name(card)); kfree(mqrq_cur->bounce_buf); mqrq_cur->bounce_buf = NULL; } } if (mqrq_cur->bounce_buf && mqrq_prev->bounce_buf) { blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY); blk_queue_max_hw_sectors(mq->queue, bouncesz / 512); blk_queue_max_segments(mq->queue, bouncesz / 512); blk_queue_max_segment_size(mq->queue, bouncesz); mqrq_cur->sg = mmc_alloc_sg(1, &ret); if (ret) goto cleanup_queue; mqrq_cur->bounce_sg = mmc_alloc_sg(bouncesz / 512, &ret); if (ret) goto cleanup_queue; mqrq_prev->sg = mmc_alloc_sg(1, &ret); if (ret) goto cleanup_queue; mqrq_prev->bounce_sg = mmc_alloc_sg(bouncesz / 512, &ret); if (ret) goto cleanup_queue; } } #endif if (!mqrq_cur->bounce_buf && !mqrq_prev->bounce_buf) { blk_queue_bounce_limit(mq->queue, limit); blk_queue_max_hw_sectors(mq->queue, min(host->max_blk_count, host->max_req_size / 512)); blk_queue_max_segments(mq->queue, host->max_segs); blk_queue_max_segment_size(mq->queue, host->max_seg_size); mqrq_cur->sg = mmc_alloc_sg(host->max_segs, &ret); if (ret) goto cleanup_queue; mqrq_prev->sg = mmc_alloc_sg(host->max_segs, &ret); if (ret) goto cleanup_queue; } sema_init(&mq->thread_sem, 1); mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd/%d%s", host->index, subname ? subname : ""); if (IS_ERR(mq->thread)) { ret = PTR_ERR(mq->thread); goto free_bounce_sg; } return 0; free_bounce_sg: kfree(mqrq_cur->bounce_sg); mqrq_cur->bounce_sg = NULL; kfree(mqrq_prev->bounce_sg); mqrq_prev->bounce_sg = NULL; cleanup_queue: kfree(mqrq_cur->sg); mqrq_cur->sg = NULL; if(!mmc_card_sd(card)) kfree(mqrq_cur->bounce_buf); mqrq_cur->bounce_buf = NULL; kfree(mqrq_prev->sg); mqrq_prev->sg = NULL; if(!mmc_card_sd(card)) kfree(mqrq_prev->bounce_buf); mqrq_prev->bounce_buf = NULL; blk_cleanup_queue(mq->queue); return ret; }
/** * @brief Card initial function. * @param work[in]: Work structure. * @return None. */ static void gp_sdcard_work_init(struct work_struct *work) { gpSDInfo_t* sd = container_of(work, gpSDInfo_t,init); int pin_handle; int ret = 0,i=0; int pin_id; if(sd->device_id == 0) pin_id = GP_PIN_SD0; else if(sd->device_id == 1) pin_id = GP_PIN_SD1; else pin_id = GP_PIN_SD2; pin_handle = gp_board_pin_func_request( pin_id, GP_BOARD_WAIT_FOREVER); if(pin_handle<0) { DERROR("[%d]: can't get pin handle\n", sd->device_id); goto init_work_end; } /* ----- chris: Set Pin state for SD before power on ----- */ sd->sd_func->set_power(1); /* ----- chris: delay 250ms after card power on ----- */ msleep(250); /* ----- Initial SD card ----- */ ret = gp_sdcard_cardinit(sd); if (ret != 0) { DERROR("[%d]: initial fail\n",sd->device_id); gp_board_pin_func_release(pin_handle); goto init_work_end; } gp_board_pin_func_release(pin_handle); if(sd->present==1) { if(sd->card_type == SDIO) { sd->pin_handle = gp_board_pin_func_request(pin_id, GP_BOARD_WAIT_FOREVER); if(sd->pin_handle<0) { DERROR("[%d]: can't get pin handle\n", sd->device_id); goto init_work_end; } DEBUG("SDIO card detected\n"); gp_sdio_insert_device(sd->device_id, sd->RCA); } else { unsigned int cnt =0; /* ----- Wait 30 second for all process close handle ----- */ while((sd->users)&&cnt<120) { msleep(250); cnt++; } if(sd->users) { DERROR("Some handle do not free\n"); } if(sd->status) { gp_sdcard_blk_put(sd); sd->status = 0; } sd->handle_dma = gp_apbdma0_request(1000); if(sd->handle_dma==0) goto init_work_end; sd->queue = blk_init_queue(gp_sdcard_request, &sd->lock); if(sd->queue==NULL) { DERROR("NO MEMORY: queue\n"); goto fail_queue; } blk_queue_ordered(sd->queue, QUEUE_ORDERED_DRAIN, NULL); queue_flag_set_unlocked(QUEUE_FLAG_NONROT, sd->queue); blk_queue_logical_block_size(sd->queue, 512); blk_queue_max_sectors(sd->queue, SD_MAX_SECTORS ); blk_queue_max_phys_segments(sd->queue, SD_MAX_PHY_SEGMENTS); blk_queue_max_hw_segments(sd->queue, SD_MAX_HW_SEGMENTS); blk_queue_max_segment_size(sd->queue, SD_MAX_PHY_SEGMENTS_SIZE); /* ----- Initial scatter list ----- */ sd->sg = kmalloc(sizeof(struct scatterlist) *SD_MAX_PHY_SEGMENTS, GFP_KERNEL); if (!sd->sg) { DERROR("NO MEMORY: queue\n"); goto fail_thread; } sg_init_table(sd->sg, SD_MAX_PHY_SEGMENTS); init_MUTEX(&sd->thread_sem); /* ----- Enable thread ----- */ sd->thread = kthread_run(gp_sdcard_queue_thread, sd, "sd-qd"); if (IS_ERR(sd->thread)) { goto fail_thread; } sd->queue->queuedata = sd; /* ----- Check SD card for GP special header ----- */ if(gp_sdcard_parse_header(sd)<0) { goto fail_gd; } /* ----- Setup gendisk structure ----- */ sd->gd = alloc_disk(SD_MINORS); if (sd->gd==NULL) { DERROR("NO MEMORY: gendisk\n"); blk_cleanup_queue(sd->queue); goto fail_gd; } /* ----- Set gendisk structure ----- */ sd->gd->major = sd_major; sd->gd->first_minor = sd->device_id*SD_MINORS; sd->gd->fops = &gp_sdcard_ops; sd->gd->queue = sd->queue; sd->gd->private_data = sd; snprintf (sd->gd->disk_name, 32, "sdcard%c", sd->device_id + 'a'); /* ----- Set GP partition ----- */ if(sd->partition.activity) { set_capacity(sd->gd,0); add_disk(sd->gd); for(i=0;i<MAX_SD_PART;i++) { if(sd->partition.capacity[i]==0) continue; gp_add_partition(sd->gd,i+1,sd->partition.offset[i],sd->partition.capacity[i],ADDPART_FLAG_WHOLEDISK); } } /* ----- Normal Setting ----- */ else { set_capacity(sd->gd,sd->capacity); add_disk(sd->gd); } } //DEBUG("Initial success\n"); goto init_work_end; } else { DERROR("Initial fail\n"); goto init_work_end; } fail_gd: /* ----- Then terminate our worker thread ----- */ kthread_stop(sd->thread); sd->thread = NULL; fail_thread: if (sd->sg) kfree(sd->sg); sd->sg = NULL; blk_cleanup_queue (sd->queue); sd->queue = NULL; fail_queue: if(sd->handle_dma) gp_apbdma0_release(sd->handle_dma); sd->handle_dma = 0; /* ----- For re-initialize ----- */ sd->present = 0; init_work_end: sd->timer.expires = jiffies + SD_CD_POLL; add_timer(&sd->timer); }
static int null_add_dev(void) { struct gendisk *disk; struct nullb *nullb; sector_t size; int rv; nullb = kzalloc_node(sizeof(*nullb), GFP_KERNEL, home_node); if (!nullb) { rv = -ENOMEM; goto out; } spin_lock_init(&nullb->lock); if (queue_mode == NULL_Q_MQ && use_per_node_hctx) submit_queues = nr_online_nodes; rv = setup_queues(nullb); if (rv) goto out_free_nullb; if (queue_mode == NULL_Q_MQ) { nullb->tag_set.ops = &null_mq_ops; nullb->tag_set.nr_hw_queues = submit_queues; nullb->tag_set.queue_depth = hw_queue_depth; nullb->tag_set.numa_node = home_node; nullb->tag_set.cmd_size = sizeof(struct nullb_cmd); nullb->tag_set.flags = BLK_MQ_F_SHOULD_MERGE; nullb->tag_set.driver_data = nullb; rv = blk_mq_alloc_tag_set(&nullb->tag_set); if (rv) goto out_cleanup_queues; nullb->q = blk_mq_init_queue(&nullb->tag_set); if (IS_ERR(nullb->q)) { rv = -ENOMEM; goto out_cleanup_tags; } } else if (queue_mode == NULL_Q_BIO) { nullb->q = blk_alloc_queue_node(GFP_KERNEL, home_node); if (!nullb->q) { rv = -ENOMEM; goto out_cleanup_queues; } blk_queue_make_request(nullb->q, null_queue_bio); rv = init_driver_queues(nullb); if (rv) goto out_cleanup_blk_queue; } else { nullb->q = blk_init_queue_node(null_request_fn, &nullb->lock, home_node); if (!nullb->q) { rv = -ENOMEM; goto out_cleanup_queues; } blk_queue_prep_rq(nullb->q, null_rq_prep_fn); blk_queue_softirq_done(nullb->q, null_softirq_done_fn); rv = init_driver_queues(nullb); if (rv) goto out_cleanup_blk_queue; } nullb->q->queuedata = nullb; queue_flag_set_unlocked(QUEUE_FLAG_NONROT, nullb->q); queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, nullb->q); disk = nullb->disk = alloc_disk_node(1, home_node); if (!disk) { rv = -ENOMEM; goto out_cleanup_blk_queue; } mutex_lock(&lock); list_add_tail(&nullb->list, &nullb_list); nullb->index = nullb_indexes++; mutex_unlock(&lock); blk_queue_logical_block_size(nullb->q, bs); blk_queue_physical_block_size(nullb->q, bs); size = gb * 1024 * 1024 * 1024ULL; sector_div(size, bs); set_capacity(disk, size); disk->flags |= GENHD_FL_EXT_DEVT | GENHD_FL_SUPPRESS_PARTITION_INFO; disk->major = null_major; disk->first_minor = nullb->index; disk->fops = &null_fops; disk->private_data = nullb; disk->queue = nullb->q; sprintf(disk->disk_name, "nullb%d", nullb->index); add_disk(disk); return 0; out_cleanup_blk_queue: blk_cleanup_queue(nullb->q); out_cleanup_tags: if (queue_mode == NULL_Q_MQ) blk_mq_free_tag_set(&nullb->tag_set); out_cleanup_queues: cleanup_queues(nullb); out_free_nullb: kfree(nullb); out: return rv; }
static int __zvol_create_minor(const char *name) { zvol_state_t *zv; objset_t *os; dmu_object_info_t *doi; uint64_t volsize; unsigned minor = 0; int error = 0; ASSERT(MUTEX_HELD(&zvol_state_lock)); zv = zvol_find_by_name(name); if (zv) { error = EEXIST; goto out; } doi = kmem_alloc(sizeof(dmu_object_info_t), KM_SLEEP); error = dmu_objset_own(name, DMU_OST_ZVOL, B_TRUE, zvol_tag, &os); if (error) goto out_doi; /* Make sure we have the key loaded if we need one. */ error = dsl_crypto_key_inherit(name); if (error != 0 && error != EEXIST) goto out_dmu_objset_disown; error = dmu_object_info(os, ZVOL_OBJ, doi); if (error) goto out_dmu_objset_disown; error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize); if (error) goto out_dmu_objset_disown; error = zvol_find_minor(&minor); if (error) goto out_dmu_objset_disown; zv = zvol_alloc(MKDEV(zvol_major, minor), name); if (zv == NULL) { error = EAGAIN; goto out_dmu_objset_disown; } if (dmu_objset_is_snapshot(os)) zv->zv_flags |= ZVOL_RDONLY; zv->zv_volblocksize = doi->doi_data_block_size; zv->zv_volsize = volsize; zv->zv_objset = os; set_capacity(zv->zv_disk, zv->zv_volsize >> 9); blk_queue_max_hw_sectors(zv->zv_queue, UINT_MAX); blk_queue_max_segments(zv->zv_queue, UINT16_MAX); blk_queue_max_segment_size(zv->zv_queue, UINT_MAX); blk_queue_physical_block_size(zv->zv_queue, zv->zv_volblocksize); blk_queue_io_opt(zv->zv_queue, zv->zv_volblocksize); #ifdef HAVE_BLK_QUEUE_DISCARD blk_queue_max_discard_sectors(zv->zv_queue, (zvol_max_discard_blocks * zv->zv_volblocksize) >> 9); blk_queue_discard_granularity(zv->zv_queue, zv->zv_volblocksize); queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, zv->zv_queue); #endif #ifdef HAVE_BLK_QUEUE_NONROT queue_flag_set_unlocked(QUEUE_FLAG_NONROT, zv->zv_queue); #endif if (zil_replay_disable) zil_destroy(dmu_objset_zil(os), B_FALSE); else zil_replay(os, zv, zvol_replay_vector); out_dmu_objset_disown: dmu_objset_disown(os, zvol_tag); zv->zv_objset = NULL; out_doi: kmem_free(doi, sizeof(dmu_object_info_t)); out: if (error == 0) { zvol_insert(zv); add_disk(zv->zv_disk); } return (error); }
int blk_register_queue(struct gendisk *disk) { int ret; struct device *dev = disk_to_dev(disk); struct request_queue *q = disk->queue; if (WARN_ON(!q)) return -ENXIO; WARN_ONCE(test_bit(QUEUE_FLAG_REGISTERED, &q->queue_flags), "%s is registering an already registered queue\n", kobject_name(&dev->kobj)); queue_flag_set_unlocked(QUEUE_FLAG_REGISTERED, q); /* * SCSI probing may synchronously create and destroy a lot of * request_queues for non-existent devices. Shutting down a fully * functional queue takes measureable wallclock time as RCU grace * periods are involved. To avoid excessive latency in these * cases, a request_queue starts out in a degraded mode which is * faster to shut down and is made fully functional here as * request_queues for non-existent devices never get registered. */ if (!blk_queue_init_done(q)) { queue_flag_set_unlocked(QUEUE_FLAG_INIT_DONE, q); percpu_ref_switch_to_percpu(&q->q_usage_counter); blk_queue_bypass_end(q); } ret = blk_trace_init_sysfs(dev); if (ret) return ret; /* Prevent changes through sysfs until registration is completed. */ mutex_lock(&q->sysfs_lock); ret = kobject_add(&q->kobj, kobject_get(&dev->kobj), "%s", "queue"); if (ret < 0) { blk_trace_remove_sysfs(dev); goto unlock; } if (q->mq_ops) { __blk_mq_register_dev(dev, q); blk_mq_debugfs_register(q); } kobject_uevent(&q->kobj, KOBJ_ADD); wbt_enable_default(q); blk_throtl_register_queue(q); if (q->request_fn || (q->mq_ops && q->elevator)) { ret = elv_register_queue(q); if (ret) { kobject_uevent(&q->kobj, KOBJ_REMOVE); kobject_del(&q->kobj); blk_trace_remove_sysfs(dev); kobject_put(&dev->kobj); goto unlock; } } ret = 0; unlock: mutex_unlock(&q->sysfs_lock); return ret; }
/** * @brief Card initial function. * @param work[in]: Work structure. * @return None. */ static void gp_sdcard_work_init(struct work_struct *work) { gpSDInfo_t* sd = container_of(work, gpSDInfo_t,init); int pin_handle; pin_handle = gp_board_pin_func_request((sd->device_id==0)?GP_PIN_SD0:GP_PIN_SD1, GP_BOARD_WAIT_FOREVER); if(pin_handle<0) { DERROR("SD%d: can't get pin handle\n", sd->device_id); goto init_work_end; } /* ----- Initial SD module (controller) ----- */ gpHalSDInit(sd->device_id); /* ----- Initial SD card ----- */ gp_sdcard_cardinit(sd); gp_board_pin_func_release(pin_handle); if(sd->present==1) { if(sd->card_type == SDIO) { sd->pin_handle = gp_board_pin_func_request((sd->device_id==0)?GP_PIN_SD0:GP_PIN_SD1, GP_BOARD_WAIT_FOREVER); if(sd->pin_handle<0) { DERROR("SD%d: can't get pin handle\n", sd->device_id); goto init_work_end; } DEBUG("SDIO card detected\n"); gp_sdio_insert_device(sd->device_id, sd->RCA); } else { sd->queue = blk_init_queue(gp_sdcard_request, &sd->lock); if(sd->queue==NULL) { DERROR("NO MEMORY: queue\n"); goto init_work_end; } blk_queue_ordered(sd->queue, QUEUE_ORDERED_DRAIN, NULL); queue_flag_set_unlocked(QUEUE_FLAG_NONROT, sd->queue); blk_queue_logical_block_size(sd->queue, 512); blk_queue_max_sectors(sd->queue, SD_MAX_SECTORS ); blk_queue_max_phys_segments(sd->queue, SD_MAX_PHY_SEGMENTS); blk_queue_max_hw_segments(sd->queue, SD_MAX_HW_SEGMENTS); blk_queue_max_segment_size(sd->queue, SD_MAX_PHY_SEGMENTS_SIZE); /* ----- Initial scatter list ----- */ sd->sg = kmalloc(sizeof(struct scatterlist) *SD_MAX_PHY_SEGMENTS, GFP_KERNEL); if (!sd->sg) { DERROR("NO MEMORY: queue\n"); goto fail_thread; } sg_init_table(sd->sg, SD_MAX_PHY_SEGMENTS); init_MUTEX(&sd->thread_sem); /* ----- Enable thread ----- */ sd->thread = kthread_run(gp_sdcard_queue_thread, sd, "sd-qd"); if (IS_ERR(sd->thread)) { goto fail_thread; } sd->queue->queuedata = sd; /* ----- Setup gendisk structure ----- */ sd->gd = alloc_disk(SD_MINORS); if (sd->gd==NULL) { DERROR("NO MEMORY: gendisk\n"); blk_cleanup_queue(sd->queue); goto fail_gd; } /* ----- Set gendisk structure ----- */ sd->gd->major = sd_major; sd->gd->first_minor = sd->device_id*SD_MINORS; sd->gd->fops = &gp_sdcard_ops; sd->gd->queue = sd->queue; sd->gd->private_data = sd; snprintf (sd->gd->disk_name, 32, "sdcard%c", sd->device_id + 'a'); set_capacity(sd->gd,sd->capacity); add_disk(sd->gd); } goto init_work_end; } else { DERROR("Initial fail\n"); goto init_work_end; } fail_gd: /* ----- Then terminate our worker thread ----- */ kthread_stop(sd->thread); fail_thread: if (sd->sg) kfree(sd->sg); sd->sg = NULL; blk_cleanup_queue (sd->queue); init_work_end: sd->timer.expires = jiffies + SD_CD_POLL; add_timer(&sd->timer); }
void kfioc_test_blk_queue_set_discard(void) { queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,NULL); }
int nbdx_register_block_device(struct nbdx_file *nbdx_file) { sector_t size = nbdx_file->stbuf.st_size; int page_size = PAGE_SIZE; int err = 0; pr_debug("%s called\n", __func__); nbdx_file->major = nbdx_major; #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) nbdx_mq_reg.nr_hw_queues = submit_queues; nbdx_file->queue = blk_mq_init_queue(&nbdx_mq_reg, nbdx_file); #else nbdx_file->tag_set.ops = &nbdx_mq_ops; nbdx_file->tag_set.nr_hw_queues = submit_queues; nbdx_file->tag_set.queue_depth = NBDX_QUEUE_DEPTH; nbdx_file->tag_set.numa_node = NUMA_NO_NODE; nbdx_file->tag_set.cmd_size = sizeof(struct raio_io_u); nbdx_file->tag_set.flags = BLK_MQ_F_SHOULD_MERGE; nbdx_file->tag_set.driver_data = nbdx_file; err = blk_mq_alloc_tag_set(&nbdx_file->tag_set); if (err) goto out; nbdx_file->queue = blk_mq_init_queue(&nbdx_file->tag_set); #endif if (IS_ERR(nbdx_file->queue)) { pr_err("%s: Failed to allocate blk queue ret=%ld\n", __func__, PTR_ERR(nbdx_file->queue)); err = PTR_ERR(nbdx_file->queue); goto blk_mq_init; } nbdx_file->queue->queuedata = nbdx_file; queue_flag_set_unlocked(QUEUE_FLAG_NONROT, nbdx_file->queue); queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, nbdx_file->queue); nbdx_file->disk = alloc_disk_node(1, NUMA_NO_NODE); if (!nbdx_file->disk) { pr_err("%s: Failed to allocate disk node\n", __func__); err = -ENOMEM; goto alloc_disk; } nbdx_file->disk->major = nbdx_file->major; nbdx_file->disk->first_minor = nbdx_file->index; nbdx_file->disk->fops = &nbdx_ops; nbdx_file->disk->queue = nbdx_file->queue; nbdx_file->disk->private_data = nbdx_file; blk_queue_logical_block_size(nbdx_file->queue, NBDX_SECT_SIZE); blk_queue_physical_block_size(nbdx_file->queue, NBDX_SECT_SIZE); sector_div(page_size, NBDX_SECT_SIZE); blk_queue_max_hw_sectors(nbdx_file->queue, page_size * MAX_SGL_LEN); sector_div(size, NBDX_SECT_SIZE); set_capacity(nbdx_file->disk, size); sscanf(nbdx_file->dev_name, "%s", nbdx_file->disk->disk_name); add_disk(nbdx_file->disk); goto out; alloc_disk: blk_cleanup_queue(nbdx_file->queue); blk_mq_init: #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) blk_mq_free_tag_set(&nbdx_file->tag_set); #endif out: return err; }
/** * mmc_init_queue - initialise a queue structure. * @mq: mmc queue * @card: mmc card to attach this queue * @lock: queue lock * @subname: partition subname * * Initialise a MMC card request queue. */ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock, const char *subname) { struct mmc_host *host = card->host; u64 limit = BLK_BOUNCE_HIGH; int ret; if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) limit = *mmc_dev(host)->dma_mask; mq->card = card; mq->queue = blk_init_queue(mmc_request, lock); if (!mq->queue) return -ENOMEM; mq->queue->queuedata = mq; mq->req = NULL; blk_queue_prep_rq(mq->queue, mmc_prep_request); queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue); if (mmc_can_erase(card)) { queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mq->queue); mq->queue->limits.max_discard_sectors = UINT_MAX; if (card->erased_byte == 0) mq->queue->limits.discard_zeroes_data = 1; mq->queue->limits.discard_granularity = card->pref_erase << 9; if (mmc_can_secure_erase_trim(card)) queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, mq->queue); } #ifdef CONFIG_MMC_BLOCK_BOUNCE if (host->max_segs == 1) { unsigned int bouncesz; bouncesz = MMC_QUEUE_BOUNCESZ; if (bouncesz > host->max_req_size) bouncesz = host->max_req_size; if (bouncesz > host->max_seg_size) bouncesz = host->max_seg_size; if (bouncesz > (host->max_blk_count * 512)) bouncesz = host->max_blk_count * 512; if (bouncesz > 512) { mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL); if (!mq->bounce_buf) { printk(KERN_WARNING "%s: unable to " "allocate bounce buffer\n", mmc_card_name(card)); } } if (mq->bounce_buf) { blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY); blk_queue_max_hw_sectors(mq->queue, bouncesz / 512); blk_queue_max_segments(mq->queue, bouncesz / 512); blk_queue_max_segment_size(mq->queue, bouncesz); mq->sg = kmalloc(sizeof(struct scatterlist), GFP_KERNEL); if (!mq->sg) { ret = -ENOMEM; goto cleanup_queue; } sg_init_table(mq->sg, 1); mq->bounce_sg = kmalloc(sizeof(struct scatterlist) * bouncesz / 512, GFP_KERNEL); if (!mq->bounce_sg) { ret = -ENOMEM; goto cleanup_queue; } sg_init_table(mq->bounce_sg, bouncesz / 512); } } #endif if (!mq->bounce_buf) { blk_queue_bounce_limit(mq->queue, limit); blk_queue_max_hw_sectors(mq->queue, min(host->max_blk_count, host->max_req_size / 512)); blk_queue_max_segments(mq->queue, host->max_segs); blk_queue_max_segment_size(mq->queue, host->max_seg_size); mq->sg = kmalloc(sizeof(struct scatterlist) * host->max_segs, GFP_KERNEL); if (!mq->sg) { ret = -ENOMEM; goto cleanup_queue; } sg_init_table(mq->sg, host->max_segs); } sema_init(&mq->thread_sem, 1); mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd/%d%s", host->index, subname ? subname : ""); if (IS_ERR(mq->thread)) { ret = PTR_ERR(mq->thread); goto free_bounce_sg; } return 0; free_bounce_sg: if (mq->bounce_sg) kfree(mq->bounce_sg); mq->bounce_sg = NULL; cleanup_queue: if (mq->sg) kfree(mq->sg); mq->sg = NULL; if (mq->bounce_buf) kfree(mq->bounce_buf); mq->bounce_buf = NULL; blk_cleanup_queue(mq->queue); return ret; }
static int null_add_dev(void) { struct nullb *nullb; int rv; nullb = kzalloc_node(sizeof(*nullb), GFP_KERNEL, home_node); if (!nullb) { rv = -ENOMEM; goto out; } spin_lock_init(&nullb->lock); if (queue_mode == NULL_Q_MQ && use_per_node_hctx) submit_queues = nr_online_nodes; rv = setup_queues(nullb); if (rv) goto out_free_nullb; if (queue_mode == NULL_Q_MQ) { nullb->tag_set.ops = &null_mq_ops; nullb->tag_set.nr_hw_queues = submit_queues; nullb->tag_set.queue_depth = hw_queue_depth; nullb->tag_set.numa_node = home_node; nullb->tag_set.cmd_size = sizeof(struct nullb_cmd); nullb->tag_set.flags = BLK_MQ_F_SHOULD_MERGE; nullb->tag_set.driver_data = nullb; rv = blk_mq_alloc_tag_set(&nullb->tag_set); if (rv) goto out_cleanup_queues; nullb->q = blk_mq_init_queue(&nullb->tag_set); if (IS_ERR(nullb->q)) { rv = -ENOMEM; goto out_cleanup_tags; } } else if (queue_mode == NULL_Q_BIO) { nullb->q = blk_alloc_queue_node(GFP_KERNEL, home_node); if (!nullb->q) { rv = -ENOMEM; goto out_cleanup_queues; } blk_queue_make_request(nullb->q, null_queue_bio); rv = init_driver_queues(nullb); if (rv) goto out_cleanup_blk_queue; } else { nullb->q = blk_init_queue_node(null_request_fn, &nullb->lock, home_node); if (!nullb->q) { rv = -ENOMEM; goto out_cleanup_queues; } blk_queue_prep_rq(nullb->q, null_rq_prep_fn); blk_queue_softirq_done(nullb->q, null_softirq_done_fn); rv = init_driver_queues(nullb); if (rv) goto out_cleanup_blk_queue; } nullb->q->queuedata = nullb; queue_flag_set_unlocked(QUEUE_FLAG_NONROT, nullb->q); queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, nullb->q); mutex_lock(&lock); nullb->index = nullb_indexes++; mutex_unlock(&lock); blk_queue_logical_block_size(nullb->q, bs); blk_queue_physical_block_size(nullb->q, bs); sprintf(nullb->disk_name, "nullb%d", nullb->index); if (use_lightnvm) rv = null_nvm_register(nullb); else rv = null_gendisk_register(nullb); if (rv) goto out_cleanup_blk_queue; mutex_lock(&lock); list_add_tail(&nullb->list, &nullb_list); mutex_unlock(&lock); return 0; out_cleanup_blk_queue: blk_cleanup_queue(nullb->q); out_cleanup_tags: if (queue_mode == NULL_Q_MQ) blk_mq_free_tag_set(&nullb->tag_set); out_cleanup_queues: cleanup_queues(nullb); out_free_nullb: kfree(nullb); out: return rv; }
/** * mmc_init_queue - initialise a queue structure. * @mq: mmc queue * @card: mmc card to attach this queue * @lock: queue lock * @subname: partition subname * * Initialise a MMC card request queue. */ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock, const char *subname) { struct mmc_host *host = card->host; u64 limit = BLK_BOUNCE_HIGH; bool bounce = false; int ret = -ENOMEM; if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT; mq->card = card; mq->queue = blk_init_queue(mmc_request_fn, lock); if (!mq->queue) return -ENOMEM; mq->qdepth = 2; mq->mqrq = kcalloc(mq->qdepth, sizeof(struct mmc_queue_req), GFP_KERNEL); if (!mq->mqrq) goto blk_cleanup; mq->mqrq_cur = &mq->mqrq[0]; mq->mqrq_prev = &mq->mqrq[1]; mq->queue->queuedata = mq; blk_queue_prep_rq(mq->queue, mmc_prep_request); queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue); queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, mq->queue); if (mmc_can_erase(card)) mmc_queue_setup_discard(mq->queue, card); #ifdef CONFIG_MMC_BLOCK_BOUNCE if (host->max_segs == 1) { unsigned int bouncesz; bouncesz = MMC_QUEUE_BOUNCESZ; if (bouncesz > host->max_req_size) bouncesz = host->max_req_size; if (bouncesz > host->max_seg_size) bouncesz = host->max_seg_size; if (bouncesz > (host->max_blk_count * 512)) bouncesz = host->max_blk_count * 512; if (bouncesz > 512 && mmc_queue_alloc_bounce_bufs(mq, bouncesz)) { blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY); blk_queue_max_hw_sectors(mq->queue, bouncesz / 512); blk_queue_max_segments(mq->queue, bouncesz / 512); blk_queue_max_segment_size(mq->queue, bouncesz); ret = mmc_queue_alloc_bounce_sgs(mq, bouncesz); if (ret) goto cleanup_queue; bounce = true; } } #endif if (!bounce) { blk_queue_bounce_limit(mq->queue, limit); blk_queue_max_hw_sectors(mq->queue, min(host->max_blk_count, host->max_req_size / 512)); blk_queue_max_segments(mq->queue, host->max_segs); blk_queue_max_segment_size(mq->queue, host->max_seg_size); ret = mmc_queue_alloc_sgs(mq, host->max_segs); if (ret) goto cleanup_queue; } sema_init(&mq->thread_sem, 1); mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd/%d%s", host->index, subname ? subname : ""); if (IS_ERR(mq->thread)) { ret = PTR_ERR(mq->thread); goto cleanup_queue; } return 0; cleanup_queue: mmc_queue_reqs_free_bufs(mq); kfree(mq->mqrq); mq->mqrq = NULL; blk_cleanup: blk_cleanup_queue(mq->queue); return ret; }
/* * Create a block device minor node and setup the linkage between it * and the specified volume. Once this function returns the block * device is live and ready for use. */ static int zvol_create_minor_impl(const char *name) { zvol_state_t *zv; objset_t *os; dmu_object_info_t *doi; uint64_t volsize; uint64_t len; unsigned minor = 0; int error = 0; mutex_enter(&zvol_state_lock); zv = zvol_find_by_name(name); if (zv) { error = SET_ERROR(EEXIST); goto out; } doi = kmem_alloc(sizeof (dmu_object_info_t), KM_SLEEP); error = dmu_objset_own(name, DMU_OST_ZVOL, B_TRUE, zvol_tag, &os); if (error) goto out_doi; error = dmu_object_info(os, ZVOL_OBJ, doi); if (error) goto out_dmu_objset_disown; error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize); if (error) goto out_dmu_objset_disown; error = zvol_find_minor(&minor); if (error) goto out_dmu_objset_disown; zv = zvol_alloc(MKDEV(zvol_major, minor), name); if (zv == NULL) { error = SET_ERROR(EAGAIN); goto out_dmu_objset_disown; } if (dmu_objset_is_snapshot(os)) zv->zv_flags |= ZVOL_RDONLY; zv->zv_volblocksize = doi->doi_data_block_size; zv->zv_volsize = volsize; zv->zv_objset = os; set_capacity(zv->zv_disk, zv->zv_volsize >> 9); blk_queue_max_hw_sectors(zv->zv_queue, (DMU_MAX_ACCESS / 4) >> 9); blk_queue_max_segments(zv->zv_queue, UINT16_MAX); blk_queue_max_segment_size(zv->zv_queue, UINT_MAX); blk_queue_physical_block_size(zv->zv_queue, zv->zv_volblocksize); blk_queue_io_opt(zv->zv_queue, zv->zv_volblocksize); blk_queue_max_discard_sectors(zv->zv_queue, (zvol_max_discard_blocks * zv->zv_volblocksize) >> 9); blk_queue_discard_granularity(zv->zv_queue, zv->zv_volblocksize); queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, zv->zv_queue); #ifdef QUEUE_FLAG_NONROT queue_flag_set_unlocked(QUEUE_FLAG_NONROT, zv->zv_queue); #endif #ifdef QUEUE_FLAG_ADD_RANDOM queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, zv->zv_queue); #endif if (spa_writeable(dmu_objset_spa(os))) { if (zil_replay_disable) zil_destroy(dmu_objset_zil(os), B_FALSE); else zil_replay(os, zv, zvol_replay_vector); } /* * When udev detects the addition of the device it will immediately * invoke blkid(8) to determine the type of content on the device. * Prefetching the blocks commonly scanned by blkid(8) will speed * up this process. */ len = MIN(MAX(zvol_prefetch_bytes, 0), SPA_MAXBLOCKSIZE); if (len > 0) { dmu_prefetch(os, ZVOL_OBJ, 0, 0, len, ZIO_PRIORITY_SYNC_READ); dmu_prefetch(os, ZVOL_OBJ, 0, volsize - len, len, ZIO_PRIORITY_SYNC_READ); } zv->zv_objset = NULL; out_dmu_objset_disown: dmu_objset_disown(os, zvol_tag); out_doi: kmem_free(doi, sizeof (dmu_object_info_t)); out: if (error == 0) { zvol_insert(zv); /* * Drop the lock to prevent deadlock with sys_open() -> * zvol_open(), which first takes bd_disk->bd_mutex and then * takes zvol_state_lock, whereas this code path first takes * zvol_state_lock, and then takes bd_disk->bd_mutex. */ mutex_exit(&zvol_state_lock); add_disk(zv->zv_disk); } else { mutex_exit(&zvol_state_lock); } return (SET_ERROR(error)); }
static int null_add_dev(void) { struct gendisk *disk; struct nullb *nullb; sector_t size; nullb = kzalloc_node(sizeof(*nullb), GFP_KERNEL, home_node); if (!nullb) return -ENOMEM; spin_lock_init(&nullb->lock); if (setup_queues(nullb)) goto err; if (queue_mode == NULL_Q_MQ) { null_mq_reg.numa_node = home_node; null_mq_reg.queue_depth = hw_queue_depth; if (use_per_node_hctx) { null_mq_reg.ops->alloc_hctx = null_alloc_hctx; null_mq_reg.ops->free_hctx = null_free_hctx; null_mq_reg.nr_hw_queues = nr_online_nodes; } else { null_mq_reg.ops->alloc_hctx = blk_mq_alloc_single_hw_queue; null_mq_reg.ops->free_hctx = blk_mq_free_single_hw_queue; null_mq_reg.nr_hw_queues = submit_queues; } nullb->q = blk_mq_init_queue(&null_mq_reg, nullb); } else if (queue_mode == NULL_Q_BIO) { nullb->q = blk_alloc_queue_node(GFP_KERNEL, home_node); blk_queue_make_request(nullb->q, null_queue_bio); } else { nullb->q = blk_init_queue_node(null_request_fn, &nullb->lock, home_node); blk_queue_prep_rq(nullb->q, null_rq_prep_fn); if (nullb->q) blk_queue_softirq_done(nullb->q, null_softirq_done_fn); } if (!nullb->q) goto queue_fail; nullb->q->queuedata = nullb; queue_flag_set_unlocked(QUEUE_FLAG_NONROT, nullb->q); disk = nullb->disk = alloc_disk_node(1, home_node); if (!disk) { queue_fail: if (queue_mode == NULL_Q_MQ) blk_mq_free_queue(nullb->q); else blk_cleanup_queue(nullb->q); cleanup_queues(nullb); err: kfree(nullb); return -ENOMEM; } mutex_lock(&lock); list_add_tail(&nullb->list, &nullb_list); nullb->index = nullb_indexes++; mutex_unlock(&lock); blk_queue_logical_block_size(nullb->q, bs); blk_queue_physical_block_size(nullb->q, bs); size = gb * 1024 * 1024 * 1024ULL; sector_div(size, bs); set_capacity(disk, size); disk->flags |= GENHD_FL_EXT_DEVT; disk->major = null_major; disk->first_minor = nullb->index; disk->fops = &null_fops; disk->private_data = nullb; disk->queue = nullb->q; sprintf(disk->disk_name, "nullb%d", nullb->index); add_disk(disk); return 0; }
static int mmc_queue_thread(void *d) { struct mmc_queue *mq = d; struct request_queue *q = mq->queue; current->flags |= PF_MEMALLOC; down(&mq->thread_sem); do { struct request *req = NULL; struct mmc_queue_req *tmp; spin_lock_irq(q->queue_lock); set_current_state(TASK_INTERRUPTIBLE); req = blk_fetch_request(q); mq->mqrq_cur->req = req; spin_unlock_irq(q->queue_lock); #ifdef MTK_MMC_USE_ASYNC_REQUEST if (req || mq->mqrq_prev->req) { #else if (req) { #endif set_current_state(TASK_RUNNING); mq->issue_fn(mq, req); } else { if (kthread_should_stop()) { set_current_state(TASK_RUNNING); break; } up(&mq->thread_sem); schedule(); down(&mq->thread_sem); } /* Current request becomes previous request and vice versa. */ mq->mqrq_prev->brq.mrq.data = NULL; mq->mqrq_prev->req = NULL; tmp = mq->mqrq_prev; #ifdef MTK_MMC_USE_ASYNC_REQUEST mq->mqrq_prev = mq->mqrq_cur; #endif mq->mqrq_cur = tmp; } while (1); up(&mq->thread_sem); return 0; } /* * Generic MMC request handler. This is called for any queue on a * particular host. When the host is not busy, we look for a request * on any queue on this host, and attempt to issue it. This may * not be the queue we were asked to process. */ static void mmc_request(struct request_queue *q) { struct mmc_queue *mq = q->queuedata; struct request *req; if (!mq) { while ((req = blk_fetch_request(q)) != NULL) { req->cmd_flags |= REQ_QUIET; __blk_end_request_all(req, -EIO); } return; } if (!mq->mqrq_cur->req && !mq->mqrq_prev->req) wake_up_process(mq->thread); } static struct scatterlist *mmc_alloc_sg(int sg_len, int *err) { struct scatterlist *sg; sg = kmalloc(sizeof(struct scatterlist)*sg_len, GFP_KERNEL); if (!sg) *err = -ENOMEM; else { *err = 0; sg_init_table(sg, sg_len); } return sg; } static void mmc_queue_setup_discard(struct request_queue *q, struct mmc_card *card) { unsigned max_discard; max_discard = mmc_calc_max_discard(card); if (!max_discard) return; queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); q->limits.max_discard_sectors = max_discard; if (card->erased_byte == 0 && !mmc_can_discard(card)) q->limits.discard_zeroes_data = 1; q->limits.discard_granularity = card->pref_erase << 9; /* granularity must not be greater than max. discard */ if (card->pref_erase > max_discard) q->limits.discard_granularity = 0; if (mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card)) queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, q); }
/** * mmc_init_queue - initialise a queue structure. * @mq: mmc queue * @card: mmc card to attach this queue * @lock: queue lock * * Initialise a MMC card request queue. */ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock) { struct mmc_host *host = card->host; u64 limit = BLK_BOUNCE_HIGH; int ret; if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) limit = *mmc_dev(host)->dma_mask; mq->card = card; mq->queue = blk_init_queue(mmc_request, lock); if (!mq->queue) return -ENOMEM; mq->queue->queuedata = mq; mq->req = NULL; blk_queue_prep_rq(mq->queue, mmc_prep_request); blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN, NULL); queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue); #ifdef CONFIG_MMC_BLOCK_BOUNCE if (host->max_hw_segs == 1) { unsigned int bouncesz; bouncesz = MMC_QUEUE_BOUNCESZ; if (bouncesz > host->max_req_size) bouncesz = host->max_req_size; if (bouncesz > host->max_seg_size) bouncesz = host->max_seg_size; if (bouncesz > (host->max_blk_count * 512)) bouncesz = host->max_blk_count * 512; if (bouncesz > 512) { mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL); if (!mq->bounce_buf) { printk(KERN_WARNING "%s: unable to " "allocate bounce buffer\n", mmc_card_name(card)); } } if (mq->bounce_buf) { blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY); blk_queue_max_sectors(mq->queue, bouncesz / 512); blk_queue_max_phys_segments(mq->queue, bouncesz / 512); blk_queue_max_hw_segments(mq->queue, bouncesz / 512); blk_queue_max_segment_size(mq->queue, bouncesz); mq->sg = kmalloc(sizeof(struct scatterlist), GFP_KERNEL); if (!mq->sg) { ret = -ENOMEM; goto cleanup_queue; } sg_init_table(mq->sg, 1); mq->bounce_sg = kmalloc(sizeof(struct scatterlist) * bouncesz / 512, GFP_KERNEL); if (!mq->bounce_sg) { ret = -ENOMEM; goto cleanup_queue; } sg_init_table(mq->bounce_sg, bouncesz / 512); } } #endif if (!mq->bounce_buf) { blk_queue_bounce_limit(mq->queue, limit); blk_queue_max_sectors(mq->queue, min(host->max_blk_count, host->max_req_size / 512)); blk_queue_max_phys_segments(mq->queue, host->max_phys_segs); blk_queue_max_hw_segments(mq->queue, host->max_hw_segs); blk_queue_max_segment_size(mq->queue, host->max_seg_size); mq->sg = kmalloc(sizeof(struct scatterlist) * host->max_phys_segs, GFP_KERNEL); if (!mq->sg) { ret = -ENOMEM; goto cleanup_queue; } sg_init_table(mq->sg, host->max_phys_segs); } init_MUTEX(&mq->thread_sem); mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd"); if (IS_ERR(mq->thread)) { ret = PTR_ERR(mq->thread); goto free_bounce_sg; } return 0; free_bounce_sg: if (mq->bounce_sg) kfree(mq->bounce_sg); mq->bounce_sg = NULL; cleanup_queue: if (mq->sg) kfree(mq->sg); mq->sg = NULL; if (mq->bounce_buf) kfree(mq->bounce_buf); mq->bounce_buf = NULL; blk_cleanup_queue(mq->queue); return ret; }
/** * mmc_init_queue - initialise a queue structure. * @mq: mmc queue * @card: mmc card to attach this queue * @lock: queue lock * * Initialise a MMC card request queue. */ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock) { struct mmc_host *host = card->host; u64 limit = BLK_BOUNCE_HIGH; int ret; if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) limit = *mmc_dev(host)->dma_mask; mq->card = card; mq->queue = blk_init_queue(mmc_request, lock); if (!mq->queue) return -ENOMEM; mq->queue->queuedata = mq; mq->req = NULL; blk_queue_prep_rq(mq->queue, mmc_prep_request); blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN, NULL); queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue); /* Set max discard size, << 11 converts to megabytes in sectors */ blk_queue_max_discard_sectors(mq->queue, 16 << 11); if (card->csd.cmdclass & CCC_ERASE) queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mq->queue); /* * Calculating a correct span is way to messy if this * assumption is broken, so remove the erase support */ if (unlikely(mmc_card_blockaddr(card) && (card->csd.erase_size % 512))) queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mq->queue); #ifdef CONFIG_MMC_BLOCK_BOUNCE if (host->max_hw_segs == 1) { unsigned int bouncesz; bouncesz = MMC_QUEUE_BOUNCESZ; if (bouncesz > host->max_req_size) bouncesz = host->max_req_size; if (bouncesz > host->max_seg_size) bouncesz = host->max_seg_size; if (bouncesz > (host->max_blk_count * 512)) bouncesz = host->max_blk_count * 512; if (bouncesz > 512) { mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL); if (!mq->bounce_buf) { printk(KERN_WARNING "%s: unable to " "allocate bounce buffer\n", mmc_card_name(card)); } } if (mq->bounce_buf) { blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY); blk_queue_max_hw_sectors(mq->queue, bouncesz / 512); blk_queue_max_segments(mq->queue, bouncesz / 512); blk_queue_max_segment_size(mq->queue, bouncesz); mq->sg = kmalloc(sizeof(struct scatterlist), GFP_KERNEL); if (!mq->sg) { ret = -ENOMEM; goto cleanup_queue; } sg_init_table(mq->sg, 1); mq->bounce_sg = kmalloc(sizeof(struct scatterlist) * bouncesz / 512, GFP_KERNEL); if (!mq->bounce_sg) { ret = -ENOMEM; goto cleanup_queue; } sg_init_table(mq->bounce_sg, bouncesz / 512); } } #endif if (!mq->bounce_buf) { blk_queue_bounce_limit(mq->queue, limit); blk_queue_max_hw_sectors(mq->queue, min(host->max_blk_count, host->max_req_size / 512)); blk_queue_max_segments(mq->queue, host->max_hw_segs); blk_queue_max_segment_size(mq->queue, host->max_seg_size); mq->sg = kmalloc(sizeof(struct scatterlist) * host->max_phys_segs, GFP_KERNEL); if (!mq->sg) { ret = -ENOMEM; goto cleanup_queue; } sg_init_table(mq->sg, host->max_phys_segs); } init_MUTEX(&mq->thread_sem); mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd"); if (IS_ERR(mq->thread)) { ret = PTR_ERR(mq->thread); goto free_bounce_sg; } return 0; free_bounce_sg: if (mq->bounce_sg) kfree(mq->bounce_sg); mq->bounce_sg = NULL; cleanup_queue: if (mq->sg) kfree(mq->sg); mq->sg = NULL; if (mq->bounce_buf) kfree(mq->bounce_buf); mq->bounce_buf = NULL; blk_cleanup_queue(mq->queue); return ret; }