Print this page
4031 scsa1394 violates DDI scsi_pkt(9S) allocation rules

@@ -54,12 +54,10 @@
 static void     scsa1394_detach_1394(scsa1394_state_t *);
 static int      scsa1394_attach_threads(scsa1394_state_t *);
 static void     scsa1394_detach_threads(scsa1394_state_t *);
 static int      scsa1394_attach_scsa(scsa1394_state_t *);
 static void     scsa1394_detach_scsa(scsa1394_state_t *);
-static int      scsa1394_create_cmd_cache(scsa1394_state_t *);
-static void     scsa1394_destroy_cmd_cache(scsa1394_state_t *);
 static int      scsa1394_add_events(scsa1394_state_t *);
 static void     scsa1394_remove_events(scsa1394_state_t *);
 
 /* device configuration */
 static int      scsa1394_scsi_bus_config(dev_info_t *, uint_t,

@@ -96,15 +94,10 @@
 static void     scsa1394_scsi_dmafree(struct scsi_address *, struct scsi_pkt *);
 static void     scsa1394_scsi_sync_pkt(struct scsi_address *,
                 struct scsi_pkt *);
 
 /* pkt resource allocation routines */
-static int      scsa1394_cmd_cache_constructor(void *, void *, int);
-static void     scsa1394_cmd_cache_destructor(void *, void *);
-static int      scsa1394_cmd_ext_alloc(scsa1394_state_t *, scsa1394_cmd_t *,
-                int);
-static void     scsa1394_cmd_ext_free(scsa1394_state_t *, scsa1394_cmd_t *);
 static int      scsa1394_cmd_cdb_dma_alloc(scsa1394_state_t *, scsa1394_cmd_t *,
                 int, int (*)(), caddr_t);
 static void     scsa1394_cmd_cdb_dma_free(scsa1394_state_t *, scsa1394_cmd_t *);
 static int      scsa1394_cmd_buf_dma_alloc(scsa1394_state_t *, scsa1394_cmd_t *,
                 int, int (*)(), caddr_t, struct buf *);

@@ -304,17 +297,12 @@
         if (scsa1394_attach_scsa(sp) != DDI_SUCCESS) {
                 scsa1394_cleanup(sp, 4);
                 return (DDI_FAILURE);
         }
 
-        if (scsa1394_create_cmd_cache(sp) != DDI_SUCCESS) {
-                scsa1394_cleanup(sp, 5);
-                return (DDI_FAILURE);
-        }
-
         if (scsa1394_add_events(sp) != DDI_SUCCESS) {
-                scsa1394_cleanup(sp, 6);
+                scsa1394_cleanup(sp, 5);
                 return (DDI_FAILURE);
         }
 
         /* prevent async PM changes until we are done */
         (void) pm_busy_component(dip, 0);

@@ -457,15 +445,12 @@
 
         switch (level) {
         default:
                 scsa1394_remove_events(sp);
                 /* FALLTHRU */
-        case 6:
-                scsa1394_detach_scsa(sp);
-                /* FALLTHRU */
         case 5:
-                scsa1394_destroy_cmd_cache(sp);
+                scsa1394_detach_scsa(sp);
                 /* FALLTHRU */
         case 4:
                 scsa1394_detach_threads(sp);
                 /* FALLTHRU */
         case 3:

@@ -595,30 +580,10 @@
 
         scsi_hba_tran_free(sp->s_tran);
 }
 
 static int
-scsa1394_create_cmd_cache(scsa1394_state_t *sp)
-{
-        char    name[64];
-
-        (void) sprintf(name, "scsa1394%d_cache", sp->s_instance);
-        sp->s_cmd_cache = kmem_cache_create(name,
-            SCSA1394_CMD_SIZE, sizeof (void *),
-            scsa1394_cmd_cache_constructor, scsa1394_cmd_cache_destructor,
-            NULL, (void *)sp, NULL, 0);
-
-        return ((sp->s_cmd_cache == NULL) ? DDI_FAILURE : DDI_SUCCESS);
-}
-
-static void
-scsa1394_destroy_cmd_cache(scsa1394_state_t *sp)
-{
-        kmem_cache_destroy(sp->s_cmd_cache);
-}
-
-static int
 scsa1394_add_events(scsa1394_state_t *sp)
 {
         ddi_eventcookie_t       br_evc, rem_evc, ins_evc;
 
         if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_BUS_RESET_EVENT,

@@ -1293,40 +1258,21 @@
         /*
          * allocate cmd space
          */
         if (pkt == NULL) {
                 is_new = B_TRUE;
-                if ((cmd = kmem_cache_alloc(sp->s_cmd_cache, kf)) == NULL) {
+                pkt = scsi_hba_pkt_alloc(NULL, ap, max(SCSI_CDB_SIZE, cmdlen),
+                    statuslen, tgtlen, sizeof (scsa1394_cmd_t), callback, arg);
+                if (!pkt)
                         return (NULL);
-                }
 
                 /* initialize cmd */
-                pkt = &cmd->sc_scsi_pkt;
-                pkt->pkt_ha_private     = cmd;
-                pkt->pkt_address        = *ap;
-                pkt->pkt_private        = cmd->sc_priv;
-                pkt->pkt_scbp           = (uchar_t *)&cmd->sc_scb;
-                pkt->pkt_cdbp           = (uchar_t *)&cmd->sc_pkt_cdb;
-                pkt->pkt_resid          = 0;
-
+                cmd = pkt->pkt_ha_private;
                 cmd->sc_lun             = lp;
                 cmd->sc_pkt             = pkt;
-                cmd->sc_cdb_len         = cmdlen;
-                cmd->sc_scb_len         = statuslen;
-                cmd->sc_priv_len        = tgtlen;
-
-                /* need external space? */
-                if ((cmdlen > sizeof (cmd->sc_pkt_cdb)) ||
-                    (statuslen > sizeof (cmd->sc_scb)) ||
-                    (tgtlen > sizeof (cmd->sc_priv))) {
-                        if (scsa1394_cmd_ext_alloc(sp, cmd, kf) !=
-                            DDI_SUCCESS) {
-                                kmem_cache_free(sp->s_cmd_cache, cmd);
-                                lp->l_stat.stat_err_pkt_kmem_alloc++;
-                                return (NULL);
-                        }
-                }
+                cmd->sc_orig_cdblen = cmdlen;
+                cmd->sc_task.ts_drv_priv = cmd;
 
                 /* allocate DMA resources for CDB */
                 if (scsa1394_cmd_cdb_dma_alloc(sp, cmd, flags, callback, arg) !=
                     DDI_SUCCESS) {
                         scsa1394_scsi_destroy_pkt(ap, pkt);

@@ -1387,15 +1333,12 @@
         }
         if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_MAPIN) {
                 bp_mapout(cmd->sc_bp);
                 cmd->sc_flags &= ~SCSA1394_CMD_DMA_BUF_MAPIN;
         }
-        if (cmd->sc_flags & SCSA1394_CMD_EXT) {
-                scsa1394_cmd_ext_free(sp, cmd);
-        }
 
-        kmem_cache_free(sp->s_cmd_cache, cmd);
+        scsi_hba_pkt_free(ap, pkt);
 }
 
 static void
 scsa1394_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
 {

@@ -1411,85 +1354,10 @@
         }
 }
 
 /*ARGSUSED*/
 static int
