Commit 88fbf183 authored by Eric Rossman's avatar Eric Rossman Committed by Linus Torvalds

[PATCH] s390: add support for cex2a crypto cards

Signed-off-by: default avatarEric Rossman <edrossma@us.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent fb6958a5
/*
* linux/drivers/s390/crypto/z90common.h
*
* z90crypt 1.3.2
* z90crypt 1.3.3
*
* Copyright (C) 2001, 2004 IBM Corporation
* Copyright (C) 2001, 2005 IBM Corporation
* Author(s): Robert Burroughs (burrough@us.ibm.com)
* Eric Rossman (edrossma@us.ibm.com)
*
......@@ -91,12 +91,13 @@ enum hdstat {
#define TSQ_FATAL_ERROR 34
#define RSQ_FATAL_ERROR 35
#define Z90CRYPT_NUM_TYPES 5
#define Z90CRYPT_NUM_TYPES 6
#define PCICA 0
#define PCICC 1
#define PCIXCC_MCL2 2
#define PCIXCC_MCL3 3
#define CEX2C 4
#define CEX2A 5
#define NILDEV -1
#define ANYDEV -1
#define PCIXCC_UNK -2
......@@ -105,7 +106,7 @@ enum hdevice_type {
PCICC_HW = 3,
PCICA_HW = 4,
PCIXCC_HW = 5,
OTHER_HW = 6,
CEX2A_HW = 6,
CEX2C_HW = 7
};
......
/*
* linux/drivers/s390/crypto/z90crypt.h
*
* z90crypt 1.3.2
* z90crypt 1.3.3
*
* Copyright (C) 2001, 2004 IBM Corporation
* Copyright (C) 2001, 2005 IBM Corporation
* Author(s): Robert Burroughs (burrough@us.ibm.com)
* Eric Rossman (edrossma@us.ibm.com)
*
......@@ -29,11 +29,11 @@
#include <linux/ioctl.h>
#define VERSION_Z90CRYPT_H "$Revision: 1.11 $"
#define VERSION_Z90CRYPT_H "$Revision: 1.2.2.4 $"
#define z90crypt_VERSION 1
#define z90crypt_RELEASE 3 // 2 = PCIXCC, 3 = rewrite for coding standards
#define z90crypt_VARIANT 2 // 2 = added PCIXCC MCL3 and CEX2C support
#define z90crypt_VARIANT 3 // 3 = CEX2A support
/**
* struct ica_rsa_modexpo
......@@ -122,6 +122,9 @@ struct ica_rsa_modexpo_crt {
* Z90STAT_CEX2CCOUNT
* Return an integer count of all CEX2Cs.
*
* Z90STAT_CEX2ACOUNT
* Return an integer count of all CEX2As.
*
* Z90STAT_REQUESTQ_COUNT
* Return an integer count of the number of entries waiting to be
* sent to a device.
......@@ -144,6 +147,7 @@ struct ica_rsa_modexpo_crt {
* 0x03: PCIXCC_MCL2
* 0x04: PCIXCC_MCL3
* 0x05: CEX2C
* 0x06: CEX2A
* 0x0d: device is disabled via the proc filesystem
*
* Z90STAT_QDEPTH_MASK
......@@ -199,6 +203,7 @@ struct ica_rsa_modexpo_crt {
#define Z90STAT_PCIXCCMCL2COUNT _IOR(Z90_IOCTL_MAGIC, 0x4b, int)
#define Z90STAT_PCIXCCMCL3COUNT _IOR(Z90_IOCTL_MAGIC, 0x4c, int)
#define Z90STAT_CEX2CCOUNT _IOR(Z90_IOCTL_MAGIC, 0x4d, int)
#define Z90STAT_CEX2ACOUNT _IOR(Z90_IOCTL_MAGIC, 0x4e, int)
#define Z90STAT_REQUESTQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x44, int)
#define Z90STAT_PENDINGQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x45, int)
#define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int)
......
This diff is collapsed.
......@@ -228,7 +228,7 @@ struct device_x {
*/
struct device {
int dev_type; // PCICA, PCICC, PCIXCC_MCL2,
// PCIXCC_MCL3, CEX2C
// PCIXCC_MCL3, CEX2C, CEX2A
enum devstat dev_stat; // current device status
int dev_self_x; // Index in array
int disabled; // Set when device is in error
......@@ -295,26 +295,30 @@ struct caller {
/**
* Function prototypes from z90hardware.c
*/
enum hdstat query_online(int, int, int, int *, int *);
enum devstat reset_device(int, int, int);
enum devstat send_to_AP(int, int, int, unsigned char *);
enum devstat receive_from_AP(int, int, int, unsigned char *, unsigned char *);
int convert_request(unsigned char *, int, short, int, int, int *,
unsigned char *);
int convert_response(unsigned char *, unsigned char *, int *, unsigned char *);
enum hdstat query_online(int deviceNr, int cdx, int resetNr, int *q_depth,
int *dev_type);
enum devstat reset_device(int deviceNr, int cdx, int resetNr);
enum devstat send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext);
enum devstat receive_from_AP(int dev_nr, int cdx, int resplen,
unsigned char *resp, unsigned char *psmid);
int convert_request(unsigned char *buffer, int func, unsigned short function,
int cdx, int dev_type, int *msg_l_p, unsigned char *msg_p);
int convert_response(unsigned char *response, unsigned char *buffer,
int *respbufflen_p, unsigned char *resp_buff);
/**
* Low level function prototypes
*/
static int create_z90crypt(int *);
static int refresh_z90crypt(int *);
static int find_crypto_devices(struct status *);
static int create_crypto_device(int);
static int destroy_crypto_device(int);
static int create_z90crypt(int *cdx_p);
static int refresh_z90crypt(int *cdx_p);
static int find_crypto_devices(struct status *deviceMask);
static int create_crypto_device(int index);
static int destroy_crypto_device(int index);
static void destroy_z90crypt(void);
static int refresh_index_array(struct status *, struct device_x *);
static int probe_device_type(struct device *);
static int probe_PCIXCC_type(struct device *);
static int refresh_index_array(struct status *status_str,
struct device_x *index_array);
static int probe_device_type(struct device *devPtr);
static int probe_PCIXCC_type(struct device *devPtr);
/**
* proc fs definitions
......@@ -425,7 +429,7 @@ static struct miscdevice z90crypt_misc_device = {
MODULE_AUTHOR("zSeries Linux Crypto Team: Robert H. Burroughs, Eric D. Rossman"
"and Jochen Roehrig");
MODULE_DESCRIPTION("zSeries Linux Cryptographic Coprocessor device driver, "
"Copyright 2001, 2004 IBM Corporation");
"Copyright 2001, 2005 IBM Corporation");
MODULE_LICENSE("GPL");
module_param(domain, int, 0);
MODULE_PARM_DESC(domain, "domain index for device");
......@@ -859,6 +863,12 @@ get_status_CEX2Ccount(void)
return z90crypt.hdware_info->type_mask[CEX2C].st_count;
}
static inline int
get_status_CEX2Acount(void)
{
return z90crypt.hdware_info->type_mask[CEX2A].st_count;
}
static inline int
get_status_requestq_count(void)
{
......@@ -1008,11 +1018,13 @@ static inline int
select_device_type(int *dev_type_p, int bytelength)
{
static int count = 0;
int PCICA_avail, PCIXCC_MCL3_avail, CEX2C_avail, index_to_use;
int PCICA_avail, PCIXCC_MCL3_avail, CEX2C_avail, CEX2A_avail,
index_to_use;
struct status *stat;
if ((*dev_type_p != PCICC) && (*dev_type_p != PCICA) &&
(*dev_type_p != PCIXCC_MCL2) && (*dev_type_p != PCIXCC_MCL3) &&
(*dev_type_p != CEX2C) && (*dev_type_p != ANYDEV))
(*dev_type_p != CEX2C) && (*dev_type_p != CEX2A) &&
(*dev_type_p != ANYDEV))
return -1;
if (*dev_type_p != ANYDEV) {
stat = &z90crypt.hdware_info->type_mask[*dev_type_p];
......@@ -1022,7 +1034,13 @@ select_device_type(int *dev_type_p, int bytelength)
return -1;
}
/* Assumption: PCICA, PCIXCC_MCL3, and CEX2C are all similar in speed */
/**
* Assumption: PCICA, PCIXCC_MCL3, CEX2C, and CEX2A are all similar in
* speed.
*
* PCICA and CEX2A do NOT co-exist, so it would be either one or the
* other present.
*/
stat = &z90crypt.hdware_info->type_mask[PCICA];
PCICA_avail = stat->st_count -
(stat->disabled_count + stat->user_disabled_count);
......@@ -1032,29 +1050,38 @@ select_device_type(int *dev_type_p, int bytelength)
stat = &z90crypt.hdware_info->type_mask[CEX2C];
CEX2C_avail = stat->st_count -
(stat->disabled_count + stat->user_disabled_count);
if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail) {
stat = &z90crypt.hdware_info->type_mask[CEX2A];
CEX2A_avail = stat->st_count -
(stat->disabled_count + stat->user_disabled_count);
if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail || CEX2A_avail) {
/**
* bitlength is a factor, PCICA is the most capable, even with
* the new MCL for PCIXCC.
* bitlength is a factor, PCICA or CEX2A are the most capable,
* even with the new MCL for PCIXCC.
*/
if ((bytelength < PCIXCC_MIN_MOD_SIZE) ||
(!ext_bitlens && (bytelength < OLD_PCIXCC_MIN_MOD_SIZE))) {
if (!PCICA_avail)
return -1;
else {
if (PCICA_avail) {
*dev_type_p = PCICA;
return 0;
}
if (CEX2A_avail) {
*dev_type_p = CEX2A;
return 0;
}
return -1;
}
index_to_use = count % (PCICA_avail + PCIXCC_MCL3_avail +
CEX2C_avail);
CEX2C_avail + CEX2A_avail);
if (index_to_use < PCICA_avail)
*dev_type_p = PCICA;
else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail))
*dev_type_p = PCIXCC_MCL3;
else
else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail +
CEX2C_avail))
*dev_type_p = CEX2C;
else
*dev_type_p = CEX2A;
count++;
return 0;
}
......@@ -1359,7 +1386,7 @@ build_caller(struct work_element *we_p, short function)
if ((we_p->devtype != PCICC) && (we_p->devtype != PCICA) &&
(we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) &&
(we_p->devtype != CEX2C))
(we_p->devtype != CEX2C) && (we_p->devtype != CEX2A))
return SEN_NOT_AVAIL;
memcpy(caller_p->caller_id, we_p->caller_id,
......@@ -1428,7 +1455,8 @@ get_crypto_request_buffer(struct work_element *we_p)
if ((we_p->devtype != PCICA) && (we_p->devtype != PCICC) &&
(we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) &&
(we_p->devtype != CEX2C) && (we_p->devtype != ANYDEV)) {
(we_p->devtype != CEX2C) && (we_p->devtype != CEX2A) &&
(we_p->devtype != ANYDEV)) {
PRINTK("invalid device type\n");
return SEN_USER_ERROR;
}
......@@ -1503,8 +1531,9 @@ get_crypto_request_buffer(struct work_element *we_p)
function = PCI_FUNC_KEY_ENCRYPT;
switch (we_p->devtype) {
/* PCICA does everything with a simple RSA mod-expo operation */
/* PCICA and CEX2A do everything with a simple RSA mod-expo operation */
case PCICA:
case CEX2A:
function = PCI_FUNC_KEY_ENCRYPT;
break;
/**
......@@ -1662,7 +1691,8 @@ z90crypt_rsa(struct priv_data *private_data_p, pid_t pid,
* trigger a fallback to software.
*/
case -EINVAL:
if (we_p->devtype != PCICA)
if ((we_p->devtype != PCICA) &&
(we_p->devtype != CEX2A))
rv = -EGETBUFF;
break;
case -ETIMEOUT:
......@@ -1779,6 +1809,12 @@ z90crypt_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
ret = -EFAULT;
break;
case Z90STAT_CEX2ACOUNT:
tempstat = get_status_CEX2Acount();
if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0)
ret = -EFAULT;
break;
case Z90STAT_REQUESTQ_COUNT:
tempstat = get_status_requestq_count();
if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0)
......@@ -2019,6 +2055,8 @@ z90crypt_status(char *resp_buff, char **start, off_t offset,
get_status_PCIXCCMCL3count());
len += sprintf(resp_buff+len, "CEX2C count: %d\n",
get_status_CEX2Ccount());
len += sprintf(resp_buff+len, "CEX2A count: %d\n",
get_status_CEX2Acount());
len += sprintf(resp_buff+len, "requestq count: %d\n",
get_status_requestq_count());
len += sprintf(resp_buff+len, "pendingq count: %d\n",
......@@ -2026,8 +2064,8 @@ z90crypt_status(char *resp_buff, char **start, off_t offset,
len += sprintf(resp_buff+len, "Total open handles: %d\n\n",
get_status_totalopen_count());
len += sprinthx(
"Online devices: 1: PCICA, 2: PCICC, 3: PCIXCC (MCL2), "
"4: PCIXCC (MCL3), 5: CEX2C",
"Online devices: 1=PCICA 2=PCICC 3=PCIXCC(MCL2) "
"4=PCIXCC(MCL3) 5=CEX2C 6=CEX2A",
resp_buff+len,
get_status_status_mask(workarea),
Z90CRYPT_NUM_APS);
......@@ -2140,6 +2178,7 @@ z90crypt_status_write(struct file *file, const char __user *buffer,
case '3': // PCIXCC_MCL2
case '4': // PCIXCC_MCL3
case '5': // CEX2C
case '6': // CEX2A
j++;
break;
case 'd':
......@@ -3007,7 +3046,9 @@ create_crypto_device(int index)
z90crypt.hdware_info->device_type_array[index] = 4;
else if (deviceType == CEX2C)
z90crypt.hdware_info->device_type_array[index] = 5;
else
else if (deviceType == CEX2A)
z90crypt.hdware_info->device_type_array[index] = 6;
else // No idea how this would happen.
z90crypt.hdware_info->device_type_array[index] = -1;
}
......
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