85 extern uint32_t fct_rscn_options;
86
87 /*
88 * NOTE: if anybody drops the iport_worker_lock then they should not return
89 * DISC_ACTION_NO_WORK. Which also means, dont drop the lock if you have
90 * nothing to do. Or else return DISC_ACTION_RESCAN or DISC_ACTION_DELAY_RESCAN.
91 * But you cannot be infinitly returning those so have some logic to
92 * determine that there is nothing to do without dropping the lock.
93 */
94 void
95 fct_port_worker(void *arg)
96 {
97 fct_local_port_t *port = (fct_local_port_t *)arg;
98 fct_i_local_port_t *iport = (fct_i_local_port_t *)
99 port->port_fct_private;
100 disc_action_t suggested_action;
101 clock_t dl, short_delay, long_delay;
102 int64_t tmp_delay;
103
104 iport->iport_cmdcheck_clock = ddi_get_lbolt() +
105 drv_usectohz(FCT_CMDLIST_CHECK_SECONDS * 1000000);
106 short_delay = drv_usectohz(10000);
107 long_delay = drv_usectohz(1000000);
108
109 stmf_trace(iport->iport_alias, "iport is %p", iport);
110 /* Discovery loop */
111 mutex_enter(&iport->iport_worker_lock);
112 atomic_or_32(&iport->iport_flags, IPORT_WORKER_RUNNING);
113 while ((iport->iport_flags & IPORT_TERMINATE_WORKER) == 0) {
114 suggested_action = DISC_ACTION_NO_WORK;
115 /*
116 * Local port events are of the highest prioriy
117 */
118 if (iport->iport_event_head) {
119 suggested_action |= fct_handle_local_port_event(iport);
120 }
121
122 /*
123 * We could post solicited ELSes to discovery queue.
124 * solicited CT will be processed inside fct_check_solcmd_queue
125 */
126 if (iport->iport_solcmd_queue) {
127 suggested_action |= fct_check_solcmd_queue(iport);
139 */
140 if ((iport->iport_link_state == PORT_STATE_LINK_INIT_START) &&
141 !(iport->iport_li_state & (LI_STATE_FLAG_CMD_WAITING |
142 LI_STATE_FLAG_NO_LI_YET))) {
143 suggested_action |= fct_process_link_init(iport);
144 }
145
146 /*
147 * We process cmd aborting in the end
148 */
149 if (iport->iport_abort_queue) {
150 suggested_action |= fct_cmd_terminator(iport);
151 }
152
153 /*
154 * Check cmd max/free
155 */
156 if (iport->iport_cmdcheck_clock <= ddi_get_lbolt()) {
157 suggested_action |= fct_check_cmdlist(iport);
158 iport->iport_cmdcheck_clock = ddi_get_lbolt() +
159 drv_usectohz(FCT_CMDLIST_CHECK_SECONDS * 1000000);
160 iport->iport_max_active_ncmds = 0;
161 }
162
163 if (iport->iport_offline_prstate != FCT_OPR_DONE) {
164 suggested_action |= fct_handle_port_offline(iport);
165 }
166
167 if (suggested_action & DISC_ACTION_RESCAN) {
168 continue;
169 } else if (suggested_action & DISC_ACTION_DELAY_RESCAN) {
170 /*
171 * This is not very optimum as whoever returned
172 * DISC_ACTION_DELAY_RESCAN must have dropped the lock
173 * and more things might have queued up. But since
174 * we are only doing small delays, it only delays
175 * things by a few ms, which is okey.
176 */
177 if (suggested_action & DISC_ACTION_USE_SHORT_DELAY) {
178 dl = short_delay;
179 } else {
579 */
580 if ((li->port_topology ^
581 iport->iport_link_old_topology) &
582 PORT_TOPOLOGY_FABRIC_BIT) {
583 mutex_exit(&iport->iport_worker_lock);
584 fct_rehash(iport);
585 mutex_enter(&iport->iport_worker_lock);
586 }
587 }
588 iport->iport_link_old_topology = li->port_topology;
589 }
590 /* Skip next level if topo is not N2N */
591 if (li->port_topology != PORT_TOPOLOGY_PT_TO_PT) {
592 iport->iport_li_state += 2;
593 atomic_and_32(&iport->iport_flags,
594 ~IPORT_ALLOW_UNSOL_FLOGI);
595 } else {
596 iport->iport_li_state++;
597 iport->iport_login_retry = 0;
598 iport->iport_li_cmd_timeout = ddi_get_lbolt() +
599 drv_usectohz(25 * 1000000);
600 }
601 goto check_state_again;
602
603 case LI_STATE_N2N_PLOGI:
604 ASSERT(IPORT_FLOGI_DONE(iport));
605 ASSERT(iport->iport_link_info.port_topology ==
606 PORT_TOPOLOGY_PT_TO_PT);
607 if (iport->iport_li_state & LI_STATE_FLAG_CMD_RETCHECK) {
608 iport->iport_li_state &= ~LI_STATE_FLAG_CMD_RETCHECK;
609 if (iport->iport_li_comp_status != FCT_SUCCESS) {
610 iport->iport_login_retry++;
611 if (iport->iport_login_retry >= 3) {
612 stmf_trace(iport->iport_alias, "Failing"
613 " to PLOGI to remote port in N2N "
614 " ret=%llx, forcing link down",
615 iport->iport_li_comp_status);
616 mutex_exit(&iport->iport_worker_lock);
617 fct_handle_event(iport->iport_port,
618 FCT_EVENT_LINK_DOWN, 0, 0);
619 mutex_enter(&iport->iport_worker_lock);
|
85 extern uint32_t fct_rscn_options;
86
87 /*
88 * NOTE: if anybody drops the iport_worker_lock then they should not return
89 * DISC_ACTION_NO_WORK. Which also means, dont drop the lock if you have
90 * nothing to do. Or else return DISC_ACTION_RESCAN or DISC_ACTION_DELAY_RESCAN.
91 * But you cannot be infinitly returning those so have some logic to
92 * determine that there is nothing to do without dropping the lock.
93 */
94 void
95 fct_port_worker(void *arg)
96 {
97 fct_local_port_t *port = (fct_local_port_t *)arg;
98 fct_i_local_port_t *iport = (fct_i_local_port_t *)
99 port->port_fct_private;
100 disc_action_t suggested_action;
101 clock_t dl, short_delay, long_delay;
102 int64_t tmp_delay;
103
104 iport->iport_cmdcheck_clock = ddi_get_lbolt() +
105 drv_sectohz(FCT_CMDLIST_CHECK_SECONDS);
106 short_delay = drv_usectohz(10000);
107 long_delay = drv_sectohz(1);
108
109 stmf_trace(iport->iport_alias, "iport is %p", iport);
110 /* Discovery loop */
111 mutex_enter(&iport->iport_worker_lock);
112 atomic_or_32(&iport->iport_flags, IPORT_WORKER_RUNNING);
113 while ((iport->iport_flags & IPORT_TERMINATE_WORKER) == 0) {
114 suggested_action = DISC_ACTION_NO_WORK;
115 /*
116 * Local port events are of the highest prioriy
117 */
118 if (iport->iport_event_head) {
119 suggested_action |= fct_handle_local_port_event(iport);
120 }
121
122 /*
123 * We could post solicited ELSes to discovery queue.
124 * solicited CT will be processed inside fct_check_solcmd_queue
125 */
126 if (iport->iport_solcmd_queue) {
127 suggested_action |= fct_check_solcmd_queue(iport);
139 */
140 if ((iport->iport_link_state == PORT_STATE_LINK_INIT_START) &&
141 !(iport->iport_li_state & (LI_STATE_FLAG_CMD_WAITING |
142 LI_STATE_FLAG_NO_LI_YET))) {
143 suggested_action |= fct_process_link_init(iport);
144 }
145
146 /*
147 * We process cmd aborting in the end
148 */
149 if (iport->iport_abort_queue) {
150 suggested_action |= fct_cmd_terminator(iport);
151 }
152
153 /*
154 * Check cmd max/free
155 */
156 if (iport->iport_cmdcheck_clock <= ddi_get_lbolt()) {
157 suggested_action |= fct_check_cmdlist(iport);
158 iport->iport_cmdcheck_clock = ddi_get_lbolt() +
159 drv_sectohz(FCT_CMDLIST_CHECK_SECONDS);
160 iport->iport_max_active_ncmds = 0;
161 }
162
163 if (iport->iport_offline_prstate != FCT_OPR_DONE) {
164 suggested_action |= fct_handle_port_offline(iport);
165 }
166
167 if (suggested_action & DISC_ACTION_RESCAN) {
168 continue;
169 } else if (suggested_action & DISC_ACTION_DELAY_RESCAN) {
170 /*
171 * This is not very optimum as whoever returned
172 * DISC_ACTION_DELAY_RESCAN must have dropped the lock
173 * and more things might have queued up. But since
174 * we are only doing small delays, it only delays
175 * things by a few ms, which is okey.
176 */
177 if (suggested_action & DISC_ACTION_USE_SHORT_DELAY) {
178 dl = short_delay;
179 } else {
579 */
580 if ((li->port_topology ^
581 iport->iport_link_old_topology) &
582 PORT_TOPOLOGY_FABRIC_BIT) {
583 mutex_exit(&iport->iport_worker_lock);
584 fct_rehash(iport);
585 mutex_enter(&iport->iport_worker_lock);
586 }
587 }
588 iport->iport_link_old_topology = li->port_topology;
589 }
590 /* Skip next level if topo is not N2N */
591 if (li->port_topology != PORT_TOPOLOGY_PT_TO_PT) {
592 iport->iport_li_state += 2;
593 atomic_and_32(&iport->iport_flags,
594 ~IPORT_ALLOW_UNSOL_FLOGI);
595 } else {
596 iport->iport_li_state++;
597 iport->iport_login_retry = 0;
598 iport->iport_li_cmd_timeout = ddi_get_lbolt() +
599 drv_sectohz(25);
600 }
601 goto check_state_again;
602
603 case LI_STATE_N2N_PLOGI:
604 ASSERT(IPORT_FLOGI_DONE(iport));
605 ASSERT(iport->iport_link_info.port_topology ==
606 PORT_TOPOLOGY_PT_TO_PT);
607 if (iport->iport_li_state & LI_STATE_FLAG_CMD_RETCHECK) {
608 iport->iport_li_state &= ~LI_STATE_FLAG_CMD_RETCHECK;
609 if (iport->iport_li_comp_status != FCT_SUCCESS) {
610 iport->iport_login_retry++;
611 if (iport->iport_login_retry >= 3) {
612 stmf_trace(iport->iport_alias, "Failing"
613 " to PLOGI to remote port in N2N "
614 " ret=%llx, forcing link down",
615 iport->iport_li_comp_status);
616 mutex_exit(&iport->iport_worker_lock);
617 fct_handle_event(iport->iport_port,
618 FCT_EVENT_LINK_DOWN, 0, 0);
619 mutex_enter(&iport->iport_worker_lock);
|