- Add back code from the original aeon driver to handle missed interrupts by
authorjason <jason@openbsd.org>
Mon, 10 Apr 2000 18:40:47 +0000 (18:40 +0000)
committerjason <jason@openbsd.org>
Mon, 10 Apr 2000 18:40:47 +0000 (18:40 +0000)
enabling interrupts when the command queue has more than one entry.
- fix comment on hifn_newsession to reflect reality
- allocate session structure in softc
- compute a random IV when a session is created and try to chain from a
software kept IV for subsequent packets
- add handling of CRD_F_EXPLICIT

sys/dev/pci/hifn7751.c
sys/dev/pci/hifn7751reg.h
sys/dev/pci/hifn7751var.h

index b341037..74be7d6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: hifn7751.c,v 1.26 2000/04/05 16:52:22 jason Exp $     */
+/*     $OpenBSD: hifn7751.c,v 1.27 2000/04/10 18:40:47 jason Exp $     */
 
 /*
  * Invertex AEON / Hi/fn 7751 driver
@@ -1093,6 +1093,16 @@ hifn_crypto(sc, cmd)
        dma->cmdr[cmdi].l = cmdlen | HIFN_D_VALID | HIFN_D_LAST |
            HIFN_D_MASKDONEIRQ;
        dma->cmdu++;
+
+       /*
+        * We don't worry about missing an interrupt (which a "command wait"
+        * interrupt salvages us from), unless there is more than one command
+        * in the queue.
+        */
+       if (dma->cmdu > 1)
+               WRITE_REG_1(sc, HIFN_1_DMA_IER,
+                   HIFN_DMAIER_C_WAIT | HIFN_DMAIER_R_DONE);
+
        hifnstats.hst_ipackets++;
 
        for (i = 0; i < cmd->src_npa; i++) {
@@ -1171,13 +1181,22 @@ hifn_intr(arg)
            dma->cmdu, dma->srcu, dma->dstu, dma->resu);
 #endif
 
-       if ((dmacsr & HIFN_DMACSR_R_DONE) == 0)
+       if ((dmacsr & (HIFN_DMACSR_R_DONE | HIFN_DMACSR_C_WAIT)) == 0)
                return (0);
 
        if (dma->resu > HIFN_D_RES_RSIZE)
                printf("%s: Internal Error -- ring overflow\n",
                    sc->sc_dv.dv_xname);
 
+       if ((dmacsr & HIFN_DMACSR_C_WAIT) && (dma->cmdu == 0)) {
+               /*
+                * If no slots to process and we receive a "waiting on
+                * command" interrupt, we disable the "waiting on command"
+                * (by clearing it).
+                */
+               WRITE_REG_1(sc, HIFN_1_DMA_IER, HIFN_DMAIER_R_DONE);
+       }
+
        while (dma->resu > 0) {
                struct hifn_command *cmd;
                u_int8_t *macbuf = NULL;
@@ -1230,9 +1249,11 @@ hifn_intr(arg)
        dma->cmdk = i; dma->cmdu = u;
 
        /*
-        * Clear "result done" flags in status register.
+        * Clear "result done" and "command wait" flags in status register.
+        * If we still have slots to process and we received a "command wait"
+        * interrupt, this will interupt us again.
         */
-       WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_R_DONE);
+       WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_R_DONE|HIFN_DMACSR_C_WAIT);
        return (1);
 }
 
@@ -1240,8 +1261,6 @@ hifn_intr(arg)
  * Allocate a new 'session' and return an encoded session id.  'sidp'
  * contains our registration id, and should contain an encoded session
  * id on successful allocation.
- * XXX Mac and encrypt keys should be sent to context ram and should
- * XXX maintain some sort of state.
  */
 int
 hifn_newsession(sidp, cri)
@@ -1265,16 +1284,8 @@ hifn_newsession(sidp, cri)
        if (sc == NULL)
                return (EINVAL);
 
-       if (sc->sc_sessions == NULL) {
-               sc->sc_sessions = (u_int8_t *)malloc(sc->sc_maxses,
-                   M_DEVBUF, M_NOWAIT);
-               if (sc->sc_sessions == NULL)
-                       return (ENOMEM);
-               bzero(sc->sc_sessions, sc->sc_maxses);
-       }
-
        for (i = 0; i < sc->sc_maxses; i++) {
-               if (sc->sc_sessions[i] == 0)
+               if (sc->sc_sessions[i].hs_flags == 0)
                        break;
        }
        if (i == sc->sc_maxses)
@@ -1300,7 +1311,8 @@ hifn_newsession(sidp, cri)
                return (EINVAL);
 
        *sidp = HIFN_SID(sc->sc_dv.dv_unit, i);
-       sc->sc_sessions[i] = 1;
+       sc->sc_sessions[i].hs_flags = 1;
+       get_random_bytes(sc->sc_sessions[i].hs_iv, HIFN_IV_LENGTH);
 
        return (0);
 }
@@ -1323,10 +1335,10 @@ hifn_freesession(sid)
 
        sc = hifn_cd.cd_devs[card];
        session = HIFN_SESSION(sid);
-       if (session >= sc->sc_maxses || sc->sc_sessions == NULL)
+       if (session >= sc->sc_maxses)
                return (EINVAL);
 
-       sc->sc_sessions[session] = 0;
+       sc->sc_sessions[session].hs_flags = 0;
        return (0);
 }
 
@@ -1387,9 +1399,9 @@ hifn_process(crp)
                        maccrd = crd1;
                        enccrd = NULL;
                        cmd->flags |= HIFN_ENCODE | HIFN_MAC_TRUNC;
-                       if (sc->sc_sessions[session] == 1) {
+                       if (sc->sc_sessions[session].hs_flags == 1) {
                                cmd->flags |= HIFN_MAC_NEW_KEY;
-                               sc->sc_sessions[session] = 2;
+                               sc->sc_sessions[session].hs_flags = 2;
                        }
                }
                else if (crd1->crd_alg == CRYPTO_DES_CBC ||
@@ -1398,9 +1410,9 @@ hifn_process(crp)
                                cmd->flags |= HIFN_ENCODE;
                        else
                                cmd->flags |= HIFN_DECODE;
-                       if (sc->sc_sessions[session] == 1) {
+                       if (sc->sc_sessions[session].hs_flags == 1) {
                                cmd->flags |= HIFN_CRYPT_NEW_KEY;
-                               sc->sc_sessions[session] = 2;
+                               sc->sc_sessions[session].hs_flags = 2;
                        }
                        maccrd = NULL;
                        enccrd = crd1;
@@ -1437,22 +1449,31 @@ hifn_process(crp)
                        goto errout;
                }
 
-               if (sc->sc_sessions[session] == 1) {
+               if (sc->sc_sessions[session].hs_flags == 1) {
                        cmd->flags |= HIFN_MAC_NEW_KEY | HIFN_CRYPT_NEW_KEY;
-                       sc->sc_sessions[session] = 2;
+                       sc->sc_sessions[session].hs_flags = 2;
                }
        }
 
        if (enccrd) {
-               if ((enccrd->crd_flags & (CRD_F_ENCRYPT | CRD_F_IV_PRESENT)) ==
-                   CRD_F_ENCRYPT) {
-                       get_random_bytes(cmd->iv, HIFN_IV_LENGTH);
-                       m_copyback(cmd->src_m, enccrd->crd_inject,
-                                  HIFN_IV_LENGTH, cmd->iv);
+               if (enccrd->crd_flags & CRD_F_ENCRYPT) {
+                       if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
+                               bcopy(enccrd->crd_iv, cmd->iv, HIFN_IV_LENGTH);
+                       else
+                               bcopy(sc->sc_sessions[session].hs_iv,
+                                   cmd->iv, HIFN_IV_LENGTH);
+
+                       if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0)
+                               m_copyback(cmd->src_m, enccrd->crd_inject,
+                                   HIFN_IV_LENGTH, cmd->iv);
+               }
+               else {
+                       if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
+                               bcopy(enccrd->crd_iv, cmd->iv, HIFN_IV_LENGTH);
+                       else
+                               m_copydata(cmd->src_m, enccrd->crd_inject,
+                                   HIFN_IV_LENGTH, cmd->iv);
                }
-               else
-                       m_copydata(cmd->src_m, enccrd->crd_inject,
-                                  HIFN_IV_LENGTH, cmd->iv);
 
                if (enccrd->crd_alg == CRYPTO_DES_CBC)
                        cmd->flags |= HIFN_CRYPT_DES;
@@ -1479,6 +1500,7 @@ hifn_process(crp)
        cmd->dest_ready_callback = hifn_callback;
        cmd->private_data = (u_long)crp;
        cmd->session_num = session;
+       cmd->softc = sc;
 
        if (hifn_crypto(sc, cmd) == 0)
                return (0);
@@ -1509,6 +1531,19 @@ hifn_callback(cmd, macbuf)
                crp->crp_buf = (caddr_t)cmd->dst_m;
        }
 
+       if ((cmd->flags & HIFN_ENCODE) &&
+           ((cmd->flags & HIFN_CRYPT_DES) || (cmd->flags & HIFN_CRYPT_3DES))) {
+               for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
+                       if (crd->crd_alg != CRYPTO_DES_CBC &&
+                           crd->crd_alg != CRYPTO_3DES_CBC)
+                               continue;
+                       m_copydata((struct mbuf *)crp->crp_buf,
+                           crd->crd_skip + crd->crd_len - 8, 8,
+                           cmd->softc->sc_sessions[cmd->session_num].hs_iv);
+                       break;
+               }
+       }
+
        if (macbuf != NULL) {
                for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
                        if (crd->crd_alg != CRYPTO_MD5_HMAC96 &&
index 6bb8a16..7726a04 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: hifn7751reg.h,v 1.12 2000/04/05 16:34:07 jason Exp $  */
+/*     $OpenBSD: hifn7751reg.h,v 1.13 2000/04/10 18:40:47 jason Exp $  */
 
 /*
  * Invertex AEON / Hi/fn 7751 driver
@@ -119,6 +119,11 @@ struct hifn_dma {
        int             cmdk, srck, dstk, resk;
 };
 
+struct hifn_session {
+       int hs_flags;
+       u_int8_t hs_iv[HIFN_IV_LENGTH];
+};
+
 /*
  * Holds data specific to a single HIFN board.
  */
@@ -135,7 +140,7 @@ struct hifn_softc {
        int32_t sc_cid;
        int sc_maxses;
        int sc_ramsize;
-       u_int8_t *sc_sessions;
+       struct hifn_session sc_sessions[2048];
 };
 
 /*
index 0518e74..3619968 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: hifn7751var.h,v 1.10 2000/04/04 20:16:33 jason Exp $  */
+/*     $OpenBSD: hifn7751var.h,v 1.11 2000/04/10 18:40:47 jason Exp $  */
 
 /*
  * Invertex AEON / Hi/fn 7751 driver
@@ -201,6 +201,7 @@ typedef struct hifn_command {
 
        void (*dest_ready_callback)(struct hifn_command *, u_int8_t *);
        u_long private_data;
+       struct hifn_softc *softc;
 } hifn_command_t;
 
 /*