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 }
|