-scsa1394_cmd_cache_constructor(void *buf, void *cdrarg, int kf)
-{
-        scsa1394_cmd_t  *cmd = buf;
-
-        bzero(buf, SCSA1394_CMD_SIZE);
-        cmd->sc_task.ts_drv_priv = cmd;
-
-        return (0);
-}
-
-/*ARGSUSED*/
-static void
-scsa1394_cmd_cache_destructor(void *buf, void *cdrarg)
-{
-}
-
-/*
- * allocate and deallocate external cmd space (ie. not part of scsa1394_cmd_t)
- * for non-standard length cdb, pkt_private, status areas
- */
-static int
-scsa1394_cmd_ext_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd, int kf)
-{
-        struct scsi_pkt *pkt = cmd->sc_pkt;
-        void            *buf;
-
-        if (cmd->sc_cdb_len > sizeof (cmd->sc_pkt_cdb)) {
-                if ((buf = kmem_zalloc(cmd->sc_cdb_len, kf)) == NULL) {
-                        return (DDI_FAILURE);
-                }
-                pkt->pkt_cdbp = buf;
-                cmd->sc_flags |= SCSA1394_CMD_CDB_EXT;
-        }
-
-        if (cmd->sc_scb_len > sizeof (cmd->sc_scb)) {
-                if ((buf = kmem_zalloc(cmd->sc_scb_len, kf)) == NULL) {
-                        scsa1394_cmd_ext_free(sp, cmd);
-                        return (DDI_FAILURE);
-                }
-                pkt->pkt_scbp = buf;
-                cmd->sc_flags |= SCSA1394_CMD_SCB_EXT;
-        }
-
-        if (cmd->sc_priv_len > sizeof (cmd->sc_priv)) {
-                if ((buf = kmem_zalloc(cmd->sc_priv_len, kf)) == NULL) {
-                        scsa1394_cmd_ext_free(sp, cmd);
-                        return (DDI_FAILURE);
-                }
-                pkt->pkt_private = buf;
-                cmd->sc_flags |= SCSA1394_CMD_PRIV_EXT;
-        }
-
-        return (DDI_SUCCESS);
-}
-
-/*ARGSUSED*/
-static void
-scsa1394_cmd_ext_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
-{
-        struct scsi_pkt *pkt = cmd->sc_pkt;
-
-        if (cmd->sc_flags & SCSA1394_CMD_CDB_EXT) {
-                kmem_free(pkt->pkt_cdbp, cmd->sc_cdb_len);
-        }
-        if (cmd->sc_flags & SCSA1394_CMD_SCB_EXT) {
-                kmem_free(pkt->pkt_scbp, cmd->sc_scb_len);
-        }
-        if (cmd->sc_flags & SCSA1394_CMD_PRIV_EXT) {
-                kmem_free(pkt->pkt_private, cmd->sc_priv_len);
-        }
-        cmd->sc_flags &= ~SCSA1394_CMD_EXT;
-}
-
-/*ARGSUSED*/
-static int
 scsa1394_cmd_cdb_dma_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd,
     int flags, int (*callback)(), caddr_t arg)
 {
         if (sbp2_task_orb_alloc(cmd->sc_lun->l_lun, &cmd->sc_task,
             sizeof (scsa1394_cmd_orb_t)) != SBP2_SUCCESS) {

@@ -2039,12 +1907,10 @@
 }
 
 static void
 scsa1394_cmd_fill_cdb(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
 {
-        cmd->sc_cdb_actual_len = cmd->sc_cdb_len;
-
         mutex_enter(&lp->l_mutex);
 
         switch (lp->l_dtype_orig) {
         case DTYPE_DIRECT:
         case DTYPE_RODIRECT:

@@ -2078,17 +1944,17 @@
         case SCMD_READ:
                 /* RBC only supports 10-byte read/write */
                 lba = SCSA1394_LBA_6BYTE(pkt);
                 len = SCSA1394_LEN_6BYTE(pkt);
                 opcode = SCMD_READ_G1;
-                cmd->sc_cdb_actual_len = CDB_GROUP1;
+                cmd->sc_orig_cdblen = CDB_GROUP1;
                 break;
         case SCMD_WRITE:
                 lba = SCSA1394_LBA_6BYTE(pkt);
                 len = SCSA1394_LEN_6BYTE(pkt);
                 opcode = SCMD_WRITE_G1;
-                cmd->sc_cdb_actual_len = CDB_GROUP1;
+                cmd->sc_orig_cdblen = CDB_GROUP1;
                 break;
         case SCMD_READ_G1:
         case SCMD_READ_LONG:
                 lba = SCSA1394_LBA_10BYTE(pkt);
                 len = SCSA1394_LEN_10BYTE(pkt);

@@ -2143,22 +2009,17 @@
                 /*
                  * We rewrite READ/WRITE G0 commands as READ/WRITE G1.
                  * Build new cdb from scatch.
                  * The lba and length fields is updated below.
                  */
-                bzero(cmd->sc_cdb, cmd->sc_cdb_actual_len);
+                bzero(pkt->pkt_cdbp, cmd->sc_orig_cdblen);
                 break;
         default:
-                /*
-                 * Copy the non lba/len fields.
-                 * The lba and length fields is updated below.
-                 */
-                bcopy(pkt->pkt_cdbp, cmd->sc_cdb, cmd->sc_cdb_actual_len);
                 break;
         }
 
-        cmd->sc_cdb[0] = (uchar_t)opcode;
+        pkt->pkt_cdbp[0] = (uchar_t)opcode;
         scsa1394_cmd_fill_cdb_lba(cmd, lba);
         switch (opcode) {
         case SCMD_READ_CD:
                 scsa1394_cmd_fill_read_cd_cdb_len(cmd, len);
                 break;

@@ -2174,55 +2035,59 @@
 
 /*ARGSUSED*/
 static void
 scsa1394_cmd_fill_cdb_other(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
 {
-        struct scsi_pkt *pkt = CMD2PKT(cmd);
-
         cmd->sc_xfer_bytes = cmd->sc_win_len;
         cmd->sc_xfer_blks = cmd->sc_xfer_bytes / lp->l_lba_size;
         cmd->sc_total_blks = cmd->sc_xfer_blks;
         cmd->sc_lba = 0;
-
-        bcopy(pkt->pkt_cdbp, cmd->sc_cdb, cmd->sc_cdb_len);
 }
 
 /*
  * fill up parts of CDB
  */
 static void
 scsa1394_cmd_fill_cdb_len(scsa1394_cmd_t *cmd, int len)
 {
-        cmd->sc_cdb[7] = len >> 8;
-        cmd->sc_cdb[8] = (uchar_t)len;
+        struct scsi_pkt *pkt = CMD2PKT(cmd);
+
+        pkt->pkt_cdbp[7] = len >> 8;
+        pkt->pkt_cdbp[8] = (uchar_t)len;
 }
 
 static void
 scsa1394_cmd_fill_cdb_lba(scsa1394_cmd_t *cmd, int lba)
 {
-        cmd->sc_cdb[2] = lba >> 24;
-        cmd->sc_cdb[3] = lba >> 16;
-        cmd->sc_cdb[4] = lba >> 8;
-        cmd->sc_cdb[5] = (uchar_t)lba;
+        struct scsi_pkt *pkt = CMD2PKT(cmd);
+
+        pkt->pkt_cdbp[2] = lba >> 24;
+        pkt->pkt_cdbp[3] = lba >> 16;
+        pkt->pkt_cdbp[4] = lba >> 8;
+        pkt->pkt_cdbp[5] = (uchar_t)lba;
         cmd->sc_lba = lba;
 }
 
 static void
 scsa1394_cmd_fill_12byte_cdb_len(scsa1394_cmd_t *cmd, int len)
 {
-        cmd->sc_cdb[6] = len >> 24;
-        cmd->sc_cdb[7] = len >> 16;
-        cmd->sc_cdb[8] = len >> 8;
-        cmd->sc_cdb[9] = (uchar_t)len;
+        struct scsi_pkt *pkt = CMD2PKT(cmd);
+
+        pkt->pkt_cdbp[6] = len >> 24;
+        pkt->pkt_cdbp[7] = len >> 16;
+        pkt->pkt_cdbp[8] = len >> 8;
+        pkt->pkt_cdbp[9] = (uchar_t)len;
 }
 
 static void
 scsa1394_cmd_fill_read_cd_cdb_len(scsa1394_cmd_t *cmd, int len)
 {
-        cmd->sc_cdb[6] = len >> 16;
-        cmd->sc_cdb[7] = len >> 8;
-        cmd->sc_cdb[8] = (uchar_t)len;
+        struct scsi_pkt *pkt = CMD2PKT(cmd);
+
+        pkt->pkt_cdbp[6] = len >> 16;
+        pkt->pkt_cdbp[7] = len >> 8;
+        pkt->pkt_cdbp[8] = (uchar_t)len;
 }
 
 /*
  * For SCMD_READ_CD, figure out the block size based on expected sector type.
  * See MMC SCSI Specs section 6.1.15

@@ -2446,11 +2311,11 @@
         /* limit xfer length for Symbios workaround */
         if (len * cmd->sc_blk_size > scsa1394_symbios_size_max) {
                 len = scsa1394_symbios_size_max / cmd->sc_blk_size;
         }
 
-        switch (cmd->sc_cdb[0]) {
+        switch (cmd->sc_pkt->pkt_cdbp[0]) {
         case SCMD_READ_CD:
                 scsa1394_cmd_fill_read_cd_cdb_len(cmd, len);
                 break;
         case SCMD_WRITE_G5:
         case SCMD_READ_G5: