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