Mercurial > illumos > illumos-gate
changeset 11853:2adca8ef2c23
6548768 sata framework calls taskq_dispatch with wrong argument - can cause blocking during interrupt
6443107 sata framework: sata commands processing initiated by scsi target driver cannot use KM_SLEEP flag
author | Phi Tran <Phi.Tran@Sun.COM> |
---|---|
date | Thu, 04 Mar 2010 10:02:10 -0800 |
parents | a53ae86a39c9 |
children | 5351ddd19d45 |
files | usr/src/uts/common/io/sata/impl/sata.c |
diffstat | 1 files changed, 212 insertions(+), 67 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/io/sata/impl/sata.c Thu Mar 04 09:10:33 2010 -0700 +++ b/usr/src/uts/common/io/sata/impl/sata.c Thu Mar 04 10:02:10 2010 -0800 @@ -2439,11 +2439,19 @@ */ if (pkt->pkt_comp != NULL) { /* scsi callback required */ - if (taskq_dispatch(SATA_TXLT_TASKQ(spx), - (task_func_t *)pkt->pkt_comp, - (void *)pkt, TQ_NOSLEEP) == NULL) + if (servicing_interrupt()) { + if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_NOSLEEP) == + NULL) { + return (TRAN_BUSY); + } + } else if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_SLEEP) == NULL) { /* Scheduling the callback failed */ return (TRAN_BUSY); + } return (TRAN_ACCEPT); } /* No callback available */ @@ -3146,12 +3154,19 @@ */ if (spx->txlt_scsi_pkt->pkt_comp != NULL) { /* scsi callback required */ - if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + if (servicing_interrupt()) { + if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_NOSLEEP) == + NULL) { + return (TRAN_BUSY); + } + } else if (taskq_dispatch(SATA_TXLT_TASKQ(spx), (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, - (void *)spx->txlt_scsi_pkt, - TQ_SLEEP) == NULL) + (void *)spx->txlt_scsi_pkt, TQ_SLEEP) == NULL) { /* Scheduling the callback failed */ return (TRAN_BUSY); + } return (TRAN_ACCEPT); } @@ -3364,14 +3379,21 @@ "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason); if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 && - scsipkt->pkt_comp != NULL) + scsipkt->pkt_comp != NULL) { /* scsi callback required */ - if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + if (servicing_interrupt()) { + if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_NOSLEEP) == NULL) { + return (TRAN_BUSY); + } + } else if (taskq_dispatch(SATA_TXLT_TASKQ(spx), (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, - (void *)spx->txlt_scsi_pkt, - TQ_SLEEP) == NULL) + (void *)spx->txlt_scsi_pkt, TQ_SLEEP) == NULL) { /* Scheduling the callback failed */ return (TRAN_BUSY); + } + } return (TRAN_ACCEPT); } @@ -3405,14 +3427,22 @@ SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst, "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason); - if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0) + if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 && + scsipkt->pkt_comp != NULL) { /* scsi callback required */ - if (taskq_dispatch(SATA_TXLT_TASKQ(spx), - (task_func_t *)scsi_hba_pkt_comp, - (void *)spx->txlt_scsi_pkt, - TQ_SLEEP) == NULL) + if (servicing_interrupt()) { + if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_NOSLEEP) == NULL) { + return (TRAN_BUSY); + } + } else if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_SLEEP) == NULL) { /* Scheduling the callback failed */ return (TRAN_BUSY); + } + } return (TRAN_ACCEPT); } @@ -3447,14 +3477,21 @@ spx->txlt_scsi_pkt->pkt_reason); if ((spx->txlt_scsi_pkt->pkt_flags & FLAG_NOINTR) == 0 && - spx->txlt_scsi_pkt->pkt_comp != NULL) + spx->txlt_scsi_pkt->pkt_comp != NULL) { /* scsi callback required */ - if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + if (servicing_interrupt()) { + if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_NOSLEEP) == NULL) { + return (TRAN_BUSY); + } + } else if (taskq_dispatch(SATA_TXLT_TASKQ(spx), (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, - (void *)spx->txlt_scsi_pkt, - TQ_SLEEP) == NULL) + (void *)spx->txlt_scsi_pkt, TQ_SLEEP) == NULL) { /* Scheduling the callback failed */ return (TRAN_BUSY); + } + } return (TRAN_ACCEPT); } @@ -3668,11 +3705,18 @@ if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 && scsipkt->pkt_comp != NULL) { /* scsi callback required */ - if (taskq_dispatch(SATA_TXLT_TASKQ(spx), - (task_func_t *)scsipkt->pkt_comp, (void *) scsipkt, - TQ_SLEEP) == NULL) + if (servicing_interrupt()) { + if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_NOSLEEP) == NULL) { + return (TRAN_BUSY); + } + } else if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_SLEEP) == NULL) { /* Scheduling the callback failed */ return (TRAN_BUSY); + } } return (TRAN_ACCEPT); } @@ -3807,13 +3851,22 @@ "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason); - if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0) + if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 && + scsipkt->pkt_comp != NULL) { /* scsi callback required */ - if (taskq_dispatch(SATA_TXLT_TASKQ(spx), - (task_func_t *)scsi_hba_pkt_comp, (void *) scsipkt, - TQ_SLEEP) == NULL) + if (servicing_interrupt()) { + if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_NOSLEEP) == NULL) { + return (TRAN_BUSY); + } + } else if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_SLEEP) == NULL) { /* Scheduling the callback failed */ return (TRAN_BUSY); + } + } return (TRAN_ACCEPT); } @@ -3890,13 +3943,22 @@ SATADBG1(SATA_DBG_SCSI_IF, spx->txlt_sata_hba_inst, "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason); - if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0) + if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 && + scsipkt->pkt_comp != NULL) { /* scsi callback required */ - if (taskq_dispatch(SATA_TXLT_TASKQ(spx), - (task_func_t *)scsi_hba_pkt_comp, (void *) scsipkt, - TQ_SLEEP) == NULL) + if (servicing_interrupt()) { + if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_NOSLEEP) == NULL) { + return (TRAN_BUSY); + } + } else if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_SLEEP) == NULL) { /* Scheduling the callback failed */ return (TRAN_BUSY); + } + } return (TRAN_ACCEPT); } @@ -4229,11 +4291,19 @@ "synchronous execution status %x\n", spx->txlt_sata_pkt->satapkt_reason); - if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0) { + if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 && + scsipkt->pkt_comp != NULL) { sata_set_arq_data(spx->txlt_sata_pkt); - if (taskq_dispatch(SATA_TXLT_TASKQ(spx), - (task_func_t *)scsi_hba_pkt_comp, (void *) scsipkt, - TQ_SLEEP) == 0) { + if (servicing_interrupt()) { + if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_NOSLEEP) == NULL) { + return (TRAN_BUSY); + } + } else if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_SLEEP) == NULL) { + /* Scheduling the callback failed */ return (TRAN_BUSY); } } @@ -4319,13 +4389,21 @@ "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason); if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 && - scsipkt->pkt_comp != NULL) + scsipkt->pkt_comp != NULL) { /* scsi callback required */ - if (taskq_dispatch(SATA_TXLT_TASKQ(spx), - (task_func_t *)scsipkt->pkt_comp, (void *) scsipkt, - TQ_SLEEP) == NULL) + if (servicing_interrupt()) { + if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_NOSLEEP) == NULL) { + return (TRAN_BUSY); + } + } else if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_SLEEP) == NULL) { /* Scheduling the callback failed */ return (TRAN_BUSY); + } + } return (TRAN_ACCEPT); } @@ -4360,7 +4438,14 @@ spx->txlt_scsi_pkt->pkt_cdbp[2] >> 6, spx->txlt_scsi_pkt->pkt_cdbp[2] & 0x3f); - buf = kmem_zalloc(1024, KM_SLEEP); + if (servicing_interrupt()) { + buf = kmem_zalloc(1024, KM_NOSLEEP); + if (buf == NULL) { + return (TRAN_BUSY); + } + } else { + buf = kmem_zalloc(1024, KM_SLEEP); + } mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx))); @@ -4590,13 +4675,21 @@ "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason); if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 && - scsipkt->pkt_comp != NULL) + scsipkt->pkt_comp != NULL) { /* scsi callback required */ - if (taskq_dispatch(SATA_TXLT_TASKQ(spx), - (task_func_t *)scsipkt->pkt_comp, (void *) scsipkt, - TQ_SLEEP) == NULL) + if (servicing_interrupt()) { + if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_NOSLEEP) == NULL) { + return (TRAN_BUSY); + } + } else if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_SLEEP) == NULL) { /* Scheduling the callback failed */ return (TRAN_BUSY); + } + } return (TRAN_ACCEPT); } @@ -4910,13 +5003,21 @@ "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason); if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 && - scsipkt->pkt_comp != NULL) + scsipkt->pkt_comp != NULL) { /* scsi callback required */ - if (taskq_dispatch(SATA_TXLT_TASKQ(spx), - (task_func_t *)scsipkt->pkt_comp, (void *) scsipkt, - TQ_SLEEP) == NULL) + if (servicing_interrupt()) { + if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_NOSLEEP) == NULL) { + return (TRAN_BUSY); + } + } else if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_SLEEP) == NULL) { /* Scheduling the callback failed */ return (TRAN_BUSY); + } + } return (rval); } @@ -5182,7 +5283,14 @@ spx->txlt_scsi_pkt->pkt_cdbp[2] >> 6, spx->txlt_scsi_pkt->pkt_cdbp[2] & 0x3f); - buf = kmem_zalloc(MAX_LOG_SENSE_PAGE_SIZE, KM_SLEEP); + if (servicing_interrupt()) { + buf = kmem_zalloc(MAX_LOG_SENSE_PAGE_SIZE, KM_NOSLEEP); + if (buf == NULL) { + return (TRAN_BUSY); + } + } else { + buf = kmem_zalloc(MAX_LOG_SENSE_PAGE_SIZE, KM_SLEEP); + } mutex_enter(&(SATA_TXLT_CPORT_MUTEX(spx))); @@ -5395,13 +5503,21 @@ "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason); if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 && - scsipkt->pkt_comp != NULL) + scsipkt->pkt_comp != NULL) { /* scsi callback required */ - if (taskq_dispatch(SATA_TXLT_TASKQ(spx), - (task_func_t *)scsipkt->pkt_comp, (void *) scsipkt, - TQ_SLEEP) == NULL) + if (servicing_interrupt()) { + if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_NOSLEEP) == NULL) { + return (TRAN_BUSY); + } + } else if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_SLEEP) == NULL) { /* Scheduling the callback failed */ return (TRAN_BUSY); + } + } return (TRAN_ACCEPT); } @@ -6124,11 +6240,17 @@ if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 && scsipkt->pkt_comp != NULL) { /* scsi callback required */ - if (taskq_dispatch(SATA_TXLT_TASKQ(spx), - (task_func_t *)scsipkt->pkt_comp, (void *) scsipkt, - TQ_SLEEP) == 0) { + if (servicing_interrupt()) { + if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_NOSLEEP) == NULL) { + return (TRAN_BUSY); + } + } else if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_SLEEP) == NULL) { /* Scheduling the callback failed */ - rval = TRAN_BUSY; + return (TRAN_BUSY); } } return (rval); @@ -6545,13 +6667,21 @@ "Scsi_pkt completion reason %x\n", scsipkt->pkt_reason); if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 && - scsipkt->pkt_comp != NULL) + scsipkt->pkt_comp != NULL) { /* scsi callback required */ - if (taskq_dispatch(SATA_TXLT_TASKQ(spx), - (task_func_t *)scsipkt->pkt_comp, (void *) scsipkt, - TQ_SLEEP) == NULL) + if (servicing_interrupt()) { + if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_NOSLEEP) == NULL) { + return (TRAN_BUSY); + } + } else if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_SLEEP) == NULL) { /* Scheduling the callback failed */ return (TRAN_BUSY); + } + } return (TRAN_ACCEPT); } @@ -6679,13 +6809,21 @@ sense->es_add_code = SD_SCSI_ASC_INVALID_FIELD_IN_CDB; if ((scsipkt->pkt_flags & FLAG_NOINTR) == 0 && - scsipkt->pkt_comp != NULL) + scsipkt->pkt_comp != NULL) { /* scsi callback required */ - if (taskq_dispatch(SATA_TXLT_TASKQ(spx), - (task_func_t *)scsipkt->pkt_comp, (void *) scsipkt, - TQ_SLEEP) == NULL) + if (servicing_interrupt()) { + if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_NOSLEEP) == NULL) { + return (TRAN_BUSY); + } + } else if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_SLEEP) == NULL) { /* Scheduling the callback failed */ return (TRAN_BUSY); + } + } return (TRAN_ACCEPT); } @@ -6707,11 +6845,18 @@ *scsipkt->pkt_scbp = STATUS_GOOD; if (!(spx->txlt_sata_pkt->satapkt_op_mode & SATA_OPMODE_SYNCH)) { /* scsi callback required - have to schedule it */ - if (taskq_dispatch(SATA_TXLT_TASKQ(spx), - (task_func_t *)scsipkt->pkt_comp, - (void *)scsipkt, TQ_SLEEP) == NULL) + if (servicing_interrupt()) { + if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_NOSLEEP) == NULL) { + return (TRAN_BUSY); + } + } else if (taskq_dispatch(SATA_TXLT_TASKQ(spx), + (task_func_t *)spx->txlt_scsi_pkt->pkt_comp, + (void *)spx->txlt_scsi_pkt, TQ_SLEEP) == NULL) { /* Scheduling the callback failed */ return (TRAN_BUSY); + } } return (TRAN_ACCEPT); }