diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-11 17:42:32 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-11 17:42:32 -0800 |
commit | b3d6524ff7956c5a898d51a18eaecb62a60a2b84 (patch) | |
tree | cc049e7ec9edd9f5a76f286e04d8db9a1caa516a /drivers/s390 | |
parent | 07f80d41cf24b7e6e76cd97d420167932c9a7f82 (diff) | |
parent | 6a039eab53c01a58bfff95c78fc800ca7de27c77 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Martin Schwidefsky:
- The remaining patches for the z13 machine support: kernel build
option for z13, the cache synonym avoidance, SMT support,
compare-and-delay for spinloops and the CES5S crypto adapater.
- The ftrace support for function tracing with the gcc hotpatch option.
This touches common code Makefiles, Steven is ok with the changes.
- The hypfs file system gets an extension to access diagnose 0x0c data
in user space for performance analysis for Linux running under z/VM.
- The iucv hvc console gets wildcard spport for the user id filtering.
- The cacheinfo code is converted to use the generic infrastructure.
- Cleanup and bug fixes.
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (42 commits)
s390/process: free vx save area when releasing tasks
s390/hypfs: Eliminate hypfs interval
s390/hypfs: Add diagnose 0c support
s390/cacheinfo: don't use smp_processor_id() in preemptible context
s390/zcrypt: fixed domain scanning problem (again)
s390/smp: increase maximum value of NR_CPUS to 512
s390/jump label: use different nop instruction
s390/jump label: add sanity checks
s390/mm: correct missing space when reporting user process faults
s390/dasd: cleanup profiling
s390/dasd: add locking for global_profile access
s390/ftrace: hotpatch support for function tracing
ftrace: let notrace function attribute disable hotpatching if necessary
ftrace: allow architectures to specify ftrace compile options
s390: reintroduce diag 44 calls for cpu_relax()
s390/zcrypt: Add support for new crypto express (CEX5S) adapter.
s390/zcrypt: Number of supported ap domains is not retrievable.
s390/spinlock: add compare-and-delay to lock wait loops
s390/tape: remove redundant if statement
s390/hvc_iucv: add simple wildcard matches to the iucv allow filter
...
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/block/dasd.c | 102 | ||||
-rw-r--r-- | drivers/s390/block/dasd_int.h | 3 | ||||
-rw-r--r-- | drivers/s390/block/dasd_proc.c | 21 | ||||
-rw-r--r-- | drivers/s390/block/dcssblk.c | 15 | ||||
-rw-r--r-- | drivers/s390/char/hmcdrv_ftp.c | 6 | ||||
-rw-r--r-- | drivers/s390/char/hmcdrv_mod.c | 1 | ||||
-rw-r--r-- | drivers/s390/char/sclp_early.c | 49 | ||||
-rw-r--r-- | drivers/s390/char/tape_34xx.c | 12 | ||||
-rw-r--r-- | drivers/s390/cio/cio.c | 2 | ||||
-rw-r--r-- | drivers/s390/cio/idset.c | 20 | ||||
-rw-r--r-- | drivers/s390/cio/idset.h | 2 | ||||
-rw-r--r-- | drivers/s390/crypto/ap_bus.c | 144 | ||||
-rw-r--r-- | drivers/s390/crypto/ap_bus.h | 1 | ||||
-rw-r--r-- | drivers/s390/crypto/zcrypt_api.h | 1 | ||||
-rw-r--r-- | drivers/s390/crypto/zcrypt_cex4.c | 33 |
15 files changed, 229 insertions, 183 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 4abf11965484..be34ef41b7c7 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -674,8 +674,9 @@ 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; +struct dasd_profile dasd_global_profile = { + .lock = __SPIN_LOCK_UNLOCKED(dasd_global_profile.lock), +}; static struct dentry *dasd_debugfs_global_entry; /* @@ -696,11 +697,13 @@ static void dasd_profile_start(struct dasd_block *block, if (++counter >= 31) break; - if (dasd_global_profile_level) { - dasd_global_profile_data.dasd_io_nr_req[counter]++; + spin_lock(&dasd_global_profile.lock); + 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]++; + 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 +828,9 @@ static void dasd_profile_end(struct dasd_block *block, dasd_profile_counter(irqtime / sectors, irqtimeps_ind); dasd_profile_counter(endtime, endtime_ind); - if (dasd_global_profile_level) { - dasd_profile_end_add_data(&dasd_global_profile_data, + spin_lock(&dasd_global_profile.lock); + if (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 +839,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) @@ -876,12 +881,6 @@ void dasd_profile_reset(struct dasd_profile *profile) spin_unlock_bh(&profile->lock); } -void dasd_global_profile_reset(void) -{ - memset(&dasd_global_profile_data, 0, sizeof(dasd_global_profile_data)); - getnstimeofday(&dasd_global_profile_data.starttod); -} - int dasd_profile_on(struct dasd_profile *profile) { struct dasd_profile_info *data; @@ -949,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; } @@ -1044,57 +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; - } - dasd_stats_seq_print(m, &dasd_global_profile_data); - 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) { @@ -1123,20 +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; - dasd_global_profile_dentry = NULL; pde = debugfs_create_dir("dasd", NULL); if (!pde || IS_ERR(pde)) goto error; @@ -1145,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 8b5d4100abf7..227e3dea3155 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; @@ -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 78ac905a5b7f..aa7bb2d1da81 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -212,14 +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; } - 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 @@ -291,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"); @@ -306,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 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; } 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); 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 <linux/kernel.h> #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/version.h> #include <linux/stat.h> #include "hmcdrv_ftp.h" 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/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, 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)); 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); diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 4d41bf75c233..3d7f19fb9a4e 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -204,6 +204,24 @@ ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type) } /** + * 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 * @@ -1007,6 +1025,51 @@ 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) /* 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 bus attributes. */ static ssize_t ap_domain_show(struct bus_type *bus, char *buf) @@ -1121,6 +1184,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 +1227,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. * @@ -1434,9 +1493,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); } |