Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / s390 / crypto / z90main.c
index 9ec29bb..982acc7 100644 (file)
@@ -1,9 +1,9 @@
 /*
  *  linux/drivers/s390/crypto/z90main.c
  *
- *  z90crypt 1.3.2
+ *  z90crypt 1.3.3
  *
- *  Copyright (C)  2001, 2004 IBM Corporation
+ *  Copyright (C)  2001, 2005 IBM Corporation
  *  Author(s): Robert Burroughs (burrough@us.ibm.com)
  *             Eric Rossman (edrossma@us.ibm.com)
  *
 #include <linux/delay.h>       // mdelay
 #include <linux/init.h>
 #include <linux/interrupt.h>   // for tasklets
-#include <linux/ioctl32.h>
+#include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/kobject_uevent.h>
 #include <linux/proc_fs.h>
 #include <linux/syscalls.h>
-#include <linux/version.h>
 #include "z90crypt.h"
 #include "z90common.h"
-#ifndef Z90CRYPT_USE_HOTPLUG
-#include <linux/miscdevice.h>
-#endif
-
-#define VERSION_CODE(vers, rel, seq) (((vers)<<16) | ((rel)<<8) | (seq))
-#if LINUX_VERSION_CODE < VERSION_CODE(2,4,0) /* version < 2.4 */
-#  error "This kernel is too old: not supported"
-#endif
-#if LINUX_VERSION_CODE > VERSION_CODE(2,7,0) /* version > 2.6 */
-#  error "This kernel is too recent: not supported by this file"
-#endif
-
-#define VERSION_Z90MAIN_C "$Revision: 1.57 $"
-
-static char z90main_version[] __initdata =
-       "z90main.o (" VERSION_Z90MAIN_C "/"
-                      VERSION_Z90COMMON_H "/" VERSION_Z90CRYPT_H ")";
-
-extern char z90hardware_version[];
 
 /**
  * Defaults that may be modified.
  */
 
-#ifndef Z90CRYPT_USE_HOTPLUG
 /**
  * You can specify a different minor at compile time.
  */
 #ifndef Z90CRYPT_MINOR
 #define Z90CRYPT_MINOR MISC_DYNAMIC_MINOR
 #endif
-#else
-/**
- * You can specify a different major at compile time.
- */
-#ifndef Z90CRYPT_MAJOR
-#define Z90CRYPT_MAJOR 0
-#endif
-#endif
 
 /**
  * You can specify a different domain at compile time or on the insmod
@@ -97,7 +67,7 @@ extern char z90hardware_version[];
  * older than CLEANUPTIME seconds in the past.
  */
 #ifndef CLEANUPTIME
-#define CLEANUPTIME 20
+#define CLEANUPTIME 15
 #endif
 
 /**
@@ -249,7 +219,7 @@ struct device_x {
  */
 struct device {
        int              dev_type;          // PCICA, PCICC, PCIXCC_MCL2,
-                                           // PCIXCC_MCL3, CEX2C
+                                           // PCIXCC_MCL3, CEX2C, CEX2A
        enum devstat     dev_stat;          // current device status
        int              dev_self_x;        // Index in array
        int              disabled;          // Set when device is in error
@@ -298,6 +268,10 @@ struct z90crypt {
  * it contains the request; at READ, the response. The function
  * send_to_crypto_device converts the request to device-dependent
  * form and use the caller's OPEN-allocated buffer for the response.
+ *
+ * For the contents of caller_dev_dep_req and caller_dev_dep_req_p
+ * because that points to it, see the discussion in z90hardware.c.
+ * Search for "extended request message block".
  */
 struct caller {
        int              caller_buf_l;           // length of original request
@@ -312,26 +286,30 @@ struct caller {
 /**
  * Function prototypes from z90hardware.c
  */
-enum hdstat query_online(int, int, int, int *, int *);
-enum devstat reset_device(int, int, int);
-enum devstat send_to_AP(int, int, int, unsigned char *);
-enum devstat receive_from_AP(int, int, int, unsigned char *, unsigned char *);
-int convert_request(unsigned char *, int, short, int, int, int *,
-                   unsigned char *);
-int convert_response(unsigned char *, unsigned char *, int *, unsigned char *);
+enum hdstat query_online(int deviceNr, int cdx, int resetNr, int *q_depth,
+                        int *dev_type);
+enum devstat reset_device(int deviceNr, int cdx, int resetNr);
+enum devstat send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext);
+enum devstat receive_from_AP(int dev_nr, int cdx, int resplen,
+                            unsigned char *resp, unsigned char *psmid);
+int convert_request(unsigned char *buffer, int func, unsigned short function,
+                   int cdx, int dev_type, int *msg_l_p, unsigned char *msg_p);
+int convert_response(unsigned char *response, unsigned char *buffer,
+                    int *respbufflen_p, unsigned char *resp_buff);
 
 /**
  * Low level function prototypes
  */
-static int create_z90crypt(int *);
-static int refresh_z90crypt(int *);
-static int find_crypto_devices(struct status *);
-static int create_crypto_device(int);
-static int destroy_crypto_device(int);
+static int create_z90crypt(int *cdx_p);
+static int refresh_z90crypt(int *cdx_p);
+static int find_crypto_devices(struct status *deviceMask);
+static int create_crypto_device(int index);
+static int destroy_crypto_device(int index);
 static void destroy_z90crypt(void);
-static int refresh_index_array(struct status *, struct device_x *);
-static int probe_device_type(struct device *);
-static int probe_PCIXCC_type(struct device *);
+static int refresh_index_array(struct status *status_str,
+                              struct device_x *index_array);
+static int probe_device_type(struct device *devPtr);
+static int probe_PCIXCC_type(struct device *devPtr);
 
 /**
  * proc fs definitions
@@ -397,25 +375,10 @@ static int z90crypt_status(char *, char **, off_t, int, int *, void *);
 static int z90crypt_status_write(struct file *, const char __user *,
                                 unsigned long, void *);
 
-/**
- * Hotplug support
- */
-
-#ifdef Z90CRYPT_USE_HOTPLUG
-#define Z90CRYPT_HOTPLUG_ADD    1
-#define Z90CRYPT_HOTPLUG_REMOVE         2
-
-static void z90crypt_hotplug_event(int, int, int);
-#endif
-
 /**
  * Storage allocated at initialization and used throughout the life of
  * this insmod
  */
-#ifdef Z90CRYPT_USE_HOTPLUG
-static int z90crypt_major = Z90CRYPT_MAJOR;
-#endif
-
 static int domain = DOMAIN_INDEX;
 static struct z90crypt z90crypt;
 static int quiesce_z90crypt;
@@ -444,14 +407,12 @@ static struct file_operations z90crypt_fops = {
        .release        = z90crypt_release
 };
 
-#ifndef Z90CRYPT_USE_HOTPLUG
 static struct miscdevice z90crypt_misc_device = {
        .minor      = Z90CRYPT_MINOR,
        .name       = DEV_NAME,
        .fops       = &z90crypt_fops,
        .devfs_name = DEV_NAME
 };
-#endif
 
 /**
  * Documentation values.
@@ -459,7 +420,7 @@ static struct miscdevice z90crypt_misc_device = {
 MODULE_AUTHOR("zSeries Linux Crypto Team: Robert H. Burroughs, Eric D. Rossman"
              "and Jochen Roehrig");
 MODULE_DESCRIPTION("zSeries Linux Cryptographic Coprocessor device driver, "
-                  "Copyright 2001, 2004 IBM Corporation");
+                  "Copyright 2001, 2005 IBM Corporation");
 MODULE_LICENSE("GPL");
 module_param(domain, int, 0);
 MODULE_PARM_DESC(domain, "domain index for device");
@@ -603,7 +564,6 @@ z90crypt_init_module(void)
                return -EINVAL;
        }
 
-#ifndef Z90CRYPT_USE_HOTPLUG
        /* Register as misc device with given minor (or get a dynamic one). */
        result = misc_register(&z90crypt_misc_device);
        if (result < 0) {
@@ -611,18 +571,6 @@ z90crypt_init_module(void)
                        z90crypt_misc_device.minor, result);
                return result;
        }
-#else
-       /* Register the major (or get a dynamic one). */
-       result = register_chrdev(z90crypt_major, REG_NAME, &z90crypt_fops);
-       if (result < 0) {
-               PRINTKW("register_chrdev (major %d) failed with %d.\n",
-                       z90crypt_major, result);
-               return result;
-       }
-
-       if (z90crypt_major == 0)
-               z90crypt_major = result;
-#endif
 
        PDEBUG("Registered " DEV_NAME " with result %d\n", result);
 
@@ -638,18 +586,11 @@ z90crypt_init_module(void)
                PRINTKN("Version %d.%d.%d loaded, built on %s %s\n",
                        z90crypt_VERSION, z90crypt_RELEASE, z90crypt_VARIANT,
                        __DATE__, __TIME__);
-               PRINTKN("%s\n", z90main_version);
-               PRINTKN("%s\n", z90hardware_version);
                PDEBUG("create_z90crypt (domain index %d) successful.\n",
                       domain);
        } else
                PRINTK("No devices at startup\n");
 
-#ifdef Z90CRYPT_USE_HOTPLUG
-       /* generate hotplug event for device node generation */
-       z90crypt_hotplug_event(z90crypt_major, 0, Z90CRYPT_HOTPLUG_ADD);
-#endif
-
        /* Initialize globals. */
        spin_lock_init(&queuespinlock);
 
@@ -701,17 +642,10 @@ z90crypt_init_module(void)
        return 0; // success
 
 init_module_cleanup:
-#ifndef Z90CRYPT_USE_HOTPLUG
        if ((nresult = misc_deregister(&z90crypt_misc_device)))
                PRINTK("misc_deregister failed with %d.\n", nresult);
        else
                PDEBUG("misc_deregister successful.\n");
-#else
-       if ((nresult = unregister_chrdev(z90crypt_major, REG_NAME)))
-               PRINTK("unregister_chrdev failed with %d.\n", nresult);
-       else
-               PDEBUG("unregister_chrdev successful.\n");
-#endif
 
        return result; // failure
 }
@@ -728,19 +662,10 @@ z90crypt_cleanup_module(void)
 
        remove_proc_entry("driver/z90crypt", 0);
 
-#ifndef Z90CRYPT_USE_HOTPLUG
        if ((nresult = misc_deregister(&z90crypt_misc_device)))
                PRINTK("misc_deregister failed with %d.\n", nresult);
        else
                PDEBUG("misc_deregister successful.\n");
-#else
-       z90crypt_hotplug_event(z90crypt_major, 0, Z90CRYPT_HOTPLUG_REMOVE);
-
-       if ((nresult = unregister_chrdev(z90crypt_major, REG_NAME)))
-               PRINTK("unregister_chrdev failed with %d.\n", nresult);
-       else
-               PDEBUG("unregister_chrdev successful.\n");
-#endif
 
        /* Remove the tasks */
        tasklet_kill(&reader_tasklet);
@@ -766,8 +691,6 @@ z90crypt_cleanup_module(void)
  *     z90crypt_status_write
  *      disable_card
  *      enable_card
- *      scan_char
- *      scan_string
  *
  * Helper functions:
  *     z90crypt_rsa
@@ -784,13 +707,12 @@ z90crypt_open(struct inode *inode, struct file *filp)
        if (quiesce_z90crypt)
                return -EQUIESCE;
 
-       private_data_p = kmalloc(sizeof(struct priv_data), GFP_KERNEL);
+       private_data_p = kzalloc(sizeof(struct priv_data), GFP_KERNEL);
        if (!private_data_p) {
                PRINTK("Memory allocate failed\n");
                return -ENOMEM;
        }
 
-       memset((void *)private_data_p, 0, sizeof(struct priv_data));
        private_data_p->status = STAT_OPEN;
        private_data_p->opener_pid = PID();
        filp->private_data = private_data_p;
@@ -929,6 +851,12 @@ get_status_CEX2Ccount(void)
        return z90crypt.hdware_info->type_mask[CEX2C].st_count;
 }
 
+static inline int
+get_status_CEX2Acount(void)
+{
+       return z90crypt.hdware_info->type_mask[CEX2A].st_count;
+}
+
 static inline int
 get_status_requestq_count(void)
 {
@@ -1057,10 +985,12 @@ remove_device(struct device *device_p)
  * The MCL must be applied and the newer bitlengths enabled for these to work.
  *
  * Card Type    Old limit    New limit
+ * PCICA          ??-2048     same (the lower limit is less than 128 bit...)
  * PCICC         512-1024     512-2048
- * PCIXCC_MCL2   512-2048     no change (applying this MCL == card is MCL3+)
- * PCIXCC_MCL3   512-2048     128-2048
+ * PCIXCC_MCL2   512-2048     ----- (applying any GA LIC will make an MCL3 card)
+ * PCIXCC_MCL3   -----        128-2048
  * CEX2C         512-2048     128-2048
+ * CEX2A          ??-2048     same (the lower limit is less than 128 bit...)
  *
  * 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
@@ -1077,11 +1007,13 @@ static inline int
 select_device_type(int *dev_type_p, int bytelength)
 {
        static int count = 0;
-       int PCICA_avail, PCIXCC_MCL3_avail, CEX2C_avail, index_to_use;
+       int PCICA_avail, PCIXCC_MCL3_avail, CEX2C_avail, CEX2A_avail,
+           index_to_use;
        struct status *stat;
        if ((*dev_type_p != PCICC) && (*dev_type_p != PCICA) &&
            (*dev_type_p != PCIXCC_MCL2) && (*dev_type_p != PCIXCC_MCL3) &&
-           (*dev_type_p != CEX2C) && (*dev_type_p != ANYDEV))
+           (*dev_type_p != CEX2C) && (*dev_type_p != CEX2A) &&
+           (*dev_type_p != ANYDEV))
                return -1;
        if (*dev_type_p != ANYDEV) {
                stat = &z90crypt.hdware_info->type_mask[*dev_type_p];
@@ -1091,7 +1023,13 @@ select_device_type(int *dev_type_p, int bytelength)
                return -1;
        }
 
-       /* Assumption: PCICA, PCIXCC_MCL3, and CEX2C are all similar in speed */
+       /**
+        * Assumption: PCICA, PCIXCC_MCL3, CEX2C, and CEX2A are all similar in
+        * speed.
+        *
+        * PCICA and CEX2A do NOT co-exist, so it would be either one or the
+        * other present.
+        */
        stat = &z90crypt.hdware_info->type_mask[PCICA];
        PCICA_avail = stat->st_count -
                        (stat->disabled_count + stat->user_disabled_count);
@@ -1101,29 +1039,38 @@ select_device_type(int *dev_type_p, int bytelength)
        stat = &z90crypt.hdware_info->type_mask[CEX2C];
        CEX2C_avail = stat->st_count -
                        (stat->disabled_count + stat->user_disabled_count);
-       if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail) {
+       stat = &z90crypt.hdware_info->type_mask[CEX2A];
+       CEX2A_avail = stat->st_count -
+                       (stat->disabled_count + stat->user_disabled_count);
+       if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail || CEX2A_avail) {
                /**
-                * bitlength is a factor, PCICA is the most capable, even with
-                * the new MCL.
+                * bitlength is a factor, PCICA or CEX2A are the most capable,
+                * even with the new MCL for PCIXCC.
                 */
                if ((bytelength < PCIXCC_MIN_MOD_SIZE) ||
                    (!ext_bitlens && (bytelength < OLD_PCIXCC_MIN_MOD_SIZE))) {
-                       if (!PCICA_avail)
-                               return -1;
-                       else {
+                       if (PCICA_avail) {
                                *dev_type_p = PCICA;
                                return 0;
                        }
+                       if (CEX2A_avail) {
+                               *dev_type_p = CEX2A;
+                               return 0;
+                       }
+                       return -1;
                }
 
                index_to_use = count % (PCICA_avail + PCIXCC_MCL3_avail +
-                                       CEX2C_avail);
+                                       CEX2C_avail + CEX2A_avail);
                if (index_to_use < PCICA_avail)
                        *dev_type_p = PCICA;
                else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail))
                        *dev_type_p = PCIXCC_MCL3;
-               else
+               else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail +
+                                        CEX2C_avail))
                        *dev_type_p = CEX2C;
+               else
+                       *dev_type_p = CEX2A;
                count++;
                return 0;
        }
@@ -1428,7 +1375,7 @@ build_caller(struct work_element *we_p, short function)
 
        if ((we_p->devtype != PCICC) && (we_p->devtype != PCICA) &&
            (we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) &&
-           (we_p->devtype != CEX2C))
+           (we_p->devtype != CEX2C) && (we_p->devtype != CEX2A))
                return SEN_NOT_AVAIL;
 
        memcpy(caller_p->caller_id, we_p->caller_id,
@@ -1497,7 +1444,8 @@ get_crypto_request_buffer(struct work_element *we_p)
 
        if ((we_p->devtype != PCICA) && (we_p->devtype != PCICC) &&
            (we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) &&
-           (we_p->devtype != CEX2C) && (we_p->devtype != ANYDEV)) {
+           (we_p->devtype != CEX2C) && (we_p->devtype != CEX2A) &&
+           (we_p->devtype != ANYDEV)) {
                PRINTK("invalid device type\n");
                return SEN_USER_ERROR;
        }
@@ -1572,8 +1520,9 @@ get_crypto_request_buffer(struct work_element *we_p)
 
        function = PCI_FUNC_KEY_ENCRYPT;
        switch (we_p->devtype) {
-       /* PCICA does everything with a simple RSA mod-expo operation */
+       /* PCICA and CEX2A do everything with a simple RSA mod-expo operation */
        case PCICA:
+       case CEX2A:
                function = PCI_FUNC_KEY_ENCRYPT;
                break;
        /**
@@ -1731,7 +1680,8 @@ z90crypt_rsa(struct priv_data *private_data_p, pid_t pid,
                 * trigger a fallback to software.
                 */
                case -EINVAL:
-                       if (we_p->devtype != PCICA)
+                       if ((we_p->devtype != PCICA) &&
+                           (we_p->devtype != CEX2A))
                                rv = -EGETBUFF;
                        break;
                case -ETIMEOUT:
@@ -1848,6 +1798,12 @@ z90crypt_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        ret = -EFAULT;
                break;
 
+       case Z90STAT_CEX2ACOUNT:
+               tempstat = get_status_CEX2Acount();
+               if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0)
+                       ret = -EFAULT;
+               break;
+
        case Z90STAT_REQUESTQ_COUNT:
                tempstat = get_status_requestq_count();
                if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0)
@@ -2088,6 +2044,8 @@ z90crypt_status(char *resp_buff, char **start, off_t offset,
                get_status_PCIXCCMCL3count());
        len += sprintf(resp_buff+len, "CEX2C count: %d\n",
                get_status_CEX2Ccount());
+       len += sprintf(resp_buff+len, "CEX2A count: %d\n",
+               get_status_CEX2Acount());
        len += sprintf(resp_buff+len, "requestq count: %d\n",
                get_status_requestq_count());
        len += sprintf(resp_buff+len, "pendingq count: %d\n",
@@ -2095,8 +2053,8 @@ z90crypt_status(char *resp_buff, char **start, off_t offset,
        len += sprintf(resp_buff+len, "Total open handles: %d\n\n",
                get_status_totalopen_count());
        len += sprinthx(
-               "Online devices: 1: PCICA, 2: PCICC, 3: PCIXCC (MCL2), "
-               "4: PCIXCC (MCL3), 5: CEX2C",
+               "Online devices: 1=PCICA 2=PCICC 3=PCIXCC(MCL2) "
+               "4=PCIXCC(MCL3) 5=CEX2C 6=CEX2A",
                resp_buff+len,
                get_status_status_mask(workarea),
                Z90CRYPT_NUM_APS);
@@ -2144,73 +2102,15 @@ enable_card(int card_index)
        z90crypt.hdware_info->type_mask[devp->dev_type].user_disabled_count--;
 }
 
-static inline int
-scan_char(unsigned char *bf, unsigned int len,
-         unsigned int *offs, unsigned int *p_eof, unsigned char c)
-{
-       unsigned int i, found;
-
-       found = 0;
-       for (i = 0; i < len; i++) {
-               if (bf[i] == c) {
-                       found = 1;
-                       break;
-               }
-               if (bf[i] == '\0') {
-                       *p_eof = 1;
-                       break;
-               }
-               if (bf[i] == '\n') {
-                       break;
-               }
-       }
-       *offs = i+1;
-       return found;
-}
-
-static inline int
-scan_string(unsigned char *bf, unsigned int len,
-           unsigned int *offs, unsigned int *p_eof, unsigned char *s)
-{
-       unsigned int temp_len, temp_offs, found, eof;
-
-       temp_len = temp_offs = found = eof = 0;
-       while (!eof && !found) {
-               found = scan_char(bf+temp_len, len-temp_len,
-                                 &temp_offs, &eof, *s);
-
-               temp_len += temp_offs;
-               if (eof) {
-                       found = 0;
-                       break;
-               }
-
-               if (found) {
-                       if (len >= temp_offs+strlen(s)) {
-                               found = !strncmp(bf+temp_len-1, s, strlen(s));
-                               if (found) {
-                                       *offs = temp_len+strlen(s)-1;
-                                       break;
-                               }
-                       } else {
-                               found = 0;
-                               *p_eof = 1;
-                               break;
-                       }
-               }
-       }
-       return found;
-}
-
 static int
 z90crypt_status_write(struct file *file, const char __user *buffer,
                      unsigned long count, void *data)
 {
-       int i, j, len, offs, found, eof;
-       unsigned char *lbuf;
+       int j, eol;
+       unsigned char *lbuf, *ptr;
        unsigned int local_count;
 
-#define LBUFSIZE 600
+#define LBUFSIZE 1200
        lbuf = kmalloc(LBUFSIZE, GFP_KERNEL);
        if (!lbuf) {
                PRINTK("kmalloc failed!\n");
@@ -2227,49 +2127,47 @@ z90crypt_status_write(struct file *file, const char __user *buffer,
                return -EFAULT;
        }
 
-       lbuf[local_count-1] = '\0';
+       lbuf[local_count] = '\0';
 
-       len = 0;
-       eof = 0;
-       found = 0;
-       while (!eof) {
-               found = scan_string(lbuf+len, local_count-len, &offs, &eof,
-                                   "Online devices");
-               len += offs;
-               if (found == 1)
-                       break;
+       ptr = strstr(lbuf, "Online devices");
+       if (ptr == 0) {
+               PRINTK("Unable to parse data (missing \"Online devices\")\n");
+               kfree(lbuf);
+               return count;
        }
 
-       if (eof) {
+       ptr = strstr(ptr, "\n");
+       if (ptr == 0) {
+               PRINTK("Unable to parse data (missing newline after \"Online devices\")\n");
                kfree(lbuf);
                return count;
        }
+       ptr++;
 
-       if (found)
-               found = scan_char(lbuf+len, local_count-len, &offs, &eof, '\n');
-
-       if (!found || eof) {
+       if (strstr(ptr, "Waiting work element counts") == NULL) {
+               PRINTK("Unable to parse data (missing \"Waiting work element counts\")\n");
                kfree(lbuf);
                return count;
        }
 
-       len += offs;
        j = 0;
-       for (i = 0; i < 80; i++) {
-               switch (*(lbuf+len+i)) {
+       eol = 0;
+       while ((j < 64) && (*ptr != '\0')) {
+               switch (*ptr) {
                case '\t':
                case ' ':
                        break;
                case '\n':
                default:
-                       eof = 1;
+                       eol = 1;
                        break;
-               case '0':
-               case '1':
-               case '2':
-               case '3':
-               case '4':
-               case '5':
+               case '0':       // no device
+               case '1':       // PCICA
+               case '2':       // PCICC
+               case '3':       // PCIXCC_MCL2
+               case '4':       // PCIXCC_MCL3
+               case '5':       // CEX2C
+               case '6':       // CEX2A
                        j++;
                        break;
                case 'd':
@@ -2283,8 +2181,9 @@ z90crypt_status_write(struct file *file, const char __user *buffer,
                        j++;
                        break;
                }
-               if (eof)
+               if (eol)
                        break;
+               ptr++;
        }
 
        kfree(lbuf);
@@ -2837,13 +2736,11 @@ create_z90crypt(int *cdx_p)
        z90crypt.max_count = Z90CRYPT_NUM_DEVS;
        z90crypt.cdx = *cdx_p;
 
-       hdware_blk_p = (struct hdware_block *)
-               kmalloc(sizeof(struct hdware_block), GFP_ATOMIC);
+       hdware_blk_p = kzalloc(sizeof(struct hdware_block), GFP_ATOMIC);
        if (!hdware_blk_p) {
                PDEBUG("kmalloc for hardware block failed\n");
                return ENOMEM;
        }
-       memset(hdware_blk_p, 0x00, sizeof(struct hdware_block));
        z90crypt.hdware_info = hdware_blk_p;
 
        return 0;
@@ -3078,12 +2975,11 @@ create_crypto_device(int index)
                total_size = sizeof(struct device) +
                             z90crypt.q_depth_array[index] * sizeof(int);
 
-               dev_ptr = (struct device *) kmalloc(total_size, GFP_ATOMIC);
+               dev_ptr = kzalloc(total_size, GFP_ATOMIC);
                if (!dev_ptr) {
                        PRINTK("kmalloc device %d failed\n", index);
                        return ENOMEM;
                }
-               memset(dev_ptr, 0, total_size);
                dev_ptr->dev_resp_p = kmalloc(MAX_RESPONSE_SIZE, GFP_ATOMIC);
                if (!dev_ptr->dev_resp_p) {
                        kfree(dev_ptr);
@@ -3136,7 +3032,9 @@ create_crypto_device(int index)
                        z90crypt.hdware_info->device_type_array[index] = 4;
                else if (deviceType == CEX2C)
                        z90crypt.hdware_info->device_type_array[index] = 5;
-               else
+               else if (deviceType == CEX2A)
+                       z90crypt.hdware_info->device_type_array[index] = 6;
+               else // No idea how this would happen.
                        z90crypt.hdware_info->device_type_array[index] = -1;
        }
 
@@ -3178,8 +3076,7 @@ destroy_crypto_device(int index)
        if (dev_ptr) {
                disabledFlag = dev_ptr->disabled;
                t = dev_ptr->dev_type;
-               if (dev_ptr->dev_resp_p)
-                       kfree(dev_ptr->dev_resp_p);
+               kfree(dev_ptr->dev_resp_p);
                kfree(dev_ptr);
        } else {
                disabledFlag = 0;
@@ -3207,11 +3104,11 @@ static void
 destroy_z90crypt(void)
 {
        int i;
+
        for (i = 0; i < z90crypt.max_count; i++)
                if (z90crypt.device_p[i])
                        destroy_crypto_device(i);
-       if (z90crypt.hdware_info)
-               kfree((void *)z90crypt.hdware_info);
+       kfree(z90crypt.hdware_info);
        memset((void *)&z90crypt, 0, sizeof(z90crypt));
 }
 
@@ -3479,45 +3376,5 @@ probe_PCIXCC_type(struct device *devPtr)
        return rv;
 }
 
-#ifdef Z90CRYPT_USE_HOTPLUG
-static void
-z90crypt_hotplug_event(int dev_major, int dev_minor, int action)
-{
-#ifdef CONFIG_HOTPLUG
-       char *argv[3];
-       char *envp[6];
-       char  major[20];
-       char  minor[20];
-
-       sprintf(major, "MAJOR=%d", dev_major);
-       sprintf(minor, "MINOR=%d", dev_minor);
-
-       argv[0] = hotplug_path;
-       argv[1] = "z90crypt";
-       argv[2] = 0;
-
-       envp[0] = "HOME=/";
-       envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-
-       switch (action) {
-       case Z90CRYPT_HOTPLUG_ADD:
-               envp[2] = "ACTION=add";
-               break;
-       case Z90CRYPT_HOTPLUG_REMOVE:
-               envp[2] = "ACTION=remove";
-               break;
-       default:
-               BUG();
-               break;
-       }
-       envp[3] = major;
-       envp[4] = minor;
-       envp[5] = 0;
-
-       call_usermodehelper(argv[0], argv, envp, 0);
-#endif
-}
-#endif
-
 module_init(z90crypt_init_module);
 module_exit(z90crypt_cleanup_module);