/* -------------------------------------------------------------------- * SystemACE device setup/teardown code */ 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%llx irq=%i\n", (unsigned long long)ace->physaddr, ace->irq); spin_lock_init(&ace->lock); init_completion(&ace->id_completion); /* * Map the device */ ace->baseaddr = ioremap(ace->physaddr, 0x80); if (!ace->baseaddr) goto err_ioremap; /* * Initialize the state machine tasklet and stall timer */ tasklet_init(&ace->fsm_tasklet, ace_fsm_tasklet, (unsigned long)ace); setup_timer(&ace->stall_timer, ace_stall_timer, (unsigned long)ace); /* * Initialize the request queue */ ace->queue = blk_init_queue(ace_request, &ace->lock); if (ace->queue == NULL) goto err_blk_initq; blk_queue_hardsect_size(ace->queue, 512); /* * Allocate and initialize GD structure */ ace->gd = alloc_disk(ACE_NUM_MINORS); if (!ace->gd) goto err_alloc_disk; ace->gd->major = ace_major; ace->gd->first_minor = ace->id * ACE_NUM_MINORS; ace->gd->fops = &ace_fops; ace->gd->queue = ace->queue; ace->gd->private_data = ace; snprintf(ace->gd->disk_name, 32, "xs%c", ace->id + 'a'); /* set bus width */ if (ace->bus_width == ACE_BUS_WIDTH_16) { /* 0x0101 should work regardless of endianess */ ace_out_le16(ace, ACE_BUSMODE, 0x0101); /* read it back to determine endianess */ if (ace_in_le16(ace, ACE_BUSMODE) == 0x0001) ace->reg_ops = &ace_reg_le16_ops; else ace->reg_ops = &ace_reg_be16_ops; } else { ace_out_8(ace, ACE_BUSMODE, 0x00); ace->reg_ops = &ace_reg_8_ops; } /* Make sure version register is sane */ version = ace_in(ace, ACE_VERSION); if ((version == 0) || (version == 0xFFFF)) goto err_read; /* Put sysace in a sane state by clearing most control reg bits */ ace_out(ace, ACE_CTRL, ACE_CTRL_FORCECFGMODE | ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ); /* 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; } } /* 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); dev_dbg(ace->dev, "physaddr 0x%llx, mapped to 0x%p, irq=%i\n", (unsigned long long) ace->physaddr, ace->baseaddr, ace->irq); ace->media_change = 1; ace_revalidate_disk(ace->gd); /* Make the sysace device 'live' */ add_disk(ace->gd); return 0; err_read: put_disk(ace->gd); err_alloc_disk: blk_cleanup_queue(ace->queue); err_blk_initq: iounmap(ace->baseaddr); err_ioremap: dev_info(ace->dev, "xsysace: error initializing device at 0x%llx\n", (unsigned long long) ace->physaddr); return -ENOMEM; }
static void __exit simp_blkdev_exit(void) { del_gendisk(simp_blkdev_disk); put_disk(simp_blkdev_disk); blk_cleanup_queue(simp_blkdev_queue); }
/* pdev is NULL for eisa */ static int __init cpqarray_register_ctlr( int i, struct pci_dev *pdev) { struct request_queue *q; int j; /* * register block devices * Find disks and fill in structs * Get an interrupt, set the Q depth and get into /proc */ /* If this successful it should insure that we are the only */ /* instance of the driver */ if (register_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname)) { goto Enomem4; } hba[i]->access.set_intr_mask(hba[i], 0); if (request_irq(hba[i]->intr, do_ida_intr, IRQF_DISABLED|IRQF_SHARED, hba[i]->devname, hba[i])) { printk(KERN_ERR "cpqarray: Unable to get irq %d for %s\n", hba[i]->intr, hba[i]->devname); goto Enomem3; } for (j=0; j<NWD; j++) { ida_gendisk[i][j] = alloc_disk(1 << NWD_SHIFT); if (!ida_gendisk[i][j]) goto Enomem2; } hba[i]->cmd_pool = pci_alloc_consistent( hba[i]->pci_dev, NR_CMDS * sizeof(cmdlist_t), &(hba[i]->cmd_pool_dhandle)); hba[i]->cmd_pool_bits = kcalloc( DIV_ROUND_UP(NR_CMDS, BITS_PER_LONG), sizeof(unsigned long), GFP_KERNEL); if (!hba[i]->cmd_pool_bits || !hba[i]->cmd_pool) goto Enomem1; memset(hba[i]->cmd_pool, 0, NR_CMDS * sizeof(cmdlist_t)); printk(KERN_INFO "cpqarray: Finding drives on %s", hba[i]->devname); spin_lock_init(&hba[i]->lock); q = blk_init_queue(do_ida_request, &hba[i]->lock); if (!q) goto Enomem1; hba[i]->queue = q; q->queuedata = hba[i]; getgeometry(i); start_fwbk(i); ida_procinit(i); if (pdev) blk_queue_bounce_limit(q, hba[i]->pci_dev->dma_mask); /* This is a hardware imposed limit. */ blk_queue_max_hw_segments(q, SG_MAX); /* This is a driver limit and could be eliminated. */ blk_queue_max_phys_segments(q, SG_MAX); init_timer(&hba[i]->timer); hba[i]->timer.expires = jiffies + IDA_TIMER; hba[i]->timer.data = (unsigned long)hba[i]; hba[i]->timer.function = ida_timer; add_timer(&hba[i]->timer); /* Enable IRQ now that spinlock and rate limit timer are set up */ hba[i]->access.set_intr_mask(hba[i], FIFO_NOT_EMPTY); for(j=0; j<NWD; j++) { struct gendisk *disk = ida_gendisk[i][j]; drv_info_t *drv = &hba[i]->drv[j]; sprintf(disk->disk_name, "ida/c%dd%d", i, j); disk->major = COMPAQ_SMART2_MAJOR + i; disk->first_minor = j<<NWD_SHIFT; disk->fops = &ida_fops; if (j && !drv->nr_blks) continue; blk_queue_logical_block_size(hba[i]->queue, drv->blk_size); set_capacity(disk, drv->nr_blks); disk->queue = hba[i]->queue; disk->private_data = drv; add_disk(disk); } /* done ! */ return(i); Enomem1: nr_ctlr = i; kfree(hba[i]->cmd_pool_bits); if (hba[i]->cmd_pool) pci_free_consistent(hba[i]->pci_dev, NR_CMDS*sizeof(cmdlist_t), hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle); Enomem2: while (j--) { put_disk(ida_gendisk[i][j]); ida_gendisk[i][j] = NULL; } free_irq(hba[i]->intr, hba[i]); Enomem3: unregister_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname); Enomem4: if (pdev) pci_set_drvdata(pdev, NULL); release_io_mem(hba[i]); free_hba(i); printk( KERN_ERR "cpqarray: out of memory"); return -1; }
static int htifblk_probe(struct device *dev) { static unsigned int index = 0; static const char prefix[] = " size="; struct htif_device *htif_dev; struct htifblk_device *htifblk_dev; struct gendisk *disk; struct request_queue *queue; const char *str; u64 size; int ret; dev_info(dev, "detected disk\n"); htif_dev = to_htif_dev(dev); str = strstr(htif_dev->id, prefix); if (unlikely(str == NULL || kstrtou64(str + sizeof(prefix) - 1, 10, &size))) { dev_err(dev, "error determining size of disk\n"); return -ENODEV; } if (unlikely(size & (SECTOR_SIZE - 1))) { dev_warn(dev, "disk size not a multiple of sector size:" " %llu\n", size); } ret = -ENOMEM; htifblk_dev = devm_kzalloc(dev, sizeof(struct htifblk_device), GFP_KERNEL); if (unlikely(htifblk_dev == NULL)) goto out; htifblk_dev->size = size; htifblk_dev->dev = htif_dev; htifblk_dev->tag = index; spin_lock_init(&htifblk_dev->lock); disk = alloc_disk(1); if (unlikely(disk == NULL)) goto out; queue = blk_init_queue(htifblk_request, &htifblk_dev->lock); if (unlikely(queue == NULL)) goto out_put_disk; queue->queuedata = htifblk_dev; blk_queue_max_segments(queue, 1); blk_queue_dma_alignment(queue, HTIF_ALIGN - 1); disk->queue = queue; disk->major = major; disk->minors = 1; disk->first_minor = 0; disk->fops = &htifblk_fops; set_capacity(disk, size >> SECTOR_SIZE_SHIFT); snprintf(disk->disk_name, DISK_NAME_LEN - 1, "htifblk%u", index++); htifblk_dev->disk = disk; add_disk(disk); dev_info(dev, "added %s\n", disk->disk_name); ret = htif_request_irq(htif_dev, htifblk_isr); if (unlikely(ret)) goto out_del_disk; dev_set_drvdata(dev, htifblk_dev); return 0; out_del_disk: del_gendisk(disk); blk_cleanup_queue(disk->queue); out_put_disk: put_disk(disk); out: return ret; }
static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) { struct mmc_blk_data *md; int devidx, ret; devidx = find_first_zero_bit(dev_use, MMC_NUM_MINORS); if (devidx >= MMC_NUM_MINORS) return ERR_PTR(-ENOSPC); __set_bit(devidx, dev_use); md = kmalloc(sizeof(struct mmc_blk_data), GFP_KERNEL); if (!md) { ret = -ENOMEM; goto out; } memset(md, 0, sizeof(struct mmc_blk_data)); /* * Set the read-only status based on the supported commands * and the write protect switch. */ md->read_only = mmc_blk_readonly(card); /* * Both SD and MMC specifications state (although a bit * unclearly in the MMC case) that a block size of 512 * bytes must always be supported by the card. */ md->block_bits = 9; md->disk = alloc_disk(1 << MMC_SHIFT); if (md->disk == NULL) { ret = -ENOMEM; goto err_kfree; } spin_lock_init(&md->lock); md->usage = 1; ret = mmc_init_queue(&md->queue, card, &md->lock); if (ret) goto err_putdisk; md->queue.prep_fn = mmc_blk_prep_rq; md->queue.issue_fn = mmc_blk_issue_rq; md->queue.data = md; md->disk->major = major; md->disk->first_minor = devidx << MMC_SHIFT; md->disk->fops = &mmc_bdops; md->disk->private_data = md; md->disk->queue = md->queue.queue; md->disk->driverfs_dev = &card->dev; /* * As discussed on lkml, GENHD_FL_REMOVABLE should: * * - be set for removable media with permanent block devices * - be unset for removable block devices with permanent media * * Since MMC block devices clearly fall under the second * case, we do not set GENHD_FL_REMOVABLE. Userspace * should use the block device creation/destruction hotplug * messages to tell when the card is present. */ sprintf(md->disk->disk_name, "mmcblk%d", devidx); blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits); /* * The CSD capacity field is in units of read_blkbits. * set_capacity takes units of 512 bytes. */ set_capacity(md->disk, card->csd.capacity << (card->csd.read_blkbits - 9)); return md; err_putdisk: put_disk(md->disk); err_kfree: kfree(md); out: return ERR_PTR(ret); }
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%llx irq=%i\n", (unsigned long long)ace->physaddr, ace->irq); spin_lock_init(&ace->lock); init_completion(&ace->id_completion); ace->baseaddr = ioremap(ace->physaddr, 0x80); if (!ace->baseaddr) goto err_ioremap; tasklet_init(&ace->fsm_tasklet, ace_fsm_tasklet, (unsigned long)ace); setup_timer(&ace->stall_timer, ace_stall_timer, (unsigned long)ace); ace->queue = blk_init_queue(ace_request, &ace->lock); if (ace->queue == NULL) goto err_blk_initq; blk_queue_logical_block_size(ace->queue, 512); ace->gd = alloc_disk(ACE_NUM_MINORS); if (!ace->gd) goto err_alloc_disk; ace->gd->major = ace_major; ace->gd->first_minor = ace->id * ACE_NUM_MINORS; ace->gd->fops = &ace_fops; ace->gd->queue = ace->queue; ace->gd->private_data = ace; snprintf(ace->gd->disk_name, 32, "xs%c", ace->id + 'a'); if (ace->bus_width == ACE_BUS_WIDTH_16) { ace_out_le16(ace, ACE_BUSMODE, 0x0101); if (ace_in_le16(ace, ACE_BUSMODE) == 0x0001) ace->reg_ops = &ace_reg_le16_ops; else ace->reg_ops = &ace_reg_be16_ops; } else { ace_out_8(ace, ACE_BUSMODE, 0x00); ace->reg_ops = &ace_reg_8_ops; } version = ace_in(ace, ACE_VERSION); if ((version == 0) || (version == 0xFFFF)) goto err_read; ace_out(ace, ACE_CTRL, ACE_CTRL_FORCECFGMODE | ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ); if (ace->irq != NO_IRQ) { rc = request_irq(ace->irq, ace_interrupt, 0, "systemace", ace); if (rc) { dev_err(ace->dev, "request_irq failed\n"); ace->irq = NO_IRQ; } } val = ace_in(ace, ACE_CTRL); val |= ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ; ace_out(ace, ACE_CTRL, val); dev_info(ace->dev, "Xilinx SystemACE revision %i.%i.%i\n", (version >> 12) & 0xf, (version >> 8) & 0x0f, version & 0xff); dev_dbg(ace->dev, "physaddr 0x%llx, mapped to 0x%p, irq=%i\n", (unsigned long long) ace->physaddr, ace->baseaddr, ace->irq); ace->media_change = 1; ace_revalidate_disk(ace->gd); add_disk(ace->gd); return 0; err_read: put_disk(ace->gd); err_alloc_disk: blk_cleanup_queue(ace->queue); err_blk_initq: iounmap(ace->baseaddr); err_ioremap: dev_info(ace->dev, "xsysace: error initializing device at 0x%llx\n", (unsigned long long) ace->physaddr); return -ENOMEM; }
/* Create disk on demand. So we won't create lots of disk for un-used devices. */ static struct kobject *tzmem_blk_probe(dev_t dev, int *part, void *data) { uint32_t len; struct gendisk *disk; struct kobject *kobj; struct request_queue *queue; struct tzmem_diskinfo_s *diskInfo; int ret; KREE_SESSION_HANDLE session; #ifdef MTEE_TZMEM_DBG pr_warn("====> tzmem_blk_probe\n"); #endif mutex_lock(&tzmem_probe_mutex); diskInfo = (struct tzmem_diskinfo_s *) &_tzmem_diskInfo[tzmem_poolIndex]; if (diskInfo->disk == NULL) { disk = alloc_disk(1); if (!disk) goto out_info; queue = blk_init_queue(do_tzmem_blk_request, &tzmem_blk_lock); if (!queue) goto out_queue; blk_queue_max_hw_sectors(queue, 1024); blk_queue_bounce_limit(queue, BLK_BOUNCE_ANY); if (_tzmem_get_poolsize(&len)) goto out_init; disk->major = IO_NODE_MAJOR_TZMEM; disk->first_minor = MINOR(dev); disk->fops = &tzmem_blk_fops; disk->private_data = &_tzmem_diskInfo; snprintf(disk->disk_name, sizeof(disk->disk_name), "tzmem%d", MINOR(dev)); disk->queue = queue; set_capacity(disk, len / 512); add_disk(disk); ret = KREE_CreateSession(TZ_TA_MEM_UUID, &session); if (ret != TZ_RESULT_SUCCESS) { pr_debug(MTEE_TZMEM_TAG "[%s] _tzmem_get_poolsize: KREE_CreateSession Error = 0x%x\n", MODULE_NAME, ret); goto out_init; } diskInfo->session = session; diskInfo->pool_size = len; diskInfo->disk = disk; diskInfo->size = len; } *part = 0; kobj = diskInfo ? get_disk(diskInfo->disk) : ERR_PTR(-ENOMEM); mutex_unlock(&tzmem_probe_mutex); return kobj; out_init: blk_cleanup_queue(queue); out_queue: put_disk(disk); out_info: mutex_unlock(&tzmem_probe_mutex); return ERR_PTR(-ENOMEM); }
/* alloc_disk and add_disk can sleep */ void aoeblk_gdalloc(void *vp) { struct aoedev *d = vp; struct gendisk *gd; ulong flags; gd = alloc_disk(AOE_PARTITIONS); if (gd == NULL) { printk(KERN_ERR "aoe: cannot allocate disk structure for %ld.%d\n", d->aoemajor, d->aoeminor); goto err; } d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache); if (d->bufpool == NULL) { printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%d\n", d->aoemajor, d->aoeminor); goto err_disk; } d->blkq = blk_alloc_queue(GFP_KERNEL); if (!d->blkq) goto err_mempool; blk_queue_make_request(d->blkq, aoeblk_make_request); d->blkq->backing_dev_info.name = "aoe"; if (bdi_init(&d->blkq->backing_dev_info)) goto err_blkq; spin_lock_irqsave(&d->lock, flags); gd->major = AOE_MAJOR; gd->first_minor = d->sysminor * AOE_PARTITIONS; gd->fops = &aoe_bdops; gd->private_data = d; set_capacity(gd, d->ssize); snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d", d->aoemajor, d->aoeminor); gd->queue = d->blkq; d->gd = gd; d->flags &= ~DEVFL_GDALLOC; d->flags |= DEVFL_UP; spin_unlock_irqrestore(&d->lock, flags); add_disk(gd); aoedisk_add_sysfs(d); return; err_blkq: blk_cleanup_queue(d->blkq); d->blkq = NULL; err_mempool: mempool_destroy(d->bufpool); err_disk: put_disk(gd); err: spin_lock_irqsave(&d->lock, flags); d->flags &= ~DEVFL_GDALLOC; spin_unlock_irqrestore(&d->lock, flags); }
static int ide_gd_probe(ide_drive_t *drive) { const struct ide_disk_ops *disk_ops = NULL; struct ide_disk_obj *idkp; struct gendisk *g; /* strstr("foo", "") is non-NULL */ if (!strstr("ide-gd", drive->driver_req)) goto failed; #ifdef CONFIG_IDE_GD_ATA if (drive->media == ide_disk) disk_ops = &ide_ata_disk_ops; #endif #ifdef CONFIG_IDE_GD_ATAPI if (drive->media == ide_floppy) disk_ops = &ide_atapi_disk_ops; #endif if (disk_ops == NULL) goto failed; if (disk_ops->check(drive, DRV_NAME) == 0) { printk(KERN_ERR PFX "%s: not supported by this driver\n", drive->name); goto failed; } idkp = kzalloc(sizeof(*idkp), GFP_KERNEL); if (!idkp) { printk(KERN_ERR PFX "%s: can't allocate a disk structure\n", drive->name); goto failed; } g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif)); if (!g) goto out_free_idkp; ide_init_disk(g, drive); idkp->dev.parent = &drive->gendev; idkp->dev.release = ide_disk_release; dev_set_name(&idkp->dev, dev_name(&drive->gendev)); if (device_register(&idkp->dev)) goto out_free_disk; idkp->drive = drive; idkp->driver = &ide_gd_driver; idkp->disk = g; g->private_data = &idkp->driver; drive->driver_data = idkp; drive->debug_mask = debug_mask; drive->disk_ops = disk_ops; disk_ops->setup(drive); set_capacity(g, ide_gd_capacity(drive)); g->minors = IDE_DISK_MINORS; g->driverfs_dev = &drive->gendev; g->flags |= GENHD_FL_EXT_DEVT; if (drive->dev_flags & IDE_DFLAG_REMOVABLE) g->flags = GENHD_FL_REMOVABLE; g->fops = &ide_gd_ops; add_disk(g); return 0; out_free_disk: put_disk(g); out_free_idkp: kfree(idkp); failed: return -ENODEV; }
static int ide_scsi_probe(ide_drive_t *drive) { idescsi_scsi_t *idescsi; struct Scsi_Host *host; struct gendisk *g; static int warned; int err = -ENOMEM; if (!warned && drive->media == ide_cdrom) { printk(KERN_WARNING "ide-scsi is deprecated for cd burning! Use ide-cd and give dev=/dev/hdX as device\n"); warned = 1; } if (idescsi_nocd && drive->media == ide_cdrom) return -ENODEV; if (!strstr("ide-scsi", drive->driver_req) || !drive->present || drive->media == ide_disk || !(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t)))) return -ENODEV; drive->scsi = 1; g = alloc_disk(1 << PARTN_BITS); if (!g) goto out_host_put; ide_init_disk(g, drive); host->max_id = 1; if (drive->id->last_lun) debug_log("%s: id->last_lun=%u\n", drive->name, drive->id->last_lun); if ((drive->id->last_lun & 0x7) != 7) host->max_lun = (drive->id->last_lun & 0x7) + 1; else host->max_lun = 1; drive->driver_data = host; idescsi = scsihost_to_idescsi(host); idescsi->drive = drive; idescsi->driver = &idescsi_driver; idescsi->host = host; idescsi->disk = g; g->private_data = &idescsi->driver; ide_proc_register_driver(drive, &idescsi_driver); err = 0; idescsi_setup(drive, idescsi); g->fops = &idescsi_ops; ide_register_region(g); err = scsi_add_host(host, &drive->gendev); if (!err) { scsi_scan_host(host); return 0; } /* fall through on error */ ide_unregister_region(g); ide_proc_unregister_driver(drive, &idescsi_driver); put_disk(g); out_host_put: drive->scsi = 0; scsi_host_put(host); return err; }
/* * Exits the block layer interfaces. */ static void sd_exit_blk_dev(struct sd_host *host) { blk_cleanup_queue(host->queue); put_disk(host->disk); }
static void cyasblkdev_blk_put( struct cyasblkdev_blk_data *bd ) { DBGPRN_FUNC_NAME; down(&open_lock); if (bd) { bd->usage--; #ifndef WESTBRIDGE_NDEBUG cy_as_hal_print_message( " cyasblkdev_blk_put , bd->usage= %d\n", bd->usage); #endif } else { #ifndef WESTBRIDGE_NDEBUG cy_as_hal_print_message( "cyasblkdev: blk_put(bd) on bd = NULL!: usage = %d\n", bd->usage); #endif up(&open_lock); return; } if (bd->usage == 0) { put_disk(bd->user_disk_0); put_disk(bd->user_disk_1); put_disk(bd->system_disk); cyasblkdev_cleanup_queue(&bd->queue); if (CY_AS_ERROR_SUCCESS != cy_as_storage_release(bd->dev_handle, 0, 0, 0, 0)) { #ifndef WESTBRIDGE_NDEBUG cy_as_hal_print_message( "cyasblkdev: cannot release bus 0\n"); #endif } if (CY_AS_ERROR_SUCCESS != cy_as_storage_release(bd->dev_handle, 1, 0, 0, 0)) { #ifndef WESTBRIDGE_NDEBUG cy_as_hal_print_message( "cyasblkdev: cannot release bus 1\n"); #endif } if (CY_AS_ERROR_SUCCESS != cy_as_storage_stop(bd->dev_handle, 0, 0)) { #ifndef WESTBRIDGE_NDEBUG cy_as_hal_print_message( "cyasblkdev: cannot stop storage stack\n"); #endif } #ifdef __CY_ASTORIA_SCM_KERNEL_HAL__ /* If the SCM Kernel HAL is being used, disable the use * of scatter/gather lists at the end of block driver usage. */ cy_as_hal_disable_scatter_list(cyasdevice_gethaltag()); #endif /*ptr to global struct cyasblkdev_blk_data */ gl_bd = NULL; kfree(bd); } #ifndef WESTBRIDGE_NDEBUG cy_as_hal_print_message( "cyasblkdev (blk_put): usage = %d\n", bd->usage); #endif up(&open_lock); }
static void __exit simp_blkdev_exit(void) { put_disk(simp_blkdev_disk); del_gendisk(simp_blkdev_disk); blk_cleanup_queue(simp_blkdev_queue); vfree(simp_blkdev_data); }
int __init mcd_init(void) { struct gendisk *disk = alloc_disk(1); int count; unsigned char result[3]; char msg[80]; if (!disk) { printk(KERN_INFO "mcd: can't allocated disk.\n"); return -ENOMEM; } if (mcd_port <= 0 || mcd_irq <= 0) { printk(KERN_INFO "mcd: not probing.\n"); put_disk(disk); return -EIO; } if (register_blkdev(MAJOR_NR, "mcd")) { put_disk(disk); return -EIO; } if (!request_region(mcd_port, 4, "mcd")) { printk(KERN_ERR "mcd: Initialization failed, I/O port (%X) already in use\n", mcd_port); goto out_region; } mcd_queue = blk_init_queue(do_mcd_request, &mcd_spinlock); if (!mcd_queue) goto out_queue; /* check for card */ outb(0, MCDPORT(1)); /* send reset */ for (count = 0; count < 2000000; count++) (void) inb(MCDPORT(1)); /* delay a bit */ outb(0x40, MCDPORT(0)); /* send get-stat cmd */ for (count = 0; count < 2000000; count++) if (!(inb(MCDPORT(1)) & MFL_STATUS)) break; if (count >= 2000000) { printk(KERN_INFO "mcd: initialisation failed - No mcd device at 0x%x irq %d\n", mcd_port, mcd_irq); goto out_probe; } count = inb(MCDPORT(0)); /* pick up the status */ outb(MCMD_GET_VERSION, MCDPORT(0)); for (count = 0; count < 3; count++) if (getValue(result + count)) { printk(KERN_ERR "mcd: mitsumi get version failed at 0x%x\n", mcd_port); goto out_probe; } if (result[0] == result[1] && result[1] == result[2]) goto out_probe; mcdVersion = result[2]; if (mcdVersion >= 4) outb(4, MCDPORT(2)); /* magic happens */ /* don't get the IRQ until we know for sure the drive is there */ if (request_irq(mcd_irq, mcd_interrupt, SA_INTERRUPT, "Mitsumi CD", NULL)) { printk(KERN_ERR "mcd: Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq); goto out_probe; } if (result[1] == 'D') { MCMD_DATA_READ = MCMD_2X_READ; /* Added flag to drop to 1x speed if too many errors */ mcdDouble = 1; } else mcd_info.speed = 1; sprintf(msg, " mcd: Mitsumi %s Speed CD-ROM at port=0x%x," " irq=%d\n", mcd_info.speed == 1 ? "Single" : "Double", mcd_port, mcd_irq); outb(MCMD_CONFIG_DRIVE, MCDPORT(0)); outb(0x02, MCDPORT(0)); outb(0x00, MCDPORT(0)); getValue(result); outb(MCMD_CONFIG_DRIVE, MCDPORT(0)); outb(0x10, MCDPORT(0)); outb(0x04, MCDPORT(0)); getValue(result); mcd_invalidate_buffers(); mcdPresent = 1; disk->major = MAJOR_NR; disk->first_minor = 0; sprintf(disk->disk_name, "mcd"); disk->fops = &mcd_bdops; disk->flags = GENHD_FL_CD; mcd_gendisk = disk; if (register_cdrom(&mcd_info) != 0) { printk(KERN_ERR "mcd: Unable to register Mitsumi CD-ROM.\n"); goto out_cdrom; } disk->queue = mcd_queue; add_disk(disk); printk(msg); return 0; out_cdrom: free_irq(mcd_irq, NULL); out_queue: release_region(mcd_port, 4); out_probe: blk_cleanup_queue(mcd_queue); out_region: unregister_blkdev(MAJOR_NR, "mcd"); put_disk(disk); return -EIO; }
int td_linux_block_register(struct td_osdev *dev, int major) { int rc; int first_minor; struct gendisk *disk; td_os_info(dev, "LINUX_BLOCK_REGISTER\n"); /* WARN_TD_DEVICE_UNLOCKED(dev); */ WARN_ON(!dev->queue); if (!dev->block_params.capacity) { td_os_err(dev, "Cannot create a block device until " "capacity is known\n"); rc = -EINVAL; goto error_capacity; } /* generate a disk */ disk = dev->disk = alloc_disk(TD_DEVICE_PARTITIONS_MAX); if (!disk) { td_os_err(dev, "Error allocating disk structure\n"); rc = -ENOMEM; goto error_alloc_disk; } /* figure out where the first minor number will be */ first_minor = dev->unique_id * TD_DEVICE_PARTITIONS_MAX; disk->major = major; disk->first_minor = first_minor; disk->minors = TD_DEVICE_PARTITIONS_MAX; disk->fops = &td_device_block_fops; disk->private_data = dev; disk->queue = dev->queue; strncpy(disk->disk_name, dev->name, sizeof(disk->disk_name)-1); /* set the disk capacity */ td_os_info(dev, "Setting disk capacity to %llu bytes (%llu sectors)\n", dev->block_params.capacity, dev->block_params.capacity>>SECTOR_SHIFT); set_capacity(disk, dev->block_params.capacity >> SECTOR_SHIFT); add_disk(disk); #ifdef CONFIG_PM rc = td_osdev_os_register_platform_device(dev); if (rc) { pr_err("Failed to platform device err=%d.\n", rc); goto error_plat_dev; } #endif return 0; #ifdef CONFIG_PM error_plat_dev: #endif dev->disk = NULL; del_gendisk(disk); put_disk(disk); error_alloc_disk: error_capacity: return rc; }
static int __init hd_init(void) { int drive; if (register_blkdev(MAJOR_NR, "hd")) return -1; hd_queue = blk_init_queue(do_hd_request, &hd_lock); if (!hd_queue) { unregister_blkdev(MAJOR_NR, "hd"); return -ENOMEM; } blk_queue_max_sectors(hd_queue, 255); init_timer(&device_timer); device_timer.function = hd_times_out; blk_queue_hardsect_size(hd_queue, 512); if (!NR_HD) { /* * We don't know anything about the drive. This means * that you *MUST* specify the drive parameters to the * kernel yourself. * * If we were on an i386, we used to read this info from * the BIOS or CMOS. This doesn't work all that well, * since this assumes that this is a primary or secondary * drive, and if we're using this legacy driver, it's * probably an auxilliary controller added to recover * legacy data off an ST-506 drive. Either way, it's * definitely safest to have the user explicitly specify * the information. */ printk("hd: no drives specified - use hd=cyl,head,sectors" " on kernel command line\n"); goto out; } for (drive = 0 ; drive < NR_HD ; drive++) { struct gendisk *disk = alloc_disk(64); struct hd_i_struct *p = &hd_info[drive]; if (!disk) goto Enomem; disk->major = MAJOR_NR; disk->first_minor = drive << 6; disk->fops = &hd_fops; sprintf(disk->disk_name, "hd%c", 'a'+drive); disk->private_data = p; set_capacity(disk, p->head * p->sect * p->cyl); disk->queue = hd_queue; p->unit = drive; hd_gendisk[drive] = disk; printk("%s: %luMB, CHS=%d/%d/%d\n", disk->disk_name, (unsigned long)get_capacity(disk)/2048, p->cyl, p->head, p->sect); } if (request_irq(HD_IRQ, hd_interrupt, IRQF_DISABLED, "hd", NULL)) { printk("hd: unable to get IRQ%d for the hard disk driver\n", HD_IRQ); goto out1; } if (!request_region(HD_DATA, 8, "hd")) { printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); goto out2; } if (!request_region(HD_CMD, 1, "hd(cmd)")) { printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD); goto out3; } /* Let them fly */ for (drive = 0; drive < NR_HD; drive++) add_disk(hd_gendisk[drive]); return 0; out3: release_region(HD_DATA, 8); out2: free_irq(HD_IRQ, NULL); out1: for (drive = 0; drive < NR_HD; drive++) put_disk(hd_gendisk[drive]); NR_HD = 0; out: del_timer(&device_timer); unregister_blkdev(MAJOR_NR, "hd"); blk_cleanup_queue(hd_queue); return -1; Enomem: while (drive--) put_disk(hd_gendisk[drive]); goto out; }