Commit aabfea8d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 's390-5.3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull more s390 updates from Vasily Gorbik:

 - Fix integer overflow during stack frame unwind with invalid
   backchain.

 - Cleanup unused symbol export in zcrypt code.

 - Fix MIO addressing control activation in PCI code and expose its
   usage via sysfs.

 - Fix kernel image signature verification report presence detection.

 - Fix irq registration in vfio-ap code.

 - Add CPU measurement counters for newer machines.

 - Add base DASD thin provisioning support and code cleanups.

* tag 's390-5.3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (21 commits)
  s390/unwind: avoid int overflow in outside_of_stack
  s390/zcrypt: remove the exporting of ap_query_configuration
  s390/pci: add mio_enabled attribute
  s390: fix setting of mio addressing control
  s390/ipl: Fix detection of has_secure attribute
  s390: vfio-ap: fix irq registration
  s390/cpumf: Add extended counter set definitions for model 8561 and 8562
  s390/dasd: Handle out-of-space constraint
  s390/dasd: Add discard support for ESE volumes
  s390/dasd: Use ALIGN_DOWN macro
  s390/dasd: Make dasd_setup_queue() a discipline function
  s390/dasd: Add new ioctl to release space
  s390/dasd: Add dasd_sleep_on_queue_interruptible()
  s390/dasd: Add missing intensity definition
  s390/dasd: Fix whitespace
  s390/dasd: Add dynamic formatting support for ESE volumes
  s390/dasd: Recognise data for ESE volumes
  s390/dasd: Put sub-order definitions in a separate section
  s390/dasd: Make layout analysis ESE compatible
  s390/dasd: Remove old defines and function
  ...
parents 7181feb9 9a159190
...@@ -143,14 +143,4 @@ static inline int zpci_set_irq_ctrl(u16 ctl, u8 isc) ...@@ -143,14 +143,4 @@ static inline int zpci_set_irq_ctrl(u16 ctl, u8 isc)
return __zpci_set_irq_ctrl(ctl, isc, &iib); return __zpci_set_irq_ctrl(ctl, isc, &iib);
} }
#ifdef CONFIG_PCI
static inline void enable_mio_ctl(void)
{
if (static_branch_likely(&have_mio))
__ctl_set_bit(2, 5);
}
#else /* CONFIG_PCI */
static inline void enable_mio_ctl(void) {}
#endif /* CONFIG_PCI */
#endif #endif
...@@ -80,7 +80,6 @@ struct sclp_info { ...@@ -80,7 +80,6 @@ struct sclp_info {
unsigned char has_gisaf : 1; unsigned char has_gisaf : 1;
unsigned char has_diag318 : 1; unsigned char has_diag318 : 1;
unsigned char has_sipl : 1; unsigned char has_sipl : 1;
unsigned char has_sipl_g2 : 1;
unsigned char has_dirq : 1; unsigned char has_dirq : 1;
unsigned int ibc; unsigned int ibc;
unsigned int mtid; unsigned int mtid;
......
This diff is collapsed.
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include <asm/sclp.h> #include <asm/sclp.h>
#include <asm/facility.h> #include <asm/facility.h>
#include <asm/boot_data.h> #include <asm/boot_data.h>
#include <asm/pci_insn.h>
#include "entry.h" #include "entry.h"
/* /*
...@@ -236,7 +235,6 @@ static __init void detect_machine_facilities(void) ...@@ -236,7 +235,6 @@ static __init void detect_machine_facilities(void)
clock_comparator_max = -1ULL >> 1; clock_comparator_max = -1ULL >> 1;
__ctl_set_bit(0, 53); __ctl_set_bit(0, 53);
} }
enable_mio_ctl();
} }
static inline void save_vector_registers(void) static inline void save_vector_registers(void)
......
...@@ -286,12 +286,7 @@ static struct kobj_attribute sys_ipl_secure_attr = ...@@ -286,12 +286,7 @@ static struct kobj_attribute sys_ipl_secure_attr =
static ssize_t ipl_has_secure_show(struct kobject *kobj, static ssize_t ipl_has_secure_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page) struct kobj_attribute *attr, char *page)
{ {
if (MACHINE_IS_LPAR) return sprintf(page, "%i\n", !!sclp.has_sipl);
return sprintf(page, "%i\n", !!sclp.has_sipl);
else if (MACHINE_IS_VM)
return sprintf(page, "%i\n", !!sclp.has_sipl_g2);
else
return sprintf(page, "%i\n", 0);
} }
static struct kobj_attribute sys_ipl_has_secure_attr = static struct kobj_attribute sys_ipl_has_secure_attr =
......
...@@ -624,6 +624,8 @@ __init const struct attribute_group **cpumf_cf_event_group(void) ...@@ -624,6 +624,8 @@ __init const struct attribute_group **cpumf_cf_event_group(void)
break; break;
case 0x3906: case 0x3906:
case 0x3907: case 0x3907:
case 0x8561:
case 0x8562:
model = cpumcf_z14_pmu_event_attr; model = cpumcf_z14_pmu_event_attr;
break; break;
default: default:
......
...@@ -20,7 +20,7 @@ EXPORT_SYMBOL_GPL(unwind_get_return_address); ...@@ -20,7 +20,7 @@ EXPORT_SYMBOL_GPL(unwind_get_return_address);
static bool outside_of_stack(struct unwind_state *state, unsigned long sp) static bool outside_of_stack(struct unwind_state *state, unsigned long sp)
{ {
return (sp <= state->sp) || return (sp <= state->sp) ||
(sp + sizeof(struct stack_frame) > state->stack_info.end); (sp > state->stack_info.end - sizeof(struct stack_frame));
} }
static bool update_stack_info(struct unwind_state *state, unsigned long sp) static bool update_stack_info(struct unwind_state *state, unsigned long sp)
......
...@@ -890,8 +890,10 @@ static int __init pci_base_init(void) ...@@ -890,8 +890,10 @@ static int __init pci_base_init(void)
if (!test_facility(69) || !test_facility(71)) if (!test_facility(69) || !test_facility(71))
return 0; return 0;
if (test_facility(153) && !s390_pci_no_mio) if (test_facility(153) && !s390_pci_no_mio) {
static_branch_enable(&have_mio); static_branch_enable(&have_mio);
ctl_set_bit(2, 5);
}
rc = zpci_debug_init(); rc = zpci_debug_init();
if (rc) if (rc)
......
...@@ -37,6 +37,15 @@ zpci_attr(segment1, "0x%02x\n", pfip[1]); ...@@ -37,6 +37,15 @@ zpci_attr(segment1, "0x%02x\n", pfip[1]);
zpci_attr(segment2, "0x%02x\n", pfip[2]); zpci_attr(segment2, "0x%02x\n", pfip[2]);
zpci_attr(segment3, "0x%02x\n", pfip[3]); zpci_attr(segment3, "0x%02x\n", pfip[3]);
static ssize_t mio_enabled_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
return sprintf(buf, zpci_use_mio(zdev) ? "1\n" : "0\n");
}
static DEVICE_ATTR_RO(mio_enabled);
static ssize_t recover_store(struct device *dev, struct device_attribute *attr, static ssize_t recover_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
...@@ -115,6 +124,7 @@ static struct attribute *zpci_dev_attrs[] = { ...@@ -115,6 +124,7 @@ static struct attribute *zpci_dev_attrs[] = {
&dev_attr_vfn.attr, &dev_attr_vfn.attr,
&dev_attr_uid.attr, &dev_attr_uid.attr,
&dev_attr_recover.attr, &dev_attr_recover.attr,
&dev_attr_mio_enabled.attr,
NULL, NULL,
}; };
static struct attribute_group zpci_attr_group = { static struct attribute_group zpci_attr_group = {
......
This diff is collapsed.
...@@ -1642,6 +1642,35 @@ static DEVICE_ATTR(path_interval, 0644, dasd_path_interval_show, ...@@ -1642,6 +1642,35 @@ static DEVICE_ATTR(path_interval, 0644, dasd_path_interval_show,
dasd_path_interval_store); dasd_path_interval_store);
#define DASD_DEFINE_ATTR(_name, _func) \
static ssize_t dasd_##_name##_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
struct ccw_device *cdev = to_ccwdev(dev); \
struct dasd_device *device = dasd_device_from_cdev(cdev); \
int val = 0; \
\
if (IS_ERR(device)) \
return -ENODEV; \
if (device->discipline && _func) \
val = _func(device); \
dasd_put_device(device); \
\
return snprintf(buf, PAGE_SIZE, "%d\n", val); \
} \
static DEVICE_ATTR(_name, 0444, dasd_##_name##_show, NULL); \
DASD_DEFINE_ATTR(ese, device->discipline->is_ese);
DASD_DEFINE_ATTR(extent_size, device->discipline->ext_size);
DASD_DEFINE_ATTR(pool_id, device->discipline->ext_pool_id);
DASD_DEFINE_ATTR(space_configured, device->discipline->space_configured);
DASD_DEFINE_ATTR(space_allocated, device->discipline->space_allocated);
DASD_DEFINE_ATTR(logical_capacity, device->discipline->logical_capacity);
DASD_DEFINE_ATTR(warn_threshold, device->discipline->ext_pool_warn_thrshld);
DASD_DEFINE_ATTR(cap_at_warnlevel, device->discipline->ext_pool_cap_at_warnlevel);
DASD_DEFINE_ATTR(pool_oos, device->discipline->ext_pool_oos);
static struct attribute * dasd_attrs[] = { static struct attribute * dasd_attrs[] = {
&dev_attr_readonly.attr, &dev_attr_readonly.attr,
&dev_attr_discipline.attr, &dev_attr_discipline.attr,
...@@ -1667,6 +1696,7 @@ static struct attribute * dasd_attrs[] = { ...@@ -1667,6 +1696,7 @@ static struct attribute * dasd_attrs[] = {
&dev_attr_path_interval.attr, &dev_attr_path_interval.attr,
&dev_attr_path_reset.attr, &dev_attr_path_reset.attr,
&dev_attr_hpf.attr, &dev_attr_hpf.attr,
&dev_attr_ese.attr,
NULL, NULL,
}; };
...@@ -1674,6 +1704,39 @@ static const struct attribute_group dasd_attr_group = { ...@@ -1674,6 +1704,39 @@ static const struct attribute_group dasd_attr_group = {
.attrs = dasd_attrs, .attrs = dasd_attrs,
}; };
static struct attribute *capacity_attrs[] = {
&dev_attr_space_configured.attr,
&dev_attr_space_allocated.attr,
&dev_attr_logical_capacity.attr,
NULL,
};
static const struct attribute_group capacity_attr_group = {
.name = "capacity",
.attrs = capacity_attrs,
};
static struct attribute *ext_pool_attrs[] = {
&dev_attr_pool_id.attr,
&dev_attr_extent_size.attr,
&dev_attr_warn_threshold.attr,
&dev_attr_cap_at_warnlevel.attr,
&dev_attr_pool_oos.attr,
NULL,
};
static const struct attribute_group ext_pool_attr_group = {
.name = "extent_pool",
.attrs = ext_pool_attrs,
};
static const struct attribute_group *dasd_attr_groups[] = {
&dasd_attr_group,
&capacity_attr_group,
&ext_pool_attr_group,
NULL,
};
/* /*
* Return value of the specified feature. * Return value of the specified feature.
*/ */
...@@ -1715,16 +1778,15 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag) ...@@ -1715,16 +1778,15 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
EXPORT_SYMBOL(dasd_set_feature); EXPORT_SYMBOL(dasd_set_feature);
int int dasd_add_sysfs_files(struct ccw_device *cdev)
dasd_add_sysfs_files(struct ccw_device *cdev)
{ {
return sysfs_create_group(&cdev->dev.kobj, &dasd_attr_group); return sysfs_create_groups(&cdev->dev.kobj, dasd_attr_groups);
} }
void void
dasd_remove_sysfs_files(struct ccw_device *cdev) dasd_remove_sysfs_files(struct ccw_device *cdev)
{ {
sysfs_remove_group(&cdev->dev.kobj, &dasd_attr_group); sysfs_remove_groups(&cdev->dev.kobj, dasd_attr_groups);
} }
......
...@@ -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,
......
This diff is collapsed.
...@@ -50,15 +50,25 @@ ...@@ -50,15 +50,25 @@
#define DASD_ECKD_CCW_PFX_READ 0xEA #define DASD_ECKD_CCW_PFX_READ 0xEA
#define DASD_ECKD_CCW_RSCK 0xF9 #define DASD_ECKD_CCW_RSCK 0xF9
#define DASD_ECKD_CCW_RCD 0xFA #define DASD_ECKD_CCW_RCD 0xFA
#define DASD_ECKD_CCW_DSO 0xF7
/* Define Subssystem Function / Orders */
#define DSO_ORDER_RAS 0x81
/* /*
* Perform Subsystem Function / Sub-Orders * Perform Subsystem Function / Orders
*/ */
#define PSF_ORDER_PRSSD 0x18 #define PSF_ORDER_PRSSD 0x18
#define PSF_ORDER_CUIR_RESPONSE 0x1A #define PSF_ORDER_CUIR_RESPONSE 0x1A
#define PSF_SUBORDER_QHA 0x1C
#define PSF_ORDER_SSC 0x1D #define PSF_ORDER_SSC 0x1D
/*
* Perform Subsystem Function / Sub-Orders
*/
#define PSF_SUBORDER_QHA 0x1C /* Query Host Access */
#define PSF_SUBORDER_VSQ 0x52 /* Volume Storage Query */
#define PSF_SUBORDER_LCQ 0x53 /* Logical Configuration Query */
/* /*
* CUIR response condition codes * CUIR response condition codes
*/ */
...@@ -79,11 +89,23 @@ ...@@ -79,11 +89,23 @@
#define CUIR_QUIESCE 0x01 #define CUIR_QUIESCE 0x01
#define CUIR_RESUME 0x02 #define CUIR_RESUME 0x02
/*
* Out-of-space (OOS) Codes
*/
#define REPO_WARN 0x01
#define REPO_EXHAUST 0x02
#define POOL_WARN 0x03
#define POOL_EXHAUST 0x04
#define REPO_RELIEVE 0x05
#define POOL_RELIEVE 0x06
/* /*
* attention message definitions * attention message definitions
*/ */
#define ATTENTION_LENGTH_CUIR 0x0e #define ATTENTION_LENGTH_CUIR 0x0e
#define ATTENTION_FORMAT_CUIR 0x01 #define ATTENTION_FORMAT_CUIR 0x01
#define ATTENTION_LENGTH_OOS 0x10
#define ATTENTION_FORMAT_OOS 0x06
#define DASD_ECKD_PG_GROUPED 0x10 #define DASD_ECKD_PG_GROUPED 0x10
...@@ -99,6 +121,12 @@ ...@@ -99,6 +121,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
****************************************************************************/ ****************************************************************************/
...@@ -116,35 +144,12 @@ struct ch_t { ...@@ -116,35 +144,12 @@ struct ch_t {
__u16 head; __u16 head;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct chs_t {
__u16 cyl;
__u16 head;
__u32 sector;
} __attribute__ ((packed));
struct chr_t { struct chr_t {
__u16 cyl; __u16 cyl;
__u16 head; __u16 head;
__u8 record; __u8 record;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct geom_t {
__u16 cyl;
__u16 head;
__u32 sector;
} __attribute__ ((packed));
struct eckd_home {
__u8 skip_control[14];
__u16 cell_number;
__u8 physical_addr[3];
__u8 flag;
struct ch_t track_addr;
__u8 reserved;
__u8 key_length;
__u8 reserved2[2];
} __attribute__ ((packed));
struct DE_eckd_data { struct DE_eckd_data {
struct { struct {
unsigned char perm:2; /* Permissions on this extent */ unsigned char perm:2; /* Permissions on this extent */
...@@ -387,6 +392,86 @@ struct dasd_rssd_messages { ...@@ -387,6 +392,86 @@ struct dasd_rssd_messages {
char messages[4087]; char messages[4087];
} __packed; } __packed;
/*
* Read Subsystem Data - Volume Storage Query
*/
struct dasd_rssd_vsq {
struct {
__u8 tse:1;
__u8 space_not_available:1;
__u8 ese:1;
__u8 unused:5;
} __packed vol_info;
__u8 unused1;
__u16 extent_pool_id;
__u8 warn_cap_limit;
__u8 warn_cap_guaranteed;
__u16 unused2;
__u32 limit_capacity;
__u32 guaranteed_capacity;
__u32 space_allocated;
__u32 space_configured;
__u32 logical_capacity;
} __packed;
/*
* Extent Pool Summary
*/
struct dasd_ext_pool_sum {
__u16 pool_id;
__u8 repo_warn_thrshld;
__u8 warn_thrshld;
struct {
__u8 type:1; /* 0 - CKD / 1 - FB */
__u8 track_space_efficient:1;
__u8 extent_space_efficient:1;
__u8 standard_volume:1;
__u8 extent_size_valid:1;
__u8 capacity_at_warnlevel:1;
__u8 pool_oos:1;
__u8 unused0:1;
__u8 unused1;
} __packed flags;
struct {
__u8 reserved0:1;
__u8 size_1G:1;
__u8 reserved1:5;
__u8 size_16M:1;
} __packed extent_size;
__u8 unused;
} __packed;
/*
* Read Subsystem Data-Response - Logical Configuration Query - Header
*/
struct dasd_rssd_lcq {
__u16 data_length; /* Length of data returned */
__u16 pool_count; /* Count of extent pools returned - Max: 448 */
struct {
__u8 pool_info_valid:1; /* Detailed Information valid */
__u8 pool_id_volume:1;
__u8 pool_id_cec:1;
__u8 unused0:5;
__u8 unused1;
} __packed header_flags;
char sfi_type[6]; /* Storage Facility Image Type (EBCDIC) */
char sfi_model[3]; /* Storage Facility Image Model (EBCDIC) */
__u8 sfi_seq_num[10]; /* Storage Facility Image Sequence Number */
__u8 reserved[7];
struct dasd_ext_pool_sum ext_pool_sum[448];
} __packed;
struct dasd_oos_message {
__u16 length;
__u8 format;
__u8 code;
__u8 percentage_empty;
__u8 reserved;
__u16 ext_pool_id;
__u16 token;
__u8 unused[6];
} __packed;
struct dasd_cuir_message { struct dasd_cuir_message {
__u16 length; __u16 length;
__u8 format; __u8 format;
...@@ -461,6 +546,42 @@ struct dasd_psf_ssc_data { ...@@ -461,6 +546,42 @@ struct dasd_psf_ssc_data {
unsigned char reserved[59]; unsigned char reserved[59];
} __attribute__((packed)); } __attribute__((packed));
/* Maximum number of extents for a single Release Allocated Space command */
#define DASD_ECKD_RAS_EXTS_MAX 110U
struct dasd_dso_ras_ext_range {
struct ch_t beg_ext;
struct ch_t end_ext;
} __packed;
/*
* Define Subsytem Operation - Release Allocated Space
*/
struct dasd_dso_ras_data {
__u8 order;
struct {
__u8 message:1; /* Must be zero */
__u8 reserved1:2;
__u8 vol_type:1; /* 0 - CKD/FBA, 1 - FB */
__u8 reserved2:4;
} __packed flags;
/* Operation Flags to specify scope */
struct {
__u8 reserved1:2;
/* Release Space by Extent */
__u8 by_extent:1; /* 0 - entire volume, 1 - specified extents */
__u8 guarantee_init:1;
__u8 force_release:1; /* Internal - will be ignored */
__u16 reserved2:11;
} __packed op_flags;
__u8 lss;
__u8 dev_addr;
__u32 reserved1;
__u8 reserved2[10];
__u16 nr_exts; /* Defines number of ext_scope - max 110 */
__u16 reserved3;
} __packed;
/* /*
* some structures and definitions for alias handling * some structures and definitions for alias handling
...@@ -551,6 +672,8 @@ struct dasd_eckd_private { ...@@ -551,6 +672,8 @@ struct dasd_eckd_private {
int uses_cdl; int uses_cdl;
struct attrib_data_t attrib; /* e.g. cache operations */ struct attrib_data_t attrib; /* e.g. cache operations */
struct dasd_rssd_features features; struct dasd_rssd_features features;
struct dasd_rssd_vsq vsq;
struct dasd_ext_pool_sum eps;
u32 real_cyl; u32 real_cyl;
/* alias managemnet */ /* alias managemnet */
...@@ -572,7 +695,5 @@ int dasd_alias_remove_device(struct dasd_device *); ...@@ -572,7 +695,5 @@ int dasd_alias_remove_device(struct dasd_device *);
struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *); struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *);
void dasd_alias_handle_summary_unit_check(struct work_struct *); void dasd_alias_handle_summary_unit_check(struct work_struct *);
void dasd_eckd_reset_ccw_to_base_io(struct dasd_ccw_req *); void dasd_eckd_reset_ccw_to_base_io(struct dasd_ccw_req *);
void dasd_alias_lcu_setup_complete(struct dasd_device *);
void dasd_alias_wait_for_lcu_setup(struct dasd_device *);
int dasd_alias_update_add_device(struct dasd_device *); int dasd_alias_update_add_device(struct dasd_device *);
#endif /* DASD_ECKD_H */ #endif /* DASD_ECKD_H */
...@@ -386,6 +386,7 @@ void dasd_eer_write(struct dasd_device *device, struct dasd_ccw_req *cqr, ...@@ -386,6 +386,7 @@ void dasd_eer_write(struct dasd_device *device, struct dasd_ccw_req *cqr,
dasd_eer_write_standard_trigger(device, cqr, id); dasd_eer_write_standard_trigger(device, cqr, id);
break; break;
case DASD_EER_NOPATH: case DASD_EER_NOPATH:
case DASD_EER_NOSPC:
dasd_eer_write_standard_trigger(device, NULL, id); dasd_eer_write_standard_trigger(device, NULL, id);
break; break;
case DASD_EER_STATECHANGE: case DASD_EER_STATECHANGE:
......
...@@ -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_DOWN(max_bytes, 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
...@@ -367,6 +370,25 @@ struct dasd_discipline { ...@@ -367,6 +370,25 @@ struct dasd_discipline {
void (*disable_hpf)(struct dasd_device *); void (*disable_hpf)(struct dasd_device *);
int (*hpf_enabled)(struct dasd_device *); int (*hpf_enabled)(struct dasd_device *);
void (*reset_path)(struct dasd_device *, __u8); void (*reset_path)(struct dasd_device *, __u8);
/*
* Extent Space Efficient (ESE) relevant functions
*/
int (*is_ese)(struct dasd_device *);
/* Capacity */
int (*space_allocated)(struct dasd_device *);
int (*space_configured)(struct dasd_device *);
int (*logical_capacity)(struct dasd_device *);
int (*release_space)(struct dasd_device *, struct format_data_t *);
/* Extent Pool */
int (*ext_pool_id)(struct dasd_device *);
int (*ext_size)(struct dasd_device *);
int (*ext_pool_cap_at_warnlevel)(struct dasd_device *);
int (*ext_pool_warn_thrshld)(struct dasd_device *);
int (*ext_pool_oos)(struct dasd_device *);
int (*ext_pool_exhaust)(struct dasd_device *, struct dasd_ccw_req *);
struct dasd_ccw_req *(*ese_format)(struct dasd_device *, struct dasd_ccw_req *);
void (*ese_read)(struct dasd_ccw_req *);
}; };
extern struct dasd_discipline *dasd_diag_discipline_pointer; extern struct dasd_discipline *dasd_diag_discipline_pointer;
...@@ -386,6 +408,7 @@ extern struct dasd_discipline *dasd_diag_discipline_pointer; ...@@ -386,6 +408,7 @@ extern struct dasd_discipline *dasd_diag_discipline_pointer;
#define DASD_EER_NOPATH 2 #define DASD_EER_NOPATH 2
#define DASD_EER_STATECHANGE 3 #define DASD_EER_STATECHANGE 3
#define DASD_EER_PPRCSUSPEND 4 #define DASD_EER_PPRCSUSPEND 4
#define DASD_EER_NOSPC 5
/* DASD path handling */ /* DASD path handling */
...@@ -482,8 +505,10 @@ struct dasd_device { ...@@ -482,8 +505,10 @@ struct dasd_device {
spinlock_t mem_lock; spinlock_t mem_lock;
void *ccw_mem; void *ccw_mem;
void *erp_mem; void *erp_mem;
void *ese_mem;
struct list_head ccw_chunks; struct list_head ccw_chunks;
struct list_head erp_chunks; struct list_head erp_chunks;
struct list_head ese_chunks;
atomic_t tasklet_scheduled; atomic_t tasklet_scheduled;
struct tasklet_struct tasklet; struct tasklet_struct tasklet;
...@@ -558,6 +583,7 @@ struct dasd_queue { ...@@ -558,6 +583,7 @@ struct dasd_queue {
#define DASD_STOPPED_SU 16 /* summary unit check handling */ #define DASD_STOPPED_SU 16 /* summary unit check handling */
#define DASD_STOPPED_PM 32 /* pm state transition */ #define DASD_STOPPED_PM 32 /* pm state transition */
#define DASD_UNRESUMED_PM 64 /* pm resume failed state */ #define DASD_UNRESUMED_PM 64 /* pm resume failed state */
#define DASD_STOPPED_NOSPC 128 /* no space left */
/* per device flags */ /* per device flags */
#define DASD_FLAG_OFFLINE 3 /* device is in offline processing */ #define DASD_FLAG_OFFLINE 3 /* device is in offline processing */
...@@ -700,7 +726,9 @@ extern struct kmem_cache *dasd_page_cache; ...@@ -700,7 +726,9 @@ extern struct kmem_cache *dasd_page_cache;
struct dasd_ccw_req * struct dasd_ccw_req *
dasd_smalloc_request(int, int, int, struct dasd_device *, struct dasd_ccw_req *); dasd_smalloc_request(int, int, int, struct dasd_device *, struct dasd_ccw_req *);
struct dasd_ccw_req *dasd_fmalloc_request(int, int, int, struct dasd_device *);
void dasd_sfree_request(struct dasd_ccw_req *, struct dasd_device *); void dasd_sfree_request(struct dasd_ccw_req *, struct dasd_device *);
void dasd_ffree_request(struct dasd_ccw_req *, struct dasd_device *);
void dasd_wakeup_cb(struct dasd_ccw_req *, void *); void dasd_wakeup_cb(struct dasd_ccw_req *, void *);
struct dasd_device *dasd_alloc_device(void); struct dasd_device *dasd_alloc_device(void);
...@@ -727,6 +755,7 @@ void dasd_schedule_block_bh(struct dasd_block *); ...@@ -727,6 +755,7 @@ void dasd_schedule_block_bh(struct dasd_block *);
int dasd_sleep_on(struct dasd_ccw_req *); int dasd_sleep_on(struct dasd_ccw_req *);
int dasd_sleep_on_queue(struct list_head *); int dasd_sleep_on_queue(struct list_head *);
int dasd_sleep_on_immediatly(struct dasd_ccw_req *); int dasd_sleep_on_immediatly(struct dasd_ccw_req *);
int dasd_sleep_on_queue_interruptible(struct list_head *);
int dasd_sleep_on_interruptible(struct dasd_ccw_req *); int dasd_sleep_on_interruptible(struct dasd_ccw_req *);
void dasd_device_set_timer(struct dasd_device *, int); void dasd_device_set_timer(struct dasd_device *, int);
void dasd_device_clear_timer(struct dasd_device *); void dasd_device_clear_timer(struct dasd_device *);
...@@ -750,6 +779,8 @@ int dasd_generic_restore_device(struct ccw_device *); ...@@ -750,6 +779,8 @@ int dasd_generic_restore_device(struct ccw_device *);
enum uc_todo dasd_generic_uc_handler(struct ccw_device *, struct irb *); enum uc_todo dasd_generic_uc_handler(struct ccw_device *, struct irb *);
void dasd_generic_path_event(struct ccw_device *, int *); void dasd_generic_path_event(struct ccw_device *, int *);
int dasd_generic_verify_path(struct dasd_device *, __u8); int dasd_generic_verify_path(struct dasd_device *, __u8);
void dasd_generic_space_exhaust(struct dasd_device *, struct dasd_ccw_req *);
void dasd_generic_space_avail(struct dasd_device *);
int dasd_generic_read_dev_chars(struct dasd_device *, int, void *, int); int dasd_generic_read_dev_chars(struct dasd_device *, int, void *, int);
char *dasd_get_sense(struct irb *); char *dasd_get_sense(struct irb *);
......
...@@ -333,6 +333,59 @@ static int dasd_ioctl_check_format(struct block_device *bdev, void __user *argp) ...@@ -333,6 +333,59 @@ static int dasd_ioctl_check_format(struct block_device *bdev, void __user *argp)
return rc; return rc;
} }
static int dasd_release_space(struct dasd_device *device,
struct format_data_t *rdata)
{
if (!device->discipline->is_ese && !device->discipline->is_ese(device))
return -ENOTSUPP;
if (!device->discipline->release_space)
return -ENOTSUPP;
return device->discipline->release_space(device, rdata);
}
/*
* Release allocated space
*/
static int dasd_ioctl_release_space(struct block_device *bdev, void __user *argp)
{
struct format_data_t rdata;
struct dasd_device *base;
int rc = 0;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if (!argp)
return -EINVAL;
base = dasd_device_from_gendisk(bdev->bd_disk);
if (!base)
return -ENODEV;
if (base->features & DASD_FEATURE_READONLY ||
test_bit(DASD_FLAG_DEVICE_RO, &base->flags)) {
rc = -EROFS;
goto out_err;
}
if (bdev != bdev->bd_contains) {
pr_warn("%s: The specified DASD is a partition and tracks cannot be released\n",
dev_name(&base->cdev->dev));
rc = -EINVAL;
goto out_err;
}
if (copy_from_user(&rdata, argp, sizeof(rdata))) {
rc = -EFAULT;
goto out_err;
}
rc = dasd_release_space(base, &rdata);
out_err:
dasd_put_device(base);
return rc;
}
#ifdef CONFIG_DASD_PROFILE #ifdef CONFIG_DASD_PROFILE
/* /*
* Reset device profile information * Reset device profile information
...@@ -595,6 +648,9 @@ int dasd_ioctl(struct block_device *bdev, fmode_t mode, ...@@ -595,6 +648,9 @@ int dasd_ioctl(struct block_device *bdev, fmode_t mode,
case BIODASDREADALLCMB: case BIODASDREADALLCMB:
rc = dasd_ioctl_readall_cmb(block, cmd, argp); rc = dasd_ioctl_readall_cmb(block, cmd, argp);
break; break;
case BIODASDRAS:
rc = dasd_ioctl_release_space(bdev, argp);
break;
default: default:
/* if the discipline has an ioctl method try it. */ /* if the discipline has an ioctl method try it. */
rc = -ENOTTY; rc = -ENOTTY;
......
...@@ -41,7 +41,6 @@ static void __init sclp_early_facilities_detect(struct read_info_sccb *sccb) ...@@ -41,7 +41,6 @@ static void __init sclp_early_facilities_detect(struct read_info_sccb *sccb)
sclp.has_hvs = !!(sccb->fac119 & 0x80); sclp.has_hvs = !!(sccb->fac119 & 0x80);
sclp.has_kss = !!(sccb->fac98 & 0x01); sclp.has_kss = !!(sccb->fac98 & 0x01);
sclp.has_sipl = !!(sccb->cbl & 0x02); sclp.has_sipl = !!(sccb->cbl & 0x02);
sclp.has_sipl_g2 = !!(sccb->cbl & 0x04);
if (sccb->fac85 & 0x02) if (sccb->fac85 & 0x02)
S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP; S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP;
if (sccb->fac91 & 0x40) if (sccb->fac91 & 0x40)
......
...@@ -208,7 +208,6 @@ static inline int ap_query_configuration(struct ap_config_info *info) ...@@ -208,7 +208,6 @@ static inline int ap_query_configuration(struct ap_config_info *info)
return -EINVAL; return -EINVAL;
return ap_qci(info); return ap_qci(info);
} }
EXPORT_SYMBOL(ap_query_configuration);
/** /**
* ap_init_configuration(): Allocate and query configuration array. * ap_init_configuration(): Allocate and query configuration array.
......
...@@ -115,7 +115,6 @@ static void vfio_ap_wait_for_irqclear(int apqn) ...@@ -115,7 +115,6 @@ static void vfio_ap_wait_for_irqclear(int apqn)
* Unregisters the ISC in the GIB when the saved ISC not invalid. * Unregisters the ISC in the GIB when the saved ISC not invalid.
* Unpin the guest's page holding the NIB when it exist. * Unpin the guest's page holding the NIB when it exist.
* Reset the saved_pfn and saved_isc to invalid values. * Reset the saved_pfn and saved_isc to invalid values.
* Clear the pointer to the matrix mediated device.
* *
*/ */
static void vfio_ap_free_aqic_resources(struct vfio_ap_queue *q) static void vfio_ap_free_aqic_resources(struct vfio_ap_queue *q)
...@@ -127,7 +126,6 @@ static void vfio_ap_free_aqic_resources(struct vfio_ap_queue *q) ...@@ -127,7 +126,6 @@ static void vfio_ap_free_aqic_resources(struct vfio_ap_queue *q)
&q->saved_pfn, 1); &q->saved_pfn, 1);
q->saved_pfn = 0; q->saved_pfn = 0;
q->saved_isc = VFIO_AP_ISC_INVALID; q->saved_isc = VFIO_AP_ISC_INVALID;
q->matrix_mdev = NULL;
} }
/** /**
...@@ -179,6 +177,7 @@ struct ap_queue_status vfio_ap_irq_disable(struct vfio_ap_queue *q) ...@@ -179,6 +177,7 @@ struct ap_queue_status vfio_ap_irq_disable(struct vfio_ap_queue *q)
status.response_code); status.response_code);
end_free: end_free:
vfio_ap_free_aqic_resources(q); vfio_ap_free_aqic_resources(q);
q->matrix_mdev = NULL;
return status; return status;
} }
......
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