114 
 115 int pppt_logging = 0;
 116 
 117 static int pppt_enable_svc(void);
 118 
 119 static void pppt_disable_svc(void);
 120 
 121 static int pppt_task_avl_compare(const void *tgt1, const void *tgt2);
 122 
 123 static stmf_data_buf_t *pppt_dbuf_alloc(scsi_task_t *task,
 124     uint32_t size, uint32_t *pminsize, uint32_t flags);
 125 
 126 static void pppt_dbuf_free(stmf_dbuf_store_t *ds, stmf_data_buf_t *dbuf);
 127 
 128 static void pppt_sess_destroy_task(void *ps_void);
 129 
 130 static void pppt_task_sent_status(pppt_task_t *ptask);
 131 
 132 static pppt_status_t pppt_task_try_abort(pppt_task_t *ptask);
 133 
 134 static pppt_status_t pppt_task_hold(pppt_task_t *ptask);
 135 
 136 static void pppt_task_rele(pppt_task_t *ptask);
 137 
 138 static void pppt_task_update_state(pppt_task_t *ptask,
 139     pppt_task_state_t new_state);
 140 
 141 /*
 142  * Lock order:  global --> target --> session --> task
 143  */
 144 
 145 int
 146 _init(void)
 147 {
 148         int rc;
 149 
 150         mutex_init(&pppt_global.global_lock, NULL, MUTEX_DEFAULT, NULL);
 151         mutex_init(&pppt_global.global_door_lock, NULL, MUTEX_DEFAULT, NULL);
 152         pppt_global.global_svc_state = PSS_DETACHED;
 153 
 154         if ((rc = mod_install(&modlinkage)) != 0) {
 155                 mutex_destroy(&pppt_global.global_door_lock);
 
 784 
 785         if (ic_msg_status != STMF_IC_MSG_SUCCESS) {
 786                 pppt_task_sent_status(ptask);
 787                 stmf_send_status_done(ptask->pt_stmf_task,
 788                     STMF_FAILURE, STMF_IOF_LPORT_DONE);
 789                 return (STMF_FAILURE);
 790         } else {
 791                 pppt_task_sent_status(ptask);
 792                 stmf_send_status_done(ptask->pt_stmf_task,
 793                     STMF_SUCCESS, STMF_IOF_LPORT_DONE);
 794                 return (STMF_SUCCESS);
 795         }
 796 }
 797 
 798 void
 799 pppt_lport_task_free(scsi_task_t *task)
 800 {
 801         pppt_task_t *ptask = task->task_port_private;
 802         pppt_sess_t *ps = ptask->pt_sess;
 803 
 804         pppt_task_free(ptask);
 805         pppt_sess_rele(ps);
 806 }
 807 
 808 /*ARGSUSED*/
 809 stmf_status_t
 810 pppt_lport_abort(stmf_local_port_t *lport, int abort_cmd, void *arg,
 811     uint32_t flags)
 812 {
 813         scsi_task_t     *st = (scsi_task_t *)arg;
 814         pppt_task_t     *ptask;
 815 
 816         ptask = st->task_port_private;
 817 
 818         if (pppt_task_try_abort(ptask) == PPPT_STATUS_DONE) {
 819                 /*
 820                  * This task is beyond the point where abort makes sense
 821                  * and we will soon be sending status.  Tell STMF to
 822                  * go away.
 823                  */
 824                 return (STMF_BUSY);
 
1192         avl_remove(&tgt->target_sess_list, ps);
1193         avl_remove(&pppt_global.global_sess_list, ps);
1194         (void) taskq_dispatch(pppt_global.global_sess_taskq,
1195             &pppt_sess_destroy_task, ps, KM_SLEEP);
1196 
1197         stmf_trace("pppt", "Session close complete %p", (void *)ps);
1198 }
1199 
1200 pppt_task_t *
1201 pppt_task_alloc(void)
1202 {
1203         pppt_task_t     *ptask;
1204         pppt_buf_t      *immed_pbuf;
1205 
1206         ptask = kmem_alloc(sizeof (pppt_task_t) + sizeof (pppt_buf_t) +
1207             sizeof (stmf_data_buf_t), KM_NOSLEEP);
1208         if (ptask != NULL) {
1209                 ptask->pt_state = PTS_INIT;
1210                 ptask->pt_read_buf = NULL;
1211                 ptask->pt_read_xfer_msgid = 0;
1212                 cv_init(&ptask->pt_cv, NULL, CV_DRIVER, NULL);
1213                 mutex_init(&ptask->pt_mutex, NULL, MUTEX_DRIVER, NULL);
1214                 immed_pbuf = (pppt_buf_t *)(ptask + 1);
1215                 bzero(immed_pbuf, sizeof (*immed_pbuf));
1216                 immed_pbuf->pbuf_is_immed = B_TRUE;
1217                 immed_pbuf->pbuf_stmf_buf = (stmf_data_buf_t *)(immed_pbuf + 1);
1218 
1219                 bzero(immed_pbuf->pbuf_stmf_buf, sizeof (stmf_data_buf_t));
1220                 immed_pbuf->pbuf_stmf_buf->db_port_private = immed_pbuf;
1221                 immed_pbuf->pbuf_stmf_buf->db_sglist_length = 1;
1222                 immed_pbuf->pbuf_stmf_buf->db_flags = DB_DIRECTION_FROM_RPORT |
1223                     DB_DONT_CACHE;
1224                 ptask->pt_immed_data = immed_pbuf;
1225         }
1226 
1227         return (ptask);
1228 
1229 }
1230 
1231 void
1232 pppt_task_free(pppt_task_t *ptask)
1233 {
1234         mutex_enter(&ptask->pt_mutex);
1235         mutex_destroy(&ptask->pt_mutex);
1236         cv_destroy(&ptask->pt_cv);
1237         kmem_free(ptask, sizeof (pppt_task_t) + sizeof (pppt_buf_t) +
1238             sizeof (stmf_data_buf_t));
1239 }
1240 
1241 pppt_status_t
1242 pppt_task_start(pppt_task_t *ptask)
1243 {
1244         avl_index_t             where;
1245 
1246         ASSERT(ptask->pt_state == PTS_INIT);
1247 
1248         mutex_enter(&ptask->pt_sess->ps_mutex);
1249         mutex_enter(&ptask->pt_mutex);
1250         if (avl_find(&ptask->pt_sess->ps_task_list, ptask, &where) == NULL) {
1251                 pppt_task_update_state(ptask, PTS_ACTIVE);
1252                 avl_insert(&ptask->pt_sess->ps_task_list, ptask, where);
1253                 mutex_exit(&ptask->pt_mutex);
1254                 mutex_exit(&ptask->pt_sess->ps_mutex);
1255                 return (PPPT_STATUS_SUCCESS);
1256         }
1257         mutex_exit(&ptask->pt_mutex);
1258         mutex_exit(&ptask->pt_sess->ps_mutex);
1259 
1260         return (PPPT_STATUS_FAIL);
1261 }
1262 
1263 pppt_status_t
1264 pppt_task_done(pppt_task_t *ptask)
1265 {
1266         pppt_status_t   pppt_status = PPPT_STATUS_SUCCESS;
1267         boolean_t       remove = B_FALSE;
1268 
1269         mutex_enter(&ptask->pt_mutex);
1270 
1271         switch (ptask->pt_state) {
1272         case PTS_ACTIVE:
1273                 remove = B_TRUE;
1274                 pppt_task_update_state(ptask, PTS_DONE);
1275                 break;
1276         case PTS_ABORTED:
1277                 pppt_status = PPPT_STATUS_ABORTED;
1278                 break;
1279         case PTS_DONE:
1280                 /* Repeat calls are OK.  Do nothing, return success */
1281                 break;
1282         default:
1283                 ASSERT(0);
1284         }
1285 
1286         mutex_exit(&ptask->pt_mutex);
1287 
1288         if (remove) {
1289                 mutex_enter(&ptask->pt_sess->ps_mutex);
1290                 avl_remove(&ptask->pt_sess->ps_task_list, ptask);
1291                 mutex_exit(&ptask->pt_sess->ps_mutex);
1292         }
1293 
1294         return (pppt_status);
1295 }
1296 
1297 void
1298 pppt_task_sent_status(pppt_task_t *ptask)
1299 {
1300         /*
1301          * If STMF tries to abort a task after the task state changed to
1302          * PTS_DONE (meaning all task processing is complete from
1303          * the port provider perspective) then we return STMF_BUSY
1304          * from pppt_lport_abort.  STMF will return after a short interval
1305          * but our calls to stmf_send_status_done will be ignored since
1306          * STMF is aborting the task.  That's where this state comes in.
1307          * This state essentially says we are calling stmf_send_status_done
1308          * so we will not be touching the task again.  The next time
1309          * STMF calls pppt_lport_abort we will return a success full
1310          * status and the abort will succeed.
1311          */
 
1384                 break;
1385         case PTS_SENT_STATUS:
1386                 /*
1387                  * Already removed so leave remove set to B_FALSE
1388                  * and leave status set to PPPT_STATUS_SUCCESS.
1389                  */
1390                 pppt_task_update_state(ptask, PTS_ABORTED);
1391                 break;
1392         case PTS_ABORTED:
1393                 break;
1394         default:
1395                 ASSERT(0);
1396         }
1397 
1398         mutex_exit(&ptask->pt_mutex);
1399 
1400         if (remove) {
1401                 mutex_enter(&ptask->pt_sess->ps_mutex);
1402                 avl_remove(&ptask->pt_sess->ps_task_list, ptask);
1403                 mutex_exit(&ptask->pt_sess->ps_mutex);
1404         }
1405 
1406         return (pppt_status);
1407 }
1408 
1409 static pppt_status_t
1410 pppt_task_hold(pppt_task_t *ptask)
1411 {
1412         pppt_status_t   pppt_status = PPPT_STATUS_SUCCESS;
1413 
1414         mutex_enter(&ptask->pt_mutex);
1415         if (ptask->pt_state == PTS_ACTIVE) {
1416                 ptask->pt_refcnt++;
1417         } else {
1418                 pppt_status = PPPT_STATUS_FAIL;
1419         }
1420         mutex_exit(&ptask->pt_mutex);
1421 
1422         return (pppt_status);
1423 }
1424 
1425 static void
1426 pppt_task_rele(pppt_task_t *ptask)
1427 {
1428         mutex_enter(&ptask->pt_mutex);
1429         ptask->pt_refcnt--;
1430         cv_signal(&ptask->pt_cv);
1431         mutex_exit(&ptask->pt_mutex);
1432 }
1433 
1434 static void
1435 pppt_task_update_state(pppt_task_t *ptask,
1436     pppt_task_state_t new_state)
1437 {
1438         PPPT_LOG(CE_NOTE, "task %p %d -> %d", (void *)ptask,
1439             ptask->pt_state, new_state);
1440 
1441         ASSERT(mutex_owned(&ptask->pt_mutex));
1442         ptask->pt_state = new_state;
1443         cv_signal(&ptask->pt_cv);
1444 }
 | 
 
 
 114 
 115 int pppt_logging = 0;
 116 
 117 static int pppt_enable_svc(void);
 118 
 119 static void pppt_disable_svc(void);
 120 
 121 static int pppt_task_avl_compare(const void *tgt1, const void *tgt2);
 122 
 123 static stmf_data_buf_t *pppt_dbuf_alloc(scsi_task_t *task,
 124     uint32_t size, uint32_t *pminsize, uint32_t flags);
 125 
 126 static void pppt_dbuf_free(stmf_dbuf_store_t *ds, stmf_data_buf_t *dbuf);
 127 
 128 static void pppt_sess_destroy_task(void *ps_void);
 129 
 130 static void pppt_task_sent_status(pppt_task_t *ptask);
 131 
 132 static pppt_status_t pppt_task_try_abort(pppt_task_t *ptask);
 133 
 134 static void pppt_task_rele(pppt_task_t *ptask);
 135 
 136 static void pppt_task_update_state(pppt_task_t *ptask,
 137     pppt_task_state_t new_state);
 138 
 139 /*
 140  * Lock order:  global --> target --> session --> task
 141  */
 142 
 143 int
 144 _init(void)
 145 {
 146         int rc;
 147 
 148         mutex_init(&pppt_global.global_lock, NULL, MUTEX_DEFAULT, NULL);
 149         mutex_init(&pppt_global.global_door_lock, NULL, MUTEX_DEFAULT, NULL);
 150         pppt_global.global_svc_state = PSS_DETACHED;
 151 
 152         if ((rc = mod_install(&modlinkage)) != 0) {
 153                 mutex_destroy(&pppt_global.global_door_lock);
 
 782 
 783         if (ic_msg_status != STMF_IC_MSG_SUCCESS) {
 784                 pppt_task_sent_status(ptask);
 785                 stmf_send_status_done(ptask->pt_stmf_task,
 786                     STMF_FAILURE, STMF_IOF_LPORT_DONE);
 787                 return (STMF_FAILURE);
 788         } else {
 789                 pppt_task_sent_status(ptask);
 790                 stmf_send_status_done(ptask->pt_stmf_task,
 791                     STMF_SUCCESS, STMF_IOF_LPORT_DONE);
 792                 return (STMF_SUCCESS);
 793         }
 794 }
 795 
 796 void
 797 pppt_lport_task_free(scsi_task_t *task)
 798 {
 799         pppt_task_t *ptask = task->task_port_private;
 800         pppt_sess_t *ps = ptask->pt_sess;
 801 
 802         pppt_task_rele(ptask);
 803         pppt_sess_rele(ps);
 804 }
 805 
 806 /*ARGSUSED*/
 807 stmf_status_t
 808 pppt_lport_abort(stmf_local_port_t *lport, int abort_cmd, void *arg,
 809     uint32_t flags)
 810 {
 811         scsi_task_t     *st = (scsi_task_t *)arg;
 812         pppt_task_t     *ptask;
 813 
 814         ptask = st->task_port_private;
 815 
 816         if (pppt_task_try_abort(ptask) == PPPT_STATUS_DONE) {
 817                 /*
 818                  * This task is beyond the point where abort makes sense
 819                  * and we will soon be sending status.  Tell STMF to
 820                  * go away.
 821                  */
 822                 return (STMF_BUSY);
 
1190         avl_remove(&tgt->target_sess_list, ps);
1191         avl_remove(&pppt_global.global_sess_list, ps);
1192         (void) taskq_dispatch(pppt_global.global_sess_taskq,
1193             &pppt_sess_destroy_task, ps, KM_SLEEP);
1194 
1195         stmf_trace("pppt", "Session close complete %p", (void *)ps);
1196 }
1197 
1198 pppt_task_t *
1199 pppt_task_alloc(void)
1200 {
1201         pppt_task_t     *ptask;
1202         pppt_buf_t      *immed_pbuf;
1203 
1204         ptask = kmem_alloc(sizeof (pppt_task_t) + sizeof (pppt_buf_t) +
1205             sizeof (stmf_data_buf_t), KM_NOSLEEP);
1206         if (ptask != NULL) {
1207                 ptask->pt_state = PTS_INIT;
1208                 ptask->pt_read_buf = NULL;
1209                 ptask->pt_read_xfer_msgid = 0;
1210                 ptask->pt_refcnt = 0;
1211                 mutex_init(&ptask->pt_mutex, NULL, MUTEX_DRIVER, NULL);
1212                 immed_pbuf = (pppt_buf_t *)(ptask + 1);
1213                 bzero(immed_pbuf, sizeof (*immed_pbuf));
1214                 immed_pbuf->pbuf_is_immed = B_TRUE;
1215                 immed_pbuf->pbuf_stmf_buf = (stmf_data_buf_t *)(immed_pbuf + 1);
1216 
1217                 bzero(immed_pbuf->pbuf_stmf_buf, sizeof (stmf_data_buf_t));
1218                 immed_pbuf->pbuf_stmf_buf->db_port_private = immed_pbuf;
1219                 immed_pbuf->pbuf_stmf_buf->db_sglist_length = 1;
1220                 immed_pbuf->pbuf_stmf_buf->db_flags = DB_DIRECTION_FROM_RPORT |
1221                     DB_DONT_CACHE;
1222                 ptask->pt_immed_data = immed_pbuf;
1223         }
1224 
1225         return (ptask);
1226 
1227 }
1228 
1229 void
1230 pppt_task_free(pppt_task_t *ptask)
1231 {
1232         mutex_enter(&ptask->pt_mutex);
1233         ASSERT(ptask->pt_refcnt == 0);
1234         mutex_destroy(&ptask->pt_mutex);
1235         kmem_free(ptask, sizeof (pppt_task_t) + sizeof (pppt_buf_t) +
1236             sizeof (stmf_data_buf_t));
1237 }
1238 
1239 pppt_status_t
1240 pppt_task_start(pppt_task_t *ptask)
1241 {
1242         avl_index_t             where;
1243 
1244         ASSERT(ptask->pt_state == PTS_INIT);
1245 
1246         mutex_enter(&ptask->pt_sess->ps_mutex);
1247         mutex_enter(&ptask->pt_mutex);
1248         if (avl_find(&ptask->pt_sess->ps_task_list, ptask, &where) == NULL) {
1249                 pppt_task_update_state(ptask, PTS_ACTIVE);
1250                 /* Manually increment refcnt, sincd we hold the mutex... */
1251                 ptask->pt_refcnt++;
1252                 avl_insert(&ptask->pt_sess->ps_task_list, ptask, where);
1253                 mutex_exit(&ptask->pt_mutex);
1254                 mutex_exit(&ptask->pt_sess->ps_mutex);
1255                 return (PPPT_STATUS_SUCCESS);
1256         }
1257         mutex_exit(&ptask->pt_mutex);
1258         mutex_exit(&ptask->pt_sess->ps_mutex);
1259 
1260         return (PPPT_STATUS_FAIL);
1261 }
1262 
1263 pppt_status_t
1264 pppt_task_done(pppt_task_t *ptask)
1265 {
1266         pppt_status_t   pppt_status = PPPT_STATUS_SUCCESS;
1267         boolean_t       remove = B_FALSE;
1268 
1269         mutex_enter(&ptask->pt_mutex);
1270 
1271         switch (ptask->pt_state) {
1272         case PTS_ACTIVE:
1273                 remove = B_TRUE;
1274                 pppt_task_update_state(ptask, PTS_DONE);
1275                 break;
1276         case PTS_ABORTED:
1277                 pppt_status = PPPT_STATUS_ABORTED;
1278                 break;
1279         case PTS_DONE:
1280                 /* Repeat calls are OK.  Do nothing, return success */
1281                 break;
1282         default:
1283                 ASSERT(0);
1284         }
1285 
1286         mutex_exit(&ptask->pt_mutex);
1287 
1288         if (remove) {
1289                 mutex_enter(&ptask->pt_sess->ps_mutex);
1290                 avl_remove(&ptask->pt_sess->ps_task_list, ptask);
1291                 mutex_exit(&ptask->pt_sess->ps_mutex);
1292                 /* Out of the AVL tree, so drop a reference. */
1293                 pppt_task_rele(ptask);
1294         }
1295 
1296         return (pppt_status);
1297 }
1298 
1299 void
1300 pppt_task_sent_status(pppt_task_t *ptask)
1301 {
1302         /*
1303          * If STMF tries to abort a task after the task state changed to
1304          * PTS_DONE (meaning all task processing is complete from
1305          * the port provider perspective) then we return STMF_BUSY
1306          * from pppt_lport_abort.  STMF will return after a short interval
1307          * but our calls to stmf_send_status_done will be ignored since
1308          * STMF is aborting the task.  That's where this state comes in.
1309          * This state essentially says we are calling stmf_send_status_done
1310          * so we will not be touching the task again.  The next time
1311          * STMF calls pppt_lport_abort we will return a success full
1312          * status and the abort will succeed.
1313          */
 
1386                 break;
1387         case PTS_SENT_STATUS:
1388                 /*
1389                  * Already removed so leave remove set to B_FALSE
1390                  * and leave status set to PPPT_STATUS_SUCCESS.
1391                  */
1392                 pppt_task_update_state(ptask, PTS_ABORTED);
1393                 break;
1394         case PTS_ABORTED:
1395                 break;
1396         default:
1397                 ASSERT(0);
1398         }
1399 
1400         mutex_exit(&ptask->pt_mutex);
1401 
1402         if (remove) {
1403                 mutex_enter(&ptask->pt_sess->ps_mutex);
1404                 avl_remove(&ptask->pt_sess->ps_task_list, ptask);
1405                 mutex_exit(&ptask->pt_sess->ps_mutex);
1406                 /* Out of the AVL tree, so drop a reference. */
1407                 pppt_task_rele(ptask);
1408         }
1409 
1410         return (pppt_status);
1411 }
1412 
1413 pppt_status_t
1414 pppt_task_hold(pppt_task_t *ptask)
1415 {
1416         pppt_status_t   pppt_status = PPPT_STATUS_SUCCESS;
1417 
1418         mutex_enter(&ptask->pt_mutex);
1419         if (ptask->pt_state == PTS_ACTIVE) {
1420                 ptask->pt_refcnt++;
1421         } else {
1422                 pppt_status = PPPT_STATUS_FAIL;
1423         }
1424         mutex_exit(&ptask->pt_mutex);
1425 
1426         return (pppt_status);
1427 }
1428 
1429 static void
1430 pppt_task_rele(pppt_task_t *ptask)
1431 {
1432         boolean_t freeit;
1433 
1434         mutex_enter(&ptask->pt_mutex);
1435         ptask->pt_refcnt--;
1436         freeit = (ptask->pt_refcnt == 0);
1437         mutex_exit(&ptask->pt_mutex);
1438         if (freeit)
1439                 pppt_task_free(ptask);
1440 }
1441 
1442 static void
1443 pppt_task_update_state(pppt_task_t *ptask,
1444     pppt_task_state_t new_state)
1445 {
1446         PPPT_LOG(CE_NOTE, "task %p %d -> %d", (void *)ptask,
1447             ptask->pt_state, new_state);
1448 
1449         ASSERT(mutex_owned(&ptask->pt_mutex));
1450         ptask->pt_state = new_state;
1451 }
 |