stmf.c revision 640428ae0ffb68033a9bf38dcc271e17d13933cb
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER START
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The contents of this file are subject to the terms of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Common Development and Distribution License (the "License").
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You may not use this file except in compliance with the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See the License for the specific language governing permissions
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and limitations under the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If applicable, add the following below this CDDL HEADER, with the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER END
5679c89fcd2facbb4334df8870d3d7a4d2b11673jv * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Use is subject to license terms.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int stmf_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int stmf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int stmf_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int stmf_open(dev_t *devp, int flag, int otype, cred_t *credp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int stmf_close(dev_t dev, int flag, int otype, cred_t *credp);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int stmf_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int stmf_get_stmf_state(stmf_state_desc_t *std);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int stmf_set_stmf_state(stmf_state_desc_t *std);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void stmf_abort_task_offline(scsi_task_t *task, int offline_lu,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid stmf_svc_queue(int cmd, void *obj, stmf_state_change_info_t *info);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_status_t stmf_lun_reset_poll(stmf_lu_t *lu, struct scsi_task *task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid stmf_target_reset_poll(struct scsi_task *task);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetoint stmf_load_ppd_ioctl(stmf_ppioctl_data_t *ppi, uint64_t *ppi_token,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteint stmf_delete_ppd_ioctl(stmf_ppioctl_data_t *ppi);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetoint stmf_get_ppd_ioctl(stmf_ppioctl_data_t *ppi, stmf_ppioctl_data_t *ppi_out,
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szetostatic void stmf_update_kstat_lu_q(scsi_task_t *, void());
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szetostatic void stmf_update_kstat_lport_q(scsi_task_t *, void());
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szetostatic void stmf_update_kstat_lu_io(scsi_task_t *, stmf_data_buf_t *);
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szetostatic void stmf_update_kstat_lport_io(scsi_task_t *, stmf_data_buf_t *);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* =====[ Tunables ]===== */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* Internal tracing */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevolatile int stmf_trace_buf_size = (1 * 1024 * 1024);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The reason default task timeout is 75 is because we want the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * host to timeout 1st and mostly host timeout is 60 seconds.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Setting this to one means, you are responsible for config load and keeping
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * things in sync with persistent database.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevolatile int stmf_allow_modunload = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* === [ Debugging and fault injection ] === */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevolatile int stmf_drop_task_counter = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevolatile int stmf_drop_buf_counter = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte { 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 0xff };
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte { 0xff, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic enum {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int stmf_nworkers_cur; /* # of workers currently running */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int stmf_nworkers_needed; /* # of workers need to be running */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This is equal to stmf_nworkers_cur while we are increasing # workers and
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * stmf_nworkers_needed while we are decreasing the worker count.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte 0, /* streamtab */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace_buf = kmem_zalloc(stmf_trace_buf_size, KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_init(&trace_buf_lock, NULL, MUTEX_DRIVER, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* STMF service is off by default */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_init(&stmf_state.stmf_lock, NULL, MUTEX_DRIVER, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cv_init(&stmf_state.stmf_cv, NULL, CV_DRIVER, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_session_counter = (uint64_t)ddi_get_lbolt();
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (stmf_state.stmf_config_state != STMF_CONFIG_NONE)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_state.stmf_nlps || stmf_state.stmf_npps) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (void *)(uintptr_t)ddi_get_instance(stmf_state.stmf_dip);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ddi_create_minor_node(dip, "admin", S_IFCHR, 0,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_open(dev_t *devp, int flag, int otype, cred_t *credp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_close(dev_t dev, int flag, int otype, cred_t *credp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (stmf_state.stmf_config_state != STMF_CONFIG_INIT_DONE)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_copyin_iocdata(intptr_t data, int mode, stmf_iocdata_t **iocd,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *iocd = kmem_zalloc(sizeof (stmf_iocdata_t), KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = ddi_copyin((void *)data, *iocd, sizeof (stmf_iocdata_t), mode);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *ibuf = kmem_zalloc((*iocd)->stmf_ibuf_size, KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = ddi_copyin((void *)((unsigned long)(*iocd)->stmf_ibuf),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *obuf = kmem_zalloc((*iocd)->stmf_obuf_size, KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_copyout_iocdata(intptr_t data, int mode, stmf_iocdata_t *iocd, void *obuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = ddi_copyout(obuf, (void *)(unsigned long)iocd->stmf_obuf,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = ddi_copyout(iocd, (void *)data, sizeof (stmf_iocdata_t), mode);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = stmf_copyin_iocdata(data, mode, &iocd, &ibuf, &obuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* retrieves both registered/unregistered */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto for (i = 0; i < n; i++) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto bcopy(id_entry->id_data, luid_list[i].lu_guid, 16);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto for (ilu = stmf_state.stmf_ilulist; ilu; ilu = ilu->ilu_next) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (stmf_lookup_id(id_list, 16, id + 4) == NULL) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (i < n) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iocd->stmf_obuf_max_nentries = stmf_state.stmf_nlus;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = 0; i < n; i++) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto for (i = 0; i < n; i++) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto bcopy(id_entry->id_data, luid_list[i].lu_guid, 16);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iocd->stmf_obuf_max_nentries = stmf_state.stmf_nlports;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = 0; i < n; i++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((p_id == NULL) || (iocd->stmf_ibuf_size < 4) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport; ilport =
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iocd->stmf_obuf_max_nentries = ilport->ilport_nsessions;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iocd->stmf_obuf_size)/sizeof (slist_scsi_session_t));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = 0; i < n; i++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iocd->stmf_obuf_size < sizeof (sioc_lu_props_t)) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (p_id[0] == 0)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ilu = stmf_state.stmf_ilulist; ilu; ilu = ilu->ilu_next) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (bcmp(p_id, ilu->ilu_lu->lu_id->ident, 16) == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(ilu->ilu_lu->lu_id->ident, lup->lu_guid, 16);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(ilport->ilport_lport->lport_id, lportp->tgt_id,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ilport->ilport_lport->lport_id->ident_length + 4);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_state_desc_t))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = stmf_set_stmf_state((stmf_state_desc_t *)ibuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iocd->stmf_obuf_size < sizeof (stmf_state_desc_t))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = stmf_get_stmf_state((stmf_state_desc_t *)obuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_state_desc_t))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ilu = stmf_state.stmf_ilulist; ilu; ilu = ilu->ilu_next) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (bcmp(p_id, ilu->ilu_lu->lu_id->ident, 16) == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmd = (std->state == STMF_STATE_ONLINE) ? STMF_CMD_LU_ONLINE :
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ctl_ret = stmf_ctl(cmd, (void *)ilu->ilu_lu, &ssi);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_state_desc_t))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ctl_ret = stmf_ctl(cmd, (void *)ilport->ilport_lport, &ssi);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* FALLTHROUGH */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_group_op_data_t))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break; /* not allowed */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = stmf_add_group_member(grp_entry->group.name,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* FALLTHROUGH */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_group_op_data_t))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break; /* not allowed */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = stmf_remove_group_member(grp_entry->group.name,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* FALLTHROUGH */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_group_name_t))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break; /* not allowed */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* FALLTHROUGH */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_group_name_t))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break; /* not allowed */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_view_op_entry_t))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (!ve->ve_ndx_valid || !ve->ve_lu_number_valid) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iocd->stmf_obuf_size >= sizeof (stmf_view_op_entry_t)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_view_op_entry_t))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = stmf_remove_ve_by_id(ve->ve_guid, ve->ve_ndx,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* FALLTHROUGH */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iocd->stmf_obuf_max_nentries = id_list->id_count;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iocd->stmf_obuf_size)/sizeof (stmf_group_name_t));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = 0; i < n; i++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* FALLTHROUGH */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_group_name_t))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte id_entry = stmf_lookup_id(id_list, grpname->name_size,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte id_list = (stmf_id_list_t *)id_entry->id_impl_specific;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iocd->stmf_obuf_max_nentries = id_list->id_count;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = 0; i < n; i++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte n = iocd->stmf_obuf_size/sizeof (stmf_view_op_entry_t);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto for (id_entry = stmf_state.stmf_luid_list.idl_head;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (iocd->stmf_obuf_size < sizeof (stmf_view_op_entry_t))) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto n = iocd->stmf_obuf_size/sizeof (stmf_view_op_entry_t);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto for (id_entry = stmf_state.stmf_luid_list.idl_head;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_ppioctl_data_t))) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* returned token */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ret = stmf_load_ppd_ioctl(ppi, ppi_token, &iocd->stmf_error);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (iocd->stmf_ibuf_size < sizeof (stmf_ppioctl_data_t))) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (iocd->stmf_obuf_size < sizeof (stmf_ppioctl_data_t))) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ret = stmf_get_ppd_ioctl(ppi, ppi_out, &iocd->stmf_error);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_NONE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iocd->stmf_error = STMF_IOCERR_UPDATE_NEED_CFG_INIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (iocd->stmf_ibuf_size < sizeof (stmf_ppioctl_data_t))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((iocd->stmf_obuf_size == 0) || (iocd->stmf_ibuf_size < 4)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte i = *((int *)ibuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((i > trace_buf_size) || ((i + iocd->stmf_obuf_size) >
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(stmf_trace_buf + i, obuf, iocd->stmf_obuf_size);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = stmf_copyout_iocdata(data, mode, iocd, obuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_copyout_iocdata(data, mode, iocd, obuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else if (ilport->ilport_state == STMF_STATE_ONLINE)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else if (ilport->ilport_state == STMF_STATE_ONLINING)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else if (ilport->ilport_state == STMF_STATE_OFFLINING)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_INIT) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (std->config_state != STMF_CONFIG_INIT_DONE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_state.stmf_config_state = STMF_CONFIG_INIT_DONE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_INIT) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ilport->ilport_prev_state != STMF_STATE_ONLINE)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_ctl(STMF_CMD_LU_ONLINE, ilu->ilu_lu, &ssi);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* svc_state is STMF_STATE_ONLINE here */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_ctl(STMF_CMD_LU_OFFLINE, ilu->ilu_lu, &ssi);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte std->config_state = stmf_state.stmf_config_state;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortetypedef struct {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte void *bp; /* back pointer from internal struct to main struct */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortetypedef struct {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic struct {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte} stmf_sizes[] = { { 0, 0 },
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_alloc(stmf_struct_id_t struct_id, int additional_size, int flags)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((struct_id == 0) || (struct_id >= STMF_MAX_STRUCT_IDS))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((curthread->t_flag & T_INTR_THREAD) || (flags & AF_FORCE_NOSLEEP)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sh = (__stmf_t *)kmem_zalloc(stmf_size, kmem_flag);
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang * In principle, the implementation inside stmf_alloc should not
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang * be changed anyway. But the original order of framework private
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang * data and caller private data does not support sglist in the caller
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang * private data.
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang * To work around this, the memory segments of framework private
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang * data and caller private data are re-ordered here.
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang * A better solution is to provide a specific interface to allocate
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang * the sglist, then we will not need this workaround any more.
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang * But before the new interface is available, the memory segment
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang * ordering should be kept as is.
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang sh->cp = GET_BYTE_OFFSET(sh, stmf_sizes[struct_id].shared);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Just store the total size instead of storing additional size */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * So far we dont need any struct specific processing. If such
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * a need ever arises, then store the struct id in the framework
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * private section and get it here as sh->fp->struct_id.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Given a pointer to stmf_lu_t, verifies if this lu is registered with the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * framework and returns a pointer to framework private data for the lu.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Returns NULL if the lu was not found.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ilu = stmf_state.stmf_ilulist; ilu != NULL; ilu = ilu->ilu_next) {
1b7fc709228029b3f29f1c3de6d817a476f7c583tim szeto * Given a pointer to stmf_local_port_t, verifies if this lport is registered
1b7fc709228029b3f29f1c3de6d817a476f7c583tim szeto * with the framework and returns a pointer to framework private data for
1b7fc709228029b3f29f1c3de6d817a476f7c583tim szeto * the lport.
1b7fc709228029b3f29f1c3de6d817a476f7c583tim szeto * Returns NULL if the lport was not found.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_lu_provider_t *ilp = (stmf_i_lu_provider_t *)lp->lp_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* See if we need to do a callback */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_INIT)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lp->lp_cb(lp, STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_deregister_lu_provider(stmf_lu_provider_t *lp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_lu_provider_t *ilp = (stmf_i_lu_provider_t *)lp->lp_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ppilp = &stmf_state.stmf_ilplist; *ppilp != NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_register_port_provider(stmf_port_provider_t *pp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* See if we need to do a callback */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_INIT)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pp->pp_cb(pp, STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_deregister_port_provider(stmf_port_provider_t *pp)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ppipp = &stmf_state.stmf_ipplist; *ppipp != NULL;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetostmf_load_ppd_ioctl(stmf_ppioctl_data_t *ppi, uint64_t *ppi_token,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((ppi->ppi_lu_provider + ppi->ppi_port_provider) != 1) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (strncmp(ppi->ppi_name, ppd->ppd_name, 254) == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* New provider */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (s > 254) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* See if this provider already exists */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Link this ppd in */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * User is requesting that the token be checked.
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * If there was another set after the user's get
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * it's an error
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (size_t)ppi->ppi_data_size, &nv, KM_NOSLEEP)) != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Free any existing lists and add this one to the ppd */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* set the token for writes */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* return token to caller */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* If there is a provider registered, do the notifications */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_state.stmf_config_state == STMF_CONFIG_INIT)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ipp = (stmf_i_port_provider_t *)ppd->ppd_provider;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_PROVIDER_DATA_UPDATED, ppd->ppd_nv, cb_flags);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (pppd = &stmf_state.stmf_ppdlist; *pppd != NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((ppi->ppi_lu_provider + ppi->ppi_port_provider) != 1) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (strncmp(ppi->ppi_name, ppd->ppd_name, 254) == 0)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetostmf_get_ppd_ioctl(stmf_ppioctl_data_t *ppi, stmf_ppioctl_data_t *ppi_out,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((ppi->ppi_lu_provider + ppi->ppi_port_provider) != 1) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = ppd->ppd_next) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (strncmp(ppi->ppi_name, ppd->ppd_name, 254) == 0)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((ret = nvlist_pack(ppd->ppd_nv, &bufp, &req_size,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ppd = stmf_state.stmf_ppdlist; ppd != NULL; ppd = nppd) {
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto * 16 is the max string length of a protocol_ident, increase
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto * the size if needed.
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto#define STMF_KSTAT_LU_SZ (STMF_GUID_INPUT + 1 + 256)
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szetotypedef struct stmf_kstat_lu_info {
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szetotypedef struct stmf_kstat_tgt_info {
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto * This array matches the Protocol Identifier in stmf_ioctl.h
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto "Fibre Channel",
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto "Parallel SCSI",
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto "IEEE_1394",
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN"
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto * Update the lun wait/run queue count
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szetostmf_update_kstat_lu_q(scsi_task_t *task, void func())
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto * Update the target(lport) wait/run queue count
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szetostmf_update_kstat_lport_q(scsi_task_t *task, void func())
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto ilp = (stmf_i_local_port_t *)task->task_lport->lport_stmf_private;
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto if (ilp != NULL && ilp->ilport_kstat_io != NULL) {
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szetostmf_update_kstat_lport_io(scsi_task_t *task, stmf_data_buf_t *dbuf)
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto ilp = (stmf_i_local_port_t *)task->task_lport->lport_stmf_private;
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto if (ilp != NULL && ilp->ilport_kstat_io != NULL) {
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szetostmf_update_kstat_lu_io(scsi_task_t *task, stmf_data_buf_t *dbuf)
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto /* create kstat lun info */
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto ks_lu = (stmf_kstat_lu_info_t *)kmem_zalloc(STMF_KSTAT_LU_SZ,
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto (void) sprintf(ks_nm, "stmf_lu_%"PRIxPTR"", (uintptr_t)ilu);
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto if ((ilu->ilu_kstat_info = kstat_create(STMF_MODULE_NAME, 0,
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto sizeof (stmf_kstat_lu_info_t) / sizeof (kstat_named_t),
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto ilu->ilu_kstat_info->ks_data_size = STMF_KSTAT_LU_SZ;
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto kstat_named_init(&ks_lu->i_lun_alias, "lun-alias",
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto /* convert guid to hex string */
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto bzero(ilu->ilu_ascii_hex_guid, sizeof (ilu->ilu_ascii_hex_guid));
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto (void) sprintf(&ilu->ilu_ascii_hex_guid[i * 2], "%02x", p[i]);
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto /* create kstat lun io */
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto (void) sprintf(ks_nm, "stmf_lu_io_%"PRIxPTR"", (uintptr_t)ilu);
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto if ((ilu->ilu_kstat_io = kstat_create(STMF_MODULE_NAME, 0,
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto cmn_err(CE_WARN, "STMF: kstat_create lu_io failed");
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto mutex_init(&ilu->ilu_kstat_lock, NULL, MUTEX_DRIVER, 0);
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto ilu->ilu_kstat_io->ks_lock = &ilu->ilu_kstat_lock;
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szetostmf_create_kstat_lport(stmf_i_local_port_t *ilport)
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto /* create kstat lport info */
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto ks_tgt = (stmf_kstat_tgt_info_t *)kmem_zalloc(STMF_KSTAT_TGT_SZ,
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto (void) sprintf(ks_nm, "stmf_tgt_%"PRIxPTR"", (uintptr_t)ilport);
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto if ((ilport->ilport_kstat_info = kstat_create(STMF_MODULE_NAME,
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto sizeof (stmf_kstat_tgt_info_t) / sizeof (kstat_named_t),
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto cmn_err(CE_WARN, "STMF: kstat_create target failed");
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto ilport->ilport_kstat_info->ks_data_size = STMF_KSTAT_TGT_SZ;
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto kstat_named_init(&ks_tgt->i_tgt_name, "target-name",
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto kstat_named_init(&ks_tgt->i_tgt_alias, "target-alias",
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto /* ident might not be null terminated */
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto len = ilport->ilport_lport->lport_id->ident_length;
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto /* protocol */
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto if ((id = ilport->ilport_lport->lport_id->protocol_id) > PROTOCOL_ANY) {
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto cmn_err(CE_WARN, "STMF: protocol_id out of bound");
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto kstat_named_setstr(&ks_tgt->i_protocol, protocol_ident[id]);
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto /* create kstat lport io */
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto (void) sprintf(ks_nm, "stmf_tgt_io_%"PRIxPTR"", (uintptr_t)ilport);
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto if ((ilport->ilport_kstat_io = kstat_create(STMF_MODULE_NAME, 0,
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto cmn_err(CE_WARN, "STMF: kstat_create target_io failed");
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto mutex_init(&ilport->ilport_kstat_lock, NULL, MUTEX_DRIVER, 0);
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto ilport->ilport_kstat_io->ks_lock = &ilport->ilport_kstat_lock;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ilu = stmf_state.stmf_ilulist; ilu != NULL; ilu = ilu->ilu_next) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte luid = stmf_lookup_id(&stmf_state.stmf_luid_list,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* XXX we should probably check if this lu can be brought online */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* XXX: Generate event */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cv_wait(&stmf_state.stmf_cv, &stmf_state.stmf_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_state.stmf_svc_ilu_draining = ilu->ilu_next;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((stmf_id_data_t *)ilu->ilu_luid)->id_pt_to_object =
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_register_local_port(stmf_local_port_t *lport)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ilport = (stmf_i_local_port_t *)lport->lport_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rw_init(&ilport->ilport_lock, NULL, RW_DRIVER, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ilport->ilport_next = stmf_state.stmf_ilportlist;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_lookup_group_for_target(lport->lport_id->ident,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ilport->ilport_rtpid = atomic_add_16_nv(&stmf_rtpid_counter, 1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_EVENT_ALLOC_HANDLE(ilport->ilport_event_hdl);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_workers_state == STMF_WORKERS_DISABLED) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* XXX we should probably check if this lport can be brought online */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_ctl(STMF_CMD_LPORT_ONLINE, lport, &ssci);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* XXX: Generate event */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_deregister_local_port(stmf_local_port_t *lport)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ilport = (stmf_i_local_port_t *)lport->lport_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ilport->ilport_next->ilport_prev = ilport->ilport_prev;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ilport->ilport_prev->ilport_next = ilport->ilport_next;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_state.stmf_ilportlist = ilport->ilport_next;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_EVENT_FREE_HANDLE(ilport->ilport_event_hdl);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Port provider has to make sure that register/deregister session and
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * port are serialized calls.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_register_scsi_session(stmf_local_port_t *lport, stmf_scsi_session_t *ss)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_local_port_t *ilport = (stmf_i_local_port_t *)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Port state has to be online to register a scsi session. It is
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * possible that we started an offline operation and a new SCSI
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * session started at the same time (in that case also we are going
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to fail the registeration). But any other state is simply
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * a bad port provider implementation.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ilport->ilport_state != STMF_STATE_OFFLINING) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(lport->lport_alias, "Port is trying to "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "register a session while the state is neither "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "online nor offlining");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* sessions use the ilport_lock. No separate lock is required */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ss->ss_session_id = atomic_add_64_nv(&stmf_session_counter, 1);
e17f3b2227c590f1d761b9ec4613cfb05982e6abtim szeto DTRACE_PROBE2(session__online, stmf_local_port_t *, lport,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_deregister_scsi_session(stmf_local_port_t *lport, stmf_scsi_session_t *ss)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_local_port_t *ilport = (stmf_i_local_port_t *)
e17f3b2227c590f1d761b9ec4613cfb05982e6abtim szeto DTRACE_PROBE2(session__offline, stmf_local_port_t *, lport,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ppss = &ilport->ilport_ss_list; *ppss != NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_PANIC, "Deregister session called for non existent"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " session");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_session_destroy_lun_map(ilport, iss);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_session_id_to_issptr(uint64_t session_id, int stay_locked)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_release_itl_handle(stmf_lu_t *lu, stmf_itl_data_t *itl)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(itl->itl_flags & STMF_ITL_BEING_TERMINATED);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (itlpp = &ilu->ilu_itl_list; (*itlpp) != NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lu->lu_abort(lu, STMF_LU_ITL_HANDLE_REMOVED, itl->itl_handle,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_register_itl_handle(stmf_lu_t *lu, uint8_t *lun,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsi_session_t *ss, uint64_t session_id, void *itl_handle)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte n = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((lun_map_ent == NULL) || (lun_map_ent->ent_lu != lu)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte itl = (stmf_itl_data_t *)kmem_zalloc(sizeof (*itl), KM_NOSLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_do_itl_dereg(stmf_lu_t *lu, stmf_itl_data_t *itl, uint8_t hdlrm_reason)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while (atomic_cas_8(&itl->itl_flags, old, new) != old);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Something changed, start all over */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(itl_list, nmaps * sizeof (stmf_itl_data_t *));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } /* lun table for a session */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } /* sessions */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } /* ports */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = 0; i < nu; i++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(itl_list, nmaps * sizeof (stmf_itl_data_t *));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_deregister_itl_handle(stmf_lu_t *lu, uint8_t *lun,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsi_session_t *ss, uint64_t session_id, void *itl_handle)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte n = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (ent->ent_itl_datap->itl_handle == itl_handle)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_do_itl_dereg(lu, itl, STMF_ITL_REASON_DEREG_REQUEST);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_get_itl_handle(stmf_lu_t *lu, uint8_t *lun, stmf_scsi_session_t *ss,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte n = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *itl_handle_retp = ent->ent_itl_datap->itl_handle;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_alloc_dbuf(scsi_task_t *task, uint32_t size, uint32_t *pminsize,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ndx = stmf_first_zero[itask->itask_allocated_buf_map];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf = itask->itask_dbufs[ndx] = lport->lport_ds->ds_alloc_data_buf(
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_free_dbuf(scsi_task_t *task, stmf_data_buf_t *dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte itask->itask_allocated_buf_map &= ~(1 << dbuf->db_handle);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lport->lport_ds->ds_free_data_buf(lport->lport_ds, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_task_alloc(struct stmf_local_port *lport, stmf_scsi_session_t *ss,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t *lun, uint16_t cdb_length_in, uint16_t ext_id)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We allocate 7 extra bytes for CDB to provide a cdb pointer which
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * is guaranteed to be 8 byte aligned. Some LU providers like OSD
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * depend upon this alignment.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte luNbr = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (stmf_lun_map_ent_t *)stmf_get_ent_from_map(iss->iss_sm, luNbr);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ppitask = &ilu->ilu_free_tasks; (*ppitask != NULL) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ilu->ilu_ntasks_free < ilu->ilu_ntasks_min_free)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* CONSTCOND */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while (0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *p++ = 0; *p++ = 0; p++; p++; *p++ = 0; *p++ = 0; *p = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task = (scsi_task_t *)stmf_alloc(STMF_STRUCT_SCSI_TASK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_cdb = (uint8_t *)task->task_port_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* kmem_zalloc automatically makes itask->itask_lu_prev NULL */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte itask->itask_ilu_task_cntr = ilu->ilu_cur_task_cntr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((lun_map_ent != NULL) && ((itask->itask_itl_datap =
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_add_32(&itask->itask_itl_datap->itl_counter, 1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_lu_itl_handle = itask->itask_itl_datap->itl_handle;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(ilu->ilu_ntasks_min_free <= ilu->ilu_ntasks_free);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* free half of the minimal free of the free tasks */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte num_to_release = (ilu->ilu_ntasks_min_free + 1) / 2;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Called with stmf_lock held
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte clock_t endtime = ddi_get_lbolt() + drv_usectohz(10000);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* stmf_svc_ilu_draining may get changed after stmf_lock is released */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while ((ilu = stmf_state.stmf_svc_ilu_draining) != NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_state.stmf_svc_ilu_draining = ilu->ilu_next;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * we do not care about the accuracy of
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ilu_ntasks_min_free, so we don't lock here
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Called with stmf_lock held
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte clock_t endtime = ddi_get_lbolt() + drv_usectohz(10000);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* stmf_svc_ilu_timing may get changed after stmf_lock is released */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte while ((ilu = stmf_state.stmf_svc_ilu_timing) != NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ilu->ilu_cur_task_cntr == (&ilu->ilu_task_cntr1)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If we are here then it means that there is some slowdown
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * in tasks on this lu. We need to check.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Kills all tasks on a lu except tm_task
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_task_lu_killall(stmf_lu_t *lu, scsi_task_t *tm_task, stmf_status_t s)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, itask->itask_task, s, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_free_task_bufs(stmf_i_scsi_task_t *itask, stmf_local_port_t *lport)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((map = itask->itask_allocated_buf_map) != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = 0; i < 4; i++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *)
e17f3b2227c590f1d761b9ec4613cfb05982e6abtim szeto DTRACE_PROBE1(stmf__task__end, scsi_task_t *, task);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (atomic_add_32_nv(&itask->itask_itl_datap->itl_counter,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_add_32(&itask->itask_worker->worker_ref_count, -1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * After calling stmf_task_lu_free, the task pointer can no longer
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * be trusted.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_post_task(scsi_task_t *task, stmf_data_buf_t *dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Latest value of currently running tasks */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Select the next worker using round robin */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte nv = (int)atomic_add_32_nv((uint32_t *)&stmf_worker_sel_counter, 1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Its ok if this cas fails */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) atomic_cas_32((uint32_t *)&stmf_worker_sel_counter,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * A worker can be pinned by interrupt. So select the next one
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * if it has lower load.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (w1->worker_queue_depth < w->worker_queue_depth)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (((w->worker_flags & STMF_WORKER_STARTED) == 0) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Maybe we are in the middle of a change. Just go to
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the 1st worker.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Track max system load inside the worker as we already have the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * worker lock (no point implementing another lock). The service
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * thread will do the comparisons and figure out the max overall
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * system load.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte new |= ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (task->task_cdb[0] == SCMD_REPORT_LUNS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) {
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto stmf_update_kstat_lport_q(task, kstat_waitq_enter);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This can only happen if during stmf_task_alloc(), ILU_RESET_ACTIVE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * was set between checking of ILU_RESET_ACTIVE and clearing of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ITASK_IN_FREE_LIST flag. Take care of these "sneaked-in" tasks here.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task, STMF_ABORTED, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ++++++++++++++ ABORT LOGIC ++++++++++++++++++++
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Once ITASK_BEING_ABORTED is set, ITASK_KNOWN_TO_LU can be reset already
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * i.e. before ITASK_BEING_ABORTED being set. But if it was not, it cannot
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * be reset until the LU explicitly calls stmf_task_lu_aborted(). Of course
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the LU will make this call only if we call the LU's abort entry point.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * we will only call that entry point if ITASK_KNOWN_TO_LU was set.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Same logic applies for the port.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Also ITASK_BEING_ABORTED will not be allowed to set if both KNOWN_TO_LU
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and KNOWN_TO_TGT_PORT are reset.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * +++++++++++++++++++++++++++++++++++++++++++++++
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_xfer_data(scsi_task_t *task, stmf_data_buf_t *dbuf, uint32_t ioflags)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
5679c89fcd2facbb4334df8870d3d7a4d2b11673jv if (atomic_add_32_nv((uint32_t *)&stmf_drop_buf_counter, -1) ==
e17f3b2227c590f1d761b9ec4613cfb05982e6abtim szeto DTRACE_PROBE2(scsi__xfer__start, scsi_task_t *, task,
e17f3b2227c590f1d761b9ec4613cfb05982e6abtim szeto ret = task->task_lport->lport_xfer_data(task, dbuf, ioflags);
e17f3b2227c590f1d761b9ec4613cfb05982e6abtim szeto DTRACE_PROBE2(scsi__xfer__end, scsi_task_t *, task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_data_xfer_done(scsi_task_t *task, stmf_data_buf_t *dbuf, uint32_t iof)
554c2b163439bbe1231a5d9ff5b9b0045c510c69tim szeto uint8_t update_queue_flags, free_it, queue_it, kstat_it;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_completion_status = dbuf->db_xfer_status;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If the task is known to LU then queue it. But if
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * it is already queued (multiple completions) then
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * just update the buffer information by grabbing the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * worker lock. If the task is not known to LU,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * completed/aborted, then see if we need to
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * free this task.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t cmd = (dbuf->db_handle << 5) | ITASK_CMD_DATA_XFER_DONE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte itask->itask_cmd_stack[itask->itask_ncmds++] = cmd;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_send_scsi_status(scsi_task_t *task, uint32_t ioflags)
e17f3b2227c590f1d761b9ec4613cfb05982e6abtim szeto DTRACE_PROBE1(scsi__send__status, scsi_task_t *, task);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!(itask->itask_flags & ITASK_KNOWN_TO_TGT_PORT)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_resid = task->task_expected_xfer_length -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (task->task_lport->lport_send_status(task, ioflags));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_send_status_done(scsi_task_t *task, stmf_status_t s, uint32_t iof)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If the task is known to LU then queue it. But if
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * it is already queued (multiple completions) then
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * just update the buffer information by grabbing the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * worker lock. If the task is not known to LU,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * completed/aborted, then see if we need to
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * free this task.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " when task is already in worker queue "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_PANIC, "LU is done with the task but LPORT "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " when task is in worker queue "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ITASK_KNOWN_TO_TGT_PORT | ITASK_IN_WORKER_QUEUE |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_PANIC, "stmf_lu_done should be the last stage but "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte " the task is still not done, task = %p", (void *)task);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_queue_task_for_abort(scsi_task_t *task, stmf_status_t s)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Queue it and get out */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (itask->itask_flags & ITASK_IN_WORKER_QUEUE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_or_32(&itask->itask_flags, ITASK_IN_WORKER_QUEUE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_abort(int abort_cmd, scsi_task_t *task, stmf_status_t s, void *arg)
e17f3b2227c590f1d761b9ec4613cfb05982e6abtim szeto DTRACE_PROBE2(scsi__task__abort, scsi_task_t *, task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((old & f) != f) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_task_lu_aborted(scsi_task_t *task, stmf_status_t s, uint32_t iof)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte unsigned long long st;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((s != STMF_ABORT_SUCCESS) && (s != STMF_NOT_FOUND)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "task %p, lu failed to abort ret=%llx", (void *)task, st);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Task aborted but LU is not finished, task ="
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * LU abort successfully
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&itask->itask_flags, ~ITASK_KNOWN_TO_LU);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_task_lport_aborted(scsi_task_t *task, stmf_status_t s, uint32_t iof)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte unsigned long long st;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((s != STMF_ABORT_SUCCESS) && (s != STMF_NOT_FOUND)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "task %p, tgt port failed to abort ret=%llx", (void *)task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Task aborted but tgt port is not finished, "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "task=%p, s=%llx, iof=%x", (void *)task, st, iof);
554c2b163439bbe1231a5d9ff5b9b0045c510c69tim szeto * LPORT abort successfully
554c2b163439bbe1231a5d9ff5b9b0045c510c69tim szeto } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
554c2b163439bbe1231a5d9ff5b9b0045c510c69tim szeto if (!(itask->itask_flags & ITASK_KSTAT_IN_RUNQ)) {
554c2b163439bbe1231a5d9ff5b9b0045c510c69tim szeto stmf_update_kstat_lport_q(task, kstat_waitq_exit);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_task_poll_lu(scsi_task_t *task, uint32_t timeout)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (itask->itask_cmd_stack[i] == ITASK_CMD_POLL_LU) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte itask->itask_cmd_stack[itask->itask_ncmds++] = ITASK_CMD_POLL_LU;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((itask->itask_flags & ITASK_IN_WORKER_QUEUE) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_or_32(&itask->itask_flags, ITASK_IN_WORKER_QUEUE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_task_poll_lport(scsi_task_t *task, uint32_t timeout)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_scsi_task_t *itask = (stmf_i_scsi_task_t *)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(itask->itask_flags & ITASK_KNOWN_TO_TGT_PORT);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (itask->itask_cmd_stack[i] == ITASK_CMD_POLL_LPORT) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte itask->itask_cmd_stack[itask->itask_ncmds++] = ITASK_CMD_POLL_LPORT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((itask->itask_flags & ITASK_IN_WORKER_QUEUE) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte unsigned long long ret;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((old & (ITASK_KNOWN_TO_LU | ITASK_LU_ABORT_CALLED)) ==
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((itask->itask_flags & ITASK_DEFAULT_HANDLING) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = lu->lu_abort(lu, STMF_LU_ABORT_TASK, task, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = dlun0->lu_abort(lu, STMF_LU_ABORT_TASK, task, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((ret == STMF_ABORT_SUCCESS) || (ret == STMF_NOT_FOUND)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_task_lu_aborted(task, ret, STMF_IOF_LU_DONE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Abort failed by LU %p, ret %llx", (void *)lu, ret);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (itask->itask_flags & ITASK_KNOWN_TO_LU) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lu->lu_abort_timeout : ITASK_DEFAULT_ABORT_TIMEOUT))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "lu abort timed out");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort_task_offline(itask->itask_task, 1, info);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ITASK_TGT_PORT_ABORT_CALLED)) == ITASK_KNOWN_TO_TGT_PORT) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
5679c89fcd2facbb4334df8870d3d7a4d2b11673jv ret = lport->lport_abort(lport, STMF_LPORT_ABORT_TASK, task, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((ret == STMF_ABORT_SUCCESS) || (ret == STMF_NOT_FOUND)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_task_lport_aborted(task, ret, STMF_IOF_LPORT_DONE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "Abort failed by tgt port %p ret %llx",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (itask->itask_flags & ITASK_KNOWN_TO_TGT_PORT) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "lport abort timed out");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort_task_offline(itask->itask_task, 0, info);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_state_change_info_t *ssci = (stmf_state_change_info_t *)arg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ilport = stmf_lookup_lport((stmf_local_port_t *)obj);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (((stmf_change_status_t *)arg)->st_completion_status ==
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_add_lu_to_active_sessions((stmf_lu_t *)obj);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* XXX: should throw a meesage an record more data */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (((stmf_change_status_t *)arg)->st_completion_status ==
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_add_lu_to_active_sessions((stmf_lu_t *)obj);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * LPORT_ONLINE/OFFLINE has nothing to do with link offline/online.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * It's related with hardware disable/enable.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ilport->ilport_state != STMF_STATE_OFFLINE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Only user request can recover the port from the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * FORCED_OFFLINE state
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ilport->ilport_flags & ILPORT_FORCED_OFFLINE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!(ssci->st_rflags & STMF_RFLAG_USER_REQUEST)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Avoid too frequent request to online
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((ilport->ilport_avg_interval < STMF_AVG_ONLINE_INTERVAL) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(NULL, "stmf_ctl: too frequent request to "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "online the port");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "stmf_ctl: too frequent request to "
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "online the port, set FORCED_OFFLINE now");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ilport->ilport_last_online_clock = ddi_get_lbolt();
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Submit online service request
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ilport->ilport_state != STMF_STATE_ONLINING) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (((stmf_change_status_t *)arg)->st_completion_status ==
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ilport->ilport_state == STMF_STATE_OFFLINE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_svc_queue(cmd, obj, (stmf_state_change_info_t *)arg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ilport->ilport_state != STMF_STATE_OFFLINING) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (((stmf_change_status_t *)arg)->st_completion_status ==
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "Invalid ctl cmd received %x", cmd);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_info_impl(uint32_t cmd, void *arg1, void *arg2, uint8_t *buf,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_info(uint32_t cmd, void *arg1, void *arg2, uint8_t *buf,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (stmf_info_impl(cmd, arg1, arg2, buf, bufsizep));
5679c89fcd2facbb4334df8870d3d7a4d2b11673jv return (((stmf_local_port_t *)arg1)->lport_info(cmd, arg1,
5679c89fcd2facbb4334df8870d3d7a4d2b11673jv return (((stmf_lu_t *)arg1)->lu_info(cmd, arg1, arg2, buf,
70c284ca5360ed73476d9e94223d4905dd80b1adPeter Cudhea - Sun Microsystems - Burlington, MA United States * Used by port providers. pwwn is 8 byte wwn, sdid is the devid used by
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * stmf to register local ports. The ident should have 20 bytes in buffer
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * space to convert the wwn to "wwn.xxxxxxxxxxxxxxxx" string.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_wwn_to_devid_desc(scsi_devid_desc_t *sdid, uint8_t *wwn,
70c284ca5360ed73476d9e94223d4905dd80b1adPeter Cudhea - Sun Microsystems - Burlington, MA United States char wwn_str[20+1];
70c284ca5360ed73476d9e94223d4905dd80b1adPeter Cudhea - Sun Microsystems - Burlington, MA United States
70c284ca5360ed73476d9e94223d4905dd80b1adPeter Cudhea - Sun Microsystems - Burlington, MA United States /* Convert wwn value to "wwn.XXXXXXXXXXXXXXXX" format */
70c284ca5360ed73476d9e94223d4905dd80b1adPeter Cudhea - Sun Microsystems - Burlington, MA United States (void) snprintf(wwn_str, sizeof (wwn_str),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "wwn.%02X%02X%02X%02X%02X%02X%02X%02X",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
70c284ca5360ed73476d9e94223d4905dd80b1adPeter Cudhea - Sun Microsystems - Burlington, MA United States bcopy(wwn_str, (char *)sdid->ident, 20);
70c284ca5360ed73476d9e94223d4905dd80b1adPeter Cudhea - Sun Microsystems - Burlington, MA United States
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* The spec only allows for 255 ports to be reported */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte xd = (stmf_xfer_data_t *)kmem_zalloc(asz, KM_NOSLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport && nports;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte nports++, ilport = ilport->ilport_next, p += 4) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((uint16_t *)p)[1] = BE_16(ilport->ilport_rtpid);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto scsi_devid_desc_t *id = ilport->ilport_lport->lport_id;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetostmf_scsilib_get_lport_rtid(struct scsi_devid_desc *devid)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (memcmp(devid->ident, id->ident, id->ident_length) == 0)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_scsilib_uniq_lu_id(uint32_t company_id, scsi_devid_desc_t *lu_id)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (!localetheraddr((struct ether_addr *)NULL, &mac)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * saa is sense key, ASC, ASCQ
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_scsilib_send_status(scsi_task_t *task, uint8_t st, uint32_t saa)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_send_scsi_status(task, STMF_IOF_LU_DONE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_scsilib_prepare_vpd_page83(scsi_task_t *task, uint8_t *page,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t page_len, uint8_t byte0, uint32_t vpd_mask)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* CONSTCOND */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte copysz = page_len > (n + sz) ? sz : page_len - n;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sz = task->task_lport->lport_id->ident_length + 4;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Group ID is always 0 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_scsilib_handle_report_tpgs(scsi_task_t *task, stmf_data_buf_t *dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * For now we will abort all I/Os on the LU in case of ABORT_TASK_SET
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and ABORT_TASK. But unlike LUN_RESET we will not reset LU state
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * in these cases. This needs to be changed to abort only the required
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* We dont support this task mgmt function */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * To sync with target reset, grab this lock. The LU is not going
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * anywhere as there is atleast one task pending (this task).
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Mark this task as the one causing LU reset so that we know who
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * was responsible for setting the ILU_RESET_ACTIVE. In case this
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * task itself gets aborted, we will clear ILU_RESET_ACTIVE.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte itask->itask_flags |= ITASK_DEFAULT_HANDLING | ITASK_CAUSING_LU_RESET;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Initiatiate abort on all commands on this LU except this one */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_ABORT_LU, task, STMF_ABORTED, task->task_lu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Start polling on this task */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task, STMF_ALLOC_FAILURE,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte itask = (stmf_i_scsi_task_t *)task->task_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iss = (stmf_i_scsi_session_t *)task->task_session->ss_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * To sync with LUN reset, grab this lock. The session is not going
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * anywhere as there is atleast one task pending (this task).
d6b3018d1023e158e4d4f1315056f98b55c6f590Sumit Gupta /* Grab the session lock as a writer to prevent any changes in it */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Now go through each LUN in this session and make sure all of them
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * can be reset.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ilu = (stmf_i_lu_t *)(lm_ent->ent_lu->lu_stmf_private);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (lf == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* No luns in this session */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* ok, start the damage */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ilu = (stmf_i_lu_t *)(lm_ent->ent_lu->lu_stmf_private);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_ABORT_LU, task, STMF_ABORTED,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Start polling on this task */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task, STMF_ALLOC_FAILURE,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_handle_cmd_during_ic(stmf_i_scsi_task_t *itask)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (((iss->iss_flags & ISS_LUN_INVENTORY_CHANGED) == 0) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Make local copy of global tunables */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sizeof (stmf_worker_t) * stmf_i_max_nworkers, KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = 0; i < stmf_i_max_nworkers; i++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte mutex_init(&w->worker_lock, NULL, MUTEX_DRIVER, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_worker_mgmt_delay = drv_usectohz(20 * 1000);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Workers will be started by stmf_worker_mgmt() */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Lets wait for atleast one worker to start */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_worker_mgmt_delay = drv_usectohz(3 * 1000 * 1000);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_worker_mgmt_delay = drv_usectohz(20 * 1000);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sb = ddi_get_lbolt() + drv_usectohz(10 * 1000 * 1000);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Wait for all the threads to die */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = 0; i < stmf_i_max_nworkers; i++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(stmf_workers, sizeof (stmf_worker_t) * stmf_i_max_nworkers);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte w->worker_flags |= STMF_WORKER_STARTED | STMF_WORKER_ACTIVE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((w->worker_ref_count == 0) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* CONSTCOND */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (wait_timer && (ddi_get_lbolt() >= wait_timer)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte curcmd = itask->itask_cmd_stack[itask->itask_ncmds - 1];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(itask->itask_flags & ITASK_BEING_ABORTED);
554c2b163439bbe1231a5d9ff5b9b0045c510c69tim szeto * set ITASK_KSTAT_IN_RUNQ, this flag
554c2b163439bbe1231a5d9ff5b9b0045c510c69tim szeto * will not reset until task completed
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while (atomic_cas_32(&itask->itask_flags, old, new) != old);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Decide if this task needs to go to a queue and/or if
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * we can decrement the itask_cmd_stack.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This is where the queue depth should go down by
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * one but we delay that on purpose to account for
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the call into the provider. The actual decrement
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * happens after the worker has done its job.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* We made it here means we are going to call LU */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((itask->itask_flags & ITASK_DEFAULT_HANDLING) == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf = itask->itask_dbufs[ITASK_CMD_BUF_NDX(curcmd)];
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto stmf_update_kstat_lu_q(task, kstat_waitq_to_runq);
034d83c4b3be1c9bbe03552a652ebb90d4d66885tim szeto stmf_update_kstat_lport_q(task, kstat_waitq_to_runq);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (iss->iss_flags & ISS_LUN_INVENTORY_CHANGED) {
e17f3b2227c590f1d761b9ec4613cfb05982e6abtim szeto DTRACE_PROBE1(scsi__task__start, scsi_task_t *, task);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* case ITASK_CMD_XFER_DATA: */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((w->worker_flags & STMF_WORKER_TERMINATE) && (wait_timer == 0)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) cv_timedwait(&w->worker_cv, &w->worker_lock, wait_timer);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check if we are trying to increase the # of threads */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = stmf_nworkers_cur; i < stmf_nworkers_needed; i++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_workers[i].worker_flags & STMF_WORKER_STARTED) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Wait for transition to complete */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check if we are trying to decrease the # of workers */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = (stmf_nworkers_cur - 1); i >= stmf_nworkers_needed; i--) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((stmf_workers[i].worker_flags & STMF_WORKER_STARTED) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * stmf_nworkers_accepting_cmds has already been
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * updated by the request to reduce the # of workers.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Wait for transition to complete */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check if we are being asked to quit */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_workers_state != STMF_WORKERS_ENABLED) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check if we are starting */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = 0; i < stmf_nworkers_accepting_cmds; i++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* still ramping up */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* max qdepth cannot be more than max tasks */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* See if we have more workers */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Since we dont reduce the worker count right away, monitor
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the highest load during the scale_down_delay.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (ddi_get_lbolt() < stmf_worker_scale_down_timer) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Its time to reduce the workers */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_worker_scale_down_qd < stmf_i_min_nworkers)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_worker_scale_down_qd > stmf_i_max_nworkers)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_worker_scale_down_qd == stmf_nworkers_cur)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* NOTREACHED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = stmf_nworkers_cur; i < workers_needed; i++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte w->worker_tid = thread_create(NULL, 0, stmf_worker_task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* At this point we know that we are decreasing the # of workers */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Signal the workers that its time to quit */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = (stmf_nworkers_cur - 1); i >= stmf_nworkers_needed; i--) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(w && (w->worker_flags & STMF_WORKER_STARTED));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Fills out a dbuf from stmf_xfer_data_t (contained in the db_lu_private).
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If all the data has been filled out, frees the xd and makes
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * db_lu_private NULL.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte s = min(xd->size_left, dbuf->db_sglist[i].seg_length);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_dlun0_new_task(scsi_task_t *task, stmf_data_buf_t *dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (cdbp[0]) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Basic protocol checks. In addition, only reply to
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * standard inquiry. Otherwise, the LU provider needs
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to respond.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (sz == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbuf && (dbuf->db_sglist[0].seg_length < 36)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Ignore any preallocated dbuf if the size is less
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * than 36. It will be freed during the task_free.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((dbuf == NULL) || (dbuf->db_sglist[0].seg_length < sz)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Standard inquiry handling only.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte xd = stmf_session_prepare_report_lun_data(iss->iss_sm);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK, STMF_SAA_INVALID_OPCODE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_dlun0_dbuf_done(scsi_task_t *task, stmf_data_buf_t *dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_nbytes_transferred = dbuf->db_data_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* There is more */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_dlun0_abort(struct stmf_lu *lu, int abort_cmd, void *arg, uint32_t flags)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((task->task_mgmt_function) && (itask->itask_flags &
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (ITASK_CAUSING_LU_RESET | ITASK_CAUSING_TARGET_RESET))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&ilu->ilu_flags, ~ILU_RESET_ACTIVE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * OK so its not a task mgmt. Make sure we free any xd sitting
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * inside any dbuf.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((map = itask->itask_allocated_buf_map) != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = 0; i < 4; i++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Right now we only do this for handling task management functions */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_lun_reset_poll(task->task_lu, task, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_dlun0_ctl(struct stmf_lu *lu, int cmd, void *arg)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* This function will never be called */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_WARN, "stmf_dlun0_ctl called with cmd %x", cmd);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dlun0->lu_send_status_done = stmf_dlun0_status_done;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ilu = (stmf_i_lu_t *)lm_ent->ent_lu->lu_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&ilu->ilu_flags, ~ILU_RESET_ACTIVE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The return value is only used by function managing target reset.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_lun_reset_poll(stmf_lu_t *lu, struct scsi_task *task, int target_reset)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ntasks_pending = ilu->ilu_ntasks - ilu->ilu_ntasks_free;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This function is also used during Target reset. The idea is that
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * once all the commands are aborted, call the LU's reset entry
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * point (abort entry point with a reset flag). But if this Task
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * mgmt is running on this LU then all the tasks cannot be aborted.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * one task (this task) will still be running which is OK.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((ntasks_pending == 0) || ((task->task_lu == lu) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((task->task_mgmt_function == TM_LUN_RESET) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (task->task_mgmt_function == TM_TARGET_WARM_RESET) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (task->task_mgmt_function == TM_TARGET_COLD_RESET)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = lu->lu_abort(lu, STMF_LU_RESET_STATE, task, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&ilu->ilu_flags, ~ILU_RESET_ACTIVE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task, ret, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Tell target reset polling code that we are not done */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_scsi_session_t *iss = (stmf_i_scsi_session_t *)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ilu = (stmf_i_lu_t *)lm_ent->ent_lu->lu_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ret = stmf_lun_reset_poll(lm_ent->ent_lu, task, 1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_task_poll_lu(task, ITASK_DEFAULT_POLL_TIMEOUT)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte atomic_and_32(&iss->iss_flags, ~ISS_RESET_ACTIVE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_i_lu_t *ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_lport_add_event(stmf_local_port_t *lport, int eventid)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_EVENT_ADD(ilport->ilport_event_hdl, eventid);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_lport_remove_event(stmf_local_port_t *lport, int eventid)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((eventid < 0) || (eventid >= STMF_MAX_NUM_EVENTS)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_EVENT_REMOVE(ilport->ilport_event_hdl, eventid);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_generate_lu_event(stmf_i_lu_t *ilu, int eventid, void *arg, uint32_t flags)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (STMF_EVENT_ENABLED(ilu->ilu_event_hdl, eventid) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ilu->ilu_lu->lu_event_handler(ilu->ilu_lu, eventid, arg, flags);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_generate_lport_event(stmf_i_local_port_t *ilport, int eventid, void *arg,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (STMF_EVENT_ENABLED(ilport->ilport_event_hdl, eventid) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (ilport->ilport_lport->lport_event_handler != NULL)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_state.stmf_svc_taskq = ddi_taskq_create(0, "STMF_SVC_TASKQ", 1,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) ddi_taskq_dispatch(stmf_state.stmf_svc_taskq,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Wait for 5 seconds */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = 0; i < 500; i++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (i == 500)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_state.stmf_svc_flags |= STMF_SVC_STARTED | STMF_SVC_ACTIVE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_state.stmf_svc_flags & STMF_SVC_TERMINATE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Fallthrough */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Fallthrough */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Nothing to do */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Remove all mappings of this LU */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_session_lu_unmapall((stmf_lu_t *)req->svc_obj);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Kill all the pending I/Os for this LU */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_task_lu_killall((stmf_lu_t *)req->svc_obj, NULL,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Put it in the wait queue */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* The waiting list is not going to be modified by anybody else */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (preq = &stmf_state.stmf_svc_waiting; (*preq) != NULL; ) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Fallthrough */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lport->lport_ctl(lport, req->svc_cmd, &req->svc_info);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Do timeouts */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((!timing_next) || (ddi_get_lbolt() >= timing_next))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* we are starting a new round */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* we finished a complete round */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* we still have some ilu items to check */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check if there are free tasks to clear */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((!drain_next) || (ddi_get_lbolt() >= drain_next))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* we are starting a new round */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* we finished a complete round */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* we still have some ilu items to check */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check if we need to run worker_mgmt */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Check if any active session got its 1st LUN */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (ilport = stmf_state.stmf_ilportlist; ilport;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * scan all the ilports again as the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ilport list might have changed.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* drop the lock if we are holding it. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Max 4 session at a time */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) cv_timedwait(&stmf_state.stmf_cv, &stmf_state.stmf_lock,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_svc_queue(int cmd, void *obj, stmf_state_change_info_t *info)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte req->svc_info.st_additional_info = (char *)(GET_BYTE_OFFSET(req,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((stmf_state.stmf_svc_flags & STMF_SVC_ACTIVE) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = snprintf(tbuf, 158, "%s:%07lu: ", ident ? ident : "",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len += vsnprintf(tbuf + len, 158 - len, fmt, args);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(tbuf, &stmf_trace_buf[trace_buf_curndx], len+1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_abort_task_offline(scsi_task_t *task, int offline_lu, char *info)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace("FROM STMF", "abort_task_offline called for %s: %s",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte offline_lu ? "LU" : "LPORT", info ? info : "no additional info");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_lport->lport_stmf_private)->ilport_state ==
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_trace(0, "Calling stmf_ctl to offline %s : %s",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "<no additional info>");