Commit a0610a8a authored by Jan Höppner's avatar Jan Höppner Committed by Vasily Gorbik

s390/dasd: Make dasd_setup_queue() a discipline function

ECKD, FBA, and the DIAG discipline use slightly different block layer
settings. In preparation of even more diverse queue settings, make
dasd_setup_queue() a discipline function.
Signed-off-by: default avatarJan Höppner <hoeppner@linux.ibm.com>
Reviewed-by: default avatarStefan Haberland <sth@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 91dc4a19
...@@ -70,7 +70,6 @@ MODULE_LICENSE("GPL"); ...@@ -70,7 +70,6 @@ MODULE_LICENSE("GPL");
* SECTION: prototypes for static functions of dasd.c * SECTION: prototypes for static functions of dasd.c
*/ */
static int dasd_alloc_queue(struct dasd_block *); static int dasd_alloc_queue(struct dasd_block *);
static void dasd_setup_queue(struct dasd_block *);
static void dasd_free_queue(struct dasd_block *); static void dasd_free_queue(struct dasd_block *);
static int dasd_flush_block_queue(struct dasd_block *); static int dasd_flush_block_queue(struct dasd_block *);
static void dasd_device_tasklet(unsigned long); static void dasd_device_tasklet(unsigned long);
...@@ -358,7 +357,8 @@ static int dasd_state_basic_to_ready(struct dasd_device *device) ...@@ -358,7 +357,8 @@ static int dasd_state_basic_to_ready(struct dasd_device *device)
} }
return rc; return rc;
} }
dasd_setup_queue(block); if (device->discipline->setup_blk_queue)
device->discipline->setup_blk_queue(block);
set_capacity(block->gdp, set_capacity(block->gdp,
block->blocks << block->s2b_shift); block->blocks << block->s2b_shift);
device->state = DASD_STATE_READY; device->state = DASD_STATE_READY;
...@@ -3249,55 +3249,6 @@ static int dasd_alloc_queue(struct dasd_block *block) ...@@ -3249,55 +3249,6 @@ static int dasd_alloc_queue(struct dasd_block *block)
return 0; return 0;
} }
/*
* Allocate and initialize request queue.
*/
static void dasd_setup_queue(struct dasd_block *block)
{
unsigned int logical_block_size = block->bp_block;
struct request_queue *q = block->request_queue;
unsigned int max_bytes, max_discard_sectors;
int max;
if (block->base->features & DASD_FEATURE_USERAW) {
/*
* the max_blocks value for raw_track access is 256
* it is higher than the native ECKD value because we
* only need one ccw per track
* so the max_hw_sectors are
* 2048 x 512B = 1024kB = 16 tracks
*/
max = 2048;
} else {
max = block->base->discipline->max_blocks << block->s2b_shift;
}
blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
q->limits.max_dev_sectors = max;
blk_queue_logical_block_size(q, logical_block_size);
blk_queue_max_hw_sectors(q, max);
blk_queue_max_segments(q, USHRT_MAX);
/* with page sized segments we can translate each segement into
* one idaw/tidaw
*/
blk_queue_max_segment_size(q, PAGE_SIZE);
blk_queue_segment_boundary(q, PAGE_SIZE - 1);
/* Only activate blocklayer discard support for devices that support it */
if (block->base->features & DASD_FEATURE_DISCARD) {
q->limits.discard_granularity = logical_block_size;
q->limits.discard_alignment = PAGE_SIZE;
/* Calculate max_discard_sectors and make it PAGE aligned */
max_bytes = USHRT_MAX * logical_block_size;
max_bytes = ALIGN(max_bytes, PAGE_SIZE) - PAGE_SIZE;
max_discard_sectors = max_bytes / logical_block_size;
blk_queue_max_discard_sectors(q, max_discard_sectors);
blk_queue_max_write_zeroes_sectors(q, max_discard_sectors);
blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
}
}
/* /*
* Deactivate and free request queue. * Deactivate and free request queue.
*/ */
......
...@@ -615,14 +615,34 @@ dasd_diag_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, ...@@ -615,14 +615,34 @@ dasd_diag_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
"dump sense not available for DIAG data"); "dump sense not available for DIAG data");
} }
/*
* Initialize block layer request queue.
*/
static void dasd_diag_setup_blk_queue(struct dasd_block *block)
{
unsigned int logical_block_size = block->bp_block;
struct request_queue *q = block->request_queue;
int max;
max = DIAG_MAX_BLOCKS << block->s2b_shift;
blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
q->limits.max_dev_sectors = max;
blk_queue_logical_block_size(q, logical_block_size);
blk_queue_max_hw_sectors(q, max);
blk_queue_max_segments(q, USHRT_MAX);
/* With page sized segments each segment can be translated into one idaw/tidaw */
blk_queue_max_segment_size(q, PAGE_SIZE);
blk_queue_segment_boundary(q, PAGE_SIZE - 1);
}
static struct dasd_discipline dasd_diag_discipline = { static struct dasd_discipline dasd_diag_discipline = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "DIAG", .name = "DIAG",
.ebcname = "DIAG", .ebcname = "DIAG",
.max_blocks = DIAG_MAX_BLOCKS,
.check_device = dasd_diag_check_device, .check_device = dasd_diag_check_device,
.verify_path = dasd_generic_verify_path, .verify_path = dasd_generic_verify_path,
.fill_geometry = dasd_diag_fill_geometry, .fill_geometry = dasd_diag_fill_geometry,
.setup_blk_queue = dasd_diag_setup_blk_queue,
.start_IO = dasd_start_diag, .start_IO = dasd_start_diag,
.term_IO = dasd_diag_term_IO, .term_IO = dasd_diag_term_IO,
.handle_terminated_request = dasd_diag_handle_terminated_request, .handle_terminated_request = dasd_diag_handle_terminated_request,
......
...@@ -6349,6 +6349,38 @@ static void dasd_eckd_handle_hpf_error(struct dasd_device *device, ...@@ -6349,6 +6349,38 @@ static void dasd_eckd_handle_hpf_error(struct dasd_device *device,
dasd_schedule_requeue(device); dasd_schedule_requeue(device);
} }
/*
* Initialize block layer request queue.
*/
static void dasd_eckd_setup_blk_queue(struct dasd_block *block)
{
unsigned int logical_block_size = block->bp_block;
struct request_queue *q = block->request_queue;
struct dasd_device *device = block->base;
int max;
if (device->features & DASD_FEATURE_USERAW) {
/*
* the max_blocks value for raw_track access is 256
* it is higher than the native ECKD value because we
* only need one ccw per track
* so the max_hw_sectors are
* 2048 x 512B = 1024kB = 16 tracks
*/
max = DASD_ECKD_MAX_BLOCKS_RAW << block->s2b_shift;
} else {
max = DASD_ECKD_MAX_BLOCKS << block->s2b_shift;
}
blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
q->limits.max_dev_sectors = max;
blk_queue_logical_block_size(q, logical_block_size);
blk_queue_max_hw_sectors(q, max);
blk_queue_max_segments(q, USHRT_MAX);
/* With page sized segments each segment can be translated into one idaw/tidaw */
blk_queue_max_segment_size(q, PAGE_SIZE);
blk_queue_segment_boundary(q, PAGE_SIZE - 1);
}
static struct ccw_driver dasd_eckd_driver = { static struct ccw_driver dasd_eckd_driver = {
.driver = { .driver = {
.name = "dasd-eckd", .name = "dasd-eckd",
...@@ -6369,24 +6401,10 @@ static struct ccw_driver dasd_eckd_driver = { ...@@ -6369,24 +6401,10 @@ static struct ccw_driver dasd_eckd_driver = {
.int_class = IRQIO_DAS, .int_class = IRQIO_DAS,
}; };
/*
* max_blocks is dependent on the amount of storage that is available
* in the static io buffer for each device. Currently each device has
* 8192 bytes (=2 pages). For 64 bit one dasd_mchunkt_t structure has
* 24 bytes, the struct dasd_ccw_req has 136 bytes and each block can use
* up to 16 bytes (8 for the ccw and 8 for the idal pointer). In
* addition we have one define extent ccw + 16 bytes of data and one
* locate record ccw + 16 bytes of data. That makes:
* (8192 - 24 - 136 - 8 - 16 - 8 - 16) / 16 = 499 blocks at maximum.
* We want to fit two into the available memory so that we can immediately
* start the next request if one finishes off. That makes 249.5 blocks
* for one request. Give a little safety and the result is 240.
*/
static struct dasd_discipline dasd_eckd_discipline = { static struct dasd_discipline dasd_eckd_discipline = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "ECKD", .name = "ECKD",
.ebcname = "ECKD", .ebcname = "ECKD",
.max_blocks = 190,
.check_device = dasd_eckd_check_characteristics, .check_device = dasd_eckd_check_characteristics,
.uncheck_device = dasd_eckd_uncheck_device, .uncheck_device = dasd_eckd_uncheck_device,
.do_analysis = dasd_eckd_do_analysis, .do_analysis = dasd_eckd_do_analysis,
...@@ -6394,6 +6412,7 @@ static struct dasd_discipline dasd_eckd_discipline = { ...@@ -6394,6 +6412,7 @@ static struct dasd_discipline dasd_eckd_discipline = {
.basic_to_ready = dasd_eckd_basic_to_ready, .basic_to_ready = dasd_eckd_basic_to_ready,
.online_to_ready = dasd_eckd_online_to_ready, .online_to_ready = dasd_eckd_online_to_ready,
.basic_to_known = dasd_eckd_basic_to_known, .basic_to_known = dasd_eckd_basic_to_known,
.setup_blk_queue = dasd_eckd_setup_blk_queue,
.fill_geometry = dasd_eckd_fill_geometry, .fill_geometry = dasd_eckd_fill_geometry,
.start_IO = dasd_start_IO, .start_IO = dasd_start_IO,
.term_IO = dasd_term_IO, .term_IO = dasd_term_IO,
......
...@@ -109,6 +109,12 @@ ...@@ -109,6 +109,12 @@
#define DASD_ECKD_PATH_THRHLD 256 #define DASD_ECKD_PATH_THRHLD 256
#define DASD_ECKD_PATH_INTERVAL 300 #define DASD_ECKD_PATH_INTERVAL 300
/*
* Maximum number of blocks to be chained
*/
#define DASD_ECKD_MAX_BLOCKS 190
#define DASD_ECKD_MAX_BLOCKS_RAW 256
/***************************************************************************** /*****************************************************************************
* SECTION: Type Definitions * SECTION: Type Definitions
****************************************************************************/ ****************************************************************************/
......
...@@ -770,27 +770,46 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, ...@@ -770,27 +770,46 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
} }
/* /*
* max_blocks is dependent on the amount of storage that is available * Initialize block layer request queue.
* in the static io buffer for each device. Currently each device has
* 8192 bytes (=2 pages). For 64 bit one dasd_mchunkt_t structure has
* 24 bytes, the struct dasd_ccw_req has 136 bytes and each block can use
* up to 16 bytes (8 for the ccw and 8 for the idal pointer). In
* addition we have one define extent ccw + 16 bytes of data and a
* locate record ccw for each block (stupid devices!) + 16 bytes of data.
* That makes:
* (8192 - 24 - 136 - 8 - 16) / 40 = 200.2 blocks at maximum.
* We want to fit two into the available memory so that we can immediately
* start the next request if one finishes off. That makes 100.1 blocks
* for one request. Give a little safety and the result is 96.
*/ */
static void dasd_fba_setup_blk_queue(struct dasd_block *block)
{
unsigned int logical_block_size = block->bp_block;
struct request_queue *q = block->request_queue;
unsigned int max_bytes, max_discard_sectors;
int max;
max = DASD_FBA_MAX_BLOCKS << block->s2b_shift;
blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
q->limits.max_dev_sectors = max;
blk_queue_logical_block_size(q, logical_block_size);
blk_queue_max_hw_sectors(q, max);
blk_queue_max_segments(q, USHRT_MAX);
/* With page sized segments each segment can be translated into one idaw/tidaw */
blk_queue_max_segment_size(q, PAGE_SIZE);
blk_queue_segment_boundary(q, PAGE_SIZE - 1);
q->limits.discard_granularity = logical_block_size;
q->limits.discard_alignment = PAGE_SIZE;
/* Calculate max_discard_sectors and make it PAGE aligned */
max_bytes = USHRT_MAX * logical_block_size;
max_bytes = ALIGN(max_bytes, PAGE_SIZE) - PAGE_SIZE;
max_discard_sectors = max_bytes / logical_block_size;
blk_queue_max_discard_sectors(q, max_discard_sectors);
blk_queue_max_write_zeroes_sectors(q, max_discard_sectors);
blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
}
static struct dasd_discipline dasd_fba_discipline = { static struct dasd_discipline dasd_fba_discipline = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "FBA ", .name = "FBA ",
.ebcname = "FBA ", .ebcname = "FBA ",
.max_blocks = 96,
.check_device = dasd_fba_check_characteristics, .check_device = dasd_fba_check_characteristics,
.do_analysis = dasd_fba_do_analysis, .do_analysis = dasd_fba_do_analysis,
.verify_path = dasd_generic_verify_path, .verify_path = dasd_generic_verify_path,
.setup_blk_queue = dasd_fba_setup_blk_queue,
.fill_geometry = dasd_fba_fill_geometry, .fill_geometry = dasd_fba_fill_geometry,
.start_IO = dasd_start_IO, .start_IO = dasd_start_IO,
.term_IO = dasd_term_IO, .term_IO = dasd_term_IO,
......
...@@ -9,6 +9,11 @@ ...@@ -9,6 +9,11 @@
#ifndef DASD_FBA_H #ifndef DASD_FBA_H
#define DASD_FBA_H #define DASD_FBA_H
/*
* Maximum number of blocks to be chained
*/
#define DASD_FBA_MAX_BLOCKS 96
struct DE_fba_data { struct DE_fba_data {
struct { struct {
unsigned char perm:2; /* Permissions on this extent */ unsigned char perm:2; /* Permissions on this extent */
......
...@@ -268,7 +268,6 @@ struct dasd_discipline { ...@@ -268,7 +268,6 @@ struct dasd_discipline {
struct module *owner; struct module *owner;
char ebcname[8]; /* a name used for tagging and printks */ char ebcname[8]; /* a name used for tagging and printks */
char name[8]; /* a name used for tagging and printks */ char name[8]; /* a name used for tagging and printks */
int max_blocks; /* maximum number of blocks to be chained */
struct list_head list; /* used for list of disciplines */ struct list_head list; /* used for list of disciplines */
...@@ -307,6 +306,10 @@ struct dasd_discipline { ...@@ -307,6 +306,10 @@ struct dasd_discipline {
int (*online_to_ready) (struct dasd_device *); int (*online_to_ready) (struct dasd_device *);
int (*basic_to_known)(struct dasd_device *); int (*basic_to_known)(struct dasd_device *);
/*
* Initialize block layer request queue.
*/
void (*setup_blk_queue)(struct dasd_block *);
/* (struct dasd_device *); /* (struct dasd_device *);
* Device operation functions. build_cp creates a ccw chain for * Device operation functions. build_cp creates a ccw chain for
* a block device request, start_io starts the request and * a block device request, start_io starts the request and
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment