Commit a9db48b7 authored by Eric Rossman's avatar Eric Rossman Committed by Linus Torvalds

[PATCH] s390: crypto device driver

crypto driver changes:
 - Add support for zero-pad and crypto express II (CEX2C).
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 f2e30152
/* /*
* linux/drivers/s390/misc/z90common.h * linux/drivers/s390/misc/z90common.h
* *
* z90crypt 1.3.1 * z90crypt 1.3.2
* *
* Copyright (C) 2001, 2004 IBM Corporation * Copyright (C) 2001, 2004 IBM Corporation
* Author(s): Robert Burroughs (burrough@us.ibm.com) * Author(s): Robert Burroughs (burrough@us.ibm.com)
...@@ -27,12 +27,13 @@ ...@@ -27,12 +27,13 @@
#ifndef _Z90COMMON_ #ifndef _Z90COMMON_
#define _Z90COMMON_ #define _Z90COMMON_
#define VERSION_Z90COMMON_H "$Revision: 1.8 $" #define VERSION_Z90COMMON_H "$Revision: 1.15 $"
#define RESPBUFFSIZE 256 #define RESPBUFFSIZE 256
#define PCI_FUNC_KEY_DECRYPT 0x5044 #define PCI_FUNC_KEY_DECRYPT 0x5044
#define PCI_FUNC_KEY_ENCRYPT 0x504B #define PCI_FUNC_KEY_ENCRYPT 0x504B
extern int ext_bitlens;
enum devstat { enum devstat {
DEV_GONE, DEV_GONE,
...@@ -56,6 +57,7 @@ enum hdstat { ...@@ -56,6 +57,7 @@ enum hdstat {
HD_TSQ_EXCEPTION HD_TSQ_EXCEPTION
}; };
#define Z90C_NO_DEVICES 1
#define Z90C_AMBIGUOUS_DOMAIN 2 #define Z90C_AMBIGUOUS_DOMAIN 2
#define Z90C_INCORRECT_DOMAIN 3 #define Z90C_INCORRECT_DOMAIN 3
#define ENOTINIT 4 #define ENOTINIT 4
...@@ -80,7 +82,7 @@ enum hdstat { ...@@ -80,7 +82,7 @@ enum hdstat {
#define REC_USER_GONE 15 #define REC_USER_GONE 15
#define REC_BAD_MESSAGE 16 #define REC_BAD_MESSAGE 16
#define REC_INVALID_PAD 17 #define REC_INVALID_PAD 17
#define REC_RELEASED 28 #define REC_USE_PCICA 18
#define WRONG_DEVICE_TYPE 20 #define WRONG_DEVICE_TYPE 20
...@@ -89,18 +91,55 @@ enum hdstat { ...@@ -89,18 +91,55 @@ enum hdstat {
#define TSQ_FATAL_ERROR 34 #define TSQ_FATAL_ERROR 34
#define RSQ_FATAL_ERROR 35 #define RSQ_FATAL_ERROR 35
#define Z90CRYPT_NUM_TYPES 5
#define PCICA 0 #define PCICA 0
#define PCICC 1 #define PCICC 1
#define PCIXCC 2 #define PCIXCC_MCL2 2
#define PCIXCC_MCL3 3
#define CEX2C 4
#define NILDEV -1 #define NILDEV -1
#define ANYDEV -1 #define ANYDEV -1
#define PCIXCC_UNK -2
enum hdevice_type { enum hdevice_type {
PCICC_HW = 3, PCICC_HW = 3,
PCICA_HW = 4, PCICA_HW = 4,
PCIXCC_HW = 5, PCIXCC_HW = 5,
OTHER_HW = 6, OTHER_HW = 6,
OTHER2_HW = 7 CEX2C_HW = 7
};
struct CPRBX {
unsigned short cprb_len;
unsigned char cprb_ver_id;
unsigned char pad_000[3];
unsigned char func_id[2];
unsigned char cprb_flags[4];
unsigned int req_parml;
unsigned int req_datal;
unsigned int rpl_msgbl;
unsigned int rpld_parml;
unsigned int rpl_datal;
unsigned int rpld_datal;
unsigned int req_extbl;
unsigned char pad_001[4];
unsigned int rpld_extbl;
unsigned char req_parmb[16];
unsigned char req_datab[16];
unsigned char rpl_parmb[16];
unsigned char rpl_datab[16];
unsigned char req_extb[16];
unsigned char rpl_extb[16];
unsigned short ccp_rtcode;
unsigned short ccp_rscode;
unsigned int mac_data_len;
unsigned char logon_id[8];
unsigned char mac_value[8];
unsigned char mac_content_flgs;
unsigned char pad_002;
unsigned short domain;
unsigned char pad_003[12];
unsigned char pad_004[36];
}; };
#ifndef DEV_NAME #ifndef DEV_NAME
......
/* /*
* linux/drivers/s390/misc/z90crypt.h * linux/drivers/s390/misc/z90crypt.h
* *
* z90crypt 1.3.1 * z90crypt 1.3.2
* *
* Copyright (C) 2001, 2004 IBM Corporation * Copyright (C) 2001, 2004 IBM Corporation
* Author(s): Robert Burroughs (burrough@us.ibm.com) * Author(s): Robert Burroughs (burrough@us.ibm.com)
...@@ -29,11 +29,20 @@ ...@@ -29,11 +29,20 @@
#include <linux/ioctl.h> #include <linux/ioctl.h>
#define VERSION_Z90CRYPT_H "$Revision: 1.2 $" #define VERSION_Z90CRYPT_H "$Revision: 1.10 $"
#define z90crypt_VERSION 1 #define z90crypt_VERSION 1
#define z90crypt_RELEASE 3 // 2 = PCIXCC, 3 = rewrite for coding standards #define z90crypt_RELEASE 3 // 2 = PCIXCC, 3 = rewrite for coding standards
#define z90crypt_VARIANT 1 #define z90crypt_VARIANT 2 // 2 = added PCIXCC MCL3 and CEX2C support
/**
* If we are not using the sparse checker, __user has no use.
*/
#ifdef __CHECKER__
# define __user __attribute__((noderef, address_space(1)))
#else
# define __user
#endif
/** /**
* struct ica_rsa_modexpo * struct ica_rsa_modexpo
...@@ -113,8 +122,14 @@ struct ica_rsa_modexpo_crt { ...@@ -113,8 +122,14 @@ struct ica_rsa_modexpo_crt {
* Z90STAT_PCICCCOUNT * Z90STAT_PCICCCOUNT
* Return an integer count of all PCICCs. * Return an integer count of all PCICCs.
* *
* Z90STAT_PCIXCCCOUNT * Z90STAT_PCIXCCMCL2COUNT
* Return an integer count of all PCIXCCs. * Return an integer count of all MCL2 PCIXCCs.
*
* Z90STAT_PCIXCCMCL3COUNT
* Return an integer count of all MCL3 PCIXCCs.
*
* Z90STAT_CEX2CCOUNT
* Return an integer count of all CEX2Cs.
* *
* Z90STAT_REQUESTQ_COUNT * Z90STAT_REQUESTQ_COUNT
* Return an integer count of the number of entries waiting to be * Return an integer count of the number of entries waiting to be
...@@ -135,7 +150,9 @@ struct ica_rsa_modexpo_crt { ...@@ -135,7 +150,9 @@ struct ica_rsa_modexpo_crt {
* all devices. * all devices.
* 0x01: PCICA * 0x01: PCICA
* 0x02: PCICC * 0x02: PCICC
* 0x03: PCIXCC * 0x03: PCIXCC_MCL2
* 0x04: PCIXCC_MCL3
* 0x05: CEX2C
* 0x0d: device is disabled via the proc filesystem * 0x0d: device is disabled via the proc filesystem
* *
* Z90STAT_QDEPTH_MASK * Z90STAT_QDEPTH_MASK
...@@ -154,9 +171,14 @@ struct ica_rsa_modexpo_crt { ...@@ -154,9 +171,14 @@ struct ica_rsa_modexpo_crt {
* NOTE: this ioctl() is deprecated, and has been replaced with * NOTE: this ioctl() is deprecated, and has been replaced with
* single ioctl()s for each type of status being requested * single ioctl()s for each type of status being requested
* *
* Z90STAT_PCIXCCCOUNT (deprecated)
* Return an integer count of all PCIXCCs (MCL2 + MCL3).
* This is DEPRECATED now that MCL3 PCIXCCs are treated differently from
* MCL2 PCIXCCs.
*
* Z90QUIESCE (not recommended) * Z90QUIESCE (not recommended)
* Quiesce the driver. This is intended to stop all new * Quiesce the driver. This is intended to stop all new
* requests from being processed. Its use is not recommended, * requests from being processed. Its use is NOT recommended,
* except in circumstances where there is no other way to stop * except in circumstances where there is no other way to stop
* callers from accessing the driver. Its original use was to * callers from accessing the driver. Its original use was to
* allow the driver to be "drained" of work in preparation for * allow the driver to be "drained" of work in preparation for
...@@ -172,8 +194,9 @@ struct ica_rsa_modexpo_crt { ...@@ -172,8 +194,9 @@ struct ica_rsa_modexpo_crt {
#define ICARSAMODEXPO _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x05, 0) #define ICARSAMODEXPO _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x05, 0)
#define ICARSACRT _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x06, 0) #define ICARSACRT _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x06, 0)
/* DEPRECATED status call (bound for removal SOON) */ /* DEPRECATED status calls (bound for removal at some point) */
#define ICAZ90STATUS _IOR(Z90_IOCTL_MAGIC, 0x10, struct ica_z90_status) #define ICAZ90STATUS _IOR(Z90_IOCTL_MAGIC, 0x10, struct ica_z90_status)
#define Z90STAT_PCIXCCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x43, int)
/* unrelated to ICA callers */ /* unrelated to ICA callers */
#define Z90QUIESCE _IO(Z90_IOCTL_MAGIC, 0x11) #define Z90QUIESCE _IO(Z90_IOCTL_MAGIC, 0x11)
...@@ -182,7 +205,9 @@ struct ica_rsa_modexpo_crt { ...@@ -182,7 +205,9 @@ struct ica_rsa_modexpo_crt {
#define Z90STAT_TOTALCOUNT _IOR(Z90_IOCTL_MAGIC, 0x40, int) #define Z90STAT_TOTALCOUNT _IOR(Z90_IOCTL_MAGIC, 0x40, int)
#define Z90STAT_PCICACOUNT _IOR(Z90_IOCTL_MAGIC, 0x41, int) #define Z90STAT_PCICACOUNT _IOR(Z90_IOCTL_MAGIC, 0x41, int)
#define Z90STAT_PCICCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x42, int) #define Z90STAT_PCICCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x42, int)
#define Z90STAT_PCIXCCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x43, int) #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_REQUESTQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x44, int) #define Z90STAT_REQUESTQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x44, int)
#define Z90STAT_PENDINGQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x45, int) #define Z90STAT_PENDINGQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x45, int)
#define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int) #define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int)
...@@ -199,8 +224,9 @@ struct ica_rsa_modexpo_crt { ...@@ -199,8 +224,9 @@ struct ica_rsa_modexpo_crt {
#define ERELEASED 131 // user released while ioctl pending #define ERELEASED 131 // user released while ioctl pending
#define EQUIESCE 132 // z90crypt quiescing (no more work allowed) #define EQUIESCE 132 // z90crypt quiescing (no more work allowed)
#define ETIMEOUT 133 // request timed out #define ETIMEOUT 133 // request timed out
#define EUNKNOWN 134 // some unrecognized error occured #define EUNKNOWN 134 // some unrecognized error occured (retry may succeed)
#define EGETBUFF 135 // Error getting buffer #define EGETBUFF 135 // Error getting buffer or hardware lacks capability
// (retry in software)
/** /**
* DEPRECATED STRUCTURES * DEPRECATED STRUCTURES
...@@ -222,7 +248,8 @@ struct ica_z90_status { ...@@ -222,7 +248,8 @@ struct ica_z90_status {
int pendingqWaitCount; int pendingqWaitCount;
int totalOpenCount; int totalOpenCount;
int cryptoDomain; int cryptoDomain;
// status: 0=not there. 1=PCICA. 2=PCICC. 3=PCIXCC // status: 0=not there, 1=PCICA, 2=PCICC, 3=PCIXCC_MCL2, 4=PCIXCC_MCL3,
// 5=CEX2C
unsigned char status[MASK_LENGTH]; unsigned char status[MASK_LENGTH];
// qdepth: # work elements waiting for each device // qdepth: # work elements waiting for each device
unsigned char qdepth[MASK_LENGTH]; unsigned char qdepth[MASK_LENGTH];
......
/* /*
* linux/drivers/s390/misc/z90hardware.c * linux/drivers/s390/misc/z90hardware.c
* *
* z90crypt 1.3.1 * z90crypt 1.3.2
* *
* Copyright (C) 2001, 2004 IBM Corporation * Copyright (C) 2001, 2004 IBM Corporation
* Author(s): Robert Burroughs (burrough@us.ibm.com) * Author(s): Robert Burroughs (burrough@us.ibm.com)
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#include "z90crypt.h" #include "z90crypt.h"
#include "z90common.h" #include "z90common.h"
#define VERSION_Z90HARDWARE_C "$Revision: 1.19 $" #define VERSION_Z90HARDWARE_C "$Revision: 1.32 $"
char z90chardware_version[] __initdata = char z90chardware_version[] __initdata =
"z90hardware.o (" VERSION_Z90HARDWARE_C "/" "z90hardware.o (" VERSION_Z90HARDWARE_C "/"
...@@ -224,7 +224,7 @@ struct type6_hdr { ...@@ -224,7 +224,7 @@ struct type6_hdr {
unsigned char right[4]; unsigned char right[4];
unsigned char reserved3[2]; unsigned char reserved3[2];
unsigned char reserved4[2]; unsigned char reserved4[2];
unsigned char pfs[4]; unsigned char apfs[4];
unsigned int offset1; unsigned int offset1;
unsigned int offset2; unsigned int offset2;
unsigned int offset3; unsigned int offset3;
...@@ -278,39 +278,6 @@ struct CPRB { ...@@ -278,39 +278,6 @@ struct CPRB {
unsigned char svr_name[8]; unsigned char svr_name[8];
}; };
struct CPRBX {
unsigned short cprb_len;
unsigned char cprb_ver_id;
unsigned char pad_000[3];
unsigned char func_id[2];
unsigned char cprb_flags[4];
unsigned int req_parml;
unsigned int req_datal;
unsigned int rpl_msgbl;
unsigned int rpld_parml;
unsigned int rpl_datal;
unsigned int rpld_datal;
unsigned int req_extbl;
unsigned char pad_001[4];
unsigned int rpld_extbl;
unsigned char req_parmb[16];
unsigned char req_datab[16];
unsigned char rpl_parmb[16];
unsigned char rpl_datab[16];
unsigned char req_extb[16];
unsigned char rpl_extb[16];
unsigned short ccp_rtcode;
unsigned short ccp_rscode;
unsigned int mac_data_len;
unsigned char logon_id[8];
unsigned char mac_value[8];
unsigned char mac_content_flgs;
unsigned char pad_002;
unsigned short domain;
unsigned char pad_003[12];
unsigned char pad_004[36];
};
struct type6_msg { struct type6_msg {
struct type6_hdr header; struct type6_hdr header;
struct CPRB CPRB; struct CPRB CPRB;
...@@ -347,12 +314,13 @@ struct type82_hdr { ...@@ -347,12 +314,13 @@ struct type82_hdr {
#define REPLY_ERROR_FORMAT_FIELD 0x29 #define REPLY_ERROR_FORMAT_FIELD 0x29
#define REPLY_ERROR_INVALID_COMMAND 0x30 #define REPLY_ERROR_INVALID_COMMAND 0x30
#define REPLY_ERROR_MALFORMED_MSG 0x40 #define REPLY_ERROR_MALFORMED_MSG 0x40
#define REPLY_ERROR_RESERVED_FIELD 0x50 #define REPLY_ERROR_RESERVED_FIELDO 0x50
#define REPLY_ERROR_WORD_ALIGNMENT 0x60 #define REPLY_ERROR_WORD_ALIGNMENT 0x60
#define REPLY_ERROR_MESSAGE_LENGTH 0x80 #define REPLY_ERROR_MESSAGE_LENGTH 0x80
#define REPLY_ERROR_OPERAND_INVALID 0x82 #define REPLY_ERROR_OPERAND_INVALID 0x82
#define REPLY_ERROR_OPERAND_SIZE 0x84 #define REPLY_ERROR_OPERAND_SIZE 0x84
#define REPLY_ERROR_EVEN_MOD_IN_OPND 0x85 #define REPLY_ERROR_EVEN_MOD_IN_OPND 0x85
#define REPLY_ERROR_RESERVED_FIELD 0x88
#define REPLY_ERROR_TRANSPORT_FAIL 0x90 #define REPLY_ERROR_TRANSPORT_FAIL 0x90
#define REPLY_ERROR_PACKET_TRUNCATED 0xA0 #define REPLY_ERROR_PACKET_TRUNCATED 0xA0
#define REPLY_ERROR_ZERO_BUFFER_LEN 0xB0 #define REPLY_ERROR_ZERO_BUFFER_LEN 0xB0
...@@ -379,7 +347,7 @@ struct type86_fmt2_msg { ...@@ -379,7 +347,7 @@ struct type86_fmt2_msg {
unsigned int offset2; unsigned int offset2;
unsigned int count3; unsigned int count3;
unsigned int offset3; unsigned int offset3;
unsigned int ount4; unsigned int count4;
unsigned int offset4; unsigned int offset4;
}; };
...@@ -546,18 +514,30 @@ static struct CPRBX static_cprbx = { ...@@ -546,18 +514,30 @@ static struct CPRBX static_cprbx = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
}; };
static struct function_and_rules_block static_pkd_function_and_rulesX = { static struct function_and_rules_block static_pkd_function_and_rulesX_MCL2 = {
{0x50,0x44}, {0x50,0x44},
{0x00,0x0A}, {0x00,0x0A},
{'P','K','C','S','-','1','.','2'} {'P','K','C','S','-','1','.','2'}
}; };
static struct function_and_rules_block static_pke_function_and_rulesX = { static struct function_and_rules_block static_pke_function_and_rulesX_MCL2 = {
{0x50,0x4B}, {0x50,0x4B},
{0x00,0x0A}, {0x00,0x0A},
{'Z','E','R','O','-','P','A','D'} {'Z','E','R','O','-','P','A','D'}
}; };
static struct function_and_rules_block static_pkd_function_and_rulesX = {
{0x50,0x44},
{0x00,0x0A},
{'Z','E','R','O','-','P','A','D'}
};
static struct function_and_rules_block static_pke_function_and_rulesX = {
{0x50,0x4B},
{0x00,0x0A},
{'M','R','P',' ',' ',' ',' ',' '}
};
struct T6_keyBlock_hdrX { struct T6_keyBlock_hdrX {
unsigned short blen; unsigned short blen;
unsigned short ulen; unsigned short ulen;
...@@ -701,11 +681,9 @@ static struct cca_public_sec static_cca_pub_sec = { ...@@ -701,11 +681,9 @@ static struct cca_public_sec static_cca_pub_sec = {
#define FIXED_TYPE6_CR_LENX 0x000001E3 #define FIXED_TYPE6_CR_LENX 0x000001E3
#ifndef MAX_RESPONSE_SIZE
#define MAX_RESPONSE_SIZE 0x00000710 #define MAX_RESPONSE_SIZE 0x00000710
#define MAX_RESPONSEX_SIZE 0x0000077C #define MAX_RESPONSEX_SIZE 0x0000077C
#endif
#define RESPONSE_CPRB_SIZE 0x000006B8 #define RESPONSE_CPRB_SIZE 0x000006B8
#define RESPONSE_CPRBX_SIZE 0x00000724 #define RESPONSE_CPRBX_SIZE 0x00000724
...@@ -1063,7 +1041,6 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type) ...@@ -1063,7 +1041,6 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type)
*q_depth = t_depth + 1; *q_depth = t_depth + 1;
switch (t_dev_type) { switch (t_dev_type) {
case OTHER_HW: case OTHER_HW:
case OTHER2_HW:
stat = HD_NOT_THERE; stat = HD_NOT_THERE;
*dev_type = NILDEV; *dev_type = NILDEV;
break; break;
...@@ -1074,7 +1051,10 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type) ...@@ -1074,7 +1051,10 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type)
*dev_type = PCICC; *dev_type = PCICC;
break; break;
case PCIXCC_HW: case PCIXCC_HW:
*dev_type = PCIXCC; *dev_type = PCIXCC_UNK;
break;
case CEX2C_HW:
*dev_type = CEX2C;
break; break;
default: default:
*dev_type = NILDEV; *dev_type = NILDEV;
...@@ -1133,6 +1113,7 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type) ...@@ -1133,6 +1113,7 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type)
default: default:
stat = HD_NOT_THERE; stat = HD_NOT_THERE;
break_out = 1; break_out = 1;
break;
} }
if (break_out) if (break_out)
break; break;
...@@ -1170,18 +1151,11 @@ reset_device(int deviceNr, int cdx, int resetNr) ...@@ -1170,18 +1151,11 @@ reset_device(int deviceNr, int cdx, int resetNr)
switch (stat_word.response_code) { switch (stat_word.response_code) {
case AP_RESPONSE_NORMAL: case AP_RESPONSE_NORMAL:
stat = DEV_ONLINE; stat = DEV_ONLINE;
if (stat_word.q_stat_flags & if (stat_word.q_stat_flags & AP_Q_STATUS_EMPTY)
AP_Q_STATUS_EMPTY)
break_out = 1; break_out = 1;
break; break;
case AP_RESPONSE_Q_NOT_AVAIL: case AP_RESPONSE_Q_NOT_AVAIL:
stat = DEV_GONE;
break_out = 1;
break;
case AP_RESPONSE_DECONFIGURED: case AP_RESPONSE_DECONFIGURED:
stat = DEV_GONE;
break_out = 1;
break;
case AP_RESPONSE_CHECKSTOPPED: case AP_RESPONSE_CHECKSTOPPED:
stat = DEV_GONE; stat = DEV_GONE;
break_out = 1; break_out = 1;
...@@ -1195,6 +1169,7 @@ reset_device(int deviceNr, int cdx, int resetNr) ...@@ -1195,6 +1169,7 @@ reset_device(int deviceNr, int cdx, int resetNr)
default: default:
stat = DEV_GONE; stat = DEV_GONE;
break_out = 1; break_out = 1;
break;
} }
if (break_out == 1) if (break_out == 1)
break; break;
...@@ -1251,7 +1226,7 @@ send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext) ...@@ -1251,7 +1226,7 @@ send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext)
msg_ext[0], msg_ext[1], msg_ext[2], msg_ext[3], msg_ext[0], msg_ext[1], msg_ext[2], msg_ext[3],
msg_ext[4], msg_ext[5], msg_ext[6], msg_ext[7], msg_ext[4], msg_ext[5], msg_ext[6], msg_ext[7],
msg_ext[8], msg_ext[9], msg_ext[10], msg_ext[11]); msg_ext[8], msg_ext[9], msg_ext[10], msg_ext[11]);
print_buffer(msg_ext+12, msg_len); print_buffer(msg_ext+CALLER_HEADER, msg_len);
#endif #endif
ccode = sen(msg_len, msg_ext, &stat_word); ccode = sen(msg_len, msg_ext, &stat_word);
...@@ -1283,14 +1258,15 @@ send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext) ...@@ -1283,14 +1258,15 @@ send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext)
break; break;
default: default:
stat = DEV_GONE; stat = DEV_GONE;
break;
} }
return stat; return stat;
} }
enum devstat enum devstat
receive_from_AP(int dev_nr, int cdx, int resplen, receive_from_AP(int dev_nr, int cdx, int resplen, unsigned char *resp,
unsigned char *resp, unsigned char *psmid) unsigned char *psmid)
{ {
int ccode; int ccode;
struct ap_status_word stat_word; struct ap_status_word stat_word;
...@@ -1543,6 +1519,7 @@ ICAMEX_msg_to_type6MEX_de_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx, ...@@ -1543,6 +1519,7 @@ ICAMEX_msg_to_type6MEX_de_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx,
struct type6_hdr *tp6Hdr_p; struct type6_hdr *tp6Hdr_p;
struct CPRB *cprb_p; struct CPRB *cprb_p;
struct cca_private_ext_ME *key_p; struct cca_private_ext_ME *key_p;
static int deprecated_msg_count = 0;
mod_len = icaMsg_p->inputdatalength; mod_len = icaMsg_p->inputdatalength;
tmp_size = FIXED_TYPE6_ME_LEN + mod_len; tmp_size = FIXED_TYPE6_ME_LEN + mod_len;
...@@ -1593,13 +1570,19 @@ ICAMEX_msg_to_type6MEX_de_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx, ...@@ -1593,13 +1570,19 @@ ICAMEX_msg_to_type6MEX_de_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx,
return SEN_USER_ERROR; return SEN_USER_ERROR;
if (is_common_public_key(temp, mod_len)) { if (is_common_public_key(temp, mod_len)) {
if (deprecated_msg_count < 20) {
PRINTK("Common public key used for modex decrypt\n"); PRINTK("Common public key used for modex decrypt\n");
deprecated_msg_count++;
if (deprecated_msg_count == 20)
PRINTK("No longer issuing messages about common"
" public key for modex decrypt.\n");
}
return SEN_NOT_AVAIL; return SEN_NOT_AVAIL;
} }
temp = key_p->pvtMESec.modulus + sizeof(key_p->pvtMESec.modulus) temp = key_p->pvtMESec.modulus + sizeof(key_p->pvtMESec.modulus)
- mod_len; - mod_len;
if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len) != 0) if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len))
return SEN_RELEASED; return SEN_RELEASED;
if (is_empty(temp, mod_len)) if (is_empty(temp, mod_len))
return SEN_USER_ERROR; return SEN_USER_ERROR;
...@@ -1617,24 +1600,33 @@ ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx, ...@@ -1617,24 +1600,33 @@ ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx,
{ {
int mod_len, vud_len, exp_len, key_len; int mod_len, vud_len, exp_len, key_len;
int pad_len, tmp_size, total_CPRB_len, parmBlock_l, i; int pad_len, tmp_size, total_CPRB_len, parmBlock_l, i;
unsigned char temp_exp[256], *exp_p, *temp; unsigned char *temp_exp, *exp_p, *temp;
struct type6_hdr *tp6Hdr_p; struct type6_hdr *tp6Hdr_p;
struct CPRB *cprb_p; struct CPRB *cprb_p;
struct cca_public_key *key_p; struct cca_public_key *key_p;
struct T6_keyBlock_hdr *keyb_p; struct T6_keyBlock_hdr *keyb_p;
temp_exp = kmalloc(256, GFP_KERNEL);
if (!temp_exp)
return EGETBUFF;
mod_len = icaMsg_p->inputdatalength; mod_len = icaMsg_p->inputdatalength;
if (copy_from_user(temp_exp, icaMsg_p->b_key, mod_len)) if (copy_from_user(temp_exp, icaMsg_p->b_key, mod_len)) {
kfree(temp_exp);
return SEN_RELEASED; return SEN_RELEASED;
if (is_empty(temp_exp, mod_len)) }
if (is_empty(temp_exp, mod_len)) {
kfree(temp_exp);
return SEN_USER_ERROR; return SEN_USER_ERROR;
}
exp_p = temp_exp; exp_p = temp_exp;
for (i = 0; i < mod_len; i++) for (i = 0; i < mod_len; i++)
if (exp_p[i]) if (exp_p[i])
break; break;
if (i >= mod_len) if (i >= mod_len) {
kfree(temp_exp);
return SEN_USER_ERROR; return SEN_USER_ERROR;
}
exp_len = mod_len - i; exp_len = mod_len - i;
exp_p += i; exp_p += i;
...@@ -1665,17 +1657,25 @@ ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx, ...@@ -1665,17 +1657,25 @@ ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx,
sizeof(struct function_and_rules_block)); sizeof(struct function_and_rules_block));
temp += sizeof(struct function_and_rules_block); temp += sizeof(struct function_and_rules_block);
temp += 2; temp += 2;
if (copy_from_user(temp, icaMsg_p->inputdata, mod_len)) if (copy_from_user(temp, icaMsg_p->inputdata, mod_len)) {
kfree(temp_exp);
return SEN_RELEASED; return SEN_RELEASED;
if (is_empty(temp, mod_len)) }
if (is_empty(temp, mod_len)) {
kfree(temp_exp);
return SEN_USER_ERROR; return SEN_USER_ERROR;
if (temp[0] != 0x00 || temp[1] != 0x02) }
if ((temp[0] != 0x00) || (temp[1] != 0x02)) {
kfree(temp_exp);
return SEN_NOT_AVAIL; return SEN_NOT_AVAIL;
}
for (i = 2; i < mod_len; i++) for (i = 2; i < mod_len; i++)
if (temp[i] == 0x00) if (temp[i] == 0x00)
break; break;
if ((i < 9) || (i > (mod_len - 2))) if ((i < 9) || (i > (mod_len - 2))) {
kfree(temp_exp);
return SEN_NOT_AVAIL; return SEN_NOT_AVAIL;
}
pad_len = i + 1; pad_len = i + 1;
vud_len = mod_len - pad_len; vud_len = mod_len - pad_len;
memmove(temp, temp+pad_len, vud_len); memmove(temp, temp+pad_len, vud_len);
...@@ -1689,6 +1689,7 @@ ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx, ...@@ -1689,6 +1689,7 @@ ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx,
key_p = (struct cca_public_key *)temp; key_p = (struct cca_public_key *)temp;
temp = key_p->pubSec.exponent; temp = key_p->pubSec.exponent;
memcpy(temp, exp_p, exp_len); memcpy(temp, exp_p, exp_len);
kfree(temp_exp);
temp += exp_len; temp += exp_len;
if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len)) if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len))
return SEN_RELEASED; return SEN_RELEASED;
...@@ -1697,7 +1698,7 @@ ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx, ...@@ -1697,7 +1698,7 @@ ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx,
key_p->pubSec.modulus_bit_len = 8 * mod_len; key_p->pubSec.modulus_bit_len = 8 * mod_len;
key_p->pubSec.modulus_byte_len = mod_len; key_p->pubSec.modulus_byte_len = mod_len;
key_p->pubSec.exponent_len = exp_len; key_p->pubSec.exponent_len = exp_len;
key_p->pubSec.section_length = 12 + mod_len + exp_len; key_p->pubSec.section_length = CALLER_HEADER + mod_len + exp_len;
key_len = key_p->pubSec.section_length + sizeof(struct cca_token_hdr); key_len = key_p->pubSec.section_length + sizeof(struct cca_token_hdr);
key_p->pubHdr.token_length = key_len; key_p->pubHdr.token_length = key_len;
key_len += 4; key_len += 4;
...@@ -1824,27 +1825,37 @@ ICACRT_msg_to_type6CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx, ...@@ -1824,27 +1825,37 @@ ICACRT_msg_to_type6CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx,
static int static int
ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx, ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx,
int *z90cMsg_l_p, struct type6_msg *z90cMsg_p) int *z90cMsg_l_p, struct type6_msg *z90cMsg_p,
int dev_type)
{ {
int mod_len, exp_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l; int mod_len, exp_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l;
int key_len, i; int key_len, i;
unsigned char temp_exp[256], *tgt_p, *temp, *exp_p; unsigned char *temp_exp, *tgt_p, *temp, *exp_p;
struct type6_hdr *tp6Hdr_p; struct type6_hdr *tp6Hdr_p;
struct CPRBX *cprbx_p; struct CPRBX *cprbx_p;
struct cca_public_key *key_p; struct cca_public_key *key_p;
struct T6_keyBlock_hdrX *keyb_p; struct T6_keyBlock_hdrX *keyb_p;
temp_exp = kmalloc(256, GFP_KERNEL);
if (!temp_exp)
return EGETBUFF;
mod_len = icaMsg_p->inputdatalength; mod_len = icaMsg_p->inputdatalength;
if (copy_from_user(temp_exp, icaMsg_p->b_key, mod_len)) if (copy_from_user(temp_exp, icaMsg_p->b_key, mod_len)) {
kfree(temp_exp);
return SEN_RELEASED; return SEN_RELEASED;
if (is_empty(temp_exp, mod_len)) }
if (is_empty(temp_exp, mod_len)) {
kfree(temp_exp);
return SEN_USER_ERROR; return SEN_USER_ERROR;
}
exp_p = temp_exp; exp_p = temp_exp;
for (i = 0; i < mod_len; i++) for (i = 0; i < mod_len; i++)
if (exp_p[i]) if (exp_p[i])
break; break;
if (i >= mod_len) if (i >= mod_len) {
kfree(temp_exp);
return SEN_USER_ERROR; return SEN_USER_ERROR;
}
exp_len = mod_len - i; exp_len = mod_len - i;
exp_p += i; exp_p += i;
PDEBUG("exp_len after computation: %08x\n", exp_len); PDEBUG("exp_len after computation: %08x\n", exp_len);
...@@ -1867,15 +1878,23 @@ ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx, ...@@ -1867,15 +1878,23 @@ ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx,
cprbx_p->domain = (unsigned short)cdx; cprbx_p->domain = (unsigned short)cdx;
cprbx_p->rpl_msgbl = RESPONSE_CPRBX_SIZE; cprbx_p->rpl_msgbl = RESPONSE_CPRBX_SIZE;
tgt_p += sizeof(struct CPRBX); tgt_p += sizeof(struct CPRBX);
if (dev_type == PCIXCC_MCL2)
memcpy(tgt_p, &static_pke_function_and_rulesX_MCL2,
sizeof(struct function_and_rules_block));
else
memcpy(tgt_p, &static_pke_function_and_rulesX, memcpy(tgt_p, &static_pke_function_and_rulesX,
sizeof(struct function_and_rules_block)); sizeof(struct function_and_rules_block));
tgt_p += sizeof(struct function_and_rules_block); tgt_p += sizeof(struct function_and_rules_block);
tgt_p += 2; tgt_p += 2;
if (copy_from_user(tgt_p, icaMsg_p->inputdata, mod_len)) if (copy_from_user(tgt_p, icaMsg_p->inputdata, mod_len)) {
kfree(temp_exp);
return SEN_RELEASED; return SEN_RELEASED;
if (is_empty(tgt_p, mod_len)) }
if (is_empty(tgt_p, mod_len)) {
kfree(temp_exp);
return SEN_USER_ERROR; return SEN_USER_ERROR;
}
tgt_p -= 2; tgt_p -= 2;
*((short *)tgt_p) = (short) vud_len; *((short *)tgt_p) = (short) vud_len;
tgt_p += vud_len; tgt_p += vud_len;
...@@ -1885,6 +1904,7 @@ ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx, ...@@ -1885,6 +1904,7 @@ ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx,
key_p = (struct cca_public_key *)tgt_p; key_p = (struct cca_public_key *)tgt_p;
temp = key_p->pubSec.exponent; temp = key_p->pubSec.exponent;
memcpy(temp, exp_p, exp_len); memcpy(temp, exp_p, exp_len);
kfree(temp_exp);
temp += exp_len; temp += exp_len;
if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len)) if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len))
return SEN_RELEASED; return SEN_RELEASED;
...@@ -1893,7 +1913,7 @@ ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx, ...@@ -1893,7 +1913,7 @@ ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx,
key_p->pubSec.modulus_bit_len = 8 * mod_len; key_p->pubSec.modulus_bit_len = 8 * mod_len;
key_p->pubSec.modulus_byte_len = mod_len; key_p->pubSec.modulus_byte_len = mod_len;
key_p->pubSec.exponent_len = exp_len; key_p->pubSec.exponent_len = exp_len;
key_p->pubSec.section_length = 12 + mod_len + exp_len; key_p->pubSec.section_length = CALLER_HEADER + mod_len + exp_len;
key_len = key_p->pubSec.section_length + sizeof(struct cca_token_hdr); key_len = key_p->pubSec.section_length + sizeof(struct cca_token_hdr);
key_p->pubHdr.token_length = key_len; key_p->pubHdr.token_length = key_len;
key_len += 4; key_len += 4;
...@@ -1908,7 +1928,8 @@ ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx, ...@@ -1908,7 +1928,8 @@ ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx,
static int static int
ICACRT_msg_to_type6CRT_msgX(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx, ICACRT_msg_to_type6CRT_msgX(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx,
int *z90cMsg_l_p, struct type6_msg *z90cMsg_p) int *z90cMsg_l_p, struct type6_msg *z90cMsg_p,
int dev_type)
{ {
int mod_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l, short_len; int mod_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l, short_len;
int long_len, pad_len, keyPartsLen, tmp_l; int long_len, pad_len, keyPartsLen, tmp_l;
...@@ -1943,6 +1964,10 @@ ICACRT_msg_to_type6CRT_msgX(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx, ...@@ -1943,6 +1964,10 @@ ICACRT_msg_to_type6CRT_msgX(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx,
cprbx_p->req_parml = parmBlock_l; cprbx_p->req_parml = parmBlock_l;
cprbx_p->rpl_msgbl = parmBlock_l; cprbx_p->rpl_msgbl = parmBlock_l;
tgt_p += sizeof(struct CPRBX); tgt_p += sizeof(struct CPRBX);
if (dev_type == PCIXCC_MCL2)
memcpy(tgt_p, &static_pkd_function_and_rulesX_MCL2,
sizeof(struct function_and_rules_block));
else
memcpy(tgt_p, &static_pkd_function_and_rulesX, memcpy(tgt_p, &static_pkd_function_and_rulesX,
sizeof(struct function_and_rules_block)); sizeof(struct function_and_rules_block));
tgt_p += sizeof(struct function_and_rules_block); tgt_p += sizeof(struct function_and_rules_block);
...@@ -2043,20 +2068,37 @@ convert_request(unsigned char *buffer, int func, unsigned short function, ...@@ -2043,20 +2068,37 @@ convert_request(unsigned char *buffer, int func, unsigned short function,
(struct ica_rsa_modexpo *) buffer, (struct ica_rsa_modexpo *) buffer,
cdx, msg_l_p, (struct type6_msg *) msg_p); cdx, msg_l_p, (struct type6_msg *) msg_p);
} }
if (dev_type == PCIXCC) { if ((dev_type == PCIXCC_MCL2) ||
(dev_type == PCIXCC_MCL3) ||
(dev_type == CEX2C)) {
if (func == ICARSACRT) if (func == ICARSACRT)
return ICACRT_msg_to_type6CRT_msgX( return ICACRT_msg_to_type6CRT_msgX(
(struct ica_rsa_modexpo_crt *) buffer, (struct ica_rsa_modexpo_crt *) buffer,
cdx, msg_l_p, (struct type6_msg *) msg_p); cdx, msg_l_p, (struct type6_msg *) msg_p,
dev_type);
else else
return ICAMEX_msg_to_type6MEX_msgX( return ICAMEX_msg_to_type6MEX_msgX(
(struct ica_rsa_modexpo *) buffer, (struct ica_rsa_modexpo *) buffer,
cdx, msg_l_p, (struct type6_msg *) msg_p); cdx, msg_l_p, (struct type6_msg *) msg_p,
dev_type);
} }
return 0; return 0;
} }
int ext_bitlens_msg_count = 0;
static inline void
unset_ext_bitlens(void)
{
if (!ext_bitlens_msg_count) {
PRINTK("Unable to use coprocessors for extended bitlengths. "
"Using PCICAs (if present) for extended bitlengths. "
"This is not an error.\n");
ext_bitlens_msg_count++;
}
ext_bitlens = 0;
}
int int
convert_response(unsigned char *response, unsigned char *buffer, convert_response(unsigned char *response, unsigned char *buffer,
int *respbufflen_p, unsigned char *resp_buff) int *respbufflen_p, unsigned char *resp_buff)
...@@ -2064,8 +2106,8 @@ convert_response(unsigned char *response, unsigned char *buffer, ...@@ -2064,8 +2106,8 @@ convert_response(unsigned char *response, unsigned char *buffer,
struct ica_rsa_modexpo *icaMsg_p = (struct ica_rsa_modexpo *) buffer; struct ica_rsa_modexpo *icaMsg_p = (struct ica_rsa_modexpo *) buffer;
struct type82_hdr *t82h_p = (struct type82_hdr *) response; struct type82_hdr *t82h_p = (struct type82_hdr *) response;
struct type84_hdr *t84h_p = (struct type84_hdr *) response; struct type84_hdr *t84h_p = (struct type84_hdr *) response;
struct type86_hdr *t86h_p = (struct type86_hdr *) response; struct type86_fmt2_msg *t86m_p = (struct type86_fmt2_msg *) response;
int rv, reply_code, service_rc, service_rs, src_l; int reply_code, service_rc, service_rs, src_l;
unsigned char *src_p, *tgt_p; unsigned char *src_p, *tgt_p;
struct CPRB *cprb_p; struct CPRB *cprb_p;
struct CPRBX *cprbx_p; struct CPRBX *cprbx_p;
...@@ -2075,11 +2117,9 @@ convert_response(unsigned char *response, unsigned char *buffer, ...@@ -2075,11 +2117,9 @@ convert_response(unsigned char *response, unsigned char *buffer,
service_rc = 0; service_rc = 0;
service_rs = 0; service_rs = 0;
src_l = 0; src_l = 0;
rv = 0;
switch (t82h_p->type) { switch (t82h_p->type) {
case TYPE82_RSP_CODE: case TYPE82_RSP_CODE:
reply_code = t82h_p->reply_code; reply_code = t82h_p->reply_code;
rv = 4;
src_p = (unsigned char *)t82h_p; src_p = (unsigned char *)t82h_p;
PRINTK("Hardware error: Type 82 Message Header: " PRINTK("Hardware error: Type 82 Message Header: "
"%02x%02x%02x%02x%02x%02x%02x%02x\n", "%02x%02x%02x%02x%02x%02x%02x%02x\n",
...@@ -2091,15 +2131,9 @@ convert_response(unsigned char *response, unsigned char *buffer, ...@@ -2091,15 +2131,9 @@ convert_response(unsigned char *response, unsigned char *buffer,
src_p = response + (int)t84h_p->len - src_l; src_p = response + (int)t84h_p->len - src_l;
break; break;
case TYPE86_RSP_CODE: case TYPE86_RSP_CODE:
reply_code = t86h_p->reply_code; reply_code = t86m_p->hdr.reply_code;
if (t86h_p->format != TYPE86_FMT2) { if (reply_code != 0)
rv = 4;
break;
}
if (reply_code != 0) {
rv = 4;
break; break;
}
cprb_p = (struct CPRB *) cprb_p = (struct CPRB *)
(response + sizeof(struct type86_fmt2_msg)); (response + sizeof(struct type86_fmt2_msg));
cprbx_p = (struct CPRBX *) cprb_p; cprbx_p = (struct CPRBX *) cprb_p;
...@@ -2108,11 +2142,22 @@ convert_response(unsigned char *response, unsigned char *buffer, ...@@ -2108,11 +2142,22 @@ convert_response(unsigned char *response, unsigned char *buffer,
if (service_rc != 0) { if (service_rc != 0) {
le2toI(cprb_p->ccp_rscode, &service_rs); le2toI(cprb_p->ccp_rscode, &service_rs);
if ((service_rc == 8) && (service_rs == 66)) if ((service_rc == 8) && (service_rs == 66))
PDEBUG("8/66 on PCICC\n"); PDEBUG("Bad block format on PCICC\n");
else if ((service_rc == 8) && (service_rs == 770)) {
PDEBUG("Invalid key length on PCICC\n");
unset_ext_bitlens();
return REC_USE_PCICA;
}
else if ((service_rc == 8) && (service_rs == 783)) {
PDEBUG("Extended bitlengths not enabled"
"on PCICC\n");
unset_ext_bitlens();
return REC_USE_PCICA;
}
else else
PRINTK("service rc/rs: %d/%d\n", PRINTK("service rc/rs: %d/%d\n",
service_rc, service_rs); service_rc, service_rs);
rv = 8; return REC_OPERAND_INV;
} }
src_p = (unsigned char *)cprb_p + sizeof(struct CPRB); src_p = (unsigned char *)cprb_p + sizeof(struct CPRB);
src_p += 4; src_p += 4;
...@@ -2124,11 +2169,22 @@ convert_response(unsigned char *response, unsigned char *buffer, ...@@ -2124,11 +2169,22 @@ convert_response(unsigned char *response, unsigned char *buffer,
if (service_rc != 0) { if (service_rc != 0) {
service_rs = (int) cprbx_p->ccp_rscode; service_rs = (int) cprbx_p->ccp_rscode;
if ((service_rc == 8) && (service_rs == 66)) if ((service_rc == 8) && (service_rs == 66))
PDEBUG("8/66 on PCIXCC\n"); PDEBUG("Bad block format on PCXICC\n");
else if ((service_rc == 8) && (service_rs == 770)) {
PDEBUG("Invalid key length on PCIXCC\n");
unset_ext_bitlens();
return REC_USE_PCICA;
}
else if ((service_rc == 8) && (service_rs == 783)) {
PDEBUG("Extended bitlengths not enabled"
"on PCIXCC\n");
unset_ext_bitlens();
return REC_USE_PCICA;
}
else else
PRINTK("service rc/rs: %d/%d\n", PRINTK("service rc/rs: %d/%d\n",
service_rc, service_rs); service_rc, service_rs);
rv = 8; return REC_OPERAND_INV;
} }
src_p = (unsigned char *) src_p = (unsigned char *)
cprbx_p + sizeof(struct CPRBX); cprbx_p + sizeof(struct CPRBX);
...@@ -2139,12 +2195,10 @@ convert_response(unsigned char *response, unsigned char *buffer, ...@@ -2139,12 +2195,10 @@ convert_response(unsigned char *response, unsigned char *buffer,
} }
break; break;
default: default:
break; return REC_BAD_MESSAGE;
} }
if (rv == 8) if (reply_code)
return 8;
if (rv == 4)
switch (reply_code) { switch (reply_code) {
case REPLY_ERROR_OPERAND_INVALID: case REPLY_ERROR_OPERAND_INVALID:
return REC_OPERAND_INV; return REC_OPERAND_INV;
...@@ -2154,8 +2208,14 @@ convert_response(unsigned char *response, unsigned char *buffer, ...@@ -2154,8 +2208,14 @@ convert_response(unsigned char *response, unsigned char *buffer,
return REC_EVEN_MOD; return REC_EVEN_MOD;
case REPLY_ERROR_MESSAGE_TYPE: case REPLY_ERROR_MESSAGE_TYPE:
return WRONG_DEVICE_TYPE; return WRONG_DEVICE_TYPE;
case REPLY_ERROR_TRANSPORT_FAIL:
PRINTKW("Transport failed (APFS = %02X%02X%02X%02X)\n",
t86m_p->apfs[0], t86m_p->apfs[1],
t86m_p->apfs[2], t86m_p->apfs[3]);
return REC_HARDWAR_ERR;
default: default:
return 12; PRINTKW("reply code = %d\n", reply_code);
return REC_HARDWAR_ERR;
} }
if (service_rc != 0) if (service_rc != 0)
...@@ -2171,14 +2231,13 @@ convert_response(unsigned char *response, unsigned char *buffer, ...@@ -2171,14 +2231,13 @@ convert_response(unsigned char *response, unsigned char *buffer,
memcpy(tgt_p, src_p, src_l); memcpy(tgt_p, src_p, src_l);
if ((t82h_p->type == TYPE86_RSP_CODE) && (resp_buff < tgt_p)) { if ((t82h_p->type == TYPE86_RSP_CODE) && (resp_buff < tgt_p)) {
memset(resp_buff, 0, icaMsg_p->outputdatalength - src_l); memset(resp_buff, 0, icaMsg_p->outputdatalength - src_l);
rv = pad_msg(resp_buff, icaMsg_p->outputdatalength, src_l); if (pad_msg(resp_buff, icaMsg_p->outputdatalength, src_l))
if (rv != 0) return REC_INVALID_PAD;
return rv;
} }
*respbufflen_p = icaMsg_p->outputdatalength; *respbufflen_p = icaMsg_p->outputdatalength;
if (*respbufflen_p == 0) if (*respbufflen_p == 0)
PRINTK("Zero *respbufflen_p\n"); PRINTK("Zero *respbufflen_p\n");
return rv; return 0;
} }
/* /*
* linux/drivers/s390/misc/z90main.c * linux/drivers/s390/misc/z90main.c
* *
* z90crypt 1.3.1 * z90crypt 1.3.2
* *
* Copyright (C) 2001, 2004 IBM Corporation * Copyright (C) 2001, 2004 IBM Corporation
* Author(s): Robert Burroughs (burrough@us.ibm.com) * Author(s): Robert Burroughs (burrough@us.ibm.com)
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
# error "This kernel is too recent: not supported by this file" # error "This kernel is too recent: not supported by this file"
#endif #endif
#define VERSION_Z90MAIN_C "$Revision: 1.31 $" #define VERSION_Z90MAIN_C "$Revision: 1.54 $"
static char z90cmain_version[] __initdata = static char z90cmain_version[] __initdata =
"z90main.o (" VERSION_Z90MAIN_C "/" "z90main.o (" VERSION_Z90MAIN_C "/"
...@@ -116,9 +116,15 @@ extern char z90chardware_version[]; ...@@ -116,9 +116,15 @@ extern char z90chardware_version[];
/** /**
* Reader should run every READERTIME milliseconds * Reader should run every READERTIME milliseconds
* With the 100Hz patch for s390, z90crypt can lock the system solid while
* under heavy load. We'll try to avoid that.
*/ */
#ifndef READERTIME #ifndef READERTIME
#if HZ > 1000
#define READERTIME 2 #define READERTIME 2
#else
#define READERTIME 10
#endif
#endif #endif
/** /**
...@@ -209,18 +215,13 @@ extern char z90chardware_version[]; ...@@ -209,18 +215,13 @@ extern char z90chardware_version[];
#ifndef Z90CRYPT_NUM_DEVS #ifndef Z90CRYPT_NUM_DEVS
#define Z90CRYPT_NUM_DEVS Z90CRYPT_NUM_APS #define Z90CRYPT_NUM_DEVS Z90CRYPT_NUM_APS
#endif #endif
#ifndef Z90CRYPT_NUM_TYPES
#define Z90CRYPT_NUM_TYPES 3
#endif
/** /**
* Buffer size for receiving responses. The maximum Response Size * Buffer size for receiving responses. The maximum Response Size
* is actually the maximum request size, since in an error condition * is actually the maximum request size, since in an error condition
* the request itself may be returned unchanged. * the request itself may be returned unchanged.
*/ */
#ifndef MAX_RESPONSE_SIZE
#define MAX_RESPONSE_SIZE 0x0000077C #define MAX_RESPONSE_SIZE 0x0000077C
#endif
/** /**
* A count and status-byte mask * A count and status-byte mask
...@@ -246,7 +247,8 @@ struct device_x { ...@@ -246,7 +247,8 @@ struct device_x {
* All devices are arranged in a single array: 64 APs * All devices are arranged in a single array: 64 APs
*/ */
struct device { struct device {
int dev_type; // PCICA, PCICC, or PCIXCC int dev_type; // PCICA, PCICC, PCIXCC_MCL2,
// PCIXCC_MCL3, CEX2C
enum devstat dev_stat; // current device status enum devstat dev_stat; // current device status
int dev_self_x; // Index in array int dev_self_x; // Index in array
int disabled; // Set when device is in error int disabled; // Set when device is in error
...@@ -328,6 +330,7 @@ static int destroy_crypto_device(int); ...@@ -328,6 +330,7 @@ static int destroy_crypto_device(int);
static void destroy_z90crypt(void); static void destroy_z90crypt(void);
static int refresh_index_array(struct status *, struct device_x *); static int refresh_index_array(struct status *, struct device_x *);
static int probe_device_type(struct device *); static int probe_device_type(struct device *);
static int probe_PCIXCC_type(struct device *);
/** /**
* proc fs definitions * proc fs definitions
...@@ -449,9 +452,9 @@ static struct miscdevice z90crypt_misc_device = { ...@@ -449,9 +452,9 @@ static struct miscdevice z90crypt_misc_device = {
/** /**
* Documentation values. * Documentation values.
*/ */
MODULE_AUTHOR("zLinux Crypto Team: Robert H. Burroughs, Eric D. Rossman" MODULE_AUTHOR("zSeries Linux Crypto Team: Robert H. Burroughs, Eric D. Rossman"
"and Jochen Roehrig"); "and Jochen Roehrig");
MODULE_DESCRIPTION("zLinux Cryptographic Coprocessor device driver, " MODULE_DESCRIPTION("zSeries Linux Cryptographic Coprocessor device driver, "
"Copyright 2001, 2004 IBM Corporation"); "Copyright 2001, 2004 IBM Corporation");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_param(domain, int, 0); module_param(domain, int, 0);
...@@ -554,7 +557,8 @@ trans_modexpo_crt32(unsigned int fd, unsigned int cmd, unsigned long arg, ...@@ -554,7 +557,8 @@ trans_modexpo_crt32(unsigned int fd, unsigned int cmd, unsigned long arg,
static int compatible_ioctls[] = { static int compatible_ioctls[] = {
ICAZ90STATUS, Z90QUIESCE, Z90STAT_TOTALCOUNT, Z90STAT_PCICACOUNT, ICAZ90STATUS, Z90QUIESCE, Z90STAT_TOTALCOUNT, Z90STAT_PCICACOUNT,
Z90STAT_PCICCCOUNT, Z90STAT_PCIXCCCOUNT, Z90STAT_REQUESTQ_COUNT, Z90STAT_PCICCCOUNT, Z90STAT_PCIXCCCOUNT, Z90STAT_PCIXCCMCL2COUNT,
Z90STAT_PCIXCCMCL3COUNT, Z90STAT_CEX2CCOUNT, Z90STAT_REQUESTQ_COUNT,
Z90STAT_PENDINGQ_COUNT, Z90STAT_TOTALOPEN_COUNT, Z90STAT_DOMAIN_INDEX, Z90STAT_PENDINGQ_COUNT, Z90STAT_TOTALOPEN_COUNT, Z90STAT_DOMAIN_INDEX,
Z90STAT_STATUS_MASK, Z90STAT_QDEPTH_MASK, Z90STAT_PERDEV_REQCNT, Z90STAT_STATUS_MASK, Z90STAT_QDEPTH_MASK, Z90STAT_PERDEV_REQCNT,
}; };
...@@ -575,20 +579,33 @@ static int z90_register_ioctl32s(void) ...@@ -575,20 +579,33 @@ static int z90_register_ioctl32s(void)
int result, i; int result, i;
result = register_ioctl32_conversion(ICARSAMODEXPO, trans_modexpo32); result = register_ioctl32_conversion(ICARSAMODEXPO, trans_modexpo32);
if (result == -EBUSY) {
unregister_ioctl32_conversion(ICARSAMODEXPO);
result = register_ioctl32_conversion(ICARSAMODEXPO,
trans_modexpo32);
}
if (result) if (result)
return result; return result;
result = register_ioctl32_conversion(ICARSACRT, trans_modexpo_crt32); result = register_ioctl32_conversion(ICARSACRT, trans_modexpo_crt32);
if (result == -EBUSY) {
unregister_ioctl32_conversion(ICARSACRT);
result = register_ioctl32_conversion(ICARSACRT,
trans_modexpo_crt32);
}
if (result) if (result)
return result; return result;
for(i = 0; i < ARRAY_SIZE(compatible_ioctls); i++) { for(i = 0; i < ARRAY_SIZE(compatible_ioctls); i++) {
result = register_ioctl32_conversion(compatible_ioctls[i],NULL); result = register_ioctl32_conversion(compatible_ioctls[i], 0);
if (result) { if (result == -EBUSY) {
z90_unregister_ioctl32s(); unregister_ioctl32_conversion(compatible_ioctls[i]);
return result; result = register_ioctl32_conversion(
} compatible_ioctls[i], 0);
} }
if (result)
return result; return result;
}
return 0;
} }
#else // !CONFIG_COMPAT #else // !CONFIG_COMPAT
static inline void z90_unregister_ioctl32s(void) static inline void z90_unregister_ioctl32s(void)
...@@ -612,10 +629,15 @@ z90crypt_init_module(void) ...@@ -612,10 +629,15 @@ z90crypt_init_module(void)
PDEBUG("PID %d\n", PID()); PDEBUG("PID %d\n", PID());
if ((domain < -1) || (domain > 15)) {
PRINTKW("Invalid param: domain = %d. Not loading.\n", domain);
return -EINVAL;
}
#ifndef Z90CRYPT_USE_HOTPLUG #ifndef Z90CRYPT_USE_HOTPLUG
/* Register as misc device with given minor (or get a dynamic one). */ /* Register as misc device with given minor (or get a dynamic one). */
result = misc_register(&z90crypt_misc_device); result = misc_register(&z90crypt_misc_device);
if (result <0) { if (result < 0) {
PRINTKW(KERN_ERR "misc_register (minor %d) failed with %d\n", PRINTKW(KERN_ERR "misc_register (minor %d) failed with %d\n",
z90crypt_misc_device.minor, result); z90crypt_misc_device.minor, result);
return result; return result;
...@@ -923,7 +945,26 @@ get_status_PCICCcount(void) ...@@ -923,7 +945,26 @@ get_status_PCICCcount(void)
static inline int static inline int
get_status_PCIXCCcount(void) get_status_PCIXCCcount(void)
{ {
return z90crypt.hdware_info->type_mask[PCIXCC].st_count; return z90crypt.hdware_info->type_mask[PCIXCC_MCL2].st_count +
z90crypt.hdware_info->type_mask[PCIXCC_MCL3].st_count;
}
static inline int
get_status_PCIXCCMCL2count(void)
{
return z90crypt.hdware_info->type_mask[PCIXCC_MCL2].st_count;
}
static inline int
get_status_PCIXCCMCL3count(void)
{
return z90crypt.hdware_info->type_mask[PCIXCC_MCL3].st_count;
}
static inline int
get_status_CEX2Ccount(void)
{
return z90crypt.hdware_info->type_mask[CEX2C].st_count;
} }
static inline int static inline int
...@@ -1016,8 +1057,8 @@ init_work_element(struct work_element *we_p, ...@@ -1016,8 +1057,8 @@ init_work_element(struct work_element *we_p,
we_p->audit[2] = 0x00; we_p->audit[2] = 0x00;
we_p->resp_buff_size = 0; we_p->resp_buff_size = 0;
we_p->retcode = 0; we_p->retcode = 0;
we_p->devindex = -1; // send_to_crypto selects the device we_p->devindex = -1;
we_p->devtype = -1; // getCryptoBuffer selects the type we_p->devtype = -1;
atomic_set(&we_p->alarmrung, 0); atomic_set(&we_p->alarmrung, 0);
init_waitqueue_head(&we_p->waitq); init_waitqueue_head(&we_p->waitq);
INIT_LIST_HEAD(&(we_p->liste)); INIT_LIST_HEAD(&(we_p->liste));
...@@ -1040,42 +1081,113 @@ allocate_work_element(struct work_element **we_pp, ...@@ -1040,42 +1081,113 @@ allocate_work_element(struct work_element **we_pp,
static inline void static inline void
remove_device(struct device *device_p) remove_device(struct device *device_p)
{ {
if (!device_p || device_p->disabled != 0) if (!device_p || (device_p->disabled != 0))
return; return;
device_p->disabled = 1; device_p->disabled = 1;
z90crypt.hdware_info->type_mask[device_p->dev_type].disabled_count++; z90crypt.hdware_info->type_mask[device_p->dev_type].disabled_count++;
z90crypt.hdware_info->hdware_mask.disabled_count++; z90crypt.hdware_info->hdware_mask.disabled_count++;
} }
/**
* Bitlength limits for each card
*
* There are new MCLs which allow more bitlengths. See the table for details.
* The MCL must be applied and the newer bitlengths enabled for these to work.
*
* Card Type Old limit New limit
* PCICC 512-1024 512-2048
* PCIXCC_MCL2 512-2048 no change (applying this MCL == card is MCL3+)
* PCIXCC_MCL3 512-2048 128-2048
* CEX2C 512-2048 128-2048
*
* ext_bitlens (extended bitlengths) is a global, since you should not apply an
* MCL to just one card in a machine. We assume, at first, that all cards have
* these capabilities.
*/
int ext_bitlens = 1; // This is global
#define PCIXCC_MIN_MOD_SIZE 16 // 128 bits
#define OLD_PCIXCC_MIN_MOD_SIZE 64 // 512 bits
#define PCICC_MIN_MOD_SIZE 64 // 512 bits
#define OLD_PCICC_MAX_MOD_SIZE 128 // 1024 bits
#define MAX_MOD_SIZE 256 // 2048 bits
static inline int static inline int
select_device_type(int *dev_type_p) select_device_type(int *dev_type_p, int bytelength)
{ {
static int count = 0;
int PCICA_avail, PCIXCC_MCL3_avail, CEX2C_avail, index_to_use;
struct status *stat; struct status *stat;
if ((*dev_type_p != PCICC) && (*dev_type_p != PCICA) && if ((*dev_type_p != PCICC) && (*dev_type_p != PCICA) &&
(*dev_type_p != PCIXCC) && (*dev_type_p != ANYDEV)) (*dev_type_p != PCIXCC_MCL2) && (*dev_type_p != PCIXCC_MCL3) &&
(*dev_type_p != CEX2C) && (*dev_type_p != ANYDEV))
return -1; return -1;
if (*dev_type_p != ANYDEV) { if (*dev_type_p != ANYDEV) {
stat = &z90crypt.hdware_info->type_mask[*dev_type_p]; stat = &z90crypt.hdware_info->type_mask[*dev_type_p];
if (stat->st_count > if (stat->st_count >
stat->disabled_count + stat->user_disabled_count) (stat->disabled_count + stat->user_disabled_count))
return 0; return 0;
return -1; return -1;
} }
/* Assumption: PCICA, PCIXCC_MCL3, and CEX2C are all similar in speed */
stat = &z90crypt.hdware_info->type_mask[PCICA]; stat = &z90crypt.hdware_info->type_mask[PCICA];
if (stat->st_count > stat->disabled_count + stat->user_disabled_count) { PCICA_avail = stat->st_count -
(stat->disabled_count + stat->user_disabled_count);
stat = &z90crypt.hdware_info->type_mask[PCIXCC_MCL3];
PCIXCC_MCL3_avail = stat->st_count -
(stat->disabled_count + stat->user_disabled_count);
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) {
/**
* bitlength is a factor, PCICA is the most capable, even with
* the new MCL.
*/
if ((bytelength < PCIXCC_MIN_MOD_SIZE) ||
(!ext_bitlens && (bytelength < OLD_PCIXCC_MIN_MOD_SIZE))) {
if (!PCICA_avail)
return -1;
else {
*dev_type_p = PCICA; *dev_type_p = PCICA;
return 0; return 0;
} }
}
stat = &z90crypt.hdware_info->type_mask[PCIXCC]; index_to_use = count % (PCICA_avail + PCIXCC_MCL3_avail +
if (stat->st_count > stat->disabled_count + stat->user_disabled_count) { CEX2C_avail);
*dev_type_p = PCIXCC; 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
*dev_type_p = CEX2C;
count++;
return 0; return 0;
} }
/* Less than OLD_PCIXCC_MIN_MOD_SIZE cannot go to a PCIXCC_MCL2 */
if (bytelength < OLD_PCIXCC_MIN_MOD_SIZE)
return -1;
stat = &z90crypt.hdware_info->type_mask[PCIXCC_MCL2];
if (stat->st_count >
(stat->disabled_count + stat->user_disabled_count)) {
*dev_type_p = PCIXCC_MCL2;
return 0;
}
/**
* Less than PCICC_MIN_MOD_SIZE or more than OLD_PCICC_MAX_MOD_SIZE
* (if we don't have the MCL applied and the newer bitlengths enabled)
* cannot go to a PCICC
*/
if ((bytelength < PCICC_MIN_MOD_SIZE) ||
(!ext_bitlens && (bytelength > OLD_PCICC_MAX_MOD_SIZE))) {
return -1;
}
stat = &z90crypt.hdware_info->type_mask[PCICC]; stat = &z90crypt.hdware_info->type_mask[PCICC];
if (stat->st_count > stat->disabled_count + stat->user_disabled_count) { if (stat->st_count >
(stat->disabled_count + stat->user_disabled_count)) {
*dev_type_p = PCICC; *dev_type_p = PCICC;
return 0; return 0;
} }
...@@ -1087,7 +1199,7 @@ select_device_type(int *dev_type_p) ...@@ -1087,7 +1199,7 @@ select_device_type(int *dev_type_p)
* Try the selected number, then the selected type (can be ANYDEV) * Try the selected number, then the selected type (can be ANYDEV)
*/ */
static inline int static inline int
select_device(int *dev_type_p, int *device_nr_p) select_device(int *dev_type_p, int *device_nr_p, int bytelength)
{ {
int i, indx, devTp, low_count, low_indx; int i, indx, devTp, low_count, low_indx;
struct device_x *index_p; struct device_x *index_p;
...@@ -1099,9 +1211,9 @@ select_device(int *dev_type_p, int *device_nr_p) ...@@ -1099,9 +1211,9 @@ select_device(int *dev_type_p, int *device_nr_p)
dev_ptr = z90crypt.device_p[*device_nr_p]; dev_ptr = z90crypt.device_p[*device_nr_p];
if (dev_ptr && if (dev_ptr &&
dev_ptr->dev_stat != DEV_GONE && (dev_ptr->dev_stat != DEV_GONE) &&
dev_ptr->disabled == 0 && (dev_ptr->disabled == 0) &&
dev_ptr->user_disabled == 0) { (dev_ptr->user_disabled == 0)) {
PDEBUG("selected by number, index = %d\n", PDEBUG("selected by number, index = %d\n",
*device_nr_p); *device_nr_p);
*dev_type_p = dev_ptr->dev_type; *dev_type_p = dev_ptr->dev_type;
...@@ -1111,7 +1223,7 @@ select_device(int *dev_type_p, int *device_nr_p) ...@@ -1111,7 +1223,7 @@ select_device(int *dev_type_p, int *device_nr_p)
*device_nr_p = -1; *device_nr_p = -1;
PDEBUG("trying type = %d\n", *dev_type_p); PDEBUG("trying type = %d\n", *dev_type_p);
devTp = *dev_type_p; devTp = *dev_type_p;
if (select_device_type(&devTp) == -1) { if (select_device_type(&devTp, bytelength) == -1) {
PDEBUG("failed to select by type\n"); PDEBUG("failed to select by type\n");
return -1; return -1;
} }
...@@ -1123,11 +1235,11 @@ select_device(int *dev_type_p, int *device_nr_p) ...@@ -1123,11 +1235,11 @@ select_device(int *dev_type_p, int *device_nr_p)
indx = index_p->device_index[i]; indx = index_p->device_index[i];
dev_ptr = z90crypt.device_p[indx]; dev_ptr = z90crypt.device_p[indx];
if (dev_ptr && if (dev_ptr &&
dev_ptr->dev_stat != DEV_GONE && (dev_ptr->dev_stat != DEV_GONE) &&
dev_ptr->disabled == 0 && (dev_ptr->disabled == 0) &&
dev_ptr->user_disabled == 0 && (dev_ptr->user_disabled == 0) &&
devTp == dev_ptr->dev_type && (devTp == dev_ptr->dev_type) &&
low_count > dev_ptr->dev_caller_count) { (low_count > dev_ptr->dev_caller_count)) {
low_count = dev_ptr->dev_caller_count; low_count = dev_ptr->dev_caller_count;
low_indx = indx; low_indx = indx;
} }
...@@ -1142,12 +1254,13 @@ send_to_crypto_device(struct work_element *we_p) ...@@ -1142,12 +1254,13 @@ send_to_crypto_device(struct work_element *we_p)
struct caller *caller_p; struct caller *caller_p;
struct device *device_p; struct device *device_p;
int dev_nr; int dev_nr;
int bytelen = ((struct ica_rsa_modexpo *)we_p->buffer)->inputdatalength;
if (!we_p->requestptr) if (!we_p->requestptr)
return SEN_FATAL_ERROR; return SEN_FATAL_ERROR;
caller_p = (struct caller *)we_p->requestptr; caller_p = (struct caller *)we_p->requestptr;
dev_nr = we_p->devindex; dev_nr = we_p->devindex;
if (select_device(&we_p->devtype, &dev_nr) == -1) { if (select_device(&we_p->devtype, &dev_nr, bytelen) == -1) {
if (z90crypt.hdware_info->hdware_mask.st_count != 0) if (z90crypt.hdware_info->hdware_mask.st_count != 0)
return SEN_RETRY; return SEN_RETRY;
else else
...@@ -1296,15 +1409,6 @@ z90crypt_process_results(struct work_element *we_p, char __user *buf) ...@@ -1296,15 +1409,6 @@ z90crypt_process_results(struct work_element *we_p, char __user *buf)
static unsigned char NULL_psmid[8] = static unsigned char NULL_psmid[8] =
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/**
* MIN_MOD_SIZE is a PCICC and PCIXCC limit.
* MAX_PCICC_MOD_SIZE is a hard limit for the PCICC.
* MAX_MOD_SIZE is a hard limit for the PCIXCC and PCICA.
*/
#define MIN_MOD_SIZE 64
#define MAX_PCICC_MOD_SIZE 128
#define MAX_MOD_SIZE 256
/** /**
* Used in device configuration functions * Used in device configuration functions
*/ */
...@@ -1361,7 +1465,8 @@ build_caller(struct work_element *we_p, short function) ...@@ -1361,7 +1465,8 @@ build_caller(struct work_element *we_p, short function)
struct caller *caller_p = (struct caller *)we_p->requestptr; struct caller *caller_p = (struct caller *)we_p->requestptr;
if ((we_p->devtype != PCICC) && (we_p->devtype != PCICA) && if ((we_p->devtype != PCICC) && (we_p->devtype != PCICA) &&
(we_p->devtype != PCIXCC)) (we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) &&
(we_p->devtype != CEX2C))
return SEN_NOT_AVAIL; return SEN_NOT_AVAIL;
memcpy(caller_p->caller_id, we_p->caller_id, memcpy(caller_p->caller_id, we_p->caller_id,
...@@ -1393,9 +1498,8 @@ unbuild_caller(struct device *device_p, struct caller *caller_p) ...@@ -1393,9 +1498,8 @@ unbuild_caller(struct device *device_p, struct caller *caller_p)
return; return;
if (caller_p->caller_liste.next && caller_p->caller_liste.prev) if (caller_p->caller_liste.next && caller_p->caller_liste.prev)
if (!list_empty(&caller_p->caller_liste)) { if (!list_empty(&caller_p->caller_liste)) {
list_del(&caller_p->caller_liste); list_del_init(&caller_p->caller_liste);
device_p->dev_caller_count--; device_p->dev_caller_count--;
INIT_LIST_HEAD(&caller_p->caller_liste);
} }
memset(caller_p->caller_id, 0, sizeof(caller_p->caller_id)); memset(caller_p->caller_id, 0, sizeof(caller_p->caller_id));
} }
...@@ -1430,7 +1534,8 @@ get_crypto_request_buffer(struct work_element *we_p) ...@@ -1430,7 +1534,8 @@ get_crypto_request_buffer(struct work_element *we_p)
} }
if ((we_p->devtype != PCICA) && (we_p->devtype != PCICC) && if ((we_p->devtype != PCICA) && (we_p->devtype != PCICC) &&
(we_p->devtype != PCIXCC) && (we_p->devtype != ANYDEV)) { (we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) &&
(we_p->devtype != CEX2C) && (we_p->devtype != ANYDEV)) {
PRINTK("invalid device type\n"); PRINTK("invalid device type\n");
return SEN_USER_ERROR; return SEN_USER_ERROR;
} }
...@@ -1494,7 +1599,7 @@ get_crypto_request_buffer(struct work_element *we_p) ...@@ -1494,7 +1599,7 @@ get_crypto_request_buffer(struct work_element *we_p)
if (rv != 0) if (rv != 0)
return rv; return rv;
if (select_device_type(&we_p->devtype) < 0) if (select_device_type(&we_p->devtype, mex_p->inputdatalength) < 0)
return SEN_NOT_AVAIL; return SEN_NOT_AVAIL;
temp_buffer = (unsigned char *)we_p + sizeof(struct work_element) + temp_buffer = (unsigned char *)we_p + sizeof(struct work_element) +
...@@ -1510,13 +1615,19 @@ get_crypto_request_buffer(struct work_element *we_p) ...@@ -1510,13 +1615,19 @@ get_crypto_request_buffer(struct work_element *we_p)
function = PCI_FUNC_KEY_ENCRYPT; function = PCI_FUNC_KEY_ENCRYPT;
break; break;
/** /**
* PCIXCC does all Mod-Expo form with a simple RSA mod-expo * PCIXCC_MCL2 does all Mod-Expo form with a simple RSA mod-expo
* operation, and all CRT forms with a PKCS-1.2 format decrypt. * operation, and all CRT forms with a PKCS-1.2 format decrypt.
* PCIXCC_MCL3 and CEX2C do all Mod-Expo and CRT forms with a simple RSA
* mod-expo operation
*/ */
case PCIXCC: case PCIXCC_MCL2:
/* Anything less than MIN_MOD_SIZE MUST go to a PCICA */ if (we_p->funccode == ICARSAMODEXPO)
if (mex_p->inputdatalength < MIN_MOD_SIZE) function = PCI_FUNC_KEY_ENCRYPT;
return SEN_NOT_AVAIL; else
function = PCI_FUNC_KEY_DECRYPT;
break;
case PCIXCC_MCL3:
case CEX2C:
if (we_p->funccode == ICARSAMODEXPO) if (we_p->funccode == ICARSAMODEXPO)
function = PCI_FUNC_KEY_ENCRYPT; function = PCI_FUNC_KEY_ENCRYPT;
else else
...@@ -1526,14 +1637,6 @@ get_crypto_request_buffer(struct work_element *we_p) ...@@ -1526,14 +1637,6 @@ get_crypto_request_buffer(struct work_element *we_p)
* PCICC does everything as a PKCS-1.2 format request * PCICC does everything as a PKCS-1.2 format request
*/ */
case PCICC: case PCICC:
/* Anything less than MIN_MOD_SIZE MUST go to a PCICA */
if (mex_p->inputdatalength < MIN_MOD_SIZE) {
return SEN_NOT_AVAIL;
}
/* Anythings over MAX_PCICC_MOD_SIZE MUST go to a PCICA */
if (mex_p->inputdatalength > MAX_PCICC_MOD_SIZE) {
return SEN_NOT_AVAIL;
}
/* PCICC cannot handle input that is is PKCS#1.1 padded */ /* PCICC cannot handle input that is is PKCS#1.1 padded */
if (is_PKCS11_padded(temp_buffer, mex_p->inputdatalength)) { if (is_PKCS11_padded(temp_buffer, mex_p->inputdatalength)) {
return SEN_NOT_AVAIL; return SEN_NOT_AVAIL;
...@@ -1593,6 +1696,7 @@ z90crypt_prepare(struct work_element *we_p, unsigned int funccode, ...@@ -1593,6 +1696,7 @@ z90crypt_prepare(struct work_element *we_p, unsigned int funccode,
rv = -ENODEV; rv = -ENODEV;
break; break;
case SEN_NOT_AVAIL: case SEN_NOT_AVAIL:
case EGETBUFF:
rv = -EGETBUFF; rv = -EGETBUFF;
break; break;
default: default:
...@@ -1613,14 +1717,14 @@ purge_work_element(struct work_element *we_p) ...@@ -1613,14 +1717,14 @@ purge_work_element(struct work_element *we_p)
spin_lock_irq(&queuespinlock); spin_lock_irq(&queuespinlock);
list_for_each(lptr, &request_list) { list_for_each(lptr, &request_list) {
if (lptr == &we_p->liste) { if (lptr == &we_p->liste) {
list_del(lptr); list_del_init(lptr);
requestq_count--; requestq_count--;
break; break;
} }
} }
list_for_each(lptr, &pending_list) { list_for_each(lptr, &pending_list) {
if (lptr == &we_p->liste) { if (lptr == &we_p->liste) {
list_del(lptr); list_del_init(lptr);
pendingq_count--; pendingq_count--;
break; break;
} }
...@@ -1659,14 +1763,13 @@ z90crypt_rsa(struct priv_data *private_data_p, pid_t pid, ...@@ -1659,14 +1763,13 @@ z90crypt_rsa(struct priv_data *private_data_p, pid_t pid,
if ((we_p->status[0] & STAT_FAILED)) { if ((we_p->status[0] & STAT_FAILED)) {
switch (rv) { switch (rv) {
/** /**
* EINVAL *after* receive is almost always padding * EINVAL *after* receive is almost always a padding error or
* error issued by a PCICC or PCIXCC. We convert this * length error issued by a coprocessor (not an accelerator).
* return value to -EGETBUFF which should trigger a * We convert this return value to -EGETBUFF which should
* fallback to software. * trigger a fallback to software.
*/ */
case -EINVAL: case -EINVAL:
if ((we_p->devtype == PCICC) || if (we_p->devtype != PCICA)
(we_p->devtype == PCIXCC))
rv = -EGETBUFF; rv = -EGETBUFF;
break; break;
case -ETIMEOUT: case -ETIMEOUT:
...@@ -1710,7 +1813,8 @@ z90crypt_ioctl(struct inode *inode, struct file *filp, ...@@ -1710,7 +1813,8 @@ z90crypt_ioctl(struct inode *inode, struct file *filp,
unsigned int *reqcnt; unsigned int *reqcnt;
struct ica_z90_status *pstat; struct ica_z90_status *pstat;
int ret, i, loopLim, tempstat; int ret, i, loopLim, tempstat;
static int deprecated_msg_count = 0; static int deprecated_msg_count1 = 0;
static int deprecated_msg_count2 = 0;
PDEBUG("filp %p (PID %d), cmd 0x%08X\n", filp, PID(), cmd); PDEBUG("filp %p (PID %d), cmd 0x%08X\n", filp, PID(), cmd);
PDEBUG("cmd 0x%08X: dir %s, size 0x%04X, type 0x%02X, nr 0x%02X\n", PDEBUG("cmd 0x%08X: dir %s, size 0x%04X, type 0x%02X, nr 0x%02X\n",
...@@ -1765,8 +1869,20 @@ z90crypt_ioctl(struct inode *inode, struct file *filp, ...@@ -1765,8 +1869,20 @@ z90crypt_ioctl(struct inode *inode, struct file *filp,
ret = -EFAULT; ret = -EFAULT;
break; break;
case Z90STAT_PCIXCCCOUNT: case Z90STAT_PCIXCCMCL2COUNT:
tempstat = get_status_PCIXCCcount(); tempstat = get_status_PCIXCCMCL2count();
if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0)
ret = -EFAULT;
break;
case Z90STAT_PCIXCCMCL3COUNT:
tempstat = get_status_PCIXCCMCL3count();
if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0)
ret = -EFAULT;
break;
case Z90STAT_CEX2CCOUNT:
tempstat = get_status_CEX2Ccount();
if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0)
ret = -EFAULT; ret = -EFAULT;
break; break;
...@@ -1838,10 +1954,10 @@ z90crypt_ioctl(struct inode *inode, struct file *filp, ...@@ -1838,10 +1954,10 @@ z90crypt_ioctl(struct inode *inode, struct file *filp,
/* THIS IS DEPRECATED. USE THE NEW STATUS CALLS */ /* THIS IS DEPRECATED. USE THE NEW STATUS CALLS */
case ICAZ90STATUS: case ICAZ90STATUS:
if (deprecated_msg_count < 100) { if (deprecated_msg_count1 < 20) {
PRINTK("deprecated call to ioctl (ICAZ90STATUS)!\n"); PRINTK("deprecated call to ioctl (ICAZ90STATUS)!\n");
deprecated_msg_count++; deprecated_msg_count1++;
if (deprecated_msg_count == 100) if (deprecated_msg_count1 == 20)
PRINTK("No longer issuing messages related to " PRINTK("No longer issuing messages related to "
"deprecated call to ICAZ90STATUS.\n"); "deprecated call to ICAZ90STATUS.\n");
} }
...@@ -1869,6 +1985,21 @@ z90crypt_ioctl(struct inode *inode, struct file *filp, ...@@ -1869,6 +1985,21 @@ z90crypt_ioctl(struct inode *inode, struct file *filp,
kfree(pstat); kfree(pstat);
break; break;
/* THIS IS DEPRECATED. USE THE NEW STATUS CALLS */
case Z90STAT_PCIXCCCOUNT:
if (deprecated_msg_count2 < 20) {
PRINTK("deprecated ioctl (Z90STAT_PCIXCCCOUNT)!\n");
deprecated_msg_count2++;
if (deprecated_msg_count2 == 20)
PRINTK("No longer issuing messages about depre"
"cated ioctl Z90STAT_PCIXCCCOUNT.\n");
}
tempstat = get_status_PCIXCCcount();
if (copy_to_user((int *)arg, &tempstat, sizeof(int)) != 0)
ret = -EFAULT;
break;
case Z90QUIESCE: case Z90QUIESCE:
if (current->euid != 0) { if (current->euid != 0) {
PRINTK("QUIESCE fails: euid %d\n", PRINTK("QUIESCE fails: euid %d\n",
...@@ -1990,8 +2121,12 @@ z90crypt_status(char *resp_buff, char **start, off_t offset, ...@@ -1990,8 +2121,12 @@ z90crypt_status(char *resp_buff, char **start, off_t offset,
get_status_PCICAcount()); get_status_PCICAcount());
len += sprintf(resp_buff+len, "PCICC count: %d\n", len += sprintf(resp_buff+len, "PCICC count: %d\n",
get_status_PCICCcount()); get_status_PCICCcount());
len += sprintf(resp_buff+len, "PCIXCC count: %d\n", len += sprintf(resp_buff+len, "PCIXCC MCL2 count: %d\n",
get_status_PCIXCCcount()); get_status_PCIXCCMCL2count());
len += sprintf(resp_buff+len, "PCIXCC MCL3 count: %d\n",
get_status_PCIXCCMCL3count());
len += sprintf(resp_buff+len, "CEX2C count: %d\n",
get_status_CEX2Ccount());
len += sprintf(resp_buff+len, "requestq count: %d\n", len += sprintf(resp_buff+len, "requestq count: %d\n",
get_status_requestq_count()); get_status_requestq_count());
len += sprintf(resp_buff+len, "pendingq count: %d\n", len += sprintf(resp_buff+len, "pendingq count: %d\n",
...@@ -1999,7 +2134,8 @@ z90crypt_status(char *resp_buff, char **start, off_t offset, ...@@ -1999,7 +2134,8 @@ z90crypt_status(char *resp_buff, char **start, off_t offset,
len += sprintf(resp_buff+len, "Total open handles: %d\n\n", len += sprintf(resp_buff+len, "Total open handles: %d\n\n",
get_status_totalopen_count()); get_status_totalopen_count());
len += sprinthx( len += sprinthx(
"Online devices: 1 means PCICA, 2 means PCICC, 3 means PCIXCC", "Online devices: 1: PCICA, 2: PCICC, 3: PCIXCC (MCL2), "
"4: PCIXCC (MCL3), 5: CEX2C",
resp_buff+len, resp_buff+len,
get_status_status_mask(workarea), get_status_status_mask(workarea),
Z90CRYPT_NUM_APS); Z90CRYPT_NUM_APS);
...@@ -2171,6 +2307,8 @@ z90crypt_status_write(struct file *file, const char __user *buffer, ...@@ -2171,6 +2307,8 @@ z90crypt_status_write(struct file *file, const char __user *buffer,
case '1': case '1':
case '2': case '2':
case '3': case '3':
case '4':
case '5':
j++; j++;
break; break;
case 'd': case 'd':
...@@ -2228,9 +2366,8 @@ receive_from_crypto_device(int index, unsigned char *psmid, int *buff_len_p, ...@@ -2228,9 +2366,8 @@ receive_from_crypto_device(int index, unsigned char *psmid, int *buff_len_p,
dev_ptr = z90crypt.device_p[index]; dev_ptr = z90crypt.device_p[index];
rv = 0; rv = 0;
do { do {
PDEBUG("Dequeue called for device %d\n", index);
if (!dev_ptr || dev_ptr->disabled) { if (!dev_ptr || dev_ptr->disabled) {
rv = REC_NO_RESPONSE; rv = REC_NO_WORK; // a disabled device can't return work
break; break;
} }
if (dev_ptr->dev_self_x != index) { if (dev_ptr->dev_self_x != index) {
...@@ -2244,6 +2381,7 @@ receive_from_crypto_device(int index, unsigned char *psmid, int *buff_len_p, ...@@ -2244,6 +2381,7 @@ receive_from_crypto_device(int index, unsigned char *psmid, int *buff_len_p,
PRINTK("dev_resp_l = %d, dev_resp_p = %p\n", PRINTK("dev_resp_l = %d, dev_resp_p = %p\n",
dev_ptr->dev_resp_l, dev_ptr->dev_resp_p); dev_ptr->dev_resp_l, dev_ptr->dev_resp_p);
} else { } else {
PDEBUG("Dequeue called for device %d\n", index);
dv = receive_from_AP(index, z90crypt.cdx, dv = receive_from_AP(index, z90crypt.cdx,
dev_ptr->dev_resp_l, dev_ptr->dev_resp_l,
dev_ptr->dev_resp_p, psmid); dev_ptr->dev_resp_p, psmid);
...@@ -2283,15 +2421,18 @@ receive_from_crypto_device(int index, unsigned char *psmid, int *buff_len_p, ...@@ -2283,15 +2421,18 @@ receive_from_crypto_device(int index, unsigned char *psmid, int *buff_len_p,
if (!memcmp(caller_p->caller_id, psmid, if (!memcmp(caller_p->caller_id, psmid,
sizeof(caller_p->caller_id))) { sizeof(caller_p->caller_id))) {
if (!list_empty(&caller_p->caller_liste)) { if (!list_empty(&caller_p->caller_liste)) {
list_del(ptr); list_del_init(ptr);
dev_ptr->dev_caller_count--; dev_ptr->dev_caller_count--;
INIT_LIST_HEAD(&caller_p->caller_liste);
break; break;
} }
} }
caller_p = 0; caller_p = 0;
} }
if (!caller_p) { if (!caller_p) {
PRINTKW("Unable to locate PSMID %02X%02X%02X%02X%02X"
"%02X%02X%02X in device list\n",
psmid[0], psmid[1], psmid[2], psmid[3],
psmid[4], psmid[5], psmid[6], psmid[7]);
rv = REC_USER_GONE; rv = REC_USER_GONE;
break; break;
} }
...@@ -2300,22 +2441,22 @@ receive_from_crypto_device(int index, unsigned char *psmid, int *buff_len_p, ...@@ -2300,22 +2441,22 @@ receive_from_crypto_device(int index, unsigned char *psmid, int *buff_len_p,
rv = convert_response(dev_ptr->dev_resp_p, rv = convert_response(dev_ptr->dev_resp_p,
caller_p->caller_buf_p, buff_len_p, buff); caller_p->caller_buf_p, buff_len_p, buff);
switch (rv) { switch (rv) {
case REC_USE_PCICA:
break;
case REC_OPERAND_INV: case REC_OPERAND_INV:
PDEBUG("dev %d: user error %d\n", index, rv); case REC_OPERAND_SIZE:
case REC_EVEN_MOD:
case REC_INVALID_PAD:
PDEBUG("device %d: 'user error' %d\n", index, rv);
break; break;
case WRONG_DEVICE_TYPE: case WRONG_DEVICE_TYPE:
case REC_HARDWAR_ERR: case REC_HARDWAR_ERR:
case REC_BAD_MESSAGE: case REC_BAD_MESSAGE:
PRINTK("dev %d: hardware error %d\n", PRINTKW("device %d: hardware error %d\n", index, rv);
index, rv);
rv = REC_NO_RESPONSE; rv = REC_NO_RESPONSE;
break; break;
case REC_RELEASED:
PDEBUG("dev %d: REC_RELEASED = %d\n",
index, rv);
break;
default: default:
PDEBUG("dev %d: rv = %d\n", index, rv); PDEBUG("device %d: rv = %d\n", index, rv);
break; break;
} }
} while (0); } while (0);
...@@ -2329,6 +2470,7 @@ receive_from_crypto_device(int index, unsigned char *psmid, int *buff_len_p, ...@@ -2329,6 +2470,7 @@ receive_from_crypto_device(int index, unsigned char *psmid, int *buff_len_p,
PRINTK("Zero *buff_len_p\n"); PRINTK("Zero *buff_len_p\n");
break; break;
case REC_NO_RESPONSE: case REC_NO_RESPONSE:
PRINTKW("Removing device %d from availability\n", index);
remove_device(dev_ptr); remove_device(dev_ptr);
break; break;
} }
...@@ -2349,7 +2491,7 @@ helper_send_work(int index) ...@@ -2349,7 +2491,7 @@ helper_send_work(int index)
return; return;
requestq_count--; requestq_count--;
rq_p = list_entry(request_list.next, struct work_element, liste); rq_p = list_entry(request_list.next, struct work_element, liste);
list_del(&rq_p->liste); list_del_init(&rq_p->liste);
rq_p->audit[1] |= FP_REMREQUEST; rq_p->audit[1] |= FP_REMREQUEST;
if (rq_p->devtype == SHRT2DEVPTR(index)->dev_type) { if (rq_p->devtype == SHRT2DEVPTR(index)->dev_type) {
rq_p->devindex = SHRT2LONG(index); rq_p->devindex = SHRT2LONG(index);
...@@ -2408,7 +2550,7 @@ helper_handle_work_element(int index, unsigned char psmid[8], int rc, ...@@ -2408,7 +2550,7 @@ helper_handle_work_element(int index, unsigned char psmid[8], int rc,
list_for_each_safe(lptr, tptr, &pending_list) { list_for_each_safe(lptr, tptr, &pending_list) {
pq_p = list_entry(lptr, struct work_element, liste); pq_p = list_entry(lptr, struct work_element, liste);
if (!memcmp(pq_p->caller_id, psmid, sizeof(pq_p->caller_id))) { if (!memcmp(pq_p->caller_id, psmid, sizeof(pq_p->caller_id))) {
list_del(lptr); list_del_init(lptr);
pendingq_count--; pendingq_count--;
pq_p->audit[1] |= FP_NOTPENDING; pq_p->audit[1] |= FP_NOTPENDING;
break; break;
...@@ -2441,6 +2583,10 @@ helper_handle_work_element(int index, unsigned char psmid[8], int rc, ...@@ -2441,6 +2583,10 @@ helper_handle_work_element(int index, unsigned char psmid[8], int rc,
pq_p->retcode = -EINVAL; pq_p->retcode = -EINVAL;
pq_p->status[0] |= STAT_FAILED; pq_p->status[0] |= STAT_FAILED;
break; break;
case REC_USE_PCICA:
pq_p->retcode = -ERESTARTSYS;
pq_p->status[0] |= STAT_FAILED;
break;
case REC_NO_RESPONSE: case REC_NO_RESPONSE:
default: default:
if (z90crypt.mask.st_count > 1) if (z90crypt.mask.st_count > 1)
...@@ -2461,7 +2607,7 @@ helper_handle_work_element(int index, unsigned char psmid[8], int rc, ...@@ -2461,7 +2607,7 @@ helper_handle_work_element(int index, unsigned char psmid[8], int rc,
* return TRUE if the work element should be removed from the queue * return TRUE if the work element should be removed from the queue
*/ */
static inline int static inline int
helper_receive_rc(int index, int *rc_p, int *workavail_p) helper_receive_rc(int index, int *rc_p)
{ {
switch (*rc_p) { switch (*rc_p) {
case 0: case 0:
...@@ -2469,26 +2615,26 @@ helper_receive_rc(int index, int *rc_p, int *workavail_p) ...@@ -2469,26 +2615,26 @@ helper_receive_rc(int index, int *rc_p, int *workavail_p)
case REC_OPERAND_SIZE: case REC_OPERAND_SIZE:
case REC_EVEN_MOD: case REC_EVEN_MOD:
case REC_INVALID_PAD: case REC_INVALID_PAD:
return 1; case REC_USE_PCICA:
break;
case REC_BUSY: case REC_BUSY:
case REC_NO_WORK: case REC_NO_WORK:
case REC_EMPTY: case REC_EMPTY:
case REC_RETRY_DEV: case REC_RETRY_DEV:
case REC_FATAL_ERROR: case REC_FATAL_ERROR:
break; return 0;
case REC_NO_RESPONSE: case REC_NO_RESPONSE:
*workavail_p = 0;
break; break;
default: default:
PRINTK("rc %d, device %d\n", *rc_p, SHRT2LONG(index)); PRINTK("rc %d, device %d converted to REC_NO_RESPONSE\n",
*rc_p, SHRT2LONG(index));
*rc_p = REC_NO_RESPONSE; *rc_p = REC_NO_RESPONSE;
*workavail_p = 0;
break; break;
} }
return 0; return 1;
} }
static inline void static inline void
...@@ -2503,21 +2649,18 @@ z90crypt_schedule_reader_timer(void) ...@@ -2503,21 +2649,18 @@ z90crypt_schedule_reader_timer(void)
static void static void
z90crypt_reader_task(unsigned long ptr) z90crypt_reader_task(unsigned long ptr)
{ {
int workavail, remaining, index, rc, buff_len; int workavail, index, rc, buff_len;
unsigned char psmid[8]; unsigned char psmid[8];
unsigned char __user *resp_addr; unsigned char __user *resp_addr;
static unsigned char buff[1024]; static unsigned char buff[1024];
PDEBUG("jiffies %ld\n", jiffies);
/** /**
* we use workavail = 2 to ensure 2 passes with nothing dequeued before * we use workavail = 2 to ensure 2 passes with nothing dequeued before
* exiting the loop. If remaining == 0 after the loop, there is no work * exiting the loop. If pendingq_count == 0 after the loop, there is no
* remaining on the queues. * work remaining on the queues.
*/ */
resp_addr = 0; resp_addr = 0;
workavail = 2; workavail = 2;
remaining = 0;
buff_len = 0; buff_len = 0;
while (workavail) { while (workavail) {
workavail--; workavail--;
...@@ -2535,7 +2678,7 @@ z90crypt_reader_task(unsigned long ptr) ...@@ -2535,7 +2678,7 @@ z90crypt_reader_task(unsigned long ptr)
&resp_addr); &resp_addr);
PDEBUG("Dequeued: rc = %d.\n", rc); PDEBUG("Dequeued: rc = %d.\n", rc);
if (helper_receive_rc(index, &rc, &workavail)) { if (helper_receive_rc(index, &rc)) {
if (rc != REC_NO_RESPONSE) { if (rc != REC_NO_RESPONSE) {
helper_send_work(index); helper_send_work(index);
workavail = 2; workavail = 2;
...@@ -2547,19 +2690,14 @@ z90crypt_reader_task(unsigned long ptr) ...@@ -2547,19 +2690,14 @@ z90crypt_reader_task(unsigned long ptr)
} }
if (rc == REC_FATAL_ERROR) if (rc == REC_FATAL_ERROR)
remaining = 0; PRINTKW("REC_FATAL_ERROR from device %d!\n",
else if (rc != REC_NO_RESPONSE) SHRT2LONG(index));
remaining +=
SHRT2DEVPTR(index)->dev_caller_count;
} }
spin_unlock_irq(&queuespinlock); spin_unlock_irq(&queuespinlock);
} }
if (remaining) { if (pendingq_count)
spin_lock_irq(&queuespinlock);
z90crypt_schedule_reader_timer(); z90crypt_schedule_reader_timer();
spin_unlock_irq(&queuespinlock);
}
} }
static inline void static inline void
...@@ -2606,7 +2744,7 @@ helper_drain_queues(void) ...@@ -2606,7 +2744,7 @@ helper_drain_queues(void)
pq_p->status[0] |= STAT_FAILED; pq_p->status[0] |= STAT_FAILED;
unbuild_caller(LONG2DEVPTR(pq_p->devindex), unbuild_caller(LONG2DEVPTR(pq_p->devindex),
(struct caller *)pq_p->requestptr); (struct caller *)pq_p->requestptr);
list_del(lptr); list_del_init(lptr);
pendingq_count--; pendingq_count--;
pq_p->audit[1] |= FP_NOTPENDING; pq_p->audit[1] |= FP_NOTPENDING;
pq_p->audit[1] |= FP_AWAKENING; pq_p->audit[1] |= FP_AWAKENING;
...@@ -2618,7 +2756,7 @@ helper_drain_queues(void) ...@@ -2618,7 +2756,7 @@ helper_drain_queues(void)
pq_p = list_entry(lptr, struct work_element, liste); pq_p = list_entry(lptr, struct work_element, liste);
pq_p->retcode = -ENODEV; pq_p->retcode = -ENODEV;
pq_p->status[0] |= STAT_FAILED; pq_p->status[0] |= STAT_FAILED;
list_del(lptr); list_del_init(lptr);
requestq_count--; requestq_count--;
pq_p->audit[1] |= FP_REMREQUEST; pq_p->audit[1] |= FP_REMREQUEST;
pq_p->audit[1] |= FP_AWAKENING; pq_p->audit[1] |= FP_AWAKENING;
...@@ -2640,12 +2778,21 @@ helper_timeout_requests(void) ...@@ -2640,12 +2778,21 @@ helper_timeout_requests(void)
pq_p = list_entry(lptr, struct work_element, liste); pq_p = list_entry(lptr, struct work_element, liste);
if (pq_p->requestsent >= timelimit) if (pq_p->requestsent >= timelimit)
break; break;
PRINTKW("Purging(PQ) PSMID %02X%02X%02X%02X%02X%02X%02X%02X\n",
((struct caller *)pq_p->requestptr)->caller_id[0],
((struct caller *)pq_p->requestptr)->caller_id[1],
((struct caller *)pq_p->requestptr)->caller_id[2],
((struct caller *)pq_p->requestptr)->caller_id[3],
((struct caller *)pq_p->requestptr)->caller_id[4],
((struct caller *)pq_p->requestptr)->caller_id[5],
((struct caller *)pq_p->requestptr)->caller_id[6],
((struct caller *)pq_p->requestptr)->caller_id[7]);
pq_p->retcode = -ETIMEOUT; pq_p->retcode = -ETIMEOUT;
pq_p->status[0] |= STAT_FAILED; pq_p->status[0] |= STAT_FAILED;
/* get this off any caller queue it may be on */ /* get this off any caller queue it may be on */
unbuild_caller(LONG2DEVPTR(pq_p->devindex), unbuild_caller(LONG2DEVPTR(pq_p->devindex),
(struct caller *) pq_p->requestptr); (struct caller *) pq_p->requestptr);
list_del(lptr); list_del_init(lptr);
pendingq_count--; pendingq_count--;
pq_p->audit[1] |= FP_TIMEDOUT; pq_p->audit[1] |= FP_TIMEDOUT;
pq_p->audit[1] |= FP_NOTPENDING; pq_p->audit[1] |= FP_NOTPENDING;
...@@ -2663,9 +2810,18 @@ helper_timeout_requests(void) ...@@ -2663,9 +2810,18 @@ helper_timeout_requests(void)
pq_p = list_entry(lptr, struct work_element, liste); pq_p = list_entry(lptr, struct work_element, liste);
if (pq_p->requestsent >= timelimit) if (pq_p->requestsent >= timelimit)
break; break;
PRINTKW("Purging(RQ) PSMID %02X%02X%02X%02X%02X%02X%02X%02X\n",
((struct caller *)pq_p->requestptr)->caller_id[0],
((struct caller *)pq_p->requestptr)->caller_id[1],
((struct caller *)pq_p->requestptr)->caller_id[2],
((struct caller *)pq_p->requestptr)->caller_id[3],
((struct caller *)pq_p->requestptr)->caller_id[4],
((struct caller *)pq_p->requestptr)->caller_id[5],
((struct caller *)pq_p->requestptr)->caller_id[6],
((struct caller *)pq_p->requestptr)->caller_id[7]);
pq_p->retcode = -ETIMEOUT; pq_p->retcode = -ETIMEOUT;
pq_p->status[0] |= STAT_FAILED; pq_p->status[0] |= STAT_FAILED;
list_del(lptr); list_del_init(lptr);
requestq_count--; requestq_count--;
pq_p->audit[1] |= FP_TIMEDOUT; pq_p->audit[1] |= FP_TIMEDOUT;
pq_p->audit[1] |= FP_REMREQUEST; pq_p->audit[1] |= FP_REMREQUEST;
...@@ -2737,15 +2893,15 @@ helper_scan_devices(int cdx_array[16], int *cdx_p, int *correct_cdx_found) ...@@ -2737,15 +2893,15 @@ helper_scan_devices(int cdx_array[16], int *cdx_p, int *correct_cdx_found)
{ {
enum hdstat hd_stat; enum hdstat hd_stat;
int q_depth, dev_type; int q_depth, dev_type;
int i, j, k; int indx, chkdom, numdomains;
q_depth = dev_type = k = 0; q_depth = dev_type = numdomains = 0;
for (i = 0; i < z90crypt.max_count; i++) { for (chkdom = 0; chkdom <= 15; cdx_array[chkdom++] = -1);
for (indx = 0; indx < z90crypt.max_count; indx++) {
hd_stat = HD_NOT_THERE; hd_stat = HD_NOT_THERE;
for (j = 0; j <= 15; cdx_array[j++] = -1); numdomains = 0;
k = 0; for (chkdom = 0; chkdom <= 15; chkdom++) {
for (j = 0; j <= 15; j++) { hd_stat = query_online(indx, chkdom, MAX_RESET,
hd_stat = query_online(i, j, MAX_RESET,
&q_depth, &dev_type); &q_depth, &dev_type);
if (hd_stat == HD_TSQ_EXCEPTION) { if (hd_stat == HD_TSQ_EXCEPTION) {
z90crypt.terminating = 1; z90crypt.terminating = 1;
...@@ -2753,29 +2909,30 @@ helper_scan_devices(int cdx_array[16], int *cdx_p, int *correct_cdx_found) ...@@ -2753,29 +2909,30 @@ helper_scan_devices(int cdx_array[16], int *cdx_p, int *correct_cdx_found)
break; break;
} }
if (hd_stat == HD_ONLINE) { if (hd_stat == HD_ONLINE) {
cdx_array[k++] = j; cdx_array[numdomains++] = chkdom;
if (*cdx_p == j) { if (*cdx_p == chkdom) {
*correct_cdx_found = 1; *correct_cdx_found = 1;
break; break;
} }
} }
} }
if ((*correct_cdx_found == 1) || (k != 0)) if ((*correct_cdx_found == 1) || (numdomains != 0))
break; break;
if (z90crypt.terminating) if (z90crypt.terminating)
break; break;
} }
return k; return numdomains;
} }
static inline int static inline int
probe_crypto_domain(int *cdx_p) probe_crypto_domain(int *cdx_p)
{ {
int cdx_array[16]; int cdx_array[16];
int correct_cdx_found, k; char cdx_array_text[53], temp[5];
int correct_cdx_found, numdomains;
correct_cdx_found = 0; correct_cdx_found = 0;
k = helper_scan_devices(cdx_array, cdx_p, &correct_cdx_found); numdomains = helper_scan_devices(cdx_array, cdx_p, &correct_cdx_found);
if (z90crypt.terminating) if (z90crypt.terminating)
return TSQ_FATAL_ERROR; return TSQ_FATAL_ERROR;
...@@ -2783,23 +2940,31 @@ probe_crypto_domain(int *cdx_p) ...@@ -2783,23 +2940,31 @@ probe_crypto_domain(int *cdx_p)
if (correct_cdx_found) if (correct_cdx_found)
return 0; return 0;
if (k == 0) { if (numdomains == 0) {
*cdx_p = 0; PRINTKW("Unable to find crypto domain: No devices found\n");
return 0; return Z90C_NO_DEVICES;
} }
if (k == 1) { if (numdomains == 1) {
if ((*cdx_p == -1) || !z90crypt.domain_established) { if (*cdx_p == -1) {
*cdx_p = cdx_array[0]; *cdx_p = cdx_array[0];
return 0; return 0;
} }
if (*cdx_p != cdx_array[0]) { PRINTKW("incorrect domain: specified = %d, found = %d\n",
PRINTK("incorrect domain: specified = %d, found = %d\n",
*cdx_p, cdx_array[0]); *cdx_p, cdx_array[0]);
return Z90C_INCORRECT_DOMAIN; return Z90C_INCORRECT_DOMAIN;
} }
numdomains--;
sprintf(cdx_array_text, "%d", cdx_array[numdomains]);
while (numdomains) {
numdomains--;
sprintf(temp, ", %d", cdx_array[numdomains]);
strcat(cdx_array_text, temp);
} }
PRINTKW("ambiguous domain detected: specified = %d, found array = %s\n",
*cdx_p, cdx_array_text);
return Z90C_AMBIGUOUS_DOMAIN; return Z90C_AMBIGUOUS_DOMAIN;
} }
...@@ -2807,7 +2972,7 @@ static int ...@@ -2807,7 +2972,7 @@ static int
refresh_z90crypt(int *cdx_p) refresh_z90crypt(int *cdx_p)
{ {
int i, j, indx, rv; int i, j, indx, rv;
struct status local_mask; static struct status local_mask;
struct device *devPtr; struct device *devPtr;
unsigned char oldStat, newStat; unsigned char oldStat, newStat;
int return_unchanged; int return_unchanged;
...@@ -2818,25 +2983,14 @@ refresh_z90crypt(int *cdx_p) ...@@ -2818,25 +2983,14 @@ refresh_z90crypt(int *cdx_p)
return TSQ_FATAL_ERROR; return TSQ_FATAL_ERROR;
rv = 0; rv = 0;
if (!z90crypt.hdware_info->hdware_mask.st_count && if (!z90crypt.hdware_info->hdware_mask.st_count &&
!z90crypt.domain_established) !z90crypt.domain_established) {
rv = probe_crypto_domain(cdx_p); rv = probe_crypto_domain(cdx_p);
if (z90crypt.terminating) if (z90crypt.terminating)
return TSQ_FATAL_ERROR; return TSQ_FATAL_ERROR;
if (rv) { if (rv == Z90C_NO_DEVICES)
switch (rv) { return 0; // try later
case Z90C_AMBIGUOUS_DOMAIN: if (rv)
PRINTK("ambiguous domain detected\n");
break;
case Z90C_INCORRECT_DOMAIN:
PRINTK("incorrect domain specified\n");
break;
default:
PRINTK("probe domain returned %d\n", rv);
break;
}
return rv; return rv;
}
if (*cdx_p) {
z90crypt.cdx = *cdx_p; z90crypt.cdx = *cdx_p;
z90crypt.domain_established = 1; z90crypt.domain_established = 1;
} }
...@@ -2999,14 +3153,28 @@ create_crypto_device(int index) ...@@ -2999,14 +3153,28 @@ create_crypto_device(int index)
return rv; return rv;
} }
} }
if (dev_ptr->dev_type == PCIXCC_UNK) {
rv = probe_PCIXCC_type(dev_ptr);
if (rv) {
PRINTK("rv = %d from probe_PCIXCC_type %d\n",
rv, index);
kfree(dev_ptr->dev_resp_p);
kfree(dev_ptr);
return rv;
}
}
deviceType = dev_ptr->dev_type; deviceType = dev_ptr->dev_type;
z90crypt.dev_type_array[index] = deviceType; z90crypt.dev_type_array[index] = deviceType;
if (deviceType == PCICA) if (deviceType == PCICA)
z90crypt.hdware_info->device_type_array[index] = 1; z90crypt.hdware_info->device_type_array[index] = 1;
else if (deviceType == PCICC) else if (deviceType == PCICC)
z90crypt.hdware_info->device_type_array[index] = 2; z90crypt.hdware_info->device_type_array[index] = 2;
else if (deviceType == PCIXCC) else if (deviceType == PCIXCC_MCL2)
z90crypt.hdware_info->device_type_array[index] = 3; z90crypt.hdware_info->device_type_array[index] = 3;
else if (deviceType == PCIXCC_MCL3)
z90crypt.hdware_info->device_type_array[index] = 4;
else if (deviceType == CEX2C)
z90crypt.hdware_info->device_type_array[index] = 5;
else else
z90crypt.hdware_info->device_type_array[index] = -1; z90crypt.hdware_info->device_type_array[index] = -1;
} }
...@@ -3086,7 +3254,7 @@ destroy_z90crypt(void) ...@@ -3086,7 +3254,7 @@ destroy_z90crypt(void)
memset((void *)&z90crypt, 0, sizeof(z90crypt)); memset((void *)&z90crypt, 0, sizeof(z90crypt));
} }
static unsigned char static_testmsg[] = { static unsigned char static_testmsg[384] = {
0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x00,0x06,0x00,0x00, 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x00,0x06,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x58, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x58,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x43,0x43, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x43,0x43,
...@@ -3118,7 +3286,7 @@ probe_device_type(struct device *devPtr) ...@@ -3118,7 +3286,7 @@ probe_device_type(struct device *devPtr)
{ {
int rv, dv, i, index, length; int rv, dv, i, index, length;
unsigned char psmid[8]; unsigned char psmid[8];
static unsigned char loc_testmsg[384]; static unsigned char loc_testmsg[sizeof(static_testmsg)];
index = devPtr->dev_self_x; index = devPtr->dev_self_x;
rv = 0; rv = 0;
...@@ -3212,8 +3380,146 @@ probe_device_type(struct device *devPtr) ...@@ -3212,8 +3380,146 @@ probe_device_type(struct device *devPtr)
return rv; return rv;
} }
static unsigned char MCL3_testmsg[] = {
0x00,0x00,0x00,0x00,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,
0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x43,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x00,0x00,0x00,0x01,0xC4,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x24,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x02,0x00,0x00,0x00,0x54,0x32,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE8,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x24,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x0A,0x4D,0x52,0x50,0x20,0x20,0x20,0x20,0x20,
0x00,0x42,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
0x0E,0x0F,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,
0xEE,0xFF,0xFF,0xEE,0xDD,0xCC,0xBB,0xAA,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,
0x11,0x00,0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF,0xFE,0xDC,0xBA,0x98,0x76,0x54,
0x32,0x10,0x00,0x9A,0x00,0x98,0x00,0x00,0x1E,0x00,0x00,0x94,0x00,0x00,0x00,0x00,
0x04,0x00,0x00,0x8C,0x00,0x00,0x00,0x40,0x02,0x00,0x00,0x40,0xBA,0xE8,0x23,0x3C,
0x75,0xF3,0x91,0x61,0xD6,0x73,0x39,0xCF,0x7B,0x6D,0x8E,0x61,0x97,0x63,0x9E,0xD9,
0x60,0x55,0xD6,0xC7,0xEF,0xF8,0x1E,0x63,0x95,0x17,0xCC,0x28,0x45,0x60,0x11,0xC5,
0xC4,0x4E,0x66,0xC6,0xE6,0xC3,0xDE,0x8A,0x19,0x30,0xCF,0x0E,0xD7,0xAA,0xDB,0x01,
0xD8,0x00,0xBB,0x8F,0x39,0x9F,0x64,0x28,0xF5,0x7A,0x77,0x49,0xCC,0x6B,0xA3,0x91,
0x97,0x70,0xE7,0x60,0x1E,0x39,0xE1,0xE5,0x33,0xE1,0x15,0x63,0x69,0x08,0x80,0x4C,
0x67,0xC4,0x41,0x8F,0x48,0xDF,0x26,0x98,0xF1,0xD5,0x8D,0x88,0xD9,0x6A,0xA4,0x96,
0xC5,0x84,0xD9,0x30,0x49,0x67,0x7D,0x19,0xB1,0xB3,0x45,0x4D,0xB2,0x53,0x9A,0x47,
0x3C,0x7C,0x55,0xBF,0xCC,0x85,0x00,0x36,0xF1,0x3D,0x93,0x53
};
static int
probe_PCIXCC_type(struct device *devPtr)
{
int rv, dv, i, index, length;
unsigned char psmid[8];
static unsigned char loc_testmsg[548];
struct CPRBX *cprbx_p;
index = devPtr->dev_self_x;
rv = 0;
do {
memcpy(loc_testmsg, MCL3_testmsg, sizeof(MCL3_testmsg));
length = sizeof(MCL3_testmsg) - 0x0C;
dv = send_to_AP(index, z90crypt.cdx, length, loc_testmsg);
if (dv) {
PDEBUG("dv returned = %d\n", dv);
if (dv == DEV_SEN_EXCEPTION) {
rv = SEN_FATAL_ERROR;
PRINTKC("exception in send to AP %d\n", index);
break;
}
PDEBUG("return value from send_to_AP: %d\n", rv);
switch (dv) {
case DEV_GONE:
PDEBUG("dev %d not available\n", index);
rv = SEN_NOT_AVAIL;
break;
case DEV_ONLINE:
rv = 0;
break;
case DEV_EMPTY:
rv = SEN_NOT_AVAIL;
break;
case DEV_NO_WORK:
rv = SEN_FATAL_ERROR;
break;
case DEV_BAD_MESSAGE:
rv = SEN_USER_ERROR;
break;
case DEV_QUEUE_FULL:
rv = SEN_QUEUE_FULL;
break;
default:
PRINTK("unknown dv=%d for dev %d\n", dv, index);
rv = SEN_NOT_AVAIL;
break;
}
}
if (rv)
break;
for (i = 0; i < 6; i++) {
mdelay(300);
dv = receive_from_AP(index, z90crypt.cdx,
devPtr->dev_resp_l,
devPtr->dev_resp_p, psmid);
PDEBUG("dv returned by DQ = %d\n", dv);
if (dv == DEV_REC_EXCEPTION) {
rv = REC_FATAL_ERROR;
PRINTKC("exception in dequeue %d\n",
index);
break;
}
switch (dv) {
case DEV_ONLINE:
rv = 0;
break;
case DEV_EMPTY:
rv = REC_EMPTY;
break;
case DEV_NO_WORK:
rv = REC_NO_WORK;
break;
case DEV_BAD_MESSAGE:
case DEV_GONE:
default:
rv = REC_NO_RESPONSE;
break;
}
if ((rv != 0) && (rv != REC_NO_WORK))
break;
if (rv == 0)
break;
}
if (rv)
break;
cprbx_p = (struct CPRBX *) (devPtr->dev_resp_p + 48);
if ((cprbx_p->ccp_rtcode == 8) && (cprbx_p->ccp_rscode == 33)) {
devPtr->dev_type = PCIXCC_MCL2;
PDEBUG("device %d is MCL2\n", index);
} else {
devPtr->dev_type = PCIXCC_MCL3;
PDEBUG("device %d is MCL3\n", index);
}
} while (0);
/* In a general error case, the card is not marked online */
return rv;
}
#ifdef Z90CRYPT_USE_HOTPLUG #ifdef Z90CRYPT_USE_HOTPLUG
void static void
z90crypt_hotplug_event(int dev_major, int dev_minor, int action) z90crypt_hotplug_event(int dev_major, int dev_minor, int action)
{ {
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
...@@ -3241,6 +3547,7 @@ z90crypt_hotplug_event(int dev_major, int dev_minor, int action) ...@@ -3241,6 +3547,7 @@ z90crypt_hotplug_event(int dev_major, int dev_minor, int action)
break; break;
default: default:
BUG(); BUG();
break;
} }
envp[3] = major; envp[3] = major;
envp[4] = minor; envp[4] = minor;
......
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