drivers/s390/block/scm_blk.c
Source file repositories/reference/linux-study-clean/drivers/s390/block/scm_blk.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/s390/block/scm_blk.c- Extension
.c- Size
- 13610 bytes
- Lines
- 582
- Domain
- Driver Families
- Bucket
- drivers/s390
- Inferred role
- Driver Families: operation-table or driver-model contract
- Status
- pattern implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/interrupt.hlinux/spinlock.hlinux/mempool.hlinux/module.hlinux/blkdev.hlinux/blk-mq.hlinux/slab.hlinux/list.hlinux/io.hasm/eadm.hscm_blk.h
Detected Declarations
struct scm_queuefunction __scm_free_rqfunction scm_free_rqsfunction __scm_alloc_rqfunction scm_alloc_rqsfunction scm_request_donefunction scm_permit_requestfunction scm_aidaw_bytesfunction scm_request_preparefunction rq_for_each_segmentfunction scm_request_setfunction scm_request_initfunction scm_request_requeuefunction scm_request_finishfunction scm_request_startfunction scm_blk_requestfunction scm_blk_init_hctxfunction scm_blk_exit_hctxfunction __scmrq_log_errorfunction scm_blk_handle_errorfunction scm_blk_irqfunction scm_blk_request_donefunction scm_blk_dev_setupfunction scm_blk_dev_cleanupfunction scm_blk_set_availablefunction scm_blk_params_validfunction scm_blk_initfunction scm_blk_cleanupmodule init scm_blk_init
Annotated Snippet
static const struct blk_mq_ops scm_mq_ops = {
.queue_rq = scm_blk_request,
.complete = scm_blk_request_done,
.init_hctx = scm_blk_init_hctx,
.exit_hctx = scm_blk_exit_hctx,
};
int scm_blk_dev_setup(struct scm_blk_dev *bdev, struct scm_device *scmdev)
{
struct queue_limits lim = {
.logical_block_size = 1 << 12,
};
unsigned int devindex;
int len, ret;
lim.max_segments = min(scmdev->nr_max_block,
(unsigned int) (PAGE_SIZE / sizeof(struct aidaw)));
lim.max_hw_sectors = lim.max_segments << 3; /* 8 * 512 = blk_size */
devindex = atomic_inc_return(&nr_devices) - 1;
/* scma..scmz + scmaa..scmzz */
if (devindex > 701) {
ret = -ENODEV;
goto out;
}
bdev->scmdev = scmdev;
bdev->state = SCM_OPER;
spin_lock_init(&bdev->lock);
atomic_set(&bdev->queued_reqs, 0);
bdev->tag_set.ops = &scm_mq_ops;
bdev->tag_set.cmd_size = sizeof(blk_status_t);
bdev->tag_set.nr_hw_queues = nr_requests;
bdev->tag_set.queue_depth = nr_requests_per_io * nr_requests;
bdev->tag_set.numa_node = NUMA_NO_NODE;
ret = blk_mq_alloc_tag_set(&bdev->tag_set);
if (ret)
goto out;
bdev->gendisk = blk_mq_alloc_disk(&bdev->tag_set, &lim, scmdev);
if (IS_ERR(bdev->gendisk)) {
ret = PTR_ERR(bdev->gendisk);
goto out_tag;
}
bdev->gendisk->private_data = scmdev;
bdev->gendisk->fops = &scm_blk_devops;
bdev->gendisk->major = scm_major;
bdev->gendisk->first_minor = devindex * SCM_NR_PARTS;
bdev->gendisk->minors = SCM_NR_PARTS;
len = snprintf(bdev->gendisk->disk_name, DISK_NAME_LEN, "scm");
if (devindex > 25) {
len += snprintf(bdev->gendisk->disk_name + len,
DISK_NAME_LEN - len, "%c",
'a' + (devindex / 26) - 1);
devindex = devindex % 26;
}
snprintf(bdev->gendisk->disk_name + len, DISK_NAME_LEN - len, "%c",
'a' + devindex);
/* 512 byte sectors */
set_capacity(bdev->gendisk, scmdev->size >> 9);
ret = device_add_disk(&scmdev->dev, bdev->gendisk, NULL);
if (ret)
goto out_cleanup_disk;
return 0;
out_cleanup_disk:
put_disk(bdev->gendisk);
out_tag:
blk_mq_free_tag_set(&bdev->tag_set);
out:
atomic_dec(&nr_devices);
return ret;
}
void scm_blk_dev_cleanup(struct scm_blk_dev *bdev)
{
del_gendisk(bdev->gendisk);
put_disk(bdev->gendisk);
blk_mq_free_tag_set(&bdev->tag_set);
}
void scm_blk_set_available(struct scm_blk_dev *bdev)
{
unsigned long flags;
Annotation
- Immediate include surface: `linux/interrupt.h`, `linux/spinlock.h`, `linux/mempool.h`, `linux/module.h`, `linux/blkdev.h`, `linux/blk-mq.h`, `linux/slab.h`, `linux/list.h`.
- Detected declarations: `struct scm_queue`, `function __scm_free_rq`, `function scm_free_rqs`, `function __scm_alloc_rq`, `function scm_alloc_rqs`, `function scm_request_done`, `function scm_permit_request`, `function scm_aidaw_bytes`, `function scm_request_prepare`, `function rq_for_each_segment`.
- Atlas domain: Driver Families / drivers/s390.
- Implementation status: pattern implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.