From 8ebd51a705c56520481f2b813790dc5afdb0a751 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sat, 20 Dec 2014 13:27:49 +0100 Subject: s390/cio: idset.c: remove some unused functions Removes some functions that are not used anywhere: idset_clear() idset_sch_get_first() This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/idset.c | 20 -------------------- drivers/s390/cio/idset.h | 2 -- 2 files changed, 22 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/cio/idset.c b/drivers/s390/cio/idset.c index 5a999084a229..b3e06a7b9480 100644 --- a/drivers/s390/cio/idset.c +++ b/drivers/s390/cio/idset.c @@ -38,11 +38,6 @@ void idset_free(struct idset *set) vfree(set); } -void idset_clear(struct idset *set) -{ - memset(set->bitmap, 0, bitmap_size(set->num_ssid, set->num_id)); -} - void idset_fill(struct idset *set) { memset(set->bitmap, 0xff, bitmap_size(set->num_ssid, set->num_id)); @@ -103,21 +98,6 @@ int idset_sch_contains(struct idset *set, struct subchannel_id schid) return idset_contains(set, schid.ssid, schid.sch_no); } -int idset_sch_get_first(struct idset *set, struct subchannel_id *schid) -{ - int ssid = 0; - int id = 0; - int rc; - - rc = idset_get_first(set, &ssid, &id); - if (rc) { - init_subchannel_id(schid); - schid->ssid = ssid; - schid->sch_no = id; - } - return rc; -} - int idset_is_empty(struct idset *set) { return bitmap_empty(set->bitmap, set->num_ssid * set->num_id); diff --git a/drivers/s390/cio/idset.h b/drivers/s390/cio/idset.h index 06d3bc01bb09..22b58104683b 100644 --- a/drivers/s390/cio/idset.h +++ b/drivers/s390/cio/idset.h @@ -11,7 +11,6 @@ struct idset; void idset_free(struct idset *set); -void idset_clear(struct idset *set); void idset_fill(struct idset *set); struct idset *idset_sch_new(void); @@ -19,7 +18,6 @@ void idset_sch_add(struct idset *set, struct subchannel_id id); void idset_sch_del(struct idset *set, struct subchannel_id id); void idset_sch_del_subseq(struct idset *set, struct subchannel_id schid); int idset_sch_contains(struct idset *set, struct subchannel_id id); -int idset_sch_get_first(struct idset *set, struct subchannel_id *id); int idset_is_empty(struct idset *set); void idset_add_set(struct idset *to, struct idset *from); -- cgit v1.2.3 From e982506730815f9e3bcd148d06b5b6d778d9c46c Mon Sep 17 00:00:00 2001 From: Syam Sidhardhan Date: Tue, 30 Dec 2014 16:47:01 +0530 Subject: s390/hmcdrv: remove unnecessary version.h inclusion version.h inclusion is not necessary as detected by versioncheck. Signed-off-by: Syam Sidhardhan Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/hmcdrv_mod.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/hmcdrv_mod.c b/drivers/s390/char/hmcdrv_mod.c index 505c6a78ee1a..251a318a9b75 100644 --- a/drivers/s390/char/hmcdrv_mod.c +++ b/drivers/s390/char/hmcdrv_mod.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include "hmcdrv_ftp.h" -- cgit v1.2.3 From 10ad34bc76dfbc49bda327a13012f6754c0c72e0 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Wed, 14 Jan 2015 17:52:10 +0100 Subject: s390: add SMT support The multi-threading facility is introduced with the z13 processor family. This patch adds code to detect the multi-threading facility. With the facility enabled each core will surface multiple hardware threads to the system. Each hardware threads looks like a normal CPU to the operating system with all its registers and properties. The SCLP interface reports the SMT topology indirectly via the maximum thread id. Each reported CPU in the result of a read-scp-information is a core representing a number of hardware threads. To reflect the reduced CPU capacity if two hardware threads run on a single core the MT utilization counter set is used to normalize the raw cputime obtained by the CPU timer deltas. This scaled cputime is reported via the taskstats interface. The normal /proc/stat numbers are based on the raw cputime and are not affected by the normalization. Signed-off-by: Martin Schwidefsky --- drivers/s390/char/sclp_early.c | 49 +++++++++++++++++++++++++++++++++--------- drivers/s390/cio/cio.c | 2 +- 2 files changed, 40 insertions(+), 11 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index 5bd6cb145a87..daf6cd5079ec 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -20,26 +20,31 @@ struct read_info_sccb { struct sccb_header header; /* 0-7 */ u16 rnmax; /* 8-9 */ u8 rnsize; /* 10 */ - u8 _reserved0[16 - 11]; /* 11-15 */ + u8 _pad_11[16 - 11]; /* 11-15 */ u16 ncpurl; /* 16-17 */ u16 cpuoff; /* 18-19 */ - u8 _reserved7[24 - 20]; /* 20-23 */ + u8 _pad_20[24 - 20]; /* 20-23 */ u8 loadparm[8]; /* 24-31 */ - u8 _reserved1[48 - 32]; /* 32-47 */ + u8 _pad_32[42 - 32]; /* 32-41 */ + u8 fac42; /* 42 */ + u8 fac43; /* 43 */ + u8 _pad_44[48 - 44]; /* 44-47 */ u64 facilities; /* 48-55 */ - u8 _reserved2a[76 - 56]; /* 56-75 */ + u8 _pad_56[66 - 56]; /* 56-65 */ + u8 fac66; /* 66 */ + u8 _pad_67[76 - 67]; /* 67-83 */ u32 ibc; /* 76-79 */ - u8 _reserved2b[84 - 80]; /* 80-83 */ + u8 _pad80[84 - 80]; /* 80-83 */ u8 fac84; /* 84 */ u8 fac85; /* 85 */ - u8 _reserved3[91 - 86]; /* 86-90 */ + u8 _pad_86[91 - 86]; /* 86-90 */ u8 flags; /* 91 */ - u8 _reserved4[100 - 92]; /* 92-99 */ + u8 _pad_92[100 - 92]; /* 92-99 */ u32 rnsize2; /* 100-103 */ u64 rnmax2; /* 104-111 */ - u8 _reserved5[120 - 112]; /* 112-119 */ + u8 _pad_112[120 - 112]; /* 112-119 */ u16 hcpua; /* 120-121 */ - u8 _reserved6[4096 - 122]; /* 122-4095 */ + u8 _pad_122[4096 - 122]; /* 122-4095 */ } __packed __aligned(PAGE_SIZE); static char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE) __initdata; @@ -50,6 +55,10 @@ static unsigned int sclp_max_cpu; static struct sclp_ipl_info sclp_ipl_info; static unsigned char sclp_siif; static u32 sclp_ibc; +static unsigned int sclp_mtid; +static unsigned int sclp_mtid_cp; +static unsigned int sclp_mtid_max; +static unsigned int sclp_mtid_prev; u64 sclp_facilities; u8 sclp_fac84; @@ -128,7 +137,7 @@ static void __init sclp_facilities_detect(struct read_info_sccb *sccb) boot_cpu_address = stap(); cpue = (void *)sccb + sccb->cpuoff; for (cpu = 0; cpu < sccb->ncpurl; cpue++, cpu++) { - if (boot_cpu_address != cpue->address) + if (boot_cpu_address != cpue->core_id) continue; sclp_siif = cpue->siif; break; @@ -139,6 +148,11 @@ static void __init sclp_facilities_detect(struct read_info_sccb *sccb) if (sccb->flags & 0x2) sclp_ipl_info.has_dump = 1; memcpy(&sclp_ipl_info.loadparm, &sccb->loadparm, LOADPARM_LEN); + + sclp_mtid = (sccb->fac42 & 0x80) ? (sccb->fac42 & 31) : 0; + sclp_mtid_cp = (sccb->fac42 & 0x80) ? (sccb->fac43 & 31) : 0; + sclp_mtid_max = max(sclp_mtid, sclp_mtid_cp); + sclp_mtid_prev = (sccb->fac42 & 0x80) ? (sccb->fac66 & 31) : 0; } bool __init sclp_has_linemode(void) @@ -178,6 +192,21 @@ unsigned int sclp_get_ibc(void) } EXPORT_SYMBOL(sclp_get_ibc); +unsigned int sclp_get_mtid(u8 cpu_type) +{ + return cpu_type ? sclp_mtid : sclp_mtid_cp; +} + +unsigned int sclp_get_mtid_max(void) +{ + return sclp_mtid_max; +} + +unsigned int sclp_get_mtid_prev(void) +{ + return sclp_mtid_prev; +} + /* * This function will be called after sclp_facilities_detect(), which gets * called from early.c code. The sclp_facilities_detect() function retrieves diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 10eb738fc81a..3578105989a0 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -938,7 +938,7 @@ void reipl_ccw_dev(struct ccw_dev_id *devid) { struct subchannel_id uninitialized_var(schid); - s390_reset_system(NULL, NULL); + s390_reset_system(NULL, NULL, NULL); if (reipl_find_schid(devid, &schid) != 0) panic("IPL Device not found\n"); do_reipl_asm(*((__u32*)&schid)); -- cgit v1.2.3 From 5be6fdc090e156bc67b63310b65f4f54523e7b6c Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Fri, 16 Jan 2015 18:29:04 +0100 Subject: dcssblk: issue warning when trying to save SN/EN type DCSS The content of a DCSS of type SN or EN cannot be saved. Issue a warning when trying to save such a DCSS. Depending on the setup, this may be a user error or intended behaviour e.g. with a multi-DCSS device. Signed-off-by: Gerald Schaefer Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dcssblk.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index b550c8c8d010..7f900229404d 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -438,7 +438,13 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char pr_info("All DCSSs that map to device %s are " "saved\n", dev_info->segment_name); list_for_each_entry(entry, &dev_info->seg_list, lh) { - segment_save(entry->segment_name); + if (entry->segment_type == SEG_TYPE_EN || + entry->segment_type == SEG_TYPE_SN) + pr_warn("DCSS %s is of type SN or EN" + " and cannot be saved\n", + entry->segment_name); + else + segment_save(entry->segment_name); } } else { // device is busy => we save it when it becomes @@ -797,7 +803,12 @@ dcssblk_release(struct gendisk *disk, fmode_t mode) pr_info("Device %s has become idle and is being saved " "now\n", dev_info->segment_name); list_for_each_entry(entry, &dev_info->seg_list, lh) { - segment_save(entry->segment_name); + if (entry->segment_type == SEG_TYPE_EN || + entry->segment_type == SEG_TYPE_SN) + pr_warn("DCSS %s is of type SN or EN and cannot" + " be saved\n", entry->segment_name); + else + segment_save(entry->segment_name); } dev_info->save_pending = 0; } -- cgit v1.2.3 From 2ec504934e43e6c47dfdd4436ca58b36f1ab3218 Mon Sep 17 00:00:00 2001 From: Christophe Jaillet Date: Mon, 19 Jan 2015 23:02:00 +0100 Subject: s390/hmcdrv: free memory on error path Free allocated page in case of error returned by hmcdrv_ftp_startup. [heiko.carstens@de.ibm.com]: slightly changed Christophe's patch Signed-off-by: Christophe Jaillet Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/hmcdrv_ftp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/hmcdrv_ftp.c b/drivers/s390/char/hmcdrv_ftp.c index 4bd63322fc29..d4b61d9088fb 100644 --- a/drivers/s390/char/hmcdrv_ftp.c +++ b/drivers/s390/char/hmcdrv_ftp.c @@ -200,10 +200,9 @@ int hmcdrv_ftp_probe(void) rc = hmcdrv_ftp_startup(); if (rc) - return rc; + goto out; rc = hmcdrv_ftp_do(&ftp); - free_page((unsigned long) ftp.buf); hmcdrv_ftp_shutdown(); switch (rc) { @@ -216,7 +215,8 @@ int hmcdrv_ftp_probe(void) rc = 0; /* clear length (success) */ break; } /* switch */ - +out: + free_page((unsigned long) ftp.buf); return rc; } EXPORT_SYMBOL(hmcdrv_ftp_probe); -- cgit v1.2.3 From 55b5eb75e7ccdfe94b6ea1be6bba0c21149abecf Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 22 Jan 2015 11:10:39 +0100 Subject: s390/tape: remove redundant if statement The unit check handler for 3480 / 3490 tapes used to print a different warning message for erpa code 0x57 dependent on the device type. The warning messages have been remove in a cleanup, the if statement is a left over. Remove it. Reported-by: Fraser Brown Signed-off-by: Martin Schwidefsky --- drivers/s390/char/tape_34xx.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index 9aa79702b370..de69f0ddc321 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c @@ -773,13 +773,11 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, "occurred\n"); return tape_34xx_erp_failed(request, -EIO); case 0x57: - if (device->cdev->id.driver_info == tape_3480) { - /* Attention intercept. */ - return tape_34xx_erp_retry(request); - } else { - /* Global status intercept. */ - return tape_34xx_erp_retry(request); - } + /* + * 3480: Attention intercept. + * 3490: Global status intercept. + */ + return tape_34xx_erp_retry(request); case 0x5a: /* * Tape length incompatible. The tape inserted is too long, -- cgit v1.2.3 From 5bc334bff9a6e189113140ed6dce0ce61d768943 Mon Sep 17 00:00:00 2001 From: Ingo Tuchscherer Date: Fri, 23 Jan 2015 13:27:04 +0100 Subject: s390/zcrypt: Number of supported ap domains is not retrievable. Upcoming versions of secure key management facilities (CCA and EP11) require information about the maximum number of supported ap domains in order to service TKE requests properly. With IBM z13 the number of available domains (so far 16) has increased up to 85. This number varies depending on machine types and models. Therefore the new sysfs attribute 'ap_max_domain_id' provides this limit of supported ap domains. Upcoming releases for CCA and EP11 will use this new information. Without this problem fix it is not possible to retrieve reliable information about the maximum number of supported ap domains. Thus, customers are not able to perform key management for CCA and EP11 coprocessor adapters. Signed-off-by: Ingo Tuchscherer Signed-off-by: Harald Freudenberger Signed-off-by: Martin Schwidefsky --- drivers/s390/crypto/ap_bus.c | 137 ++++++++++++++++++++++++++++++------------- 1 file changed, 96 insertions(+), 41 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 4d41bf75c233..faa058016b5c 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -203,6 +203,24 @@ ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type) return reg1; } +/** + * ap_query_facilities(): PQAP(TAPQ) query facilities. + * @qid: The AP queue number + * + * Returns content of general register 2 after the PQAP(TAPQ) + * instruction was called. + */ +static inline unsigned long ap_query_facilities(ap_qid_t qid) +{ + register unsigned long reg0 asm ("0") = qid | 0x00800000UL; + register unsigned long reg1 asm ("1"); + register unsigned long reg2 asm ("2") = 0UL; + + asm volatile(".long 0xb2af0000" /* PQAP(TAPQ) */ + : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc"); + return reg2; +} + /** * ap_reset_queue(): Reset adjunct processor queue. * @qid: The AP queue number @@ -1006,6 +1024,47 @@ void ap_bus_force_rescan(void) } EXPORT_SYMBOL(ap_bus_force_rescan); +/* + * ap_test_config(): helper function to extract the nrth bit + * within the unsigned int array field. + */ +static inline int ap_test_config(unsigned int *field, unsigned int nr) +{ + if (nr > 0xFFu) + return 0; + return ap_test_bit((field + (nr >> 5)), (nr & 0x1f)); +} + +/* + * ap_test_config_card_id(): Test, whether an AP card ID is configured. + * @id AP card ID + * + * Returns 0 if the card is not configured + * 1 if the card is configured or + * if the configuration information is not available + */ +static inline int ap_test_config_card_id(unsigned int id) +{ + if (!ap_configuration) + return 1; + return ap_test_config(ap_configuration->apm, id); +} + +/* + * ap_test_config_domain(): Test, whether an AP usage domain is configured. + * @domain AP usage domain ID + * + * Returns 0 if the usage domain is not configured + * 1 if the usage domain is configured or + * if the configuration information is not available + */ +static inline int ap_test_config_domain(unsigned int domain) +{ + if (!ap_configuration) + return 1; + return ap_test_config(ap_configuration->aqm, domain); +} + /* * AP bus attributes. */ @@ -1121,6 +1180,42 @@ static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf, static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store); +static ssize_t ap_max_domain_id_show(struct bus_type *bus, char *buf) +{ + ap_qid_t qid; + int i, nd, max_domain_id = -1; + unsigned long fbits; + + if (ap_configuration) { + if (ap_domain_index >= 0 && ap_domain_index < AP_DOMAINS) { + for (i = 0; i < AP_DEVICES; i++) { + if (!ap_test_config_card_id(i)) + continue; + qid = AP_MKQID(i, ap_domain_index); + fbits = ap_query_facilities(qid); + if (fbits & (1UL << 57)) { + /* the N bit is 0, Nd field is filled */ + nd = (int)((fbits & 0x00FF0000UL)>>16); + if (nd > 0) + max_domain_id = nd; + else + max_domain_id = 15; + } else { + /* N bit is 1, max 16 domains */ + max_domain_id = 15; + } + break; + } + } + } else { + /* no APXA support, older machines with max 16 domains */ + max_domain_id = 15; + } + return snprintf(buf, PAGE_SIZE, "%d\n", max_domain_id); +} + +static BUS_ATTR(ap_max_domain_id, 0444, ap_max_domain_id_show, NULL); + static struct bus_attribute *const ap_bus_attrs[] = { &bus_attr_ap_domain, &bus_attr_ap_control_domain_mask, @@ -1128,50 +1223,10 @@ static struct bus_attribute *const ap_bus_attrs[] = { &bus_attr_poll_thread, &bus_attr_ap_interrupts, &bus_attr_poll_timeout, + &bus_attr_ap_max_domain_id, NULL, }; -static inline int ap_test_config(unsigned int *field, unsigned int nr) -{ - if (nr > 0xFFu) - return 0; - return ap_test_bit((field + (nr >> 5)), (nr & 0x1f)); -} - -/* - * ap_test_config_card_id(): Test, whether an AP card ID is configured. - * @id AP card ID - * - * Returns 0 if the card is not configured - * 1 if the card is configured or - * if the configuration information is not available - */ -static inline int ap_test_config_card_id(unsigned int id) -{ - if (!ap_configuration) - return 1; - return ap_test_config(ap_configuration->apm, id); -} - -/* - * ap_test_config_domain(): Test, whether an AP usage domain is configured. - * @domain AP usage domain ID - * - * Returns 0 if the usage domain is not configured - * 1 if the usage domain is configured or - * if the configuration information is not available - */ -static inline int ap_test_config_domain(unsigned int domain) -{ - if (!ap_configuration) /* QCI not supported */ - if (domain < 16) - return 1; /* then domains 0...15 are configured */ - else - return 0; - else - return ap_test_config(ap_configuration->aqm, domain); -} - /** * ap_query_configuration(): Query AP configuration information. * -- cgit v1.2.3 From bdea1f1bb273383312f0eca56241794b06ed4205 Mon Sep 17 00:00:00 2001 From: Ingo Tuchscherer Date: Fri, 23 Jan 2015 14:56:25 +0100 Subject: s390/zcrypt: Add support for new crypto express (CEX5S) adapter. Extends the generic cryptographic device driver (zcrypt) to support the Crypto Express 5S adapter. Signed-off-by: Ingo Tuchscherer Signed-off-by: Martin Schwidefsky --- drivers/s390/crypto/ap_bus.c | 3 --- drivers/s390/crypto/ap_bus.h | 1 + drivers/s390/crypto/zcrypt_api.h | 1 + drivers/s390/crypto/zcrypt_cex4.c | 33 +++++++++++++++++++++++++++------ 4 files changed, 29 insertions(+), 9 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index faa058016b5c..a60fc2f9f4b2 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -1489,9 +1489,6 @@ static void ap_scan_bus(struct work_struct *unused) continue; } break; - case 11: - ap_dev->device_type = 10; - break; default: ap_dev->device_type = device_type; } diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 055a0f956d17..2737d261a324 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -117,6 +117,7 @@ static inline int ap_test_bit(unsigned int *ptr, unsigned int nr) #define AP_DEVICE_TYPE_CEX3A 8 #define AP_DEVICE_TYPE_CEX3C 9 #define AP_DEVICE_TYPE_CEX4 10 +#define AP_DEVICE_TYPE_CEX5 11 /* * Known function facilities diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h index b3d496bfaa7e..750876891931 100644 --- a/drivers/s390/crypto/zcrypt_api.h +++ b/drivers/s390/crypto/zcrypt_api.h @@ -75,6 +75,7 @@ struct ica_z90_status { #define ZCRYPT_CEX3C 7 #define ZCRYPT_CEX3A 8 #define ZCRYPT_CEX4 10 +#define ZCRYPT_CEX5 11 /** * Large random numbers are pulled in 4096 byte chunks from the crypto cards diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c index 569f8b1d86c0..71e698b85772 100644 --- a/drivers/s390/crypto/zcrypt_cex4.c +++ b/drivers/s390/crypto/zcrypt_cex4.c @@ -26,6 +26,10 @@ #define CEX4A_SPEED_RATING 900 /* TODO new card, new speed rating */ #define CEX4C_SPEED_RATING 6500 /* TODO new card, new speed rating */ +#define CEX4P_SPEED_RATING 7000 /* TODO new card, new speed rating */ +#define CEX5A_SPEED_RATING 450 /* TODO new card, new speed rating */ +#define CEX5C_SPEED_RATING 3250 /* TODO new card, new speed rating */ +#define CEX5P_SPEED_RATING 3500 /* TODO new card, new speed rating */ #define CEX4A_MAX_MESSAGE_SIZE MSGTYPE50_CRB3_MAX_MSG_SIZE #define CEX4C_MAX_MESSAGE_SIZE MSGTYPE06_MAX_MSG_SIZE @@ -39,6 +43,7 @@ static struct ap_device_id zcrypt_cex4_ids[] = { { AP_DEVICE(AP_DEVICE_TYPE_CEX4) }, + { AP_DEVICE(AP_DEVICE_TYPE_CEX5) }, { /* end of list */ }, }; @@ -70,11 +75,18 @@ static int zcrypt_cex4_probe(struct ap_device *ap_dev) switch (ap_dev->device_type) { case AP_DEVICE_TYPE_CEX4: + case AP_DEVICE_TYPE_CEX5: if (ap_test_bit(&ap_dev->functions, AP_FUNC_ACCEL)) { zdev = zcrypt_device_alloc(CEX4A_MAX_MESSAGE_SIZE); if (!zdev) return -ENOMEM; - zdev->type_string = "CEX4A"; + if (ap_dev->device_type == AP_DEVICE_TYPE_CEX4) { + zdev->type_string = "CEX4A"; + zdev->speed_rating = CEX4A_SPEED_RATING; + } else { + zdev->type_string = "CEX5A"; + zdev->speed_rating = CEX5A_SPEED_RATING; + } zdev->user_space_type = ZCRYPT_CEX3A; zdev->min_mod_size = CEX4A_MIN_MOD_SIZE; if (ap_test_bit(&ap_dev->functions, AP_FUNC_MEX4K) && @@ -90,33 +102,42 @@ static int zcrypt_cex4_probe(struct ap_device *ap_dev) CEX4A_MAX_MOD_SIZE_2K; } zdev->short_crt = 1; - zdev->speed_rating = CEX4A_SPEED_RATING; zdev->ops = zcrypt_msgtype_request(MSGTYPE50_NAME, MSGTYPE50_VARIANT_DEFAULT); } else if (ap_test_bit(&ap_dev->functions, AP_FUNC_COPRO)) { zdev = zcrypt_device_alloc(CEX4C_MAX_MESSAGE_SIZE); if (!zdev) return -ENOMEM; - zdev->type_string = "CEX4C"; + if (ap_dev->device_type == AP_DEVICE_TYPE_CEX4) { + zdev->type_string = "CEX4C"; + zdev->speed_rating = CEX4C_SPEED_RATING; + } else { + zdev->type_string = "CEX5C"; + zdev->speed_rating = CEX5C_SPEED_RATING; + } zdev->user_space_type = ZCRYPT_CEX3C; zdev->min_mod_size = CEX4C_MIN_MOD_SIZE; zdev->max_mod_size = CEX4C_MAX_MOD_SIZE; zdev->max_exp_bit_length = CEX4C_MAX_MOD_SIZE; zdev->short_crt = 0; - zdev->speed_rating = CEX4C_SPEED_RATING; zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME, MSGTYPE06_VARIANT_DEFAULT); } else if (ap_test_bit(&ap_dev->functions, AP_FUNC_EP11)) { zdev = zcrypt_device_alloc(CEX4C_MAX_MESSAGE_SIZE); if (!zdev) return -ENOMEM; - zdev->type_string = "CEX4P"; + if (ap_dev->device_type == AP_DEVICE_TYPE_CEX4) { + zdev->type_string = "CEX4P"; + zdev->speed_rating = CEX4P_SPEED_RATING; + } else { + zdev->type_string = "CEX5P"; + zdev->speed_rating = CEX5P_SPEED_RATING; + } zdev->user_space_type = ZCRYPT_CEX4; zdev->min_mod_size = CEX4C_MIN_MOD_SIZE; zdev->max_mod_size = CEX4C_MAX_MOD_SIZE; zdev->max_exp_bit_length = CEX4C_MAX_MOD_SIZE; zdev->short_crt = 0; - zdev->speed_rating = CEX4C_SPEED_RATING; zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME, MSGTYPE06_VARIANT_EP11); } -- cgit v1.2.3 From 8ea55c95c372a7a51fa50cb7c75240bfbe8bd337 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Wed, 28 Jan 2015 18:44:17 +0100 Subject: s390/dasd: add locking for global_profile access Access to DASDs global statistics is done without locking which can lead to inconsistent data. Add locking to fix this. Also move the relevant structs in a global dasd_profile struct. Signed-off-by: Sebastian Ott Reviewed-by: Stefan Haberland Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 32 ++++++++++++++++++++------------ drivers/s390/block/dasd_int.h | 2 +- drivers/s390/block/dasd_proc.c | 4 +++- 3 files changed, 24 insertions(+), 14 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 4abf11965484..a67e8dae73c3 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -674,8 +674,12 @@ EXPORT_SYMBOL(dasd_enable_device); unsigned int dasd_global_profile_level = DASD_PROFILE_OFF; #ifdef CONFIG_DASD_PROFILE -struct dasd_profile_info dasd_global_profile_data; -static struct dentry *dasd_global_profile_dentry; +static struct dasd_profile_info dasd_global_profile_data; +struct dasd_profile dasd_global_profile = { + .dentry = NULL, + .data = &dasd_global_profile_data, + .lock = __SPIN_LOCK_UNLOCKED(dasd_global_profile.lock), +}; static struct dentry *dasd_debugfs_global_entry; /* @@ -696,11 +700,13 @@ static void dasd_profile_start(struct dasd_block *block, if (++counter >= 31) break; + spin_lock(&dasd_global_profile.lock); if (dasd_global_profile_level) { - dasd_global_profile_data.dasd_io_nr_req[counter]++; + dasd_global_profile.data->dasd_io_nr_req[counter]++; if (rq_data_dir(req) == READ) - dasd_global_profile_data.dasd_read_nr_req[counter]++; + dasd_global_profile.data->dasd_read_nr_req[counter]++; } + spin_unlock(&dasd_global_profile.lock); spin_lock(&block->profile.lock); if (block->profile.data) { @@ -825,8 +831,9 @@ static void dasd_profile_end(struct dasd_block *block, dasd_profile_counter(irqtime / sectors, irqtimeps_ind); dasd_profile_counter(endtime, endtime_ind); + spin_lock(&dasd_global_profile.lock); if (dasd_global_profile_level) { - dasd_profile_end_add_data(&dasd_global_profile_data, + dasd_profile_end_add_data(dasd_global_profile.data, cqr->startdev != block->base, cqr->cpmode == 1, rq_data_dir(req) == READ, @@ -835,6 +842,7 @@ static void dasd_profile_end(struct dasd_block *block, irqtime_ind, irqtimeps_ind, endtime_ind); } + spin_unlock(&dasd_global_profile.lock); spin_lock(&block->profile.lock); if (block->profile.data) @@ -878,8 +886,7 @@ void dasd_profile_reset(struct dasd_profile *profile) void dasd_global_profile_reset(void) { - memset(&dasd_global_profile_data, 0, sizeof(dasd_global_profile_data)); - getnstimeofday(&dasd_global_profile_data.starttod); + dasd_profile_reset(&dasd_global_profile); } int dasd_profile_on(struct dasd_profile *profile) @@ -1077,7 +1084,9 @@ static int dasd_stats_global_show(struct seq_file *m, void *v) seq_puts(m, "disabled\n"); return 0; } - dasd_stats_seq_print(m, &dasd_global_profile_data); + spin_lock_bh(&dasd_global_profile.lock); + dasd_stats_seq_print(m, dasd_global_profile.data); + spin_unlock_bh(&dasd_global_profile.lock); return 0; } @@ -1123,8 +1132,8 @@ static void dasd_profile_exit(struct dasd_profile *profile) static void dasd_statistics_removeroot(void) { dasd_global_profile_level = DASD_PROFILE_OFF; - debugfs_remove(dasd_global_profile_dentry); - dasd_global_profile_dentry = NULL; + debugfs_remove(dasd_global_profile.dentry); + dasd_global_profile.dentry = NULL; debugfs_remove(dasd_debugfs_global_entry); debugfs_remove(dasd_debugfs_root_entry); } @@ -1136,7 +1145,6 @@ static void dasd_statistics_createroot(void) dasd_debugfs_root_entry = NULL; dasd_debugfs_global_entry = NULL; - dasd_global_profile_dentry = NULL; pde = debugfs_create_dir("dasd", NULL); if (!pde || IS_ERR(pde)) goto error; @@ -1151,7 +1159,7 @@ static void dasd_statistics_createroot(void) NULL, &dasd_stats_global_fops); if (!pde || IS_ERR(pde)) goto error; - dasd_global_profile_dentry = pde; + dasd_global_profile.dentry = pde; return; error: diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 8b5d4100abf7..91731fa05604 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -651,7 +651,7 @@ dasd_check_blocksize(int bsize) #define DASD_PROFILE_GLOBAL_ONLY 2 extern debug_info_t *dasd_debug_area; -extern struct dasd_profile_info dasd_global_profile_data; +extern struct dasd_profile dasd_global_profile; extern unsigned int dasd_global_profile_level; extern const struct block_device_operations dasd_device_operations; diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 78ac905a5b7f..76410084c48f 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -219,7 +219,8 @@ static int dasd_stats_proc_show(struct seq_file *m, void *v) "/proc/dasd/statistics'\n"); return 0; } - prof = &dasd_global_profile_data; + spin_lock_bh(&dasd_global_profile.lock); + prof = dasd_global_profile.data; /* prevent counter 'overflow' on output */ for (factor = 1; (prof->dasd_io_reqs / factor) > 9999999; @@ -255,6 +256,7 @@ static int dasd_stats_proc_show(struct seq_file *m, void *v) dasd_statistics_array(m, prof->dasd_io_time3, factor); seq_printf(m, "# of req in chanq at enqueuing (1..32) \n"); dasd_statistics_array(m, prof->dasd_io_nr_req, factor); + spin_unlock_bh(&dasd_global_profile.lock); #else seq_printf(m, "Statistics are not activated in this kernel\n"); #endif -- cgit v1.2.3 From 6765cc2ac60f124ffffd0232e095c5ec6eb70d57 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Wed, 28 Jan 2015 19:06:29 +0100 Subject: s390/dasd: cleanup profiling The dasd driver has a lot of duplicated code to handle dasd_global_profile. With this patch we use the same code for the global and the per device profiling data. Note that dasd_stats_write had to change slightly to maintain some odd differences between A) per device and global profile and B) proc and sysfs interface usage. Signed-off-by: Sebastian Ott Reviewed-by: Stefan Haberland Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 90 +++++++----------------------------------- drivers/s390/block/dasd_int.h | 1 - drivers/s390/block/dasd_proc.c | 21 ++++++---- 3 files changed, 27 insertions(+), 85 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index a67e8dae73c3..be34ef41b7c7 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -674,10 +674,7 @@ EXPORT_SYMBOL(dasd_enable_device); unsigned int dasd_global_profile_level = DASD_PROFILE_OFF; #ifdef CONFIG_DASD_PROFILE -static struct dasd_profile_info dasd_global_profile_data; struct dasd_profile dasd_global_profile = { - .dentry = NULL, - .data = &dasd_global_profile_data, .lock = __SPIN_LOCK_UNLOCKED(dasd_global_profile.lock), }; static struct dentry *dasd_debugfs_global_entry; @@ -701,7 +698,7 @@ static void dasd_profile_start(struct dasd_block *block, break; spin_lock(&dasd_global_profile.lock); - if (dasd_global_profile_level) { + if (dasd_global_profile.data) { dasd_global_profile.data->dasd_io_nr_req[counter]++; if (rq_data_dir(req) == READ) dasd_global_profile.data->dasd_read_nr_req[counter]++; @@ -832,7 +829,7 @@ static void dasd_profile_end(struct dasd_block *block, dasd_profile_counter(endtime, endtime_ind); spin_lock(&dasd_global_profile.lock); - if (dasd_global_profile_level) { + if (dasd_global_profile.data) { dasd_profile_end_add_data(dasd_global_profile.data, cqr->startdev != block->base, cqr->cpmode == 1, @@ -884,11 +881,6 @@ void dasd_profile_reset(struct dasd_profile *profile) spin_unlock_bh(&profile->lock); } -void dasd_global_profile_reset(void) -{ - dasd_profile_reset(&dasd_global_profile); -} - int dasd_profile_on(struct dasd_profile *profile) { struct dasd_profile_info *data; @@ -956,12 +948,20 @@ static ssize_t dasd_stats_write(struct file *file, dasd_profile_reset(prof); } else if (strncmp(str, "on", 2) == 0) { rc = dasd_profile_on(prof); - if (!rc) - rc = user_len; + if (rc) + goto out; + rc = user_len; + if (prof == &dasd_global_profile) { + dasd_profile_reset(prof); + dasd_global_profile_level = DASD_PROFILE_GLOBAL_ONLY; + } } else if (strncmp(str, "off", 3) == 0) { + if (prof == &dasd_global_profile) + dasd_global_profile_level = DASD_PROFILE_OFF; dasd_profile_off(prof); } else rc = -EINVAL; +out: vfree(buffer); return rc; } @@ -1051,59 +1051,6 @@ static const struct file_operations dasd_stats_raw_fops = { .write = dasd_stats_write, }; -static ssize_t dasd_stats_global_write(struct file *file, - const char __user *user_buf, - size_t user_len, loff_t *pos) -{ - char *buffer, *str; - ssize_t rc; - - if (user_len > 65536) - user_len = 65536; - buffer = dasd_get_user_string(user_buf, user_len); - if (IS_ERR(buffer)) - return PTR_ERR(buffer); - str = skip_spaces(buffer); - rc = user_len; - if (strncmp(str, "reset", 5) == 0) { - dasd_global_profile_reset(); - } else if (strncmp(str, "on", 2) == 0) { - dasd_global_profile_reset(); - dasd_global_profile_level = DASD_PROFILE_GLOBAL_ONLY; - } else if (strncmp(str, "off", 3) == 0) { - dasd_global_profile_level = DASD_PROFILE_OFF; - } else - rc = -EINVAL; - vfree(buffer); - return rc; -} - -static int dasd_stats_global_show(struct seq_file *m, void *v) -{ - if (!dasd_global_profile_level) { - seq_puts(m, "disabled\n"); - return 0; - } - spin_lock_bh(&dasd_global_profile.lock); - dasd_stats_seq_print(m, dasd_global_profile.data); - spin_unlock_bh(&dasd_global_profile.lock); - return 0; -} - -static int dasd_stats_global_open(struct inode *inode, struct file *file) -{ - return single_open(file, dasd_stats_global_show, NULL); -} - -static const struct file_operations dasd_stats_global_fops = { - .owner = THIS_MODULE, - .open = dasd_stats_global_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = dasd_stats_global_write, -}; - static void dasd_profile_init(struct dasd_profile *profile, struct dentry *base_dentry) { @@ -1132,19 +1079,16 @@ static void dasd_profile_exit(struct dasd_profile *profile) static void dasd_statistics_removeroot(void) { dasd_global_profile_level = DASD_PROFILE_OFF; - debugfs_remove(dasd_global_profile.dentry); - dasd_global_profile.dentry = NULL; + dasd_profile_exit(&dasd_global_profile); debugfs_remove(dasd_debugfs_global_entry); debugfs_remove(dasd_debugfs_root_entry); } static void dasd_statistics_createroot(void) { - umode_t mode; struct dentry *pde; dasd_debugfs_root_entry = NULL; - dasd_debugfs_global_entry = NULL; pde = debugfs_create_dir("dasd", NULL); if (!pde || IS_ERR(pde)) goto error; @@ -1153,13 +1097,7 @@ static void dasd_statistics_createroot(void) if (!pde || IS_ERR(pde)) goto error; dasd_debugfs_global_entry = pde; - - mode = (S_IRUSR | S_IWUSR | S_IFREG); - pde = debugfs_create_file("statistics", mode, dasd_debugfs_global_entry, - NULL, &dasd_stats_global_fops); - if (!pde || IS_ERR(pde)) - goto error; - dasd_global_profile.dentry = pde; + dasd_profile_init(&dasd_global_profile, dasd_debugfs_global_entry); return; error: diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 91731fa05604..227e3dea3155 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -728,7 +728,6 @@ int dasd_device_is_ro(struct dasd_device *); void dasd_profile_reset(struct dasd_profile *); int dasd_profile_on(struct dasd_profile *); void dasd_profile_off(struct dasd_profile *); -void dasd_global_profile_reset(void); char *dasd_get_user_string(const char __user *, size_t); /* externals in dasd_devmap.c */ diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 76410084c48f..aa7bb2d1da81 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -212,15 +212,15 @@ static int dasd_stats_proc_show(struct seq_file *m, void *v) struct dasd_profile_info *prof; int factor; - /* check for active profiling */ - if (!dasd_global_profile_level) { + spin_lock_bh(&dasd_global_profile.lock); + prof = dasd_global_profile.data; + if (!prof) { + spin_unlock_bh(&dasd_global_profile.lock); seq_printf(m, "Statistics are off - they might be " "switched on using 'echo set on > " "/proc/dasd/statistics'\n"); return 0; } - spin_lock_bh(&dasd_global_profile.lock); - prof = dasd_global_profile.data; /* prevent counter 'overflow' on output */ for (factor = 1; (prof->dasd_io_reqs / factor) > 9999999; @@ -293,14 +293,19 @@ static ssize_t dasd_stats_proc_write(struct file *file, dasd_stats_all_block_off(); goto out_error; } - dasd_global_profile_reset(); + rc = dasd_profile_on(&dasd_global_profile); + if (rc) { + dasd_stats_all_block_off(); + goto out_error; + } + dasd_profile_reset(&dasd_global_profile); dasd_global_profile_level = DASD_PROFILE_ON; pr_info("The statistics feature has been switched " "on\n"); } else if (strcmp(str, "off") == 0) { - /* switch off and reset statistics profiling */ + /* switch off statistics profiling */ dasd_global_profile_level = DASD_PROFILE_OFF; - dasd_global_profile_reset(); + dasd_profile_off(&dasd_global_profile); dasd_stats_all_block_off(); pr_info("The statistics feature has been switched " "off\n"); @@ -308,7 +313,7 @@ static ssize_t dasd_stats_proc_write(struct file *file, goto out_parse_error; } else if (strncmp(str, "reset", 5) == 0) { /* reset the statistics */ - dasd_global_profile_reset(); + dasd_profile_reset(&dasd_global_profile); dasd_stats_all_block_reset(); pr_info("The statistics have been reset\n"); } else -- cgit v1.2.3 From ea96f78813823ab186e7e52122c06fb9c3cf6e20 Mon Sep 17 00:00:00 2001 From: Ingo Tuchscherer Date: Mon, 2 Feb 2015 17:50:17 +0100 Subject: s390/zcrypt: fixed domain scanning problem (again) Older machines with more then 16 domains need a special check before PQAP instructions can be processed. With commit 5bc334bff9a6e189 this check was reverted by accident. This patch re-establishes the additional code needed for checking the extended domains for older machines. Signed-off-by: Ingo Tuchscherer Signed-off-by: Martin Schwidefsky --- drivers/s390/crypto/ap_bus.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index a60fc2f9f4b2..3d7f19fb9a4e 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -1060,9 +1060,13 @@ static inline int ap_test_config_card_id(unsigned int id) */ static inline int ap_test_config_domain(unsigned int domain) { - if (!ap_configuration) - return 1; - return ap_test_config(ap_configuration->aqm, domain); + if (!ap_configuration) /* QCI not supported */ + if (domain < 16) + return 1; /* then domains 0...15 are configured */ + else + return 0; + else + return ap_test_config(ap_configuration->aqm, domain); } /* -- cgit v1.2.3