Deleted Added
full compact
isp_freebsd.c (163899) isp_freebsd.c (164272)
1/*-
2 *
3 * Copyright (c) 1997-2006 by Matthew Jacob
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 15 unchanged lines hidden (view full) ---

24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28/*
29 * Platform (FreeBSD) dependent common attachment code for Qlogic adapters.
30 */
31#include <sys/cdefs.h>
1/*-
2 *
3 * Copyright (c) 1997-2006 by Matthew Jacob
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 15 unchanged lines hidden (view full) ---

24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28/*
29 * Platform (FreeBSD) dependent common attachment code for Qlogic adapters.
30 */
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/isp/isp_freebsd.c 163899 2006-11-02 03:21:32Z mjacob $");
32__FBSDID("$FreeBSD: head/sys/dev/isp/isp_freebsd.c 164272 2006-11-14 08:45:48Z mjacob $");
33#include <dev/isp/isp_freebsd.h>
34#include <sys/unistd.h>
35#include <sys/kthread.h>
36#include <machine/stdarg.h> /* for use by isp_prt below */
37#include <sys/conf.h>
38#include <sys/module.h>
39#include <sys/ioccom.h>
40#include <dev/isp/isp_ioctl.h>
41#if __FreeBSD_version >= 500000
42#include <sys/sysctl.h>
43#endif
33#include <dev/isp/isp_freebsd.h>
34#include <sys/unistd.h>
35#include <sys/kthread.h>
36#include <machine/stdarg.h> /* for use by isp_prt below */
37#include <sys/conf.h>
38#include <sys/module.h>
39#include <sys/ioccom.h>
40#include <dev/isp/isp_ioctl.h>
41#if __FreeBSD_version >= 500000
42#include <sys/sysctl.h>
43#endif
44#include <cam/cam_periph.h>
44
45
46MODULE_VERSION(isp, 1);
47MODULE_DEPEND(isp, cam, 1, 1, 1);
48int isp_announced = 0;
49int isp_fabric_hysteresis = 5;
50int isp_loop_down_limit = 300; /* default loop down limit */
45
46
47MODULE_VERSION(isp, 1);
48MODULE_DEPEND(isp, cam, 1, 1, 1);
49int isp_announced = 0;
50int isp_fabric_hysteresis = 5;
51int isp_loop_down_limit = 300; /* default loop down limit */
51int isp_quickboot_time = 5; /* don't wait more than N secs for loop up */
52int isp_change_is_bad = 0; /* "changed" devices are bad */
53int isp_quickboot_time = 15; /* don't wait more than N secs for loop up */
54int isp_gone_device_time = 30; /* grace time before reporting device lost */
55static const char *roles[4] = {
56 "(none)", "Target", "Initiator", "Target/Initiator"
57};
58static const char prom3[] =
59 "PortID 0x%06x Departed from Target %u because of %s";
52
60
61static void isp_freeze_loopdown(ispsoftc_t *, char *);
53static d_ioctl_t ispioctl;
54static void isp_intr_enable(void *);
55static void isp_cam_async(void *, uint32_t, struct cam_path *, void *);
56static void isp_poll(struct cam_sim *);
57static timeout_t isp_watchdog;
62static d_ioctl_t ispioctl;
63static void isp_intr_enable(void *);
64static void isp_cam_async(void *, uint32_t, struct cam_path *, void *);
65static void isp_poll(struct cam_sim *);
66static timeout_t isp_watchdog;
67static timeout_t isp_ldt;
58static void isp_kthread(void *);
59static void isp_action(struct cam_sim *, union ccb *);
60
61#if __FreeBSD_version < 700000
62ispfwfunc *isp_get_firmware_p = NULL;
63#endif
64
65#if __FreeBSD_version < 500000

--- 100 unchanged lines hidden (view full) ---

166 isp->isp_path = path;
167 /*
168 * Create a kernel thread for fibre channel instances. We
169 * don't have dual channel FC cards.
170 */
171 if (IS_FC(isp)) {
172 ISPLOCK_2_CAMLOCK(isp);
173#if __FreeBSD_version >= 500000
68static void isp_kthread(void *);
69static void isp_action(struct cam_sim *, union ccb *);
70
71#if __FreeBSD_version < 700000
72ispfwfunc *isp_get_firmware_p = NULL;
73#endif
74
75#if __FreeBSD_version < 500000

--- 100 unchanged lines hidden (view full) ---

176 isp->isp_path = path;
177 /*
178 * Create a kernel thread for fibre channel instances. We
179 * don't have dual channel FC cards.
180 */
181 if (IS_FC(isp)) {
182 ISPLOCK_2_CAMLOCK(isp);
183#if __FreeBSD_version >= 500000
174 /* XXX: LOCK VIOLATION */
175 cv_init(&isp->isp_osinfo.kthread_cv, "isp_kthread_cv");
176 if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
177 RFHIGHPID, 0, "%s: fc_thrd",
178 device_get_nameunit(isp->isp_dev)))
179#else
180 if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
181 "%s: fc_thrd", device_get_nameunit(isp->isp_dev)))
182#endif
183 {
184 xpt_bus_deregister(cam_sim_path(sim));
185 cam_sim_free(sim, TRUE);
186 config_intrhook_disestablish(&isp->isp_osinfo.ehook);
187 CAMLOCK_2_ISPLOCK(isp);
188 isp_prt(isp, ISP_LOGERR, "could not create kthread");
189 return;
190 }
191 CAMLOCK_2_ISPLOCK(isp);
184 cv_init(&isp->isp_osinfo.kthread_cv, "isp_kthread_cv");
185 if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
186 RFHIGHPID, 0, "%s: fc_thrd",
187 device_get_nameunit(isp->isp_dev)))
188#else
189 if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
190 "%s: fc_thrd", device_get_nameunit(isp->isp_dev)))
191#endif
192 {
193 xpt_bus_deregister(cam_sim_path(sim));
194 cam_sim_free(sim, TRUE);
195 config_intrhook_disestablish(&isp->isp_osinfo.ehook);
196 CAMLOCK_2_ISPLOCK(isp);
197 isp_prt(isp, ISP_LOGERR, "could not create kthread");
198 return;
199 }
200 CAMLOCK_2_ISPLOCK(isp);
201 /*
202 * We start by being "loop down" if we have an initiator role
203 */
204 if (isp->isp_role & ISP_ROLE_INITIATOR) {
205 isp_freeze_loopdown(isp, "isp_attach");
206 isp->isp_osinfo.ldt =
207 timeout(isp_ldt, isp, isp_quickboot_time * hz);
208 isp->isp_osinfo.ldt_running = 1;
209 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
210 "Starting Initial Loop Down Timer");
211 }
192 }
193
194
195 /*
196 * If we have a second channel, construct SIM entry for that.
197 */
198 if (IS_DUALBUS(isp)) {
199 ISPLOCK_2_CAMLOCK(isp);

--- 54 unchanged lines hidden (view full) ---

254 while (tmp->isp_osinfo.next) {
255 tmp = tmp->isp_osinfo.next;
256 }
257 tmp->isp_osinfo.next = isp;
258 }
259 isp_sysctl_update(isp);
260}
261
212 }
213
214
215 /*
216 * If we have a second channel, construct SIM entry for that.
217 */
218 if (IS_DUALBUS(isp)) {
219 ISPLOCK_2_CAMLOCK(isp);

--- 54 unchanged lines hidden (view full) ---

274 while (tmp->isp_osinfo.next) {
275 tmp = tmp->isp_osinfo.next;
276 }
277 tmp->isp_osinfo.next = isp;
278 }
279 isp_sysctl_update(isp);
280}
281
262static __inline void
282static void
263isp_freeze_loopdown(ispsoftc_t *isp, char *msg)
264{
265 if (isp->isp_osinfo.simqfrozen == 0) {
266 isp_prt(isp, ISP_LOGDEBUG0, "%s: freeze simq (loopdown)", msg);
267 isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
268 ISPLOCK_2_CAMLOCK(isp);
269 xpt_freeze_simq(isp->isp_sim, 1);
270 CAMLOCK_2_ISPLOCK(isp);

--- 356 unchanged lines hidden (view full) ---

627static void
628isp_sysctl_update(ispsoftc_t *isp)
629{
630 struct sysctl_ctx_list *ctx =
631 device_get_sysctl_ctx(isp->isp_osinfo.dev);
632 struct sysctl_oid *tree = device_get_sysctl_tree(isp->isp_osinfo.dev);
633
634 if (IS_SCSI(isp)) {
283isp_freeze_loopdown(ispsoftc_t *isp, char *msg)
284{
285 if (isp->isp_osinfo.simqfrozen == 0) {
286 isp_prt(isp, ISP_LOGDEBUG0, "%s: freeze simq (loopdown)", msg);
287 isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
288 ISPLOCK_2_CAMLOCK(isp);
289 xpt_freeze_simq(isp->isp_sim, 1);
290 CAMLOCK_2_ISPLOCK(isp);

--- 356 unchanged lines hidden (view full) ---

647static void
648isp_sysctl_update(ispsoftc_t *isp)
649{
650 struct sysctl_ctx_list *ctx =
651 device_get_sysctl_ctx(isp->isp_osinfo.dev);
652 struct sysctl_oid *tree = device_get_sysctl_tree(isp->isp_osinfo.dev);
653
654 if (IS_SCSI(isp)) {
635 isp->isp_osinfo.sysctl_info.spi.iid = DEFAULT_IID(isp);
636 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "iid",
637 CTLFLAG_RD, &isp->isp_osinfo.sysctl_info.spi.iid, 0,
638 "Initiator ID");
639 return;
640 }
655 return;
656 }
657
641 snprintf(isp->isp_osinfo.sysctl_info.fc.wwnn,
642 sizeof (isp->isp_osinfo.sysctl_info.fc.wwnn), "0x%08x%08x",
643 (uint32_t) (ISP_NODEWWN(isp) >> 32), (uint32_t) ISP_NODEWWN(isp));
644
645 snprintf(isp->isp_osinfo.sysctl_info.fc.wwpn,
646 sizeof (isp->isp_osinfo.sysctl_info.fc.wwpn), "0x%08x%08x",
647 (uint32_t) (ISP_PORTWWN(isp) >> 32), (uint32_t) ISP_PORTWWN(isp));
648
649 SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
650 "wwnn", CTLFLAG_RD, isp->isp_osinfo.sysctl_info.fc.wwnn, 0,
651 "World Wide Node Name");
658 snprintf(isp->isp_osinfo.sysctl_info.fc.wwnn,
659 sizeof (isp->isp_osinfo.sysctl_info.fc.wwnn), "0x%08x%08x",
660 (uint32_t) (ISP_NODEWWN(isp) >> 32), (uint32_t) ISP_NODEWWN(isp));
661
662 snprintf(isp->isp_osinfo.sysctl_info.fc.wwpn,
663 sizeof (isp->isp_osinfo.sysctl_info.fc.wwpn), "0x%08x%08x",
664 (uint32_t) (ISP_PORTWWN(isp) >> 32), (uint32_t) ISP_PORTWWN(isp));
665
666 SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
667 "wwnn", CTLFLAG_RD, isp->isp_osinfo.sysctl_info.fc.wwnn, 0,
668 "World Wide Node Name");
669
652 SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
653 "wwpn", CTLFLAG_RD, isp->isp_osinfo.sysctl_info.fc.wwpn, 0,
654 "World Wide Port Name");
670 SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
671 "wwpn", CTLFLAG_RD, isp->isp_osinfo.sysctl_info.fc.wwpn, 0,
672 "World Wide Port Name");
673
674 SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
675 "loop_down_limit",
676 CTLFLAG_RW, &isp->isp_osinfo.loop_down_limit, 0,
677 "How long to wait for loop to come back up");
678
679 SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
680 "gone_device_time",
681 CTLFLAG_RW, &isp->isp_osinfo.gone_device_time, 0,
682 "How long to wait for a device to reappear");
655}
656#endif
657
658static void
659isp_intr_enable(void *arg)
660{
661 ispsoftc_t *isp = arg;
662 if (isp->isp_role != ISP_ROLE_NONE) {

--- 1348 unchanged lines hidden (view full) ---

2011 ISP_LOCK(isp);
2012 if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
2013 isp_intr(isp, isr, sema, mbox);
2014 }
2015 ISP_UNLOCK(isp);
2016}
2017
2018
683}
684#endif
685
686static void
687isp_intr_enable(void *arg)
688{
689 ispsoftc_t *isp = arg;
690 if (isp->isp_role != ISP_ROLE_NONE) {

--- 1348 unchanged lines hidden (view full) ---

2039 ISP_LOCK(isp);
2040 if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
2041 isp_intr(isp, isr, sema, mbox);
2042 }
2043 ISP_UNLOCK(isp);
2044}
2045
2046
2019static void
2020isp_watchdog(void *arg)
2047static int isp_watchdog_work(ispsoftc_t *, XS_T *);
2048
2049static int
2050isp_watchdog_work(ispsoftc_t *isp, XS_T *xs)
2021{
2051{
2022 XS_T *xs = arg;
2023 ispsoftc_t *isp = XS_ISP(xs);
2024 uint32_t handle;
2025
2026 /*
2027 * We've decided this command is dead. Make sure we're not trying
2028 * to kill a command that's already dead by getting it's handle and
2029 * and seeing whether it's still alive.
2030 */
2031 ISP_LOCK(isp);
2032 handle = isp_find_handle(isp, xs);
2033 if (handle) {
2034 uint32_t isr;
2035 uint16_t sema, mbox;
2036
2037 if (XS_CMD_DONE_P(xs)) {
2038 isp_prt(isp, ISP_LOGDEBUG1,
2039 "watchdog found done cmd (handle 0x%x)", handle);
2040 ISP_UNLOCK(isp);
2052 uint32_t handle;
2053
2054 /*
2055 * We've decided this command is dead. Make sure we're not trying
2056 * to kill a command that's already dead by getting it's handle and
2057 * and seeing whether it's still alive.
2058 */
2059 ISP_LOCK(isp);
2060 handle = isp_find_handle(isp, xs);
2061 if (handle) {
2062 uint32_t isr;
2063 uint16_t sema, mbox;
2064
2065 if (XS_CMD_DONE_P(xs)) {
2066 isp_prt(isp, ISP_LOGDEBUG1,
2067 "watchdog found done cmd (handle 0x%x)", handle);
2068 ISP_UNLOCK(isp);
2041 return;
2069 return (1);;
2042 }
2043
2044 if (XS_CMD_WDOG_P(xs)) {
2045 isp_prt(isp, ISP_LOGDEBUG2,
2046 "recursive watchdog (handle 0x%x)", handle);
2047 ISP_UNLOCK(isp);
2070 }
2071
2072 if (XS_CMD_WDOG_P(xs)) {
2073 isp_prt(isp, ISP_LOGDEBUG2,
2074 "recursive watchdog (handle 0x%x)", handle);
2075 ISP_UNLOCK(isp);
2048 return;
2076 return (1);
2049 }
2050
2051 XS_CMD_S_WDOG(xs);
2052 if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
2053 isp_intr(isp, isr, sema, mbox);
2054 }
2055 if (XS_CMD_DONE_P(xs)) {
2056 isp_prt(isp, ISP_LOGDEBUG2,
2057 "watchdog cleanup for handle 0x%x", handle);
2077 }
2078
2079 XS_CMD_S_WDOG(xs);
2080 if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
2081 isp_intr(isp, isr, sema, mbox);
2082 }
2083 if (XS_CMD_DONE_P(xs)) {
2084 isp_prt(isp, ISP_LOGDEBUG2,
2085 "watchdog cleanup for handle 0x%x", handle);
2086 ISPLOCK_2_CAMLOCK(isp);
2058 xpt_done((union ccb *) xs);
2087 xpt_done((union ccb *) xs);
2088 CAMLOCK_2_ISPLOCK(isp);
2059 } else if (XS_CMD_GRACE_P(xs)) {
2060 /*
2061 * Make sure the command is *really* dead before we
2062 * release the handle (and DMA resources) for reuse.
2063 */
2089 } else if (XS_CMD_GRACE_P(xs)) {
2090 /*
2091 * Make sure the command is *really* dead before we
2092 * release the handle (and DMA resources) for reuse.
2093 */
2064 (void) isp_control(isp, ISPCTL_ABORT_CMD, arg);
2094 (void) isp_control(isp, ISPCTL_ABORT_CMD, xs);
2065
2066 /*
2067 * After this point, the comamnd is really dead.
2068 */
2069 if (XS_XFRLEN(xs)) {
2070 ISP_DMAFREE(isp, xs, handle);
2071 }
2072 isp_destroy_handle(isp, handle);
2073 xpt_print_path(xs->ccb_h.path);
2074 isp_prt(isp, ISP_LOGWARN,
2075 "watchdog timeout for handle 0x%x", handle);
2076 XS_SETERR(xs, CAM_CMD_TIMEOUT);
2077 XS_CMD_C_WDOG(xs);
2095
2096 /*
2097 * After this point, the comamnd is really dead.
2098 */
2099 if (XS_XFRLEN(xs)) {
2100 ISP_DMAFREE(isp, xs, handle);
2101 }
2102 isp_destroy_handle(isp, handle);
2103 xpt_print_path(xs->ccb_h.path);
2104 isp_prt(isp, ISP_LOGWARN,
2105 "watchdog timeout for handle 0x%x", handle);
2106 XS_SETERR(xs, CAM_CMD_TIMEOUT);
2107 XS_CMD_C_WDOG(xs);
2108 ISPLOCK_2_CAMLOCK(isp);
2078 isp_done(xs);
2109 isp_done(xs);
2110 CAMLOCK_2_ISPLOCK(isp);
2079 } else {
2080 XS_CMD_C_WDOG(xs);
2081 xs->ccb_h.timeout_ch = timeout(isp_watchdog, xs, hz);
2082 XS_CMD_S_GRACE(xs);
2083 isp->isp_sendmarker |= 1 << XS_CHANNEL(xs);
2084 }
2111 } else {
2112 XS_CMD_C_WDOG(xs);
2113 xs->ccb_h.timeout_ch = timeout(isp_watchdog, xs, hz);
2114 XS_CMD_S_GRACE(xs);
2115 isp->isp_sendmarker |= 1 << XS_CHANNEL(xs);
2116 }
2117 ISP_UNLOCK(isp);
2118 return (1);
2119 }
2120 ISP_UNLOCK(isp);
2121 return (0);
2122}
2123
2124static void
2125isp_watchdog(void *arg)
2126{
2127 ispsoftc_t *isp;
2128 XS_T *xs = arg;
2129 for (isp = isplist; isp != NULL; isp = isp->isp_osinfo.next) {
2130 if (isp_watchdog_work(isp, xs)) {
2131 break;
2132 }
2133 }
2134 if (isp == NULL) {
2135 printf("isp_watchdog: nobody had %p active\n", arg);
2136 }
2137}
2138
2139
2140#if __FreeBSD_version >= 500000
2141#define isp_make_here(isp, tgt) isp_announce(isp, tgt, AC_FOUND_DEVICE)
2142#define isp_make_gone(isp, tgt) isp_announce(isp, tgt, AC_LOST_DEVICE)
2143
2144/*
2145 * Support function for Announcement
2146 */
2147static void
2148isp_announce(ispsoftc_t *isp, int tgt, int action)
2149{
2150 struct cam_path *tmppath;
2151 ISPLOCK_2_CAMLOCK(isp);
2152 if (xpt_create_path(&tmppath, NULL, cam_sim_path(isp->isp_sim), tgt,
2153 CAM_LUN_WILDCARD) == CAM_REQ_CMP) {
2154 xpt_async(action, tmppath, NULL);
2155 xpt_free_path(tmppath);
2156 }
2157 CAMLOCK_2_ISPLOCK(isp);
2158}
2159#else
2160#define isp_make_here(isp, tgt) do { ; } while (0)
2161#define isp_make_gone(isp, tgt) do { ; } while (0)
2162#endif
2163
2164
2165/*
2166 * Gone Device Timer Function- when we have decided that a device has gone
2167 * away, we wait a specific period of time prior to telling the OS it has
2168 * gone away.
2169 *
2170 * This timer function fires once a second and then scans the port database
2171 * for devices that are marked dead but still have a virtual target assigned.
2172 * We decrement a counter for that port database entry, and when it hits zero,
2173 * we tell the OS the device has gone away.
2174 */
2175static void
2176isp_gdt(void *arg)
2177{
2178 ispsoftc_t *isp = arg;
2179 fcportdb_t *lp;
2180 int dbidx, tgt, more_to_do = 0;
2181
2182 isp_prt(isp, ISP_LOGDEBUG0, "GDT timer expired");
2183 ISP_LOCK(isp);
2184 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
2185 lp = &FCPARAM(isp)->portdb[dbidx];
2186
2187 if (lp->state != FC_PORTDB_STATE_ZOMBIE) {
2188 continue;
2189 }
2190 if (lp->ini_map_idx == 0) {
2191 continue;
2192 }
2193 if (lp->new_reserved == 0) {
2194 continue;
2195 }
2196 lp->new_reserved -= 1;
2197 if (lp->new_reserved != 0) {
2198 more_to_do++;
2199 continue;
2200 }
2201 tgt = lp->ini_map_idx - 1;
2202 FCPARAM(isp)->isp_ini_map[tgt] = 0;
2203 lp->ini_map_idx = 0;
2204 lp->state = FC_PORTDB_STATE_NIL;
2205 isp_prt(isp, ISP_LOGCONFIG, prom3, lp->portid, tgt,
2206 "Gone Device Timeout");
2207 isp_make_gone(isp, tgt);
2208 }
2209 if (more_to_do) {
2210 isp->isp_osinfo.gdt = timeout(isp_gdt, isp, hz);
2085 } else {
2211 } else {
2086 isp_prt(isp, ISP_LOGDEBUG2, "watchdog with no command");
2212 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2213 "stopping Gone Device Timer");
2214 isp->isp_osinfo.gdt_running = 0;
2087 }
2088 ISP_UNLOCK(isp);
2089}
2090
2215 }
2216 ISP_UNLOCK(isp);
2217}
2218
2219/*
2220 * Loop Down Timer Function- when loop goes down, a timer is started and
2221 * and after it expires we come here and take all probational devices that
2222 * the OS knows about and the tell the OS that they've gone away.
2223 *
2224 * We don't clear the devices out of our port database because, when loop
2225 * come back up, we have to do some actual cleanup with the chip at that
2226 * point (implicit PLOGO, e.g., to get the chip's port database state right).
2227 */
2091static void
2228static void
2092isp_kthread(void *arg)
2229isp_ldt(void *arg)
2093{
2094 ispsoftc_t *isp = arg;
2230{
2231 ispsoftc_t *isp = arg;
2095 int slp;
2232 fcportdb_t *lp;
2233 int dbidx, tgt;
2096
2234
2235 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Loop Down Timer expired");
2236 ISP_LOCK(isp);
2097
2237
2238 /*
2239 * Notify to the OS all targets who we now consider have departed.
2240 */
2241 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
2242 lp = &FCPARAM(isp)->portdb[dbidx];
2243
2244 if (lp->state != FC_PORTDB_STATE_PROBATIONAL) {
2245 continue;
2246 }
2247 if (lp->ini_map_idx == 0) {
2248 continue;
2249 }
2250
2251 /*
2252 * XXX: CLEAN UP AND COMPLETE ANY PENDING COMMANDS FIRST!
2253 */
2254
2255 /*
2256 * Mark that we've announced that this device is gone....
2257 */
2258 lp->reserved = 1;
2259
2260 /*
2261 * but *don't* change the state of the entry. Just clear
2262 * any target id stuff and announce to CAM that the
2263 * device is gone. This way any necessary PLOGO stuff
2264 * will happen when loop comes back up.
2265 */
2266
2267 tgt = lp->ini_map_idx - 1;
2268 FCPARAM(isp)->isp_ini_map[tgt] = 0;
2269 lp->ini_map_idx = 0;
2270 isp_prt(isp, ISP_LOGCONFIG, prom3, lp->portid, tgt,
2271 "Loop Down Timeout");
2272 isp_make_gone(isp, tgt);
2273 }
2274
2275 /*
2276 * The loop down timer has expired. Wake up the kthread
2277 * to notice that fact (or make it false).
2278 */
2279 isp->isp_osinfo.loop_down_time = isp->isp_osinfo.loop_down_limit+1;
2098#if __FreeBSD_version < 500000
2280#if __FreeBSD_version < 500000
2281 wakeup(&isp->isp_osinfo.kproc);
2282#else
2283#ifdef ISP_SMPLOCK
2284 cv_signal(&isp->isp_osinfo.kthread_cv);
2285#else
2286 wakeup(&isp->isp_osinfo.kthread_cv);
2287#endif
2288#endif
2289 ISP_UNLOCK(isp);
2290}
2291
2292static void
2293isp_kthread(void *arg)
2294{
2295 ispsoftc_t *isp = arg;
2296 int slp = 0;
2297#if __FreeBSD_version < 500000
2099 int s;
2100
2101 s = splcam();
2102#else
2103#ifdef ISP_SMPLOCK
2104 mtx_lock(&isp->isp_lock);
2105#else
2106 mtx_lock(&Giant);
2107#endif
2108#endif
2109 /*
2110 * The first loop is for our usage where we have yet to have
2111 * gotten good fibre channel state.
2112 */
2113 for (;;) {
2298 int s;
2299
2300 s = splcam();
2301#else
2302#ifdef ISP_SMPLOCK
2303 mtx_lock(&isp->isp_lock);
2304#else
2305 mtx_lock(&Giant);
2306#endif
2307#endif
2308 /*
2309 * The first loop is for our usage where we have yet to have
2310 * gotten good fibre channel state.
2311 */
2312 for (;;) {
2114 int wasfrozen, lb;
2313 int wasfrozen, lb, lim;
2115
2314
2116 isp_prt(isp, ISP_LOGDEBUG0, "kthread: checking FC state");
2315 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2316 "isp_kthread: checking FC state");
2317 isp->isp_osinfo.mbox_sleep_ok = 1;
2117 lb = isp_fc_runstate(isp, 250000);
2318 lb = isp_fc_runstate(isp, 250000);
2319 isp->isp_osinfo.mbox_sleep_ok = 0;
2118 if (lb) {
2320 if (lb) {
2119 unsigned int inc = 1;
2321 /*
2322 * Increment loop down time by the last sleep interval
2323 */
2324 isp->isp_osinfo.loop_down_time += slp;
2120
2121 if (lb < 0) {
2325
2326 if (lb < 0) {
2122 isp_prt(isp, ISP_LOGDEBUG0,
2327 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2123 "kthread: FC loop not up (down count %d)",
2124 isp->isp_osinfo.loop_down_time);
2125 } else {
2328 "kthread: FC loop not up (down count %d)",
2329 isp->isp_osinfo.loop_down_time);
2330 } else {
2126 isp_prt(isp, ISP_LOGDEBUG0,
2331 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2127 "kthread: FC got to %d (down count %d)",
2128 lb, isp->isp_osinfo.loop_down_time);
2129 }
2130
2131
2132 /*
2133 * If we've never seen loop up and we've waited longer
2332 "kthread: FC got to %d (down count %d)",
2333 lb, isp->isp_osinfo.loop_down_time);
2334 }
2335
2336
2337 /*
2338 * If we've never seen loop up and we've waited longer
2134 * than quickboot time, give up and go to sleep until
2135 * loop comes up. Otherwise, increment the loop down
2136 * time and figure out how long to sleep to the next
2137 * check.
2339 * than quickboot time, or we've seen loop up but we've
2340 * waited longer than loop_down_limit, give up and go
2341 * to sleep until loop comes up.
2138 */
2342 */
2139 if (FCPARAM(isp)->loop_seen_once == 0 &&
2140 isp->isp_osinfo.loop_down_time >=
2141 isp_quickboot_time) {
2142 isp->isp_osinfo.loop_down_time = 0xffff;
2143 slp = 0;
2144 } else if (isp->isp_osinfo.loop_down_time > 30) {
2145 inc = 30;
2146 slp = 30 * hz;
2147 } else if (isp->isp_osinfo.loop_down_time > 1) {
2148 slp = hz;
2343 if (FCPARAM(isp)->loop_seen_once == 0) {
2344 lim = isp_quickboot_time;
2149 } else {
2345 } else {
2150 slp = 1;
2346 lim = isp->isp_osinfo.loop_down_limit;
2151 }
2347 }
2152
2153 inc += isp->isp_osinfo.loop_down_time;
2154 if (inc < 0xffff) {
2155 isp->isp_osinfo.loop_down_time = inc;
2348 if (isp->isp_osinfo.loop_down_time >= lim) {
2349 isp_freeze_loopdown(isp, "loop limit hit");
2350 slp = 0;
2351 } else if (isp->isp_osinfo.loop_down_time < 10) {
2352 slp = 1;
2353 } else if (isp->isp_osinfo.loop_down_time < 30) {
2354 slp = 5;
2355 } else if (isp->isp_osinfo.loop_down_time < 60) {
2356 slp = 10;
2357 } else if (isp->isp_osinfo.loop_down_time < 120) {
2358 slp = 20;
2156 } else {
2359 } else {
2157 isp->isp_osinfo.loop_down_time = 0xfffe;
2360 slp = 30;
2158 }
2361 }
2362
2159 } else {
2363 } else {
2160 isp_prt(isp, ISP_LOGDEBUG0, "kthread: FC state OK");
2364 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2365 "isp_kthread: FC state OK");
2161 isp->isp_osinfo.loop_down_time = 0;
2162 slp = 0;
2163 }
2164
2165 /*
2166 * If we'd frozen the simq, unfreeze it now so that CAM
2167 * can start sending us commands. If the FC state isn't
2168 * okay yet, they'll hit that in isp_start which will
2169 * freeze the queue again.
2170 */
2171 wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN;
2172 isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN;
2173 if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) {
2366 isp->isp_osinfo.loop_down_time = 0;
2367 slp = 0;
2368 }
2369
2370 /*
2371 * If we'd frozen the simq, unfreeze it now so that CAM
2372 * can start sending us commands. If the FC state isn't
2373 * okay yet, they'll hit that in isp_start which will
2374 * freeze the queue again.
2375 */
2376 wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN;
2377 isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN;
2378 if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) {
2174 isp_prt(isp, ISP_LOGDEBUG0, "kthread: releasing simq");
2379 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2380 "isp_kthread: releasing simq");
2175 ISPLOCK_2_CAMLOCK(isp);
2176 xpt_release_simq(isp->isp_sim, 1);
2177 CAMLOCK_2_ISPLOCK(isp);
2178 }
2381 ISPLOCK_2_CAMLOCK(isp);
2382 xpt_release_simq(isp->isp_sim, 1);
2383 CAMLOCK_2_ISPLOCK(isp);
2384 }
2385 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2386 "isp_kthread: sleep time %d", slp);
2179#if __FreeBSD_version < 500000
2387#if __FreeBSD_version < 500000
2180 tsleep(&isp->isp_osinfo.kproc, PRIBIO, "ispf", slp);
2388 tsleep(&isp->isp_osinfo.kproc, PRIBIO, "ispf",
2389 slp * hz);
2181#else
2182#ifdef ISP_SMPLOCK
2390#else
2391#ifdef ISP_SMPLOCK
2183 cv_timed_wait(&isp->isp_osinfo.kthread_cv, &isp->isp_lock, slp);
2392 cv_timed_wait(&isp->isp_osinfo.kthread_cv, &isp->isp_lock,
2393 slp * hz);
2184#else
2394#else
2185 (void) tsleep(&isp->isp_osinfo.kthread_cv, PRIBIO, "ispf", slp);
2395 (void) tsleep(&isp->isp_osinfo.kthread_cv, PRIBIO, "ispf",
2396 slp * hz);
2186#endif
2187#endif
2188 /*
2189 * If slp is zero, we're waking up for the first time after
2190 * things have been okay. In this case, we set a deferral state
2191 * for all commands and delay hysteresis seconds before starting
2192 * the FC state evaluation. This gives the loop/fabric a chance
2193 * to settle.
2194 */
2195 if (slp == 0 && isp->isp_osinfo.hysteresis) {
2397#endif
2398#endif
2399 /*
2400 * If slp is zero, we're waking up for the first time after
2401 * things have been okay. In this case, we set a deferral state
2402 * for all commands and delay hysteresis seconds before starting
2403 * the FC state evaluation. This gives the loop/fabric a chance
2404 * to settle.
2405 */
2406 if (slp == 0 && isp->isp_osinfo.hysteresis) {
2407 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2408 "isp_kthread: sleep hysteresis tick time %d",
2409 isp->isp_osinfo.hysteresis * hz);
2196 (void) tsleep(&isp_fabric_hysteresis, PRIBIO, "ispT",
2197 (isp->isp_osinfo.hysteresis * hz));
2198 }
2199 }
2200}
2201
2202static void
2203isp_action(struct cam_sim *sim, union ccb *ccb)
2204{
2410 (void) tsleep(&isp_fabric_hysteresis, PRIBIO, "ispT",
2411 (isp->isp_osinfo.hysteresis * hz));
2412 }
2413 }
2414}
2415
2416static void
2417isp_action(struct cam_sim *sim, union ccb *ccb)
2418{
2205 int bus, tgt, error;
2419 int bus, tgt, error, lim;
2206 ispsoftc_t *isp;
2207 struct ccb_trans_settings *cts;
2208
2209 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n"));
2210
2211 isp = (ispsoftc_t *)cam_sim_softc(sim);
2212 ccb->ccb_h.sim_priv.entries[0].field = 0;
2213 ccb->ccb_h.sim_priv.entries[1].ptr = isp;

--- 43 unchanged lines hidden (view full) ---

2257 break;
2258 }
2259#endif
2260 ((struct ccb_scsiio *) ccb)->scsi_status = SCSI_STATUS_OK;
2261 CAMLOCK_2_ISPLOCK(isp);
2262 error = isp_start((XS_T *) ccb);
2263 switch (error) {
2264 case CMD_QUEUED:
2420 ispsoftc_t *isp;
2421 struct ccb_trans_settings *cts;
2422
2423 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n"));
2424
2425 isp = (ispsoftc_t *)cam_sim_softc(sim);
2426 ccb->ccb_h.sim_priv.entries[0].field = 0;
2427 ccb->ccb_h.sim_priv.entries[1].ptr = isp;

--- 43 unchanged lines hidden (view full) ---

2471 break;
2472 }
2473#endif
2474 ((struct ccb_scsiio *) ccb)->scsi_status = SCSI_STATUS_OK;
2475 CAMLOCK_2_ISPLOCK(isp);
2476 error = isp_start((XS_T *) ccb);
2477 switch (error) {
2478 case CMD_QUEUED:
2479 XS_CMD_S_CLEAR(ccb);
2480 ISPLOCK_2_CAMLOCK(isp);
2265 ccb->ccb_h.status |= CAM_SIM_QUEUED;
2266 if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
2481 ccb->ccb_h.status |= CAM_SIM_QUEUED;
2482 if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
2267 uint64_t ticks = (uint64_t) hz;
2268 if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT)
2269 ticks = 60 * 1000 * ticks;
2270 else
2271 ticks = ccb->ccb_h.timeout * hz;
2272 ticks = ((ticks + 999) / 1000) + hz + hz;
2273 if (ticks >= 0x80000000) {
2274 isp_prt(isp, ISP_LOGERR,
2275 "timeout overflow");
2276 ticks = 0x7fffffff;
2483 int ms = ccb->ccb_h.timeout;
2484 if (ms == CAM_TIME_DEFAULT) {
2485 ms = 60*1000;
2277 }
2486 }
2278 ccb->ccb_h.timeout_ch = timeout(isp_watchdog,
2279 (caddr_t)ccb, (int)ticks);
2487 ccb->ccb_h.timeout_ch =
2488 timeout(isp_watchdog, ccb, isp_mstohz(ms));
2280 } else {
2281 callout_handle_init(&ccb->ccb_h.timeout_ch);
2282 }
2489 } else {
2490 callout_handle_init(&ccb->ccb_h.timeout_ch);
2491 }
2283 ISPLOCK_2_CAMLOCK(isp);
2284 break;
2285 case CMD_RQLATER:
2286 /*
2287 * This can only happen for Fibre Channel
2288 */
2289 KASSERT((IS_FC(isp)), ("CMD_RQLATER for FC only"));
2492 break;
2493 case CMD_RQLATER:
2494 /*
2495 * This can only happen for Fibre Channel
2496 */
2497 KASSERT((IS_FC(isp)), ("CMD_RQLATER for FC only"));
2498
2290 /*
2499 /*
2291 * If we've exceeded the loop down limit start
2292 * failing commands.
2500 * Handle initial and subsequent loop down cases
2293 */
2501 */
2294 if (isp->isp_osinfo.loop_down_time >
2295 isp->isp_osinfo.loop_down_limit) {
2502 if (FCPARAM(isp)->loop_seen_once == 0) {
2503 lim = isp_quickboot_time;
2504 } else {
2505 lim = isp->isp_osinfo.loop_down_limit;
2506 }
2507 if (isp->isp_osinfo.loop_down_time >= lim) {
2508 isp_prt(isp, ISP_LOGDEBUG0,
2509 "%d.%d downtime (%d) > lim (%d)",
2510 XS_TGT(ccb), XS_LUN(ccb),
2511 isp->isp_osinfo.loop_down_time, lim);
2512 ccb->ccb_h.status =
2513 CAM_SEL_TIMEOUT|CAM_DEV_QFRZN;
2514 xpt_freeze_devq(ccb->ccb_h.path, 1);
2296 ISPLOCK_2_CAMLOCK(isp);
2515 ISPLOCK_2_CAMLOCK(isp);
2297 XS_SETERR(ccb, CAM_SEL_TIMEOUT);
2298 xpt_done(ccb);
2299 break;
2300 }
2516 xpt_done(ccb);
2517 break;
2518 }
2301#if __FreeBSD_version < 500000
2302 wakeup(&isp->isp_osinfo.kproc);
2303#else
2304#ifdef ISP_SMPLOCK
2305 cv_signal(&isp->isp_osinfo.kthread_cv);
2306#else
2307 wakeup(&isp->isp_osinfo.kthread_cv);
2308#endif
2309#endif
2310 isp_freeze_loopdown(isp, "isp_action(RQLATER)");
2311 XS_SETERR(ccb, CAM_REQUEUE_REQ);
2519 isp_prt(isp, ISP_LOGDEBUG0,
2520 "%d.%d retry later", XS_TGT(ccb), XS_LUN(ccb));
2521 /*
2522 * Otherwise, retry in a while.
2523 */
2312 ISPLOCK_2_CAMLOCK(isp);
2524 ISPLOCK_2_CAMLOCK(isp);
2525 cam_freeze_devq(ccb->ccb_h.path);
2526 cam_release_devq(ccb->ccb_h.path,
2527 RELSIM_RELEASE_AFTER_TIMEOUT, 0, 1000, 0);
2528 XS_SETERR(ccb, CAM_REQUEUE_REQ);
2313 xpt_done(ccb);
2314 break;
2315 case CMD_EAGAIN:
2529 xpt_done(ccb);
2530 break;
2531 case CMD_EAGAIN:
2316 XS_SETERR(ccb, CAM_REQUEUE_REQ);
2317 ISPLOCK_2_CAMLOCK(isp);
2532 ISPLOCK_2_CAMLOCK(isp);
2533 cam_freeze_devq(ccb->ccb_h.path);
2534 cam_release_devq(ccb->ccb_h.path,
2535 RELSIM_RELEASE_AFTER_TIMEOUT, 0, 250, 0);
2318 xpt_done(ccb);
2319 break;
2320 case CMD_COMPLETE:
2321 isp_done((struct ccb_scsiio *) ccb);
2322 ISPLOCK_2_CAMLOCK(isp);
2323 break;
2324 default:
2536 xpt_done(ccb);
2537 break;
2538 case CMD_COMPLETE:
2539 isp_done((struct ccb_scsiio *) ccb);
2540 ISPLOCK_2_CAMLOCK(isp);
2541 break;
2542 default:
2543 ISPLOCK_2_CAMLOCK(isp);
2325 isp_prt(isp, ISP_LOGERR,
2326 "What's this? 0x%x at %d in file %s",
2327 error, __LINE__, __FILE__);
2328 XS_SETERR(ccb, CAM_REQ_CMP_ERR);
2329 xpt_done(ccb);
2544 isp_prt(isp, ISP_LOGERR,
2545 "What's this? 0x%x at %d in file %s",
2546 error, __LINE__, __FILE__);
2547 XS_SETERR(ccb, CAM_REQ_CMP_ERR);
2548 xpt_done(ccb);
2330 ISPLOCK_2_CAMLOCK(isp);
2331 }
2332 break;
2333
2334#ifdef ISP_TARGET_MODE
2335 case XPT_EN_LUN: /* Enable LUN as a target */
2336 {
2337 int seq, i;
2338 CAMLOCK_2_ISPLOCK(isp);

--- 395 unchanged lines hidden (view full) ---

2734 default:
2735 ccb->ccb_h.status = CAM_REQ_INVALID;
2736 xpt_done(ccb);
2737 break;
2738 }
2739}
2740
2741#define ISPDDB (CAM_DEBUG_INFO|CAM_DEBUG_TRACE|CAM_DEBUG_CDB)
2549 }
2550 break;
2551
2552#ifdef ISP_TARGET_MODE
2553 case XPT_EN_LUN: /* Enable LUN as a target */
2554 {
2555 int seq, i;
2556 CAMLOCK_2_ISPLOCK(isp);

--- 395 unchanged lines hidden (view full) ---

2952 default:
2953 ccb->ccb_h.status = CAM_REQ_INVALID;
2954 xpt_done(ccb);
2955 break;
2956 }
2957}
2958
2959#define ISPDDB (CAM_DEBUG_INFO|CAM_DEBUG_TRACE|CAM_DEBUG_CDB)
2960
2742void
2743isp_done(struct ccb_scsiio *sccb)
2744{
2745 ispsoftc_t *isp = XS_ISP(sccb);
2746
2747 if (XS_NOERR(sccb))
2748 XS_SETERR(sccb, CAM_REQ_CMP);
2749

--- 5 unchanged lines hidden (view full) ---

2755 sccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
2756 } else {
2757 sccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
2758 }
2759 }
2760
2761 sccb->ccb_h.status &= ~CAM_SIM_QUEUED;
2762 if ((sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2961void
2962isp_done(struct ccb_scsiio *sccb)
2963{
2964 ispsoftc_t *isp = XS_ISP(sccb);
2965
2966 if (XS_NOERR(sccb))
2967 XS_SETERR(sccb, CAM_REQ_CMP);
2968

--- 5 unchanged lines hidden (view full) ---

2974 sccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
2975 } else {
2976 sccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
2977 }
2978 }
2979
2980 sccb->ccb_h.status &= ~CAM_SIM_QUEUED;
2981 if ((sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2982 isp_prt(isp, ISP_LOGDEBUG0,
2983 "target %d lun %d CAM status 0x%x SCSI status 0x%x",
2984 XS_TGT(sccb), XS_LUN(sccb), sccb->ccb_h.status,
2985 sccb->scsi_status);
2763 if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
2764 sccb->ccb_h.status |= CAM_DEV_QFRZN;
2765 xpt_freeze_devq(sccb->ccb_h.path, 1);
2986 if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
2987 sccb->ccb_h.status |= CAM_DEV_QFRZN;
2988 xpt_freeze_devq(sccb->ccb_h.path, 1);
2766 isp_prt(isp, ISP_LOGDEBUG0,
2767 "freeze devq %d.%d cam sts %x scsi sts %x",
2768 sccb->ccb_h.target_id, sccb->ccb_h.target_lun,
2769 sccb->ccb_h.status, sccb->scsi_status);
2770 }
2771 }
2772
2773 if ((CAM_DEBUGGED(sccb->ccb_h.path, ISPDDB)) &&
2774 (sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2775 xpt_print_path(sccb->ccb_h.path);
2776 isp_prt(isp, ISP_LOGINFO,
2777 "cam completion status 0x%x", sccb->ccb_h.status);
2778 }
2779
2780 XS_CMD_S_DONE(sccb);
2781 if (XS_CMD_WDOG_P(sccb) == 0) {
2989 }
2990 }
2991
2992 if ((CAM_DEBUGGED(sccb->ccb_h.path, ISPDDB)) &&
2993 (sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2994 xpt_print_path(sccb->ccb_h.path);
2995 isp_prt(isp, ISP_LOGINFO,
2996 "cam completion status 0x%x", sccb->ccb_h.status);
2997 }
2998
2999 XS_CMD_S_DONE(sccb);
3000 if (XS_CMD_WDOG_P(sccb) == 0) {
2782 untimeout(isp_watchdog, (caddr_t)sccb, sccb->ccb_h.timeout_ch);
3001 untimeout(isp_watchdog, sccb, sccb->ccb_h.timeout_ch);
2783 if (XS_CMD_GRACE_P(sccb)) {
2784 isp_prt(isp, ISP_LOGDEBUG2,
2785 "finished command on borrowed time");
2786 }
2787 XS_CMD_S_CLEAR(sccb);
2788 ISPLOCK_2_CAMLOCK(isp);
2789 xpt_done((union ccb *) sccb);
2790 CAMLOCK_2_ISPLOCK(isp);
2791 }
2792}
2793
2794int
2795isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
2796{
2797 int bus, rv = 0;
3002 if (XS_CMD_GRACE_P(sccb)) {
3003 isp_prt(isp, ISP_LOGDEBUG2,
3004 "finished command on borrowed time");
3005 }
3006 XS_CMD_S_CLEAR(sccb);
3007 ISPLOCK_2_CAMLOCK(isp);
3008 xpt_done((union ccb *) sccb);
3009 CAMLOCK_2_ISPLOCK(isp);
3010 }
3011}
3012
3013int
3014isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
3015{
3016 int bus, rv = 0;
2798 static const char *roles[4] = {
2799 "(none)", "Target", "Initiator", "Target/Initiator"
2800 };
2801 static const char prom[] =
2802 "PortID 0x%06x handle 0x%x role %s %s\n"
3017 static const char prom[] =
3018 "PortID 0x%06x handle 0x%x role %s %s\n"
2803 " WWNN 0x%08x%08x WWPN 0x%08x%08x";
3019 " WWNN 0x%08x%08x WWPN 0x%08x%08x";
2804 static const char prom2[] =
2805 "PortID 0x%06x handle 0x%x role %s %s tgt %u\n"
3020 static const char prom2[] =
3021 "PortID 0x%06x handle 0x%x role %s %s tgt %u\n"
2806 " WWNN 0x%08x%08x WWPN 0x%08x%08x";
3022 " WWNN 0x%08x%08x WWPN 0x%08x%08x";
3023 char *msg = NULL;
2807 target_id_t tgt;
2808 fcportdb_t *lp;
2809 struct cam_path *tmppath;
2810
2811 switch (cmd) {
2812 case ISPASYNC_NEW_TGT_PARAMS:
2813 {
2814 struct ccb_trans_settings_scsi *scsi;

--- 70 unchanged lines hidden (view full) ---

2885 CAMLOCK_2_ISPLOCK(isp);
2886 } else if (isp->isp_path) {
2887 ISPLOCK_2_CAMLOCK(isp);
2888 xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
2889 CAMLOCK_2_ISPLOCK(isp);
2890 }
2891 break;
2892 case ISPASYNC_LIP:
3024 target_id_t tgt;
3025 fcportdb_t *lp;
3026 struct cam_path *tmppath;
3027
3028 switch (cmd) {
3029 case ISPASYNC_NEW_TGT_PARAMS:
3030 {
3031 struct ccb_trans_settings_scsi *scsi;

--- 70 unchanged lines hidden (view full) ---

3102 CAMLOCK_2_ISPLOCK(isp);
3103 } else if (isp->isp_path) {
3104 ISPLOCK_2_CAMLOCK(isp);
3105 xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
3106 CAMLOCK_2_ISPLOCK(isp);
3107 }
3108 break;
3109 case ISPASYNC_LIP:
2893 if (isp->isp_path) {
2894 isp_freeze_loopdown(isp, "ISPASYNC_LIP");
3110 if (msg == NULL) {
3111 msg = "LIP Received";
2895 }
3112 }
2896 isp_prt(isp, ISP_LOGINFO, "LIP Received");
2897 break;
3113 /* FALLTHROUGH */
2898 case ISPASYNC_LOOP_RESET:
3114 case ISPASYNC_LOOP_RESET:
2899 if (isp->isp_path) {
2900 isp_freeze_loopdown(isp, "ISPASYNC_LOOP_RESET");
3115 if (msg == NULL) {
3116 msg = "LOOP Reset";
2901 }
3117 }
2902 isp_prt(isp, ISP_LOGINFO, "Loop Reset Received");
2903 break;
3118 /* FALLTHROUGH */
2904 case ISPASYNC_LOOP_DOWN:
3119 case ISPASYNC_LOOP_DOWN:
3120 if (msg == NULL) {
3121 msg = "LOOP Down";
3122 }
2905 if (isp->isp_path) {
3123 if (isp->isp_path) {
2906 isp_freeze_loopdown(isp, "ISPASYNC_LOOP_DOWN");
3124 isp_freeze_loopdown(isp, msg);
2907 }
3125 }
2908 isp_prt(isp, ISP_LOGINFO, "Loop DOWN");
3126 if (isp->isp_osinfo.ldt_running == 0) {
3127 isp->isp_osinfo.ldt = timeout(isp_ldt, isp,
3128 isp->isp_osinfo.loop_down_limit * hz);
3129 isp->isp_osinfo.ldt_running = 1;
3130 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3131 "starting Loop Down Timer");
3132 }
3133 isp_prt(isp, ISP_LOGINFO, msg);
2909 break;
2910 case ISPASYNC_LOOP_UP:
2911 /*
2912 * Now we just note that Loop has come up. We don't
2913 * actually do anything because we're waiting for a
2914 * Change Notify before activating the FC cleanup
2915 * thread to look at the state of the loop again.
2916 */
2917 isp_prt(isp, ISP_LOGINFO, "Loop UP");
2918 break;
2919 case ISPASYNC_DEV_ARRIVED:
2920 lp = arg;
3134 break;
3135 case ISPASYNC_LOOP_UP:
3136 /*
3137 * Now we just note that Loop has come up. We don't
3138 * actually do anything because we're waiting for a
3139 * Change Notify before activating the FC cleanup
3140 * thread to look at the state of the loop again.
3141 */
3142 isp_prt(isp, ISP_LOGINFO, "Loop UP");
3143 break;
3144 case ISPASYNC_DEV_ARRIVED:
3145 lp = arg;
3146 lp->reserved = 0;
3147 if ((isp->isp_role & ISP_ROLE_INITIATOR) &&
3148 (lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT))) {
3149 int dbidx = lp - FCPARAM(isp)->portdb;
3150 int i;
2921
3151
3152 for (i = 0; i < MAX_FC_TARG; i++) {
3153 if (i >= FL_ID && i <= SNS_ID) {
3154 continue;
3155 }
3156 if (FCPARAM(isp)->isp_ini_map[i] == 0) {
3157 break;
3158 }
3159 }
3160 if (i < MAX_FC_TARG) {
3161 FCPARAM(isp)->isp_ini_map[i] = dbidx + 1;
3162 lp->ini_map_idx = i + 1;
3163 } else {
3164 isp_prt(isp, ISP_LOGWARN, "out of target ids");
3165 isp_dump_portdb(isp);
3166 }
3167 }
2922 if (lp->ini_map_idx) {
2923 tgt = lp->ini_map_idx - 1;
2924 isp_prt(isp, ISP_LOGCONFIG, prom2,
2925 lp->portid, lp->handle,
3168 if (lp->ini_map_idx) {
3169 tgt = lp->ini_map_idx - 1;
3170 isp_prt(isp, ISP_LOGCONFIG, prom2,
3171 lp->portid, lp->handle,
2926 roles[lp->roles & 0x3], "arrived at", tgt,
3172 roles[lp->roles], "arrived at", tgt,
2927 (uint32_t) (lp->node_wwn >> 32),
2928 (uint32_t) lp->node_wwn,
2929 (uint32_t) (lp->port_wwn >> 32),
2930 (uint32_t) lp->port_wwn);
3173 (uint32_t) (lp->node_wwn >> 32),
3174 (uint32_t) lp->node_wwn,
3175 (uint32_t) (lp->port_wwn >> 32),
3176 (uint32_t) lp->port_wwn);
2931#if __FreeBSD_version >= 500000
2932 ISPLOCK_2_CAMLOCK(isp);
2933 if (xpt_create_path(&tmppath, NULL,
2934 cam_sim_path(isp->isp_sim), tgt,
2935 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
2936 CAMLOCK_2_ISPLOCK(isp);
2937 break;
2938 }
2939 xpt_async(AC_FOUND_DEVICE, tmppath, NULL);
2940 xpt_free_path(tmppath);
2941 CAMLOCK_2_ISPLOCK(isp);
2942#endif
3177 isp_make_here(isp, tgt);
2943 } else {
2944 isp_prt(isp, ISP_LOGCONFIG, prom,
2945 lp->portid, lp->handle,
3178 } else {
3179 isp_prt(isp, ISP_LOGCONFIG, prom,
3180 lp->portid, lp->handle,
2946 roles[lp->roles & 0x3], "arrived",
3181 roles[lp->roles], "arrived",
2947 (uint32_t) (lp->node_wwn >> 32),
2948 (uint32_t) lp->node_wwn,
2949 (uint32_t) (lp->port_wwn >> 32),
2950 (uint32_t) lp->port_wwn);
2951 }
2952 break;
2953 case ISPASYNC_DEV_CHANGED:
2954 lp = arg;
3182 (uint32_t) (lp->node_wwn >> 32),
3183 (uint32_t) lp->node_wwn,
3184 (uint32_t) (lp->port_wwn >> 32),
3185 (uint32_t) lp->port_wwn);
3186 }
3187 break;
3188 case ISPASYNC_DEV_CHANGED:
3189 lp = arg;
2955 if (lp->ini_map_idx) {
2956 tgt = lp->ini_map_idx - 1;
2957 isp_prt(isp, ISP_LOGCONFIG, prom2,
2958 lp->portid, lp->handle,
2959 roles[lp->roles & 0x3], "changed at", tgt,
2960 (uint32_t) (lp->node_wwn >> 32),
2961 (uint32_t) lp->node_wwn,
2962 (uint32_t) (lp->port_wwn >> 32),
2963 (uint32_t) lp->port_wwn);
3190 if (isp_change_is_bad) {
3191 lp->state = FC_PORTDB_STATE_NIL;
3192 if (lp->ini_map_idx) {
3193 tgt = lp->ini_map_idx - 1;
3194 FCPARAM(isp)->isp_ini_map[tgt] = 0;
3195 lp->ini_map_idx = 0;
3196 isp_prt(isp, ISP_LOGCONFIG, prom3,
3197 lp->portid, tgt, "change is bad");
3198 isp_make_gone(isp, tgt);
3199 } else {
3200 isp_prt(isp, ISP_LOGCONFIG, prom,
3201 lp->portid, lp->handle,
3202 roles[lp->roles],
3203 "changed and departed",
3204 (uint32_t) (lp->node_wwn >> 32),
3205 (uint32_t) lp->node_wwn,
3206 (uint32_t) (lp->port_wwn >> 32),
3207 (uint32_t) lp->port_wwn);
3208 }
2964 } else {
3209 } else {
2965 isp_prt(isp, ISP_LOGCONFIG, prom,
2966 lp->portid, lp->handle,
2967 roles[lp->roles & 0x3], "changed",
2968 (uint32_t) (lp->node_wwn >> 32),
2969 (uint32_t) lp->node_wwn,
2970 (uint32_t) (lp->port_wwn >> 32),
2971 (uint32_t) lp->port_wwn);
3210 lp->portid = lp->new_portid;
3211 lp->roles = lp->new_roles;
3212 if (lp->ini_map_idx) {
3213 int t = lp->ini_map_idx - 1;
3214 FCPARAM(isp)->isp_ini_map[t] =
3215 (lp - FCPARAM(isp)->portdb) + 1;
3216 tgt = lp->ini_map_idx - 1;
3217 isp_prt(isp, ISP_LOGCONFIG, prom2,
3218 lp->portid, lp->handle,
3219 roles[lp->roles], "changed at", tgt,
3220 (uint32_t) (lp->node_wwn >> 32),
3221 (uint32_t) lp->node_wwn,
3222 (uint32_t) (lp->port_wwn >> 32),
3223 (uint32_t) lp->port_wwn);
3224 } else {
3225 isp_prt(isp, ISP_LOGCONFIG, prom,
3226 lp->portid, lp->handle,
3227 roles[lp->roles], "changed",
3228 (uint32_t) (lp->node_wwn >> 32),
3229 (uint32_t) lp->node_wwn,
3230 (uint32_t) (lp->port_wwn >> 32),
3231 (uint32_t) lp->port_wwn);
3232 }
2972 }
2973 break;
2974 case ISPASYNC_DEV_STAYED:
2975 lp = arg;
2976 if (lp->ini_map_idx) {
2977 tgt = lp->ini_map_idx - 1;
2978 isp_prt(isp, ISP_LOGCONFIG, prom2,
2979 lp->portid, lp->handle,
3233 }
3234 break;
3235 case ISPASYNC_DEV_STAYED:
3236 lp = arg;
3237 if (lp->ini_map_idx) {
3238 tgt = lp->ini_map_idx - 1;
3239 isp_prt(isp, ISP_LOGCONFIG, prom2,
3240 lp->portid, lp->handle,
2980 roles[lp->roles & 0x3], "stayed at", tgt,
3241 roles[lp->roles], "stayed at", tgt,
2981 (uint32_t) (lp->node_wwn >> 32),
2982 (uint32_t) lp->node_wwn,
2983 (uint32_t) (lp->port_wwn >> 32),
2984 (uint32_t) lp->port_wwn);
2985 } else {
2986 isp_prt(isp, ISP_LOGCONFIG, prom,
2987 lp->portid, lp->handle,
3242 (uint32_t) (lp->node_wwn >> 32),
3243 (uint32_t) lp->node_wwn,
3244 (uint32_t) (lp->port_wwn >> 32),
3245 (uint32_t) lp->port_wwn);
3246 } else {
3247 isp_prt(isp, ISP_LOGCONFIG, prom,
3248 lp->portid, lp->handle,
2988 roles[lp->roles & 0x3], "stayed",
3249 roles[lp->roles], "stayed",
2989 (uint32_t) (lp->node_wwn >> 32),
2990 (uint32_t) lp->node_wwn,
2991 (uint32_t) (lp->port_wwn >> 32),
2992 (uint32_t) lp->port_wwn);
2993 }
2994 break;
2995 case ISPASYNC_DEV_GONE:
2996 lp = arg;
3250 (uint32_t) (lp->node_wwn >> 32),
3251 (uint32_t) lp->node_wwn,
3252 (uint32_t) (lp->port_wwn >> 32),
3253 (uint32_t) lp->port_wwn);
3254 }
3255 break;
3256 case ISPASYNC_DEV_GONE:
3257 lp = arg;
2997 if (lp->ini_map_idx) {
3258 /*
3259 * If this has a virtual target and we haven't marked it
3260 * that we're going to have isp_gdt tell the OS it's gone,
3261 * set the isp_gdt timer running on it.
3262 *
3263 * If it isn't marked that isp_gdt is going to get rid of it,
3264 * announce that it's gone.
3265 */
3266 if (lp->ini_map_idx && lp->reserved == 0) {
3267 lp->reserved = 1;
3268 lp->new_reserved = isp->isp_osinfo.gone_device_time;
3269 lp->state = FC_PORTDB_STATE_ZOMBIE;
3270 if (isp->isp_osinfo.gdt_running == 0) {
3271 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3272 "starting Gone Device Timer");
3273 isp->isp_osinfo.gdt = timeout(isp_gdt, isp, hz);
3274 isp->isp_osinfo.gdt_running = 1;
3275 }
2998 tgt = lp->ini_map_idx - 1;
2999 isp_prt(isp, ISP_LOGCONFIG, prom2,
3000 lp->portid, lp->handle,
3276 tgt = lp->ini_map_idx - 1;
3277 isp_prt(isp, ISP_LOGCONFIG, prom2,
3278 lp->portid, lp->handle,
3001 roles[lp->roles & 0x3], "departed from", tgt,
3279 roles[lp->roles], "gone zombie at", tgt,
3002 (uint32_t) (lp->node_wwn >> 32),
3003 (uint32_t) lp->node_wwn,
3004 (uint32_t) (lp->port_wwn >> 32),
3005 (uint32_t) lp->port_wwn);
3280 (uint32_t) (lp->node_wwn >> 32),
3281 (uint32_t) lp->node_wwn,
3282 (uint32_t) (lp->port_wwn >> 32),
3283 (uint32_t) lp->port_wwn);
3006#if __FreeBSD_version >= 500000
3007 ISPLOCK_2_CAMLOCK(isp);
3008 if (xpt_create_path(&tmppath, NULL,
3009 cam_sim_path(isp->isp_sim), tgt,
3010 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
3011 CAMLOCK_2_ISPLOCK(isp);
3012 break;
3013 }
3014 xpt_async(AC_LOST_DEVICE, tmppath, NULL);
3015 xpt_free_path(tmppath);
3016 CAMLOCK_2_ISPLOCK(isp);
3017#endif
3018 } else {
3284 } else if (lp->reserved == 0) {
3019 isp_prt(isp, ISP_LOGCONFIG, prom,
3020 lp->portid, lp->handle,
3285 isp_prt(isp, ISP_LOGCONFIG, prom,
3286 lp->portid, lp->handle,
3021 roles[lp->roles & 0x3], "departed",
3022 (uint32_t) (lp->node_wwn >> 32),
3287 roles[lp->roles], "departed",
3288 (uint32_t) (lp->node_wwn >> 32),
3023 (uint32_t) lp->node_wwn,
3289 (uint32_t) lp->node_wwn,
3024 (uint32_t) (lp->port_wwn >> 32),
3290 (uint32_t) (lp->port_wwn >> 32),
3025 (uint32_t) lp->port_wwn);
3026 }
3027 break;
3028 case ISPASYNC_CHANGE_NOTIFY:
3029 {
3030 char *msg;
3031 if (arg == ISPASYNC_CHANGE_PDB) {
3032 msg = "Port Database Changed";
3033 } else if (arg == ISPASYNC_CHANGE_SNS) {
3034 msg = "Name Server Database Changed";
3035 } else {
3036 msg = "Other Change Notify";
3037 }
3291 (uint32_t) lp->port_wwn);
3292 }
3293 break;
3294 case ISPASYNC_CHANGE_NOTIFY:
3295 {
3296 char *msg;
3297 if (arg == ISPASYNC_CHANGE_PDB) {
3298 msg = "Port Database Changed";
3299 } else if (arg == ISPASYNC_CHANGE_SNS) {
3300 msg = "Name Server Database Changed";
3301 } else {
3302 msg = "Other Change Notify";
3303 }
3304 /*
3305 * If the loop down timer is running, cancel it.
3306 */
3307 if (isp->isp_osinfo.ldt_running) {
3308 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3309 "Stopping Loop Down Timer");
3310 isp->isp_osinfo.ldt_running = 0;
3311 untimeout(isp_ldt, isp, isp->isp_osinfo.ldt);
3312 callout_handle_init(&isp->isp_osinfo.ldt);
3313 }
3038 isp_prt(isp, ISP_LOGINFO, msg);
3039 isp_freeze_loopdown(isp, msg);
3040#if __FreeBSD_version < 500000
3041 wakeup(&isp->isp_osinfo.kproc);
3042#else
3043#ifdef ISP_SMPLOCK
3044 cv_signal(&isp->isp_osinfo.kthread_cv);
3045#else

--- 103 unchanged lines hidden (view full) ---

3149 return;
3150 }
3151 printf("%s: ", device_get_nameunit(isp->isp_dev));
3152 va_start(ap, fmt);
3153 vprintf(fmt, ap);
3154 va_end(ap);
3155 printf("\n");
3156}
3314 isp_prt(isp, ISP_LOGINFO, msg);
3315 isp_freeze_loopdown(isp, msg);
3316#if __FreeBSD_version < 500000
3317 wakeup(&isp->isp_osinfo.kproc);
3318#else
3319#ifdef ISP_SMPLOCK
3320 cv_signal(&isp->isp_osinfo.kthread_cv);
3321#else

--- 103 unchanged lines hidden (view full) ---

3425 return;
3426 }
3427 printf("%s: ", device_get_nameunit(isp->isp_dev));
3428 va_start(ap, fmt);
3429 vprintf(fmt, ap);
3430 va_end(ap);
3431 printf("\n");
3432}
3433
3434uint64_t
3435isp_nanotime_sub(struct timespec *b, struct timespec *a)
3436{
3437 uint64_t elapsed;
3438 struct timespec x = *b;
3439 timespecsub(&x, a);
3440 elapsed = GET_NANOSEC(&x);
3441 if (elapsed == 0)
3442 elapsed++;
3443 return (elapsed);
3444}
3445
3446int
3447isp_mbox_acquire(ispsoftc_t *isp)
3448{
3449 if (isp->isp_osinfo.mboxbsy) {
3450 return (1);
3451 } else {
3452 isp->isp_osinfo.mboxcmd_done = 0;
3453 isp->isp_osinfo.mboxbsy = 1;
3454 return (0);
3455 }
3456}
3457
3458void
3459isp_mbox_wait_complete(ispsoftc_t *isp, mbreg_t *mbp)
3460{
3461 int usecs = mbp->timeout;
3462 int j;
3463
3464 if (usecs == 0) {
3465 usecs = MBCMD_DEFAULT_TIMEOUT;
3466 }
3467 if (isp->isp_mbxwrk0) {
3468 usecs *= isp->isp_mbxwrk0;
3469 }
3470 if (isp->isp_osinfo.mbox_sleep_ok) {
3471 int ms = usecs / 1000;
3472 isp->isp_osinfo.mbox_sleep_ok = 0;
3473 isp->isp_osinfo.mbox_sleeping = 1;
3474#if __FreeBSD_version < 500000 || !defined(ISP_SMPLOCK)
3475 tsleep(&isp->isp_mbxworkp, PRIBIO, "ispmbx_sleep",
3476 isp_mstohz(ms));
3477#else
3478 msleep(&isp->isp_mbxworkp, &isp->isp_mtx, PRIBIO,
3479 "ispmbx_sleep", isp_mstohz(ms));
3480#endif
3481 isp->isp_osinfo.mbox_sleep_ok = 1;
3482 isp->isp_osinfo.mbox_sleeping = 0;
3483 } else {
3484 for (j = 0; j < usecs; j += 100) {
3485 uint32_t isr;
3486 uint16_t sema, mbox;
3487 if (isp->isp_osinfo.mboxcmd_done) {
3488 break;
3489 }
3490 if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
3491 isp_intr(isp, isr, sema, mbox);
3492 if (isp->isp_osinfo.mboxcmd_done) {
3493 break;
3494 }
3495 }
3496 USEC_DELAY(100);
3497 }
3498 }
3499 if (isp->isp_osinfo.mboxcmd_done == 0) {
3500 isp_prt(isp, ISP_LOGWARN,
3501 "%s Mailbox Command (0x%x) Timeout",
3502 isp->isp_osinfo.mbox_sleep_ok? "Interrupting" : "Polled",
3503 isp->isp_lastmbxcmd);
3504 mbp->param[0] = MBOX_TIMEOUT;
3505 isp->isp_osinfo.mboxcmd_done = 1;
3506 }
3507}
3508
3509void
3510isp_mbox_notify_done(ispsoftc_t *isp)
3511{
3512 if (isp->isp_osinfo.mbox_sleeping) {
3513 wakeup(&isp->isp_mbxworkp);
3514 }
3515 isp->isp_osinfo.mboxcmd_done = 1;
3516}
3517
3518void
3519isp_mbox_release(ispsoftc_t *isp)
3520{
3521 isp->isp_osinfo.mboxbsy = 0;
3522}
3523
3524int
3525isp_mstohz(int ms)
3526{
3527 struct timeval t;
3528 t.tv_sec = ms / 1000;
3529 t.tv_usec = (ms % 1000) * 1000;
3530 ms = tvtohz(&t);
3531 if (ms < 0) {
3532 ms = 0x7fffffff;
3533 }
3534 return (ms);
3535}