Print this page
NEX-6018 Return of the walking dead idm_refcnt_wait_ref comstar threads
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5428 Backout the 5.0 changes
NEX-2937 Continuous write_same starves all other commands
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
NEX-5602 cpqary3: add support for more hp gen9 smart array controllers
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Marcel Telka <marcel.telka@nexenta.com>
NEX-1533 fcinfo hba-port doesn't get correct supported speeds and connection speed for 16Gb target ports
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
NEX-4532 STC comstar FC test causes panic on 5.0
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
NEX-3856 panic is occurred in module "fct" due to a NULL pointer dereference
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
NEX-2787 Multiple comstar / fibre channel / qlt threads stuck waiting on locks with a spinning interrupt thread
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Approved by: Jean McCormack <jean.mccormack@nexenta.com>
*** 111,121 ****
--- 111,137 ----
static uint32_t rportid_table_size = FCT_HASH_TABLE_SIZE;
static int max_cached_ncmds = FCT_MAX_CACHED_CMDS;
static fct_i_local_port_t *fct_iport_list = NULL;
static kmutex_t fct_global_mutex;
uint32_t fct_rscn_options = RSCN_OPTION_VERIFY;
+ /*
+ * This is to keep fibre channel from hanging if syseventd is
+ * not working correctly and the queue fills. It is a tunable
+ * to allow the user to force event logging to always happen
+ * which is the default.
+ */
+ static uint8_t fct_force_log = 0; /* use DDI_SLEEP on ddi_log_sysevent */
+ /*
+ * For use during core examination. These counts are normally really low
+ * since they're bumped during port operations. If a customer core shows
+ * really high values without having an uptime of a year something is most
+ * likely wrong with their environment.
+ */
+ int fct_els_cnt = 0;
+ int fct_abort_cnt = 0;
+
int
_init(void)
{
int ret;
*** 1186,1196 ****
/* fct_cmds for SCSI traffic */
iport->iport_total_alloced_ncmds = 0;
iport->iport_cached_ncmds = 0;
port->port_fca_fcp_cmd_size =
(port->port_fca_fcp_cmd_size + 7) & ~7;
! iport->iport_cached_cmdlist = NULL;
mutex_init(&iport->iport_cached_cmd_lock, NULL, MUTEX_DRIVER, NULL);
/* Initialize cmd slots */
iport->iport_cmd_slots = (fct_cmd_slot_t *)kmem_zalloc(
port->port_max_xchges * sizeof (fct_cmd_slot_t), KM_SLEEP);
--- 1202,1216 ----
/* fct_cmds for SCSI traffic */
iport->iport_total_alloced_ncmds = 0;
iport->iport_cached_ncmds = 0;
port->port_fca_fcp_cmd_size =
(port->port_fca_fcp_cmd_size + 7) & ~7;
! list_create(&iport->iport_cached_cmdlist, sizeof (fct_i_cmd_t),
! offsetof(fct_i_cmd_t, icmd_node));
! list_create(&iport->iport_abort_queue, sizeof (fct_i_cmd_t),
! offsetof(fct_i_cmd_t, icmd_node));
!
mutex_init(&iport->iport_cached_cmd_lock, NULL, MUTEX_DRIVER, NULL);
/* Initialize cmd slots */
iport->iport_cmd_slots = (fct_cmd_slot_t *)kmem_zalloc(
port->port_max_xchges * sizeof (fct_cmd_slot_t), KM_SLEEP);
*** 1275,1285 ****
fct_status_t
fct_deregister_local_port(fct_local_port_t *port)
{
fct_i_local_port_t *iport;
! fct_i_cmd_t *icmd, *next_icmd;
int ndx;
iport = (fct_i_local_port_t *)port->port_fct_private;
if ((iport->iport_state != FCT_STATE_OFFLINE) ||
--- 1295,1305 ----
fct_status_t
fct_deregister_local_port(fct_local_port_t *port)
{
fct_i_local_port_t *iport;
! fct_i_cmd_t *icmd;
int ndx;
iport = (fct_i_local_port_t *)port->port_fct_private;
if ((iport->iport_state != FCT_STATE_OFFLINE) ||
*** 1320,1332 ****
/*
* At this time, there should be no outstanding and pending
* I/Os, so we can just release resources.
*/
ASSERT(iport->iport_total_alloced_ncmds == iport->iport_cached_ncmds);
! for (icmd = iport->iport_cached_cmdlist; icmd; icmd = next_icmd) {
! next_icmd = icmd->icmd_next;
! fct_free(icmd->icmd_cmd);
}
mutex_destroy(&iport->iport_cached_cmd_lock);
kmem_free(iport->iport_cmd_slots, port->port_max_xchges *
sizeof (fct_cmd_slot_t));
kmem_free(iport->iport_rp_slots, port->port_max_logins *
--- 1340,1352 ----
/*
* At this time, there should be no outstanding and pending
* I/Os, so we can just release resources.
*/
ASSERT(iport->iport_total_alloced_ncmds == iport->iport_cached_ncmds);
! while (!list_is_empty(&iport->iport_cached_cmdlist)) {
! icmd = list_remove_head(&iport->iport_cached_cmdlist);
! fct_free(icmd);
}
mutex_destroy(&iport->iport_cached_cmd_lock);
kmem_free(iport->iport_cmd_slots, port->port_max_xchges *
sizeof (fct_cmd_slot_t));
kmem_free(iport->iport_rp_slots, port->port_max_logins *
*** 1475,1496 ****
rw_enter(&irp->irp_lock, RW_WRITER);
if ((irp->irp_flags & IRP_IN_DISCOVERY_QUEUE) == 0) {
logging_out = 0;
goto ilo_done;
}
! if ((irp->irp_els_list == NULL) && (irp->irp_deregister_timer)) {
if (force_implicit && irp->irp_nonfcp_xchg_count) {
logging_out = 0;
} else {
logging_out = 1;
}
goto ilo_done;
}
! if (irp->irp_els_list) {
fct_i_cmd_t *icmd;
/* Last session affecting ELS should be a LOGO */
! for (icmd = irp->irp_els_list; icmd; icmd = icmd->icmd_next) {
uint8_t op = (ICMD_TO_ELS(icmd))->els_req_payload[0];
if (op == ELS_OP_LOGO) {
if (force_implicit) {
if (icmd->icmd_flags & ICMD_IMPLICIT)
logging_out = 1;
--- 1495,1517 ----
rw_enter(&irp->irp_lock, RW_WRITER);
if ((irp->irp_flags & IRP_IN_DISCOVERY_QUEUE) == 0) {
logging_out = 0;
goto ilo_done;
}
! if (list_is_empty(&irp->irp_els_list) && (irp->irp_deregister_timer)) {
if (force_implicit && irp->irp_nonfcp_xchg_count) {
logging_out = 0;
} else {
logging_out = 1;
}
goto ilo_done;
}
! if (!list_is_empty(&irp->irp_els_list)) {
fct_i_cmd_t *icmd;
/* Last session affecting ELS should be a LOGO */
! for (icmd = list_head(&irp->irp_els_list); icmd;
! icmd = list_next(&irp->irp_els_list, icmd)) {
uint8_t op = (ICMD_TO_ELS(icmd))->els_req_payload[0];
if (op == ELS_OP_LOGO) {
if (force_implicit) {
if (icmd->icmd_flags & ICMD_IMPLICIT)
logging_out = 1;
*** 1610,1620 ****
return (1);
}
fct_cmd_t *
fct_scsi_task_alloc(fct_local_port_t *port, uint16_t rp_handle,
! uint32_t rportid, uint8_t *lun, uint16_t cdb_length, uint16_t task_ext)
{
fct_cmd_t *cmd;
fct_i_cmd_t *icmd;
fct_i_local_port_t *iport =
(fct_i_local_port_t *)port->port_fct_private;
--- 1631,1642 ----
return (1);
}
fct_cmd_t *
fct_scsi_task_alloc(fct_local_port_t *port, uint16_t rp_handle,
! uint32_t rportid, uint8_t *lun, uint16_t cdb_length,
! uint16_t task_ext)
{
fct_cmd_t *cmd;
fct_i_cmd_t *icmd;
fct_i_local_port_t *iport =
(fct_i_local_port_t *)port->port_fct_private;
*** 1658,1669 ****
"login was not done. portid=%x, rp=%p", rp->rp_id, rp);
return (NULL);
}
mutex_enter(&iport->iport_cached_cmd_lock);
! if ((icmd = iport->iport_cached_cmdlist) != NULL) {
! iport->iport_cached_cmdlist = icmd->icmd_next;
iport->iport_cached_ncmds--;
cmd = icmd->icmd_cmd;
} else {
icmd = NULL;
}
--- 1680,1691 ----
"login was not done. portid=%x, rp=%p", rp->rp_id, rp);
return (NULL);
}
mutex_enter(&iport->iport_cached_cmd_lock);
! if (!list_is_empty(&iport->iport_cached_cmdlist)) {
! icmd = list_remove_head(&iport->iport_cached_cmdlist);
iport->iport_cached_ncmds--;
cmd = icmd->icmd_cmd;
} else {
icmd = NULL;
}
*** 1678,1688 ****
"memory, port=%p", port);
return (NULL);
}
icmd = (fct_i_cmd_t *)cmd->cmd_fct_private;
! icmd->icmd_next = NULL;
cmd->cmd_port = port;
atomic_inc_32(&iport->iport_total_alloced_ncmds);
}
/*
--- 1700,1710 ----
"memory, port=%p", port);
return (NULL);
}
icmd = (fct_i_cmd_t *)cmd->cmd_fct_private;
! list_link_init(&icmd->icmd_node);
cmd->cmd_port = port;
atomic_inc_32(&iport->iport_total_alloced_ncmds);
}
/*
*** 1882,1901 ****
*/
void
fct_post_to_discovery_queue(fct_i_local_port_t *iport,
fct_i_remote_port_t *irp, fct_i_cmd_t *icmd)
{
- fct_i_cmd_t **p;
-
ASSERT(!MUTEX_HELD(&iport->iport_worker_lock));
if (icmd) {
! icmd->icmd_next = NULL;
! for (p = &irp->irp_els_list; *p != NULL;
! p = &((*p)->icmd_next))
! ;
!
! *p = icmd;
atomic_or_32(&icmd->icmd_flags, ICMD_IN_IRP_QUEUE);
}
mutex_enter(&iport->iport_worker_lock);
if ((irp->irp_flags & IRP_IN_DISCOVERY_QUEUE) == 0) {
--- 1904,1917 ----
*/
void
fct_post_to_discovery_queue(fct_i_local_port_t *iport,
fct_i_remote_port_t *irp, fct_i_cmd_t *icmd)
{
ASSERT(!MUTEX_HELD(&iport->iport_worker_lock));
if (icmd) {
! list_insert_tail(&irp->irp_els_list, icmd);
! fct_els_cnt++;
atomic_or_32(&icmd->icmd_flags, ICMD_IN_IRP_QUEUE);
}
mutex_enter(&iport->iport_worker_lock);
if ((irp->irp_flags & IRP_IN_DISCOVERY_QUEUE) == 0) {
*** 2123,2134 ****
/* Free the cmd */
if (cmd->cmd_type == FCT_CMD_FCP_XCHG) {
if (iport->iport_cached_ncmds < max_cached_ncmds) {
icmd->icmd_flags = 0;
mutex_enter(&iport->iport_cached_cmd_lock);
! icmd->icmd_next = iport->iport_cached_cmdlist;
! iport->iport_cached_cmdlist = icmd;
iport->iport_cached_ncmds++;
mutex_exit(&iport->iport_cached_cmd_lock);
} else {
atomic_dec_32(&iport->iport_total_alloced_ncmds);
fct_free(cmd);
--- 2139,2149 ----
/* Free the cmd */
if (cmd->cmd_type == FCT_CMD_FCP_XCHG) {
if (iport->iport_cached_ncmds < max_cached_ncmds) {
icmd->icmd_flags = 0;
mutex_enter(&iport->iport_cached_cmd_lock);
! list_insert_head(&iport->iport_cached_cmdlist, icmd);
iport->iport_cached_ncmds++;
mutex_exit(&iport->iport_cached_cmd_lock);
} else {
atomic_dec_32(&iport->iport_total_alloced_ncmds);
fct_free(cmd);
*** 2827,2838 ****
atomic_and_32(&icmd->icmd_flags, ~ICMD_KNOWN_TO_FCA);
/* For non FCP Rest of the work is done by the terminator */
/* For FCP stuff just call stmf */
if (cmd->cmd_type == FCT_CMD_FCP_XCHG) {
! stmf_task_lport_aborted((scsi_task_t *)cmd->cmd_specific,
! s, STMF_IOF_LPORT_DONE);
}
}
/*
* FCA drivers will use it, when they want to abort some FC transactions
--- 2842,2853 ----
atomic_and_32(&icmd->icmd_flags, ~ICMD_KNOWN_TO_FCA);
/* For non FCP Rest of the work is done by the terminator */
/* For FCP stuff just call stmf */
if (cmd->cmd_type == FCT_CMD_FCP_XCHG) {
! stmf_task_lport_aborted_unlocked(
! (scsi_task_t *)cmd->cmd_specific, s, STMF_IOF_LPORT_DONE);
}
}
/*
* FCA drivers will use it, when they want to abort some FC transactions
*** 2901,2923 ****
*((uint16_t *)(p+4)) = BE_16(cmd->cmd_oxid);
*((uint16_t *)(p+6)) = BE_16(cmd->cmd_rxid);
p[10] = p[11] = 0xff;
}
void
fct_handle_rcvd_abts(fct_cmd_t *cmd)
{
char info[FCT_INFO_LEN];
fct_local_port_t *port = cmd->cmd_port;
fct_i_local_port_t *iport =
(fct_i_local_port_t *)port->port_fct_private;
fct_i_cmd_t *icmd = (fct_i_cmd_t *)cmd->cmd_fct_private;
fct_i_remote_port_t *irp;
! fct_cmd_t *c = NULL;
fct_i_cmd_t *ic = NULL;
int found = 0;
int i;
icmd->icmd_start_time = ddi_get_lbolt();
icmd->icmd_flags |= ICMD_KNOWN_TO_FCA;
rw_enter(&iport->iport_lock, RW_WRITER);
--- 2916,2984 ----
*((uint16_t *)(p+4)) = BE_16(cmd->cmd_oxid);
*((uint16_t *)(p+6)) = BE_16(cmd->cmd_rxid);
p[10] = p[11] = 0xff;
}
+ /*
+ * fct_cmd_unlink_els -- remove icmd from ELS queue
+ *
+ * The commands are found via the slot array of active commands and will be
+ * terminated shortly after being removed.
+ */
void
+ fct_cmd_unlink_els(fct_i_remote_port_t *irp, fct_i_cmd_t *icmd)
+ {
+ ASSERT(rw_write_held(&irp->irp_lock));
+ if (icmd->icmd_node.list_next) {
+ /*
+ * Command is on two queues. Determine which queue and
+ * handle appropriately.
+ */
+ if (icmd->icmd_flags & ICMD_IN_IRP_QUEUE) {
+ /*
+ * If the command is active on the IRP queue it
+ * will be freed during command termination
+ * processing. Unfortuntely the ELS processing will
+ * peek at the command and possibly panic if it's
+ * been freed already. Remove it from the ELS
+ * queue to avoid that.
+ */
+ if (icmd->icmd_flags & ICMD_SESSION_AFFECTING)
+ atomic_dec_16(&irp->irp_sa_elses_count);
+ else
+ atomic_dec_16(&irp->irp_nsa_elses_count);
+ atomic_and_32(&icmd->icmd_flags, ~ICMD_IN_IRP_QUEUE);
+ list_remove(&irp->irp_els_list, icmd);
+ }
+ /*
+ * There's an else case here, but the processing is handled
+ * in fct_check_solcmd_queue(). In this case the command
+ * is on the solicited queue and will be marked as aborted.
+ * During command termination processing the command will be
+ * marked as complete, but not freed. The freeing of the memory
+ * is done in fct_check_solcmd_queue(). If that routine, which
+ * holds the appropriate lock, is run first it will remove the
+ * command from the abort queue so that no memory access
+ * is done after the command has been freed.
+ */
+ }
+ }
+
+ void
fct_handle_rcvd_abts(fct_cmd_t *cmd)
{
char info[FCT_INFO_LEN];
fct_local_port_t *port = cmd->cmd_port;
fct_i_local_port_t *iport =
(fct_i_local_port_t *)port->port_fct_private;
fct_i_cmd_t *icmd = (fct_i_cmd_t *)cmd->cmd_fct_private;
fct_i_remote_port_t *irp;
! fct_cmd_t *c = NULL, *term_cmd;
fct_i_cmd_t *ic = NULL;
int found = 0;
int i;
+ fct_status_t term_val;
icmd->icmd_start_time = ddi_get_lbolt();
icmd->icmd_flags |= ICMD_KNOWN_TO_FCA;
rw_enter(&iport->iport_lock, RW_WRITER);
*** 2996,3022 ****
fct_cmd_free(cmd);
}
return;
}
/* Check if this an abts retry */
if (c->cmd_link && (ic->icmd_flags & ICMD_ABTS_RECEIVED)) {
/* Kill this abts. */
! fct_q_for_termination_lock_held(iport, icmd, FCT_ABORTED);
! if (IS_WORKER_SLEEPING(iport))
! cv_signal(&iport->iport_worker_cv);
! mutex_exit(&iport->iport_worker_lock);
! rw_exit(&irp->irp_lock);
! rw_exit(&iport->iport_lock);
! return;
! }
c->cmd_link = cmd;
atomic_or_32(&ic->icmd_flags, ICMD_ABTS_RECEIVED);
cmd->cmd_link = c;
mutex_exit(&iport->iport_worker_lock);
rw_exit(&irp->irp_lock);
! fct_queue_cmd_for_termination(c, FCT_ABTS_RECEIVED);
rw_exit(&iport->iport_lock);
}
void
fct_queue_cmd_for_termination(fct_cmd_t *cmd, fct_status_t s)
--- 3057,3083 ----
fct_cmd_free(cmd);
}
return;
}
+ fct_cmd_unlink_els(irp, ic);
+
/* Check if this an abts retry */
if (c->cmd_link && (ic->icmd_flags & ICMD_ABTS_RECEIVED)) {
/* Kill this abts. */
! term_cmd = icmd->icmd_cmd;
! term_val = FCT_ABORTED;
! } else {
c->cmd_link = cmd;
atomic_or_32(&ic->icmd_flags, ICMD_ABTS_RECEIVED);
cmd->cmd_link = c;
+ term_cmd = c;
+ term_val = FCT_ABTS_RECEIVED;
+ }
mutex_exit(&iport->iport_worker_lock);
rw_exit(&irp->irp_lock);
! fct_queue_cmd_for_termination(term_cmd, term_val);
rw_exit(&iport->iport_lock);
}
void
fct_queue_cmd_for_termination(fct_cmd_t *cmd, fct_status_t s)
*** 3043,3053 ****
void
fct_q_for_termination_lock_held(fct_i_local_port_t *iport, fct_i_cmd_t *icmd,
fct_status_t s)
{
uint32_t old, new;
- fct_i_cmd_t **ppicmd;
do {
old = icmd->icmd_flags;
if (old & ICMD_BEING_ABORTED)
return;
--- 3104,3113 ----
*** 3055,3070 ****
} while (atomic_cas_32(&icmd->icmd_flags, old, new) != old);
icmd->icmd_start_time = ddi_get_lbolt();
icmd->icmd_cmd->cmd_comp_status = s;
! icmd->icmd_next = NULL;
! for (ppicmd = &(iport->iport_abort_queue); *ppicmd != NULL;
! ppicmd = &((*ppicmd)->icmd_next))
! ;
!
! *ppicmd = icmd;
}
/*
* For those cmds, for which we called fca_abort but it has not yet completed,
* reset the FCA_ABORT_CALLED flag, so that abort can be called again.
--- 3115,3126 ----
} while (atomic_cas_32(&icmd->icmd_flags, old, new) != old);
icmd->icmd_start_time = ddi_get_lbolt();
icmd->icmd_cmd->cmd_comp_status = s;
! list_insert_tail(&iport->iport_abort_queue, icmd);
! fct_abort_cnt++;
}
/*
* For those cmds, for which we called fca_abort but it has not yet completed,
* reset the FCA_ABORT_CALLED flag, so that abort can be called again.
*** 3239,3249 ****
disc_action_t
fct_cmd_terminator(fct_i_local_port_t *iport)
{
char info[FCT_INFO_LEN];
clock_t endtime;
! fct_i_cmd_t **ppicmd;
fct_i_cmd_t *icmd;
fct_cmd_t *cmd;
fct_local_port_t *port = iport->iport_port;
disc_action_t ret = DISC_ACTION_NO_WORK;
fct_status_t abort_ret;
--- 3295,3305 ----
disc_action_t
fct_cmd_terminator(fct_i_local_port_t *iport)
{
char info[FCT_INFO_LEN];
clock_t endtime;
! fct_i_cmd_t *next;
fct_i_cmd_t *icmd;
fct_cmd_t *cmd;
fct_local_port_t *port = iport->iport_port;
disc_action_t ret = DISC_ACTION_NO_WORK;
fct_status_t abort_ret;
*** 3254,3276 ****
/* Lets Limit each run to 20ms max. */
endtime = ddi_get_lbolt() + drv_usectohz(20000);
/* Start from where we left off last time */
if (iport->iport_ppicmd_term) {
! ppicmd = iport->iport_ppicmd_term;
iport->iport_ppicmd_term = NULL;
} else {
! ppicmd = &iport->iport_abort_queue;
}
/*
* Once a command gets on discovery queue, this is the only thread
* which can access it. So no need for the lock here.
*/
mutex_exit(&iport->iport_worker_lock);
! while ((icmd = *ppicmd) != NULL) {
cmd = icmd->icmd_cmd;
/* Always remember that cmd->cmd_rp can be NULL */
if ((icmd->icmd_flags & (ICMD_KNOWN_TO_FCA |
ICMD_FCA_ABORT_CALLED)) == ICMD_KNOWN_TO_FCA) {
--- 3310,3332 ----
/* Lets Limit each run to 20ms max. */
endtime = ddi_get_lbolt() + drv_usectohz(20000);
/* Start from where we left off last time */
if (iport->iport_ppicmd_term) {
! icmd = iport->iport_ppicmd_term;
iport->iport_ppicmd_term = NULL;
} else {
! icmd = list_head(&iport->iport_abort_queue);
}
/*
* Once a command gets on discovery queue, this is the only thread
* which can access it. So no need for the lock here.
*/
mutex_exit(&iport->iport_worker_lock);
! while (icmd) {
cmd = icmd->icmd_cmd;
/* Always remember that cmd->cmd_rp can be NULL */
if ((icmd->icmd_flags & (ICMD_KNOWN_TO_FCA |
ICMD_FCA_ABORT_CALLED)) == ICMD_KNOWN_TO_FCA) {
*** 3299,3309 ****
iport->iport_port,
STMF_RFLAG_FATAL_ERROR |
STMF_RFLAG_RESET, info);
mutex_enter(&iport->iport_worker_lock);
! iport->iport_ppicmd_term = ppicmd;
return (DISC_ACTION_DELAY_RESCAN);
}
atomic_and_32(&icmd->icmd_flags,
~ICMD_FCA_ABORT_CALLED);
} else if ((flags & FCT_IOF_FORCE_FCA_DONE) ||
--- 3355,3365 ----
iport->iport_port,
STMF_RFLAG_FATAL_ERROR |
STMF_RFLAG_RESET, info);
mutex_enter(&iport->iport_worker_lock);
! iport->iport_ppicmd_term = icmd;
return (DISC_ACTION_DELAY_RESCAN);
}
atomic_and_32(&icmd->icmd_flags,
~ICMD_FCA_ABORT_CALLED);
} else if ((flags & FCT_IOF_FORCE_FCA_DONE) ||
*** 3327,3339 ****
fct_done = 1;
else
fct_done = 0;
if ((fca_done || cmd_implicit) && fct_done) {
mutex_enter(&iport->iport_worker_lock);
! ASSERT(*ppicmd == icmd);
! *ppicmd = (*ppicmd)->icmd_next;
mutex_exit(&iport->iport_worker_lock);
if ((cmd->cmd_type == FCT_CMD_RCVD_ELS) ||
(cmd->cmd_type == FCT_CMD_RCVD_ABTS)) {
/* Free the cmd */
fct_cmd_free(cmd);
} else if (cmd->cmd_type == FCT_CMD_SOL_ELS) {
--- 3383,3396 ----
fct_done = 1;
else
fct_done = 0;
if ((fca_done || cmd_implicit) && fct_done) {
mutex_enter(&iport->iport_worker_lock);
! next = list_next(&iport->iport_abort_queue, icmd);
! list_remove(&iport->iport_abort_queue, icmd);
mutex_exit(&iport->iport_worker_lock);
+
if ((cmd->cmd_type == FCT_CMD_RCVD_ELS) ||
(cmd->cmd_type == FCT_CMD_RCVD_ABTS)) {
/* Free the cmd */
fct_cmd_free(cmd);
} else if (cmd->cmd_type == FCT_CMD_SOL_ELS) {
*** 3405,3425 ****
st);
(void) fct_port_shutdown(port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET,
info);
}
! ppicmd = &((*ppicmd)->icmd_next);
}
if (ddi_get_lbolt() > endtime) {
mutex_enter(&iport->iport_worker_lock);
! iport->iport_ppicmd_term = ppicmd;
return (DISC_ACTION_DELAY_RESCAN);
}
}
mutex_enter(&iport->iport_worker_lock);
! if (iport->iport_abort_queue)
return (DISC_ACTION_DELAY_RESCAN);
if (ret == DISC_ACTION_NO_WORK)
return (DISC_ACTION_RESCAN);
return (ret);
}
--- 3462,3486 ----
st);
(void) fct_port_shutdown(port,
STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET,
info);
}
! mutex_enter(&iport->iport_worker_lock);
! next = list_next(&iport->iport_abort_queue, icmd);
! mutex_exit(&iport->iport_worker_lock);
}
if (ddi_get_lbolt() > endtime) {
mutex_enter(&iport->iport_worker_lock);
! iport->iport_ppicmd_term = next;
return (DISC_ACTION_DELAY_RESCAN);
+ } else {
+ icmd = next;
}
}
mutex_enter(&iport->iport_worker_lock);
! if (!list_is_empty(&iport->iport_abort_queue))
return (DISC_ACTION_DELAY_RESCAN);
if (ret == DISC_ACTION_NO_WORK)
return (DISC_ACTION_RESCAN);
return (ret);
}
*** 3430,3439 ****
--- 3491,3501 ----
void
fct_log_local_port_event(fct_local_port_t *port, char *subclass)
{
nvlist_t *attr_list;
int port_instance;
+ int rc, sleep = DDI_SLEEP;
if (!fct_dip)
return;
port_instance = ddi_get_instance(fct_dip);
*** 3450,3461 ****
if (nvlist_add_byte_array(attr_list, "port-wwn",
port->port_pwwn, 8) != DDI_SUCCESS) {
goto error;
}
! (void) ddi_log_sysevent(fct_dip, DDI_VENDOR_SUNW, EC_SUNFC,
! subclass, attr_list, NULL, DDI_SLEEP);
nvlist_free(attr_list);
return;
error:
--- 3512,3530 ----
if (nvlist_add_byte_array(attr_list, "port-wwn",
port->port_pwwn, 8) != DDI_SUCCESS) {
goto error;
}
! if (fct_force_log == 0) {
! sleep = DDI_NOSLEEP;
! }
! rc = ddi_log_sysevent(fct_dip, DDI_VENDOR_SUNW, EC_SUNFC,
! subclass, attr_list, NULL, sleep);
! if (rc != DDI_SUCCESS) {
! cmn_err(CE_WARN, "%s: queue full event lost", __func__);
! goto error;
! }
nvlist_free(attr_list);
return;
error:
*** 3469,3478 ****
--- 3538,3548 ----
fct_log_remote_port_event(fct_local_port_t *port, char *subclass,
uint8_t *rp_pwwn, uint32_t rp_id)
{
nvlist_t *attr_list;
int port_instance;
+ int rc, sleep = DDI_SLEEP;
if (!fct_dip)
return;
port_instance = ddi_get_instance(fct_dip);
*** 3499,3510 ****
if (nvlist_add_uint32(attr_list, "target-port-id",
rp_id) != DDI_SUCCESS) {
goto error;
}
! (void) ddi_log_sysevent(fct_dip, DDI_VENDOR_SUNW, EC_SUNFC,
! subclass, attr_list, NULL, DDI_SLEEP);
nvlist_free(attr_list);
return;
error:
--- 3569,3587 ----
if (nvlist_add_uint32(attr_list, "target-port-id",
rp_id) != DDI_SUCCESS) {
goto error;
}
! if (fct_force_log == 0) {
! sleep = DDI_NOSLEEP;
! }
! rc = ddi_log_sysevent(fct_dip, DDI_VENDOR_SUNW, EC_SUNFC,
! subclass, attr_list, NULL, sleep);
! if (rc != DDI_SUCCESS) {
! cmn_err(CE_WARN, "%s:event dropped", __func__);
! goto error;
! }
nvlist_free(attr_list);
return;
error: