isp.c (291513) | isp.c (291514) |
---|---|
1/*- 2 * Copyright (c) 1997-2009 by Matthew Jacob 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * --- 33 unchanged lines hidden (view full) --- 42 */ 43#ifdef __NetBSD__ 44#include <sys/cdefs.h> 45__KERNEL_RCSID(0, "$NetBSD$"); 46#include <dev/ic/isp_netbsd.h> 47#endif 48#ifdef __FreeBSD__ 49#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1997-2009 by Matthew Jacob 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * --- 33 unchanged lines hidden (view full) --- 42 */ 43#ifdef __NetBSD__ 44#include <sys/cdefs.h> 45__KERNEL_RCSID(0, "$NetBSD$"); 46#include <dev/ic/isp_netbsd.h> 47#endif 48#ifdef __FreeBSD__ 49#include <sys/cdefs.h> |
50__FBSDID("$FreeBSD: stable/10/sys/dev/isp/isp.c 291513 2015-11-30 21:39:33Z mav $"); | 50__FBSDID("$FreeBSD: stable/10/sys/dev/isp/isp.c 291514 2015-11-30 21:40:20Z mav $"); |
51#include <dev/isp/isp_freebsd.h> 52#endif 53#ifdef __OpenBSD__ 54#include <dev/ic/isp_openbsd.h> 55#endif 56#ifdef __linux__ 57#include "isp_linux.h" 58#endif --- 4 unchanged lines hidden (view full) --- 63/* 64 * General defines 65 */ 66#define MBOX_DELAY_COUNT 1000000 / 100 67 68/* 69 * Local static data 70 */ | 51#include <dev/isp/isp_freebsd.h> 52#endif 53#ifdef __OpenBSD__ 54#include <dev/ic/isp_openbsd.h> 55#endif 56#ifdef __linux__ 57#include "isp_linux.h" 58#endif --- 4 unchanged lines hidden (view full) --- 63/* 64 * General defines 65 */ 66#define MBOX_DELAY_COUNT 1000000 / 100 67 68/* 69 * Local static data 70 */ |
71static const char fconf[] = "Chan %d PortDB[%d] changed:\n current =(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)\n database=(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)"; | |
72static const char notresp[] = "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d"; | 71static const char notresp[] = "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d"; |
73static const char topology[] = "Chan %d WWPN 0x%08x%08x PortID 0x%06x LoopID 0x%x Connection '%s'"; | |
74static const char bun[] = "bad underrun (count %d, resid %d, status %s)"; 75static const char lipd[] = "Chan %d LIP destroyed %d active commands"; 76static const char sacq[] = "unable to acquire scratch area"; 77 78static const uint8_t alpa_map[] = { 79 0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 80 0xd9, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce, 81 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc7, 0xc6, 0xc5, --- 21 unchanged lines hidden (view full) --- 103static void isp_parse_status(ispsoftc_t *, ispstatusreq_t *, XS_T *, long *); static void 104isp_parse_status_24xx(ispsoftc_t *, isp24xx_statusreq_t *, XS_T *, long *); 105static void isp_fastpost_complete(ispsoftc_t *, uint32_t); 106static int isp_mbox_continue(ispsoftc_t *); 107static void isp_scsi_init(ispsoftc_t *); 108static void isp_scsi_channel_init(ispsoftc_t *, int); 109static void isp_fibre_init(ispsoftc_t *); 110static void isp_fibre_init_2400(ispsoftc_t *); | 72static const char bun[] = "bad underrun (count %d, resid %d, status %s)"; 73static const char lipd[] = "Chan %d LIP destroyed %d active commands"; 74static const char sacq[] = "unable to acquire scratch area"; 75 76static const uint8_t alpa_map[] = { 77 0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 78 0xd9, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce, 79 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc7, 0xc6, 0xc5, --- 21 unchanged lines hidden (view full) --- 101static void isp_parse_status(ispsoftc_t *, ispstatusreq_t *, XS_T *, long *); static void 102isp_parse_status_24xx(ispsoftc_t *, isp24xx_statusreq_t *, XS_T *, long *); 103static void isp_fastpost_complete(ispsoftc_t *, uint32_t); 104static int isp_mbox_continue(ispsoftc_t *); 105static void isp_scsi_init(ispsoftc_t *); 106static void isp_scsi_channel_init(ispsoftc_t *, int); 107static void isp_fibre_init(ispsoftc_t *); 108static void isp_fibre_init_2400(ispsoftc_t *); |
111static void isp_mark_portdb(ispsoftc_t *, int, int); | 109static void isp_clear_portdb(ispsoftc_t *, int); 110static void isp_mark_portdb(ispsoftc_t *, int); |
112static int isp_plogx(ispsoftc_t *, int, uint16_t, uint32_t, int, int); 113static int isp_port_login(ispsoftc_t *, uint16_t, uint32_t); 114static int isp_port_logout(ispsoftc_t *, uint16_t, uint32_t); 115static int isp_getpdb(ispsoftc_t *, int, uint16_t, isp_pdb_t *, int); 116static int isp_gethandles(ispsoftc_t *, int, uint16_t *, int *, int, int); 117static void isp_dump_chip_portdb(ispsoftc_t *, int, int); 118static uint64_t isp_get_wwn(ispsoftc_t *, int, int, int); 119static int isp_fclink_test(ispsoftc_t *, int, int); --- 2158 unchanged lines hidden (view full) --- 2278 2279 /* 2280 * Whatever happens, we're now committed to being here. 2281 */ 2282 isp->isp_state = ISP_RUNSTATE; 2283} 2284 2285static void | 111static int isp_plogx(ispsoftc_t *, int, uint16_t, uint32_t, int, int); 112static int isp_port_login(ispsoftc_t *, uint16_t, uint32_t); 113static int isp_port_logout(ispsoftc_t *, uint16_t, uint32_t); 114static int isp_getpdb(ispsoftc_t *, int, uint16_t, isp_pdb_t *, int); 115static int isp_gethandles(ispsoftc_t *, int, uint16_t *, int *, int, int); 116static void isp_dump_chip_portdb(ispsoftc_t *, int, int); 117static uint64_t isp_get_wwn(ispsoftc_t *, int, int, int); 118static int isp_fclink_test(ispsoftc_t *, int, int); --- 2158 unchanged lines hidden (view full) --- 2277 2278 /* 2279 * Whatever happens, we're now committed to being here. 2280 */ 2281 isp->isp_state = ISP_RUNSTATE; 2282} 2283 2284static void |
2286isp_mark_portdb(ispsoftc_t *isp, int chan, int disposition) | 2285isp_clear_portdb(ispsoftc_t *isp, int chan) |
2287{ 2288 fcparam *fcp = FCPARAM(isp, chan); 2289 fcportdb_t *lp; 2290 int i; 2291 2292 for (i = 0; i < MAX_FC_TARG; i++) { 2293 lp = &fcp->portdb[i]; 2294 switch (lp->state) { | 2286{ 2287 fcparam *fcp = FCPARAM(isp, chan); 2288 fcportdb_t *lp; 2289 int i; 2290 2291 for (i = 0; i < MAX_FC_TARG; i++) { 2292 lp = &fcp->portdb[i]; 2293 switch (lp->state) { |
2295 case FC_PORTDB_STATE_PROBATIONAL: | |
2296 case FC_PORTDB_STATE_DEAD: 2297 case FC_PORTDB_STATE_CHANGED: | 2294 case FC_PORTDB_STATE_DEAD: 2295 case FC_PORTDB_STATE_CHANGED: |
2298 case FC_PORTDB_STATE_PENDING_VALID: | |
2299 case FC_PORTDB_STATE_VALID: | 2296 case FC_PORTDB_STATE_VALID: |
2300 if (disposition > 0) 2301 lp->state = FC_PORTDB_STATE_PROBATIONAL; 2302 else { 2303 lp->state = FC_PORTDB_STATE_NIL; 2304 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp); 2305 } | 2297 lp->state = FC_PORTDB_STATE_NIL; 2298 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp); |
2306 break; | 2299 break; |
2307 case FC_PORTDB_STATE_ZOMBIE: 2308 break; | |
2309 case FC_PORTDB_STATE_NIL: 2310 case FC_PORTDB_STATE_NEW: | 2300 case FC_PORTDB_STATE_NIL: 2301 case FC_PORTDB_STATE_NEW: |
2311 default: 2312 ISP_MEMZERO(lp, sizeof(*lp)); | |
2313 lp->state = FC_PORTDB_STATE_NIL; 2314 break; | 2302 lp->state = FC_PORTDB_STATE_NIL; 2303 break; |
2304 case FC_PORTDB_STATE_ZOMBIE: 2305 break; 2306 default: 2307 panic("Don't know how to clear state %d\n", lp->state); |
|
2315 } 2316 } 2317} 2318 | 2308 } 2309 } 2310} 2311 |
2312static void 2313isp_mark_portdb(ispsoftc_t *isp, int chan) 2314{ 2315 fcparam *fcp = FCPARAM(isp, chan); 2316 fcportdb_t *lp; 2317 int i; 2318 2319 for (i = 0; i < MAX_FC_TARG; i++) { 2320 lp = &fcp->portdb[i]; 2321 if (lp->state == FC_PORTDB_STATE_NIL) 2322 continue; 2323 if ((lp->portid & 0xfffc00) == 0xfffc00) 2324 continue; 2325 fcp->portdb[i].probational = 1; 2326 } 2327} 2328 |
|
2319/* 2320 * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards 2321 * or via FABRIC LOGIN/FABRIC LOGOUT for other cards. 2322 */ 2323static int 2324isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags, int gs) 2325{ 2326 mbreg_t mbs; 2327 uint8_t q[QENTRY_LEN]; 2328 isp_plogx_t *plp; 2329 fcparam *fcp; 2330 uint8_t *scp; 2331 uint32_t sst, parm1; 2332 int rval, lev; 2333 const char *msg; 2334 char buf[64]; 2335 | 2329/* 2330 * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards 2331 * or via FABRIC LOGIN/FABRIC LOGOUT for other cards. 2332 */ 2333static int 2334isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags, int gs) 2335{ 2336 mbreg_t mbs; 2337 uint8_t q[QENTRY_LEN]; 2338 isp_plogx_t *plp; 2339 fcparam *fcp; 2340 uint8_t *scp; 2341 uint32_t sst, parm1; 2342 int rval, lev; 2343 const char *msg; 2344 char buf[64]; 2345 |
2346 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d PLOGX %s PortID 0x%06x nphdl 0x%x", 2347 chan, (flags & PLOGX_FLG_CMD_MASK) == PLOGX_FLG_CMD_PLOGI ? 2348 "Login":"Logout", portid, handle); |
|
2336 if (!IS_24XX(isp)) { 2337 int action = flags & PLOGX_FLG_CMD_MASK; 2338 if (action == PLOGX_FLG_CMD_PLOGI) { 2339 return (isp_port_login(isp, handle, portid)); 2340 } else if (action == PLOGX_FLG_CMD_LOGO) { 2341 return (isp_port_logout(isp, handle, portid)); 2342 } else { 2343 return (MBOX_INVALID_COMMAND); --- 417 unchanged lines hidden (view full) --- 2761/* 2762 * Make sure we have good FC link. 2763 */ 2764 2765static int 2766isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay) 2767{ 2768 mbreg_t mbs; | 2349 if (!IS_24XX(isp)) { 2350 int action = flags & PLOGX_FLG_CMD_MASK; 2351 if (action == PLOGX_FLG_CMD_PLOGI) { 2352 return (isp_port_login(isp, handle, portid)); 2353 } else if (action == PLOGX_FLG_CMD_LOGO) { 2354 return (isp_port_logout(isp, handle, portid)); 2355 } else { 2356 return (MBOX_INVALID_COMMAND); --- 417 unchanged lines hidden (view full) --- 2774/* 2775 * Make sure we have good FC link. 2776 */ 2777 2778static int 2779isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay) 2780{ 2781 mbreg_t mbs; |
2769 int r; | 2782 int i, r; |
2770 uint16_t nphdl; 2771 fcparam *fcp; 2772 isp_pdb_t pdb; 2773 NANOTIME_T hra, hrb; 2774 2775 fcp = FCPARAM(isp, chan); 2776 | 2783 uint16_t nphdl; 2784 fcparam *fcp; 2785 isp_pdb_t pdb; 2786 NANOTIME_T hra, hrb; 2787 2788 fcp = FCPARAM(isp, chan); 2789 |
2777 /* Mark port database entries for following scan. */ 2778 isp_mark_portdb(isp, chan, 1); | 2790 /* Mark port database entries probational for following scan. */ 2791 isp_mark_portdb(isp, chan); |
2779 2780 if (fcp->isp_loopstate >= LOOP_LTEST_DONE) 2781 return (0); 2782 2783 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test", chan); 2784 fcp->isp_loopstate = LOOP_TESTING_LINK; 2785 2786 /* --- 26 unchanged lines hidden (view full) --- 2813 */ 2814 MBSINIT(&mbs, MBOX_GET_LOOP_ID, MBLOGALL, 0); 2815 mbs.param[9] = chan; 2816 isp_mboxcmd(isp, &mbs); 2817 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 2818 return (-1); 2819 } 2820 | 2792 2793 if (fcp->isp_loopstate >= LOOP_LTEST_DONE) 2794 return (0); 2795 2796 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test", chan); 2797 fcp->isp_loopstate = LOOP_TESTING_LINK; 2798 2799 /* --- 26 unchanged lines hidden (view full) --- 2826 */ 2827 MBSINIT(&mbs, MBOX_GET_LOOP_ID, MBLOGALL, 0); 2828 mbs.param[9] = chan; 2829 isp_mboxcmd(isp, &mbs); 2830 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { 2831 return (-1); 2832 } 2833 |
2821 if (ISP_CAP_2KLOGIN(isp)) { 2822 fcp->isp_loopid = mbs.param[1]; 2823 } else { 2824 fcp->isp_loopid = mbs.param[1] & 0xff; 2825 } 2826 | |
2827 if (IS_2100(isp)) { 2828 /* 2829 * Don't bother with fabric if we are using really old 2830 * 2100 firmware. It's just not worth it. 2831 */ 2832 if (ISP_FW_NEWER_THAN(isp, 1, 15, 37)) 2833 fcp->isp_topo = TOPO_FL_PORT; 2834 else 2835 fcp->isp_topo = TOPO_NL_PORT; 2836 } else { 2837 int topo = (int) mbs.param[6]; 2838 if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB) { 2839 topo = TOPO_PTP_STUB; 2840 } 2841 fcp->isp_topo = topo; 2842 } 2843 fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16); 2844 | 2834 if (IS_2100(isp)) { 2835 /* 2836 * Don't bother with fabric if we are using really old 2837 * 2100 firmware. It's just not worth it. 2838 */ 2839 if (ISP_FW_NEWER_THAN(isp, 1, 15, 37)) 2840 fcp->isp_topo = TOPO_FL_PORT; 2841 else 2842 fcp->isp_topo = TOPO_NL_PORT; 2843 } else { 2844 int topo = (int) mbs.param[6]; 2845 if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB) { 2846 topo = TOPO_PTP_STUB; 2847 } 2848 fcp->isp_topo = topo; 2849 } 2850 fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16); 2851 |
2845 /* 2846 * Check to make sure we got a valid loopid 2847 * The 24XX seems to mess this up for multiple channels. 2848 */ 2849 if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_NL_PORT) { | 2852 if (!TOPO_IS_FABRIC(fcp->isp_topo)) { 2853 fcp->isp_loopid = mbs.param[1] & 0xff; 2854 } else if (fcp->isp_topo != TOPO_F_PORT) { |
2850 uint8_t alpa = fcp->isp_portid; 2851 | 2855 uint8_t alpa = fcp->isp_portid; 2856 |
2852 if (alpa == 0) { 2853 /* "Cannot Happen" */ 2854 isp_prt(isp, ISP_LOGWARN, "Zero AL_PA for Loop Topology?"); 2855 } else { 2856 int i; 2857 for (i = 0; alpa_map[i]; i++) { 2858 if (alpa_map[i] == alpa) { 2859 break; 2860 } 2861 } 2862 if (alpa_map[i] && fcp->isp_loopid != i) { 2863 isp_prt(isp, ISP_LOG_SANCFG, 2864 "Chan %d Deriving loopid %d from AL_PA map (AL_PA 0x%x) and ignoring returned value %d (AL_PA 0x%x)", 2865 chan, i, alpa_map[i], fcp->isp_loopid, alpa); 2866 fcp->isp_loopid = i; 2867 } | 2857 for (i = 0; alpa_map[i]; i++) { 2858 if (alpa_map[i] == alpa) 2859 break; |
2868 } | 2860 } |
2861 if (alpa_map[i]) 2862 fcp->isp_loopid = i; |
|
2869 } 2870 2871 if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) { 2872 nphdl = IS_24XX(isp) ? NPH_FL_ID : FL_ID; 2873 r = isp_getpdb(isp, chan, nphdl, &pdb, 1); 2874 if (r != 0 || pdb.portid == 0) { 2875 if (IS_2100(isp)) { 2876 fcp->isp_topo = TOPO_NL_PORT; --- 17 unchanged lines hidden (view full) --- 2894 } 2895 if (r) { 2896 isp_prt(isp, ISP_LOGWARN|ISP_LOG_SANCFG, "%s: register fc4 type failed", __func__); 2897 return (-1); 2898 } 2899 } 2900 2901not_on_fabric: | 2863 } 2864 2865 if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) { 2866 nphdl = IS_24XX(isp) ? NPH_FL_ID : FL_ID; 2867 r = isp_getpdb(isp, chan, nphdl, &pdb, 1); 2868 if (r != 0 || pdb.portid == 0) { 2869 if (IS_2100(isp)) { 2870 fcp->isp_topo = TOPO_NL_PORT; --- 17 unchanged lines hidden (view full) --- 2888 } 2889 if (r) { 2890 isp_prt(isp, ISP_LOGWARN|ISP_LOG_SANCFG, "%s: register fc4 type failed", __func__); 2891 return (-1); 2892 } 2893 } 2894 2895not_on_fabric: |
2896 /* Get link speed. */ |
|
2902 fcp->isp_gbspeed = 1; 2903 if (IS_23XX(isp) || IS_24XX(isp)) { 2904 MBSINIT(&mbs, MBOX_GET_SET_DATA_RATE, MBLOGALL, 3000000); 2905 mbs.param[1] = MBGSD_GET_RATE; 2906 /* mbs.param[2] undefined if we're just getting rate */ 2907 isp_mboxcmd(isp, &mbs); 2908 if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { | 2897 fcp->isp_gbspeed = 1; 2898 if (IS_23XX(isp) || IS_24XX(isp)) { 2899 MBSINIT(&mbs, MBOX_GET_SET_DATA_RATE, MBLOGALL, 3000000); 2900 mbs.param[1] = MBGSD_GET_RATE; 2901 /* mbs.param[2] undefined if we're just getting rate */ 2902 isp_mboxcmd(isp, &mbs); 2903 if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { |
2909 if (mbs.param[1] == MBGSD_EIGHTGB) { 2910 isp_prt(isp, ISP_LOGINFO, "Chan %d 8Gb link speed", chan); | 2904 if (mbs.param[1] == MBGSD_10GB) 2905 fcp->isp_gbspeed = 10; 2906 else if (mbs.param[1] == MBGSD_16GB) 2907 fcp->isp_gbspeed = 16; 2908 else if (mbs.param[1] == MBGSD_8GB) |
2911 fcp->isp_gbspeed = 8; | 2909 fcp->isp_gbspeed = 8; |
2912 } else if (mbs.param[1] == MBGSD_FOURGB) { 2913 isp_prt(isp, ISP_LOGINFO, "Chan %d 4Gb link speed", chan); | 2910 else if (mbs.param[1] == MBGSD_4GB) |
2914 fcp->isp_gbspeed = 4; | 2911 fcp->isp_gbspeed = 4; |
2915 } else if (mbs.param[1] == MBGSD_TWOGB) { 2916 isp_prt(isp, ISP_LOGINFO, "Chan %d 2Gb link speed", chan); | 2912 else if (mbs.param[1] == MBGSD_2GB) |
2917 fcp->isp_gbspeed = 2; | 2913 fcp->isp_gbspeed = 2; |
2918 } else if (mbs.param[1] == MBGSD_ONEGB) { 2919 isp_prt(isp, ISP_LOGINFO, "Chan %d 1Gb link speed", chan); | 2914 else if (mbs.param[1] == MBGSD_1GB) |
2920 fcp->isp_gbspeed = 1; | 2915 fcp->isp_gbspeed = 1; |
2921 } | |
2922 } 2923 } 2924 2925 fcp->isp_loopstate = LOOP_LTEST_DONE; | 2916 } 2917 } 2918 2919 fcp->isp_loopstate = LOOP_LTEST_DONE; |
2926 /* 2927 * Announce ourselves, too. 2928 */ 2929 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG, topology, chan, (uint32_t) (fcp->isp_wwpn >> 32), (uint32_t) fcp->isp_wwpn, fcp->isp_portid, fcp->isp_loopid, isp_fc_toponame(fcp)); | 2920 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG, 2921 "Chan %d WWPN %016jx WWNN %016jx", 2922 chan, (uintmax_t)fcp->isp_wwpn, (uintmax_t)fcp->isp_wwnn); 2923 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG, 2924 "Chan %d %dGb %s PortID 0x%06x LoopID 0x%02x", 2925 chan, fcp->isp_gbspeed, isp_fc_toponame(fcp), fcp->isp_portid, 2926 fcp->isp_loopid); |
2930 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test done", chan); 2931 return (0); 2932} 2933 2934/* 2935 * Complete the synchronization of our Port Database. 2936 * 2937 * At this point, we've scanned the local loop (if any) and the fabric --- 20 unchanged lines hidden (view full) --- 2958 2959 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync", chan); 2960 2961 fcp->isp_loopstate = LOOP_SYNCING_PDB; 2962 2963 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { 2964 lp = &fcp->portdb[dbidx]; 2965 | 2927 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test done", chan); 2928 return (0); 2929} 2930 2931/* 2932 * Complete the synchronization of our Port Database. 2933 * 2934 * At this point, we've scanned the local loop (if any) and the fabric --- 20 unchanged lines hidden (view full) --- 2955 2956 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync", chan); 2957 2958 fcp->isp_loopstate = LOOP_SYNCING_PDB; 2959 2960 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { 2961 lp = &fcp->portdb[dbidx]; 2962 |
2966 if (lp->state == FC_PORTDB_STATE_NIL || 2967 lp->state == FC_PORTDB_STATE_VALID) { | 2963 if (lp->state == FC_PORTDB_STATE_NIL) |
2968 continue; | 2964 continue; |
2969 } 2970 | 2965 if (lp->probational && lp->state != FC_PORTDB_STATE_ZOMBIE) 2966 lp->state = FC_PORTDB_STATE_DEAD; |
2971 switch (lp->state) { | 2967 switch (lp->state) { |
2972 case FC_PORTDB_STATE_PROBATIONAL: | |
2973 case FC_PORTDB_STATE_DEAD: 2974 lp->state = FC_PORTDB_STATE_NIL; 2975 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp); 2976 if (lp->autologin == 0) { 2977 (void) isp_plogx(isp, chan, lp->handle, 2978 lp->portid, 2979 PLOGX_FLG_CMD_LOGO | 2980 PLOGX_FLG_IMPLICIT | 2981 PLOGX_FLG_FREE_NPHDL, 0); | 2968 case FC_PORTDB_STATE_DEAD: 2969 lp->state = FC_PORTDB_STATE_NIL; 2970 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp); 2971 if (lp->autologin == 0) { 2972 (void) isp_plogx(isp, chan, lp->handle, 2973 lp->portid, 2974 PLOGX_FLG_CMD_LOGO | 2975 PLOGX_FLG_IMPLICIT | 2976 PLOGX_FLG_FREE_NPHDL, 0); |
2982 } else { 2983 lp->autologin = 0; | |
2984 } | 2977 } |
2985 lp->new_prli_word3 = 0; 2986 lp->new_portid = 0; | |
2987 /* 2988 * Note that we might come out of this with our state 2989 * set to FC_PORTDB_STATE_ZOMBIE. 2990 */ 2991 break; 2992 case FC_PORTDB_STATE_NEW: | 2978 /* 2979 * Note that we might come out of this with our state 2980 * set to FC_PORTDB_STATE_ZOMBIE. 2981 */ 2982 break; 2983 case FC_PORTDB_STATE_NEW: |
2993 lp->portid = lp->new_portid; 2994 lp->prli_word3 = lp->new_prli_word3; | |
2995 lp->state = FC_PORTDB_STATE_VALID; 2996 isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp); | 2984 lp->state = FC_PORTDB_STATE_VALID; 2985 isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp); |
2997 lp->new_prli_word3 = 0; 2998 lp->new_portid = 0; | |
2999 break; 3000 case FC_PORTDB_STATE_CHANGED: 3001 lp->state = FC_PORTDB_STATE_VALID; 3002 isp_async(isp, ISPASYNC_DEV_CHANGED, chan, lp); 3003 lp->portid = lp->new_portid; 3004 lp->prli_word3 = lp->new_prli_word3; | 2986 break; 2987 case FC_PORTDB_STATE_CHANGED: 2988 lp->state = FC_PORTDB_STATE_VALID; 2989 isp_async(isp, ISPASYNC_DEV_CHANGED, chan, lp); 2990 lp->portid = lp->new_portid; 2991 lp->prli_word3 = lp->new_prli_word3; |
3005 lp->new_prli_word3 = 0; 3006 lp->new_portid = 0; | |
3007 break; | 2992 break; |
3008 case FC_PORTDB_STATE_PENDING_VALID: 3009 lp->portid = lp->new_portid; 3010 lp->prli_word3 = lp->new_prli_word3; 3011 lp->state = FC_PORTDB_STATE_VALID; | 2993 case FC_PORTDB_STATE_VALID: |
3012 isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp); 3013 break; 3014 case FC_PORTDB_STATE_ZOMBIE: 3015 break; 3016 default: 3017 isp_prt(isp, ISP_LOGWARN, 3018 "isp_pdb_sync: state %d for idx %d", 3019 lp->state, dbidx); --- 7 unchanged lines hidden (view full) --- 3027 * in isp_start. 3028 */ 3029 fcp->loop_seen_once = 1; 3030 fcp->isp_loopstate = LOOP_READY; 3031 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync done", chan); 3032 return (0); 3033} 3034 | 2994 isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp); 2995 break; 2996 case FC_PORTDB_STATE_ZOMBIE: 2997 break; 2998 default: 2999 isp_prt(isp, ISP_LOGWARN, 3000 "isp_pdb_sync: state %d for idx %d", 3001 lp->state, dbidx); --- 7 unchanged lines hidden (view full) --- 3009 * in isp_start. 3010 */ 3011 fcp->loop_seen_once = 1; 3012 fcp->isp_loopstate = LOOP_READY; 3013 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync done", chan); 3014 return (0); 3015} 3016 |
3017static void 3018isp_pdb_add_update(ispsoftc_t *isp, int chan, isp_pdb_t *pdb) 3019{ 3020 fcportdb_t *lp; 3021 uint64_t wwnn, wwpn; 3022 3023 MAKE_WWN_FROM_NODE_NAME(wwnn, pdb->nodename); 3024 MAKE_WWN_FROM_NODE_NAME(wwpn, pdb->portname); 3025 3026 /* Search port database for the same WWPN. */ 3027 if (isp_find_pdb_by_wwpn(isp, chan, wwpn, &lp)) { 3028 if (!lp->probational) { 3029 isp_prt(isp, ISP_LOGERR, 3030 "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)", 3031 chan, lp->portid, lp->handle, 3032 FC_PORTDB_TGT(isp, chan, lp), lp->state); 3033 isp_dump_portdb(isp, chan); 3034 return; 3035 } 3036 lp->probational = 0; 3037 lp->node_wwn = wwnn; 3038 3039 /* Old device, nothing new. */ 3040 if (lp->portid == pdb->portid && 3041 lp->handle == pdb->handle && 3042 lp->prli_word3 == pdb->prli_word3) { 3043 if (lp->state != FC_PORTDB_STATE_NEW) 3044 lp->state = FC_PORTDB_STATE_VALID; 3045 isp_prt(isp, ISP_LOG_SANCFG, 3046 "Chan %d Port 0x%06x@0x%04x is valid", 3047 chan, pdb->portid, pdb->handle); 3048 return; 3049 } 3050 3051 /* Something has changed. */ 3052 lp->state = FC_PORTDB_STATE_CHANGED; 3053 lp->handle = pdb->handle; 3054 lp->new_portid = pdb->portid; 3055 lp->new_prli_word3 = pdb->prli_word3; 3056 isp_prt(isp, ISP_LOG_SANCFG, 3057 "Chan %d Port 0x%06x@0x%04x is changed", 3058 chan, pdb->portid, pdb->handle); 3059 return; 3060 } 3061 3062 /* It seems like a new port. Find an empty slot for it. */ 3063 if (!isp_find_pdb_empty(isp, chan, &lp)) { 3064 isp_prt(isp, ISP_LOGERR, "Chan %d out of portdb entries", chan); 3065 return; 3066 } 3067 3068 ISP_MEMZERO(lp, sizeof (fcportdb_t)); 3069 lp->autologin = 1; 3070 lp->probational = 0; 3071 lp->state = FC_PORTDB_STATE_NEW; 3072 lp->portid = lp->new_portid = pdb->portid; 3073 lp->prli_word3 = lp->new_prli_word3 = pdb->prli_word3; 3074 lp->handle = pdb->handle; 3075 lp->port_wwn = wwpn; 3076 lp->node_wwn = wwnn; 3077 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Port 0x%06x@0x%04x is new", 3078 chan, pdb->portid, pdb->handle); 3079} 3080 |
|
3035/* 3036 * Scan local loop for devices. 3037 */ 3038static int 3039isp_scan_loop(ispsoftc_t *isp, int chan) 3040{ | 3081/* 3082 * Scan local loop for devices. 3083 */ 3084static int 3085isp_scan_loop(ispsoftc_t *isp, int chan) 3086{ |
3041 fcportdb_t *lp, tmp; | |
3042 fcparam *fcp = FCPARAM(isp, chan); | 3087 fcparam *fcp = FCPARAM(isp, chan); |
3043 int i, idx, lim, r; | 3088 int idx, lim, r; |
3044 isp_pdb_t pdb; 3045 uint16_t handles[LOCAL_LOOP_LIM]; 3046 uint16_t handle; 3047 3048 if (fcp->isp_loopstate < LOOP_LTEST_DONE) { 3049 return (-1); 3050 } 3051 if (fcp->isp_loopstate > LOOP_SCANNING_LOOP) { 3052 return (0); 3053 } 3054 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan", chan); | 3089 isp_pdb_t pdb; 3090 uint16_t handles[LOCAL_LOOP_LIM]; 3091 uint16_t handle; 3092 3093 if (fcp->isp_loopstate < LOOP_LTEST_DONE) { 3094 return (-1); 3095 } 3096 if (fcp->isp_loopstate > LOOP_SCANNING_LOOP) { 3097 return (0); 3098 } 3099 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan", chan); |
3055 if (fcp->isp_topo != TOPO_NL_PORT && fcp->isp_topo != TOPO_FL_PORT && 3056 fcp->isp_topo != TOPO_N_PORT) { | 3100 if (TOPO_IS_FABRIC(fcp->isp_topo)) { |
3057 isp_prt(isp, ISP_LOG_SANCFG, 3058 "Chan %d FC loop scan done (no loop)", chan); 3059 fcp->isp_loopstate = LOOP_LSCAN_DONE; 3060 return (0); 3061 } 3062 fcp->isp_loopstate = LOOP_SCANNING_LOOP; 3063 3064 lim = LOCAL_LOOP_LIM; 3065 r = isp_gethandles(isp, chan, handles, &lim, 1, 1); 3066 if (r != 0) { 3067 isp_prt(isp, ISP_LOG_SANCFG, 3068 "Chan %d Getting list of handles failed with %x", chan, r); | 3101 isp_prt(isp, ISP_LOG_SANCFG, 3102 "Chan %d FC loop scan done (no loop)", chan); 3103 fcp->isp_loopstate = LOOP_LSCAN_DONE; 3104 return (0); 3105 } 3106 fcp->isp_loopstate = LOOP_SCANNING_LOOP; 3107 3108 lim = LOCAL_LOOP_LIM; 3109 r = isp_gethandles(isp, chan, handles, &lim, 1, 1); 3110 if (r != 0) { 3111 isp_prt(isp, ISP_LOG_SANCFG, 3112 "Chan %d Getting list of handles failed with %x", chan, r); |
3069fail: | |
3070 isp_prt(isp, ISP_LOG_SANCFG, 3071 "Chan %d FC loop scan done (bad)", chan); 3072 return (-1); 3073 } 3074 3075 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Got %d handles", 3076 chan, lim); 3077 --- 30 unchanged lines hidden (view full) --- 3108 continue; 3109 } 3110 } 3111 3112 /* 3113 * Get the port database entity for this index. 3114 */ 3115 r = isp_getpdb(isp, chan, handle, &pdb, 1); | 3113 isp_prt(isp, ISP_LOG_SANCFG, 3114 "Chan %d FC loop scan done (bad)", chan); 3115 return (-1); 3116 } 3117 3118 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Got %d handles", 3119 chan, lim); 3120 --- 30 unchanged lines hidden (view full) --- 3151 continue; 3152 } 3153 } 3154 3155 /* 3156 * Get the port database entity for this index. 3157 */ 3158 r = isp_getpdb(isp, chan, handle, &pdb, 1); |
3159 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) 3160 goto abort; |
|
3116 if (r != 0) { 3117 isp_prt(isp, ISP_LOGDEBUG1, 3118 "Chan %d FC Scan Loop handle %d returned %x", 3119 chan, handle, r); 3120 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) 3121 goto abort; 3122 continue; 3123 } 3124 | 3161 if (r != 0) { 3162 isp_prt(isp, ISP_LOGDEBUG1, 3163 "Chan %d FC Scan Loop handle %d returned %x", 3164 chan, handle, r); 3165 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) 3166 goto abort; 3167 continue; 3168 } 3169 |
3125 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) 3126 goto abort; 3127 3128 /* 3129 * On *very* old 2100 firmware we would end up sometimes 3130 * with the firmware returning the port database entry 3131 * for something else. We used to restart this, but 3132 * now we just punt. 3133 */ 3134 if (IS_2100(isp) && pdb.handle != handle) { 3135 isp_prt(isp, ISP_LOGWARN, 3136 "Chan %d getpdb() returned wrong handle %x != %x", 3137 chan, pdb.handle, handle); 3138 goto fail; 3139 } 3140 3141 /* 3142 * Save the pertinent info locally. 3143 */ 3144 MAKE_WWN_FROM_NODE_NAME(tmp.node_wwn, pdb.nodename); 3145 MAKE_WWN_FROM_NODE_NAME(tmp.port_wwn, pdb.portname); 3146 tmp.prli_word3 = pdb.prli_word3; 3147 tmp.portid = pdb.portid; 3148 tmp.handle = pdb.handle; 3149 3150 /* 3151 * Check to make sure it's still a valid entry. The 24XX seems 3152 * to return a portid but not a WWPN/WWNN or role for devices 3153 * which shift on a loop. 3154 */ 3155 if (tmp.node_wwn == 0 || tmp.port_wwn == 0 || tmp.portid == 0) { 3156 int a, b, c; 3157 isp_prt(isp, ISP_LOGWARN, 3158 "Chan %d bad pdb (WWNN %016jx, WWPN %016jx, PortID %06x, W3 0x%x, H 0x%x) @ handle 0x%x", 3159 chan, tmp.node_wwn, tmp.port_wwn, tmp.portid, tmp.prli_word3, tmp.handle, handle); 3160 a = (tmp.node_wwn == 0); 3161 b = (tmp.port_wwn == 0); 3162 c = (tmp.portid == 0); 3163 if (a == 0 && b == 0) { 3164 tmp.node_wwn = 3165 isp_get_wwn(isp, chan, handle, 1); 3166 tmp.port_wwn = 3167 isp_get_wwn(isp, chan, handle, 0); 3168 if (tmp.node_wwn && tmp.port_wwn) { 3169 isp_prt(isp, ISP_LOGWARN, "DODGED!"); 3170 goto cont; 3171 } 3172 } 3173 isp_dump_portdb(isp, chan); 3174 continue; 3175 } 3176 cont: 3177 3178 /* 3179 * Now search the entire port database 3180 * for the same Port WWN. 3181 */ 3182 if (isp_find_pdb_by_wwn(isp, chan, tmp.port_wwn, &lp)) { 3183 /* 3184 * Okay- we've found a non-nil entry that matches. 3185 * Check to make sure it's probational or a zombie. 3186 */ 3187 if (lp->state != FC_PORTDB_STATE_PROBATIONAL && 3188 lp->state != FC_PORTDB_STATE_ZOMBIE && 3189 lp->state != FC_PORTDB_STATE_VALID) { 3190 isp_prt(isp, ISP_LOGERR, 3191 "Chan %d [%d] not probational/zombie (0x%x)", 3192 chan, FC_PORTDB_TGT(isp, chan, lp), lp->state); 3193 isp_dump_portdb(isp, chan); 3194 goto fail; 3195 } 3196 3197 /* 3198 * Mark the device as something the f/w logs into 3199 * automatically. 3200 */ 3201 lp->autologin = 1; 3202 lp->node_wwn = tmp.node_wwn; 3203 3204 /* 3205 * Check to make see if really still the same 3206 * device. If it is, we mark it pending valid. 3207 */ 3208 if (lp->portid == tmp.portid && lp->handle == tmp.handle && lp->prli_word3 == tmp.prli_word3) { 3209 lp->new_portid = tmp.portid; 3210 lp->new_prli_word3 = tmp.prli_word3; 3211 lp->state = FC_PORTDB_STATE_PENDING_VALID; 3212 isp_prt(isp, ISP_LOG_SANCFG, 3213 "Chan %d Loop port 0x%06x@0x%04x now pending valid", 3214 chan, tmp.portid, tmp.handle); 3215 continue; 3216 } 3217 3218 /* 3219 * We can wipe out the old handle value 3220 * here because it's no longer valid. 3221 */ 3222 lp->handle = tmp.handle; 3223 3224 /* 3225 * Claim that this has changed and let somebody else 3226 * decide what to do. 3227 */ 3228 isp_prt(isp, ISP_LOG_SANCFG, 3229 "Chan %d Loop port 0x%06x@0x%04x changed", 3230 chan, tmp.portid, tmp.handle); 3231 lp->state = FC_PORTDB_STATE_CHANGED; 3232 lp->new_portid = tmp.portid; 3233 lp->new_prli_word3 = tmp.prli_word3; 3234 continue; 3235 } 3236 3237 /* 3238 * Ah. A new device entry. Find an empty slot 3239 * for it and save info for later disposition. 3240 */ 3241 for (i = 0; i < MAX_FC_TARG; i++) { 3242 if (fcp->portdb[i].state == FC_PORTDB_STATE_NIL) { 3243 break; 3244 } 3245 } 3246 if (i == MAX_FC_TARG) { 3247 isp_prt(isp, ISP_LOGERR, 3248 "Chan %d out of portdb entries", chan); 3249 continue; 3250 } 3251 lp = &fcp->portdb[i]; 3252 3253 ISP_MEMZERO(lp, sizeof (fcportdb_t)); 3254 lp->autologin = 1; 3255 lp->state = FC_PORTDB_STATE_NEW; 3256 lp->new_portid = tmp.portid; 3257 lp->new_prli_word3 = tmp.prli_word3; 3258 lp->handle = tmp.handle; 3259 lp->port_wwn = tmp.port_wwn; 3260 lp->node_wwn = tmp.node_wwn; 3261 isp_prt(isp, ISP_LOG_SANCFG, 3262 "Chan %d Loop port 0x%06x@0x%04x is a new entry", 3263 chan, tmp.portid, tmp.handle); | 3170 isp_pdb_add_update(isp, chan, &pdb); |
3264 } 3265 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) 3266 goto abort; 3267 fcp->isp_loopstate = LOOP_LSCAN_DONE; 3268 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan done", chan); 3269 return (0); 3270} 3271 --- 82 unchanged lines hidden (view full) --- 3354 } un; 3355 isp_ct_pt_t *pt; 3356 ct_hdr_t *ct; 3357 uint32_t *rp; 3358 uint8_t *scp = fcp->isp_scratch; 3359 3360 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d scanning fabric (GID_FT) via CT", chan); 3361 | 3171 } 3172 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) 3173 goto abort; 3174 fcp->isp_loopstate = LOOP_LSCAN_DONE; 3175 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan done", chan); 3176 return (0); 3177} 3178 --- 82 unchanged lines hidden (view full) --- 3261 } un; 3262 isp_ct_pt_t *pt; 3263 ct_hdr_t *ct; 3264 uint32_t *rp; 3265 uint8_t *scp = fcp->isp_scratch; 3266 3267 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d scanning fabric (GID_FT) via CT", chan); 3268 |
3362 if (!IS_24XX(isp)) { 3363 return (1); 3364 } 3365 | |
3366 /* 3367 * Build a Passthrough IOCB in memory. 3368 */ 3369 pt = &un.plocal; 3370 ISP_MEMZERO(un.q, QENTRY_LEN); 3371 pt->ctp_header.rqs_entry_count = 1; 3372 pt->ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU; 3373 pt->ctp_handle = 0xffffffff; --- 66 unchanged lines hidden (view full) --- 3440 } 3441 return (0); 3442} 3443 3444static int 3445isp_scan_fabric(ispsoftc_t *isp, int chan) 3446{ 3447 fcparam *fcp = FCPARAM(isp, chan); | 3269 /* 3270 * Build a Passthrough IOCB in memory. 3271 */ 3272 pt = &un.plocal; 3273 ISP_MEMZERO(un.q, QENTRY_LEN); 3274 pt->ctp_header.rqs_entry_count = 1; 3275 pt->ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU; 3276 pt->ctp_handle = 0xffffffff; --- 66 unchanged lines hidden (view full) --- 3343 } 3344 return (0); 3345} 3346 3347static int 3348isp_scan_fabric(ispsoftc_t *isp, int chan) 3349{ 3350 fcparam *fcp = FCPARAM(isp, chan); |
3351 fcportdb_t *lp; |
|
3448 uint32_t portid; 3449 uint16_t nphdl; 3450 isp_pdb_t pdb; 3451 int portidx, portlim, r; 3452 sns_gid_ft_rsp_t *rs0, *rs1; 3453 3454 if (fcp->isp_loopstate < LOOP_LSCAN_DONE) { 3455 return (-1); 3456 } 3457 if (fcp->isp_loopstate > LOOP_SCANNING_FABRIC) { 3458 return (0); 3459 } 3460 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan", chan); | 3352 uint32_t portid; 3353 uint16_t nphdl; 3354 isp_pdb_t pdb; 3355 int portidx, portlim, r; 3356 sns_gid_ft_rsp_t *rs0, *rs1; 3357 3358 if (fcp->isp_loopstate < LOOP_LSCAN_DONE) { 3359 return (-1); 3360 } 3361 if (fcp->isp_loopstate > LOOP_SCANNING_FABRIC) { 3362 return (0); 3363 } 3364 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan", chan); |
3461 if (fcp->isp_topo != TOPO_FL_PORT && fcp->isp_topo != TOPO_F_PORT) { | 3365 if (!TOPO_IS_FABRIC(fcp->isp_topo)) { |
3462 fcp->isp_loopstate = LOOP_FSCAN_DONE; 3463 isp_prt(isp, ISP_LOG_SANCFG, 3464 "Chan %d FC fabric scan done (no fabric)", chan); 3465 return (0); 3466 } 3467 fcp->isp_loopstate = LOOP_SCANNING_FABRIC; 3468 3469 if (FC_SCRATCH_ACQUIRE(isp, chan)) { --- 20 unchanged lines hidden (view full) --- 3490 isp_dump_chip_portdb(isp, chan, 0); 3491 } 3492 if (r) { 3493 fcp->isp_loopstate = LOOP_LTEST_DONE; 3494 FC_SCRATCH_RELEASE(isp, chan); 3495 goto fail; 3496 } 3497 | 3366 fcp->isp_loopstate = LOOP_FSCAN_DONE; 3367 isp_prt(isp, ISP_LOG_SANCFG, 3368 "Chan %d FC fabric scan done (no fabric)", chan); 3369 return (0); 3370 } 3371 fcp->isp_loopstate = LOOP_SCANNING_FABRIC; 3372 3373 if (FC_SCRATCH_ACQUIRE(isp, chan)) { --- 20 unchanged lines hidden (view full) --- 3394 isp_dump_chip_portdb(isp, chan, 0); 3395 } 3396 if (r) { 3397 fcp->isp_loopstate = LOOP_LTEST_DONE; 3398 FC_SCRATCH_RELEASE(isp, chan); 3399 goto fail; 3400 } 3401 |
3498 if (IS_24XX(isp)) { | 3402 /* Get list of port IDs from SNS. */ 3403 if (IS_24XX(isp)) |
3499 r = isp_gid_ft_ct_passthru(isp, chan); | 3404 r = isp_gid_ft_ct_passthru(isp, chan); |
3500 } else { | 3405 else |
3501 r = isp_gid_ft_sns(isp, chan); | 3406 r = isp_gid_ft_sns(isp, chan); |
3502 } 3503 3504 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) { | 3407 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) |
3505 goto abort; | 3408 goto abort; |
3506 } 3507 | |
3508 if (r > 0) { 3509 fcp->isp_loopstate = LOOP_FSCAN_DONE; 3510 FC_SCRATCH_RELEASE(isp, chan); 3511 return (0); 3512 } else if (r < 0) { 3513 fcp->isp_loopstate = LOOP_LTEST_DONE; /* try again */ 3514 FC_SCRATCH_RELEASE(isp, chan); 3515 return (0); 3516 } 3517 3518 MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN, chan); 3519 rs0 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+IGPOFF); 3520 rs1 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+OGPOFF); 3521 isp_get_gid_ft_response(isp, rs0, rs1, NGENT); | 3409 if (r > 0) { 3410 fcp->isp_loopstate = LOOP_FSCAN_DONE; 3411 FC_SCRATCH_RELEASE(isp, chan); 3412 return (0); 3413 } else if (r < 0) { 3414 fcp->isp_loopstate = LOOP_LTEST_DONE; /* try again */ 3415 FC_SCRATCH_RELEASE(isp, chan); 3416 return (0); 3417 } 3418 3419 MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN, chan); 3420 rs0 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+IGPOFF); 3421 rs1 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+OGPOFF); 3422 isp_get_gid_ft_response(isp, rs0, rs1, NGENT); |
3522 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) { | 3423 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) |
3523 goto abort; | 3424 goto abort; |
3524 } | |
3525 if (rs1->snscb_cthdr.ct_cmd_resp != LS_ACC) { 3526 int level; 3527 if (rs1->snscb_cthdr.ct_reason == 9 && rs1->snscb_cthdr.ct_explanation == 7) { 3528 level = ISP_LOG_SANCFG; 3529 } else { 3530 level = ISP_LOGWARN; 3531 } 3532 isp_prt(isp, level, "Chan %d Fabric Nameserver rejected GID_FT" 3533 " (Reason=0x%x Expl=0x%x)", chan, 3534 rs1->snscb_cthdr.ct_reason, 3535 rs1->snscb_cthdr.ct_explanation); 3536 FC_SCRATCH_RELEASE(isp, chan); 3537 fcp->isp_loopstate = LOOP_FSCAN_DONE; 3538 return (0); 3539 } 3540 | 3425 if (rs1->snscb_cthdr.ct_cmd_resp != LS_ACC) { 3426 int level; 3427 if (rs1->snscb_cthdr.ct_reason == 9 && rs1->snscb_cthdr.ct_explanation == 7) { 3428 level = ISP_LOG_SANCFG; 3429 } else { 3430 level = ISP_LOGWARN; 3431 } 3432 isp_prt(isp, level, "Chan %d Fabric Nameserver rejected GID_FT" 3433 " (Reason=0x%x Expl=0x%x)", chan, 3434 rs1->snscb_cthdr.ct_reason, 3435 rs1->snscb_cthdr.ct_explanation); 3436 FC_SCRATCH_RELEASE(isp, chan); 3437 fcp->isp_loopstate = LOOP_FSCAN_DONE; 3438 return (0); 3439 } 3440 |
3541 /* 3542 * Go through the list and remove duplicate port ids. 3543 */ 3544 3545 portlim = 0; 3546 portidx = 0; | 3441 /* Check our buffer was big enough to get the full list. */ |
3547 for (portidx = 0; portidx < NGENT-1; portidx++) { | 3442 for (portidx = 0; portidx < NGENT-1; portidx++) { |
3548 if (rs1->snscb_ports[portidx].control & 0x80) { | 3443 if (rs1->snscb_ports[portidx].control & 0x80) |
3549 break; | 3444 break; |
3550 } | |
3551 } | 3445 } |
3552 3553 /* 3554 * If we're not at the last entry, our list wasn't big enough. 3555 */ | |
3556 if ((rs1->snscb_ports[portidx].control & 0x80) == 0) { 3557 isp_prt(isp, ISP_LOGWARN, 3558 "fabric too big for scratch area: increase ISP_FC_SCRLEN"); 3559 } 3560 portlim = portidx + 1; 3561 isp_prt(isp, ISP_LOG_SANCFG, 3562 "Chan %d Got %d ports back from name server", chan, portlim); 3563 | 3446 if ((rs1->snscb_ports[portidx].control & 0x80) == 0) { 3447 isp_prt(isp, ISP_LOGWARN, 3448 "fabric too big for scratch area: increase ISP_FC_SCRLEN"); 3449 } 3450 portlim = portidx + 1; 3451 isp_prt(isp, ISP_LOG_SANCFG, 3452 "Chan %d Got %d ports back from name server", chan, portlim); 3453 |
3454 /* Go through the list and remove duplicate port ids. */ |
|
3564 for (portidx = 0; portidx < portlim; portidx++) { 3565 int npidx; 3566 3567 portid = 3568 ((rs1->snscb_ports[portidx].portid[0]) << 16) | 3569 ((rs1->snscb_ports[portidx].portid[1]) << 8) | 3570 ((rs1->snscb_ports[portidx].portid[2])); 3571 --- 26 unchanged lines hidden (view full) --- 3598 * Otherwise, it's a new fabric device, and we log into it 3599 * (unconditionally). After searching the entire database 3600 * again to make sure that we never ever ever ever have more 3601 * than one entry that has the same PortID or the same 3602 * WWNN/WWPN duple, we enter the device into our database. 3603 */ 3604 3605 for (portidx = 0; portidx < portlim; portidx++) { | 3455 for (portidx = 0; portidx < portlim; portidx++) { 3456 int npidx; 3457 3458 portid = 3459 ((rs1->snscb_ports[portidx].portid[0]) << 16) | 3460 ((rs1->snscb_ports[portidx].portid[1]) << 8) | 3461 ((rs1->snscb_ports[portidx].portid[2])); 3462 --- 26 unchanged lines hidden (view full) --- 3489 * Otherwise, it's a new fabric device, and we log into it 3490 * (unconditionally). After searching the entire database 3491 * again to make sure that we never ever ever ever have more 3492 * than one entry that has the same PortID or the same 3493 * WWNN/WWPN duple, we enter the device into our database. 3494 */ 3495 3496 for (portidx = 0; portidx < portlim; portidx++) { |
3606 fcportdb_t *lp; 3607 uint64_t wwnn, wwpn; 3608 int dbidx, nr; 3609 3610 portid = 3611 ((rs1->snscb_ports[portidx].portid[0]) << 16) | 3612 ((rs1->snscb_ports[portidx].portid[1]) << 8) | 3613 ((rs1->snscb_ports[portidx].portid[2])); 3614 | 3497 portid = ((rs1->snscb_ports[portidx].portid[0]) << 16) | 3498 ((rs1->snscb_ports[portidx].portid[1]) << 8) | 3499 ((rs1->snscb_ports[portidx].portid[2])); 3500 isp_prt(isp, ISP_LOG_SANCFG, 3501 "Chan %d Checking fabric port 0x%06x", chan, portid); |
3615 if (portid == 0) { 3616 isp_prt(isp, ISP_LOG_SANCFG, 3617 "Chan %d Skipping null PortID at idx %d", 3618 chan, portidx); 3619 continue; 3620 } | 3502 if (portid == 0) { 3503 isp_prt(isp, ISP_LOG_SANCFG, 3504 "Chan %d Skipping null PortID at idx %d", 3505 chan, portidx); 3506 continue; 3507 } |
3621 | |
3622 if (portid == fcp->isp_portid) { 3623 isp_prt(isp, ISP_LOG_SANCFG, 3624 "Chan %d Skipping our PortID 0x%06x", chan, portid); 3625 continue; 3626 } 3627 | 3508 if (portid == fcp->isp_portid) { 3509 isp_prt(isp, ISP_LOG_SANCFG, 3510 "Chan %d Skipping our PortID 0x%06x", chan, portid); 3511 continue; 3512 } 3513 |
3628 isp_prt(isp, ISP_LOG_SANCFG, 3629 "Chan %d Checking fabric port 0x%06x", chan, portid); 3630 3631 /* 3632 * We now search our Port Database for any 3633 * probational entries with this PortID. We don't 3634 * look for zombies here- only probational 3635 * entries (we've already logged out of zombies). 3636 */ 3637 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { 3638 lp = &fcp->portdb[dbidx]; 3639 3640 if (lp->state != FC_PORTDB_STATE_PROBATIONAL) { 3641 continue; | 3514 /* Now search the entire port database for the same portid. */ 3515 if (isp_find_pdb_by_portid(isp, chan, portid, &lp)) { 3516 if (!lp->probational) { 3517 isp_prt(isp, ISP_LOGERR, 3518 "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)", 3519 chan, lp->portid, lp->handle, 3520 FC_PORTDB_TGT(isp, chan, lp), lp->state); 3521 FC_SCRATCH_RELEASE(isp, chan); 3522 isp_dump_portdb(isp, chan); 3523 goto fail; |
3642 } | 3524 } |
3643 if (lp->portid == portid) { 3644 break; 3645 } 3646 } | |
3647 | 3525 |
3648 /* 3649 * We found a probational entry with this Port ID. 3650 */ 3651 if (dbidx < MAX_FC_TARG) { 3652 int handle_changed = 0; 3653 3654 lp = &fcp->portdb[dbidx]; 3655 | |
3656 /* 3657 * See if we're still logged into it. 3658 * 3659 * If we aren't, mark it as a dead device and 3660 * leave the new portid in the database entry 3661 * for somebody further along to decide what to 3662 * do (policy choice). 3663 * 3664 * If we are, check to see if it's the same 3665 * device still (it should be). If for some 3666 * reason it isn't, mark it as a changed device 3667 * and leave the new portid and role in the 3668 * database entry for somebody further along to 3669 * decide what to do (policy choice). | 3526 /* 3527 * See if we're still logged into it. 3528 * 3529 * If we aren't, mark it as a dead device and 3530 * leave the new portid in the database entry 3531 * for somebody further along to decide what to 3532 * do (policy choice). 3533 * 3534 * If we are, check to see if it's the same 3535 * device still (it should be). If for some 3536 * reason it isn't, mark it as a changed device 3537 * and leave the new portid and role in the 3538 * database entry for somebody further along to 3539 * decide what to do (policy choice). |
3670 * | |
3671 */ | 3540 */ |
3672 | |
3673 r = isp_getpdb(isp, chan, lp->handle, &pdb, 0); | 3541 r = isp_getpdb(isp, chan, lp->handle, &pdb, 0); |
3674 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) { | 3542 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) |
3675 goto abort; | 3543 goto abort; |
3676 } | |
3677 if (r != 0) { | 3544 if (r != 0) { |
3678 lp->new_portid = portid; | |
3679 lp->state = FC_PORTDB_STATE_DEAD; | 3545 lp->state = FC_PORTDB_STATE_DEAD; |
3680 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Fabric PortID 0x%06x handle 0x%x is dead (%d)", chan, portid, lp->handle, r); 3681 continue; 3682 } 3683 3684 3685 /* 3686 * Check to make sure that handle, portid, WWPN and 3687 * WWNN agree. If they don't, then the association 3688 * between this PortID and the stated handle has been 3689 * broken by the firmware. 3690 */ 3691 MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename); 3692 MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname); 3693 if (pdb.handle != lp->handle || 3694 pdb.portid != portid || 3695 wwpn != lp->port_wwn || 3696 (lp->node_wwn != 0 && wwnn != lp->node_wwn)) { | |
3697 isp_prt(isp, ISP_LOG_SANCFG, | 3546 isp_prt(isp, ISP_LOG_SANCFG, |
3698 fconf, chan, dbidx, pdb.handle, pdb.portid, 3699 (uint32_t) (wwnn >> 32), (uint32_t) wwnn, 3700 (uint32_t) (wwpn >> 32), (uint32_t) wwpn, 3701 lp->handle, portid, 3702 (uint32_t) (lp->node_wwn >> 32), 3703 (uint32_t) lp->node_wwn, 3704 (uint32_t) (lp->port_wwn >> 32), 3705 (uint32_t) lp->port_wwn); 3706 /* 3707 * Try to re-login to this device using a 3708 * new handle. If that fails, mark it dead. 3709 * 3710 * isp_login_device will check for handle and 3711 * portid consistency after re-login. 3712 * 3713 */ 3714 if ((fcp->role & ISP_ROLE_INITIATOR) == 0 || 3715 isp_login_device(isp, chan, portid, &pdb, 3716 &FCPARAM(isp, 0)->isp_lasthdl)) { 3717 lp->new_portid = portid; 3718 lp->state = FC_PORTDB_STATE_DEAD; 3719 if (fcp->isp_loopstate < 3720 LOOP_SCANNING_FABRIC) { 3721 goto abort; 3722 } 3723 continue; 3724 } 3725 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) { 3726 goto abort; 3727 } 3728 MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename); 3729 MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname); 3730 if (wwpn != lp->port_wwn || 3731 (lp->node_wwn != 0 && wwnn != lp->node_wwn)) { 3732 isp_prt(isp, ISP_LOGWARN, "changed WWN" 3733 " after relogin"); 3734 lp->new_portid = portid; 3735 lp->state = FC_PORTDB_STATE_DEAD; 3736 continue; 3737 } 3738 3739 lp->handle = pdb.handle; 3740 handle_changed++; | 3547 "Chan %d Port 0x%06x handle 0x%x is dead (%d)", 3548 chan, portid, lp->handle, r); 3549 goto relogin; |
3741 } 3742 | 3550 } 3551 |
3743 nr = pdb.prli_word3; 3744 3745 /* 3746 * Check to see whether the portid and roles have 3747 * stayed the same. If they have stayed the same, 3748 * we believe that this is the same device and it 3749 * hasn't become disconnected and reconnected, so 3750 * mark it as pending valid. 3751 * 3752 * If they aren't the same, mark the device as a 3753 * changed device and save the new port id and role 3754 * and let somebody else decide. 3755 */ 3756 3757 lp->new_portid = portid; 3758 lp->new_prli_word3 = nr; 3759 if (pdb.portid != lp->portid || nr != lp->prli_word3 || handle_changed) { 3760 isp_prt(isp, ISP_LOG_SANCFG, 3761 "Chan %d Fabric port 0x%06x changed", 3762 chan, portid); 3763 lp->state = FC_PORTDB_STATE_CHANGED; 3764 } else { 3765 isp_prt(isp, ISP_LOG_SANCFG, 3766 "Chan %d Fabric port 0x%06x now pending valid", 3767 chan, portid); 3768 lp->state = FC_PORTDB_STATE_PENDING_VALID; 3769 } | 3552 isp_pdb_add_update(isp, chan, &pdb); |
3770 continue; 3771 } 3772 | 3553 continue; 3554 } 3555 |
3556relogin: |
|
3773 if ((fcp->role & ISP_ROLE_INITIATOR) == 0) 3774 continue; 3775 | 3557 if ((fcp->role & ISP_ROLE_INITIATOR) == 0) 3558 continue; 3559 |
3776 /* 3777 * Ah- a new entry. Search the database again for all non-NIL 3778 * entries to make sure we never ever make a new database entry 3779 * with the same port id. While we're at it, mark where the 3780 * last free entry was. 3781 */ 3782 3783 dbidx = MAX_FC_TARG; 3784 for (lp = fcp->portdb; lp < &fcp->portdb[MAX_FC_TARG]; lp++) { 3785 if (lp->state == FC_PORTDB_STATE_NIL) { 3786 if (dbidx == MAX_FC_TARG) { 3787 dbidx = lp - fcp->portdb; 3788 } 3789 continue; 3790 } 3791 if (lp->state == FC_PORTDB_STATE_ZOMBIE) { 3792 continue; 3793 } 3794 if (lp->portid == portid) { 3795 break; 3796 } 3797 } 3798 3799 if (lp < &fcp->portdb[MAX_FC_TARG]) { 3800 isp_prt(isp, ISP_LOGWARN, "Chan %d PortID 0x%06x " 3801 "already at %d handle %d state %d", 3802 chan, portid, dbidx, lp->handle, lp->state); 3803 continue; 3804 } 3805 3806 /* 3807 * We should have the index of the first free entry seen. 3808 */ 3809 if (dbidx == MAX_FC_TARG) { 3810 isp_prt(isp, ISP_LOGERR, 3811 "port database too small to login PortID 0x%06x" 3812 "- increase MAX_FC_TARG", portid); 3813 continue; 3814 } 3815 3816 /* 3817 * Otherwise, point to our new home. 3818 */ 3819 lp = &fcp->portdb[dbidx]; 3820 3821 /* 3822 * Try to see if we are logged into this device, 3823 * and maybe log into it. 3824 * 3825 * isp_login_device will check for handle and 3826 * portid consistency after login. 3827 */ | |
3828 if (isp_login_device(isp, chan, portid, &pdb, 3829 &FCPARAM(isp, 0)->isp_lasthdl)) { | 3560 if (isp_login_device(isp, chan, portid, &pdb, 3561 &FCPARAM(isp, 0)->isp_lasthdl)) { |
3830 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) { | 3562 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) |
3831 goto abort; | 3563 goto abort; |
3832 } | |
3833 continue; 3834 } | 3564 continue; 3565 } |
3835 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) { 3836 goto abort; 3837 } | |
3838 | 3566 |
3839 nphdl = pdb.handle; 3840 MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename); 3841 MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname); 3842 nr = pdb.prli_word3; 3843 3844 /* 3845 * And go through the database *one* more time to make sure 3846 * that we do not make more than one entry that has the same 3847 * WWNN/WWPN duple 3848 */ 3849 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { 3850 if ((fcp->portdb[dbidx].node_wwn == wwnn || 3851 fcp->portdb[dbidx].node_wwn == 0) && 3852 fcp->portdb[dbidx].port_wwn == wwpn) { 3853 break; 3854 } 3855 } 3856 3857 if (dbidx == MAX_FC_TARG) { 3858 ISP_MEMZERO(lp, sizeof (fcportdb_t)); 3859 lp->handle = nphdl; 3860 lp->node_wwn = wwnn; 3861 lp->port_wwn = wwpn; 3862 lp->new_portid = portid; 3863 lp->new_prli_word3 = nr; 3864 lp->state = FC_PORTDB_STATE_NEW; 3865 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Fabric port 0x%06x is a new entry", chan, portid); 3866 continue; 3867 } 3868 3869 if (fcp->portdb[dbidx].state != FC_PORTDB_STATE_ZOMBIE) { 3870 isp_prt(isp, ISP_LOGWARN, 3871 "Chan %d PortID 0x%x 0x%08x%08x/0x%08x%08x %ld " 3872 "already at idx %d, state 0x%x", chan, portid, 3873 (uint32_t) (wwnn >> 32), (uint32_t) wwnn, 3874 (uint32_t) (wwpn >> 32), (uint32_t) wwpn, 3875 (long) (lp - fcp->portdb), dbidx, 3876 fcp->portdb[dbidx].state); 3877 continue; 3878 } 3879 3880 /* 3881 * We found a zombie entry that matches us. 3882 * Revive it. We know that WWN and WWPN 3883 * are the same. For fabric devices, we 3884 * don't care that handle is different 3885 * as we assign that. If role or portid 3886 * are different, it maybe a changed device. 3887 */ 3888 lp = &fcp->portdb[dbidx]; 3889 lp->handle = nphdl; 3890 lp->node_wwn = wwnn; 3891 lp->new_portid = portid; 3892 lp->new_prli_word3 = nr; 3893 if (lp->portid != portid || lp->prli_word3 != nr) { 3894 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Zombie fabric port 0x%06x now changed", chan, portid); 3895 lp->state = FC_PORTDB_STATE_CHANGED; 3896 } else { 3897 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Zombie fabric port 0x%06x now pending valid", chan, portid); 3898 lp->state = FC_PORTDB_STATE_PENDING_VALID; 3899 } | 3567 isp_pdb_add_update(isp, chan, &pdb); |
3900 } 3901 | 3568 } 3569 |
3902 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) { | 3570 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) |
3903 goto abort; | 3571 goto abort; |
3904 } | |
3905 FC_SCRATCH_RELEASE(isp, chan); 3906 fcp->isp_loopstate = LOOP_FSCAN_DONE; 3907 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan done", chan); 3908 return (0); 3909} 3910 3911/* 3912 * Find an unused handle and try and use to login to a port. --- 7 unchanged lines hidden (view full) --- 3920 if (ISP_CAP_2KLOGIN(isp)) { 3921 lim = NPH_MAX_2K; 3922 } else { 3923 lim = NPH_MAX; 3924 } 3925 3926 handle = isp_next_handle(isp, ohp); 3927 for (i = 0; i < lim; i++) { | 3572 FC_SCRATCH_RELEASE(isp, chan); 3573 fcp->isp_loopstate = LOOP_FSCAN_DONE; 3574 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan done", chan); 3575 return (0); 3576} 3577 3578/* 3579 * Find an unused handle and try and use to login to a port. --- 7 unchanged lines hidden (view full) --- 3587 if (ISP_CAP_2KLOGIN(isp)) { 3588 lim = NPH_MAX_2K; 3589 } else { 3590 lim = NPH_MAX; 3591 } 3592 3593 handle = isp_next_handle(isp, ohp); 3594 for (i = 0; i < lim; i++) { |
3928 /* 3929 * See if we're still logged into something with 3930 * this handle and that something agrees with this 3931 * port id. 3932 */ | 3595 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) 3596 return (-1); 3597 3598 /* Check if this handle is free. */ |
3933 r = isp_getpdb(isp, chan, handle, p, 0); | 3599 r = isp_getpdb(isp, chan, handle, p, 0); |
3934 if (r == 0 && p->portid != portid) { 3935 (void) isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL, 1); 3936 } else if (r == 0) { | 3600 if (r == 0) { 3601 if (p->portid != portid) { 3602 /* This handle is busy, try next one. */ 3603 handle = isp_next_handle(isp, ohp); 3604 continue; 3605 } |
3937 break; 3938 } | 3606 break; 3607 } |
3939 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) { | 3608 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) |
3940 return (-1); | 3609 return (-1); |
3941 } | 3610 |
3942 /* 3943 * Now try and log into the device 3944 */ 3945 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI, 1); | 3611 /* 3612 * Now try and log into the device 3613 */ 3614 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI, 1); |
3946 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) { 3947 return (-1); 3948 } | |
3949 if (r == 0) { 3950 break; 3951 } else if ((r & 0xffff) == MBOX_PORT_ID_USED) { 3952 /* 3953 * If we get here, then the firmwware still thinks we're logged into this device, but with a different 3954 * handle. We need to break that association. We used to try and just substitute the handle, but then 3955 * failed to get any data via isp_getpdb (below). 3956 */ 3957 if (isp_plogx(isp, chan, r >> 16, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL, 1)) { 3958 isp_prt(isp, ISP_LOGERR, "baw... logout of %x failed", r >> 16); 3959 } | 3615 if (r == 0) { 3616 break; 3617 } else if ((r & 0xffff) == MBOX_PORT_ID_USED) { 3618 /* 3619 * If we get here, then the firmwware still thinks we're logged into this device, but with a different 3620 * handle. We need to break that association. We used to try and just substitute the handle, but then 3621 * failed to get any data via isp_getpdb (below). 3622 */ 3623 if (isp_plogx(isp, chan, r >> 16, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL, 1)) { 3624 isp_prt(isp, ISP_LOGERR, "baw... logout of %x failed", r >> 16); 3625 } |
3960 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) { | 3626 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) |
3961 return (-1); | 3627 return (-1); |
3962 } | |
3963 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI, 1); | 3628 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI, 1); |
3964 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) { 3965 return (-1); 3966 } | |
3967 if (r != 0) 3968 i = lim; 3969 break; 3970 } else if ((r & 0xffff) == MBOX_LOOP_ID_USED) { 3971 /* Try the next handle. */ 3972 handle = isp_next_handle(isp, ohp); 3973 } else { 3974 /* Give up. */ --- 8 unchanged lines hidden (view full) --- 3983 } 3984 3985 /* 3986 * If we successfully logged into it, get the PDB for it 3987 * so we can crosscheck that it is still what we think it 3988 * is and that we also have the role it plays 3989 */ 3990 r = isp_getpdb(isp, chan, handle, p, 0); | 3629 if (r != 0) 3630 i = lim; 3631 break; 3632 } else if ((r & 0xffff) == MBOX_LOOP_ID_USED) { 3633 /* Try the next handle. */ 3634 handle = isp_next_handle(isp, ohp); 3635 } else { 3636 /* Give up. */ --- 8 unchanged lines hidden (view full) --- 3645 } 3646 3647 /* 3648 * If we successfully logged into it, get the PDB for it 3649 * so we can crosscheck that it is still what we think it 3650 * is and that we also have the role it plays 3651 */ 3652 r = isp_getpdb(isp, chan, handle, p, 0); |
3991 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) { 3992 return (-1); 3993 } | |
3994 if (r != 0) { 3995 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x disappeared", chan, portid, handle); 3996 return (-1); 3997 } 3998 3999 if (p->handle != handle || p->portid != portid) { 4000 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x changed (0x%06x@0x%0x)", 4001 chan, portid, handle, p->portid, p->handle); --- 1831 unchanged lines hidden (view full) --- 5833 } 5834 } 5835 } else { 5836 isp->isp_intoasync++; 5837 } 5838 return (acked); 5839} 5840 | 3653 if (r != 0) { 3654 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x disappeared", chan, portid, handle); 3655 return (-1); 3656 } 3657 3658 if (p->handle != handle || p->portid != portid) { 3659 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x changed (0x%06x@0x%0x)", 3660 chan, portid, handle, p->portid, p->handle); --- 1831 unchanged lines hidden (view full) --- 5492 } 5493 } 5494 } else { 5495 isp->isp_intoasync++; 5496 } 5497 return (acked); 5498} 5499 |
5841#define GET_24XX_BUS(isp, chan, msg) \ 5842 if (IS_24XX(isp)) { \ 5843 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff; \ 5844 if (chan >= isp->isp_nchan) { \ 5845 isp_prt(isp, ISP_LOGERR, "bogus channel %u for %s at line %d", chan, msg, __LINE__); \ 5846 break; \ 5847 } \ 5848 } 5849 5850 | |
5851static int 5852isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox) 5853{ | 5500static int 5501isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox) 5502{ |
5503 fcparam *fcp; |
|
5854 int acked = 0; 5855 uint16_t chan; 5856 5857 if (IS_DUALBUS(isp)) { 5858 chan = ISP_READ(isp, OUTMAILBOX6); 5859 } else { 5860 chan = 0; 5861 } --- 65 unchanged lines hidden (view full) --- 5927 case ASYNC_LIP_F8: 5928 case ASYNC_LIP_OCCURRED: 5929 case ASYNC_PTPMODE: 5930 /* 5931 * These are broadcast events that have to be sent across 5932 * all active channels. 5933 */ 5934 for (chan = 0; chan < isp->isp_nchan; chan++) { | 5504 int acked = 0; 5505 uint16_t chan; 5506 5507 if (IS_DUALBUS(isp)) { 5508 chan = ISP_READ(isp, OUTMAILBOX6); 5509 } else { 5510 chan = 0; 5511 } --- 65 unchanged lines hidden (view full) --- 5577 case ASYNC_LIP_F8: 5578 case ASYNC_LIP_OCCURRED: 5579 case ASYNC_PTPMODE: 5580 /* 5581 * These are broadcast events that have to be sent across 5582 * all active channels. 5583 */ 5584 for (chan = 0; chan < isp->isp_nchan; chan++) { |
5935 fcparam *fcp = FCPARAM(isp, chan); | 5585 fcp = FCPARAM(isp, chan); |
5936 int topo = fcp->isp_topo; 5937 5938 if (fcp->role == ISP_ROLE_NONE) { 5939 continue; 5940 } 5941 5942 fcp->isp_loopstate = LOOP_NIL; 5943 ISP_SET_SENDMARKER(isp, chan, 1); --- 40 unchanged lines hidden (view full) --- 5984 break; 5985 5986 case ASYNC_LOOP_UP: 5987 /* 5988 * This is a broadcast event that has to be sent across 5989 * all active channels. 5990 */ 5991 for (chan = 0; chan < isp->isp_nchan; chan++) { | 5586 int topo = fcp->isp_topo; 5587 5588 if (fcp->role == ISP_ROLE_NONE) { 5589 continue; 5590 } 5591 5592 fcp->isp_loopstate = LOOP_NIL; 5593 ISP_SET_SENDMARKER(isp, chan, 1); --- 40 unchanged lines hidden (view full) --- 5634 break; 5635 5636 case ASYNC_LOOP_UP: 5637 /* 5638 * This is a broadcast event that has to be sent across 5639 * all active channels. 5640 */ 5641 for (chan = 0; chan < isp->isp_nchan; chan++) { |
5992 fcparam *fcp = FCPARAM(isp, chan); 5993 5994 if (fcp->role == ISP_ROLE_NONE) { | 5642 fcp = FCPARAM(isp, chan); 5643 if (fcp->role == ISP_ROLE_NONE) |
5995 continue; | 5644 continue; |
5996 } 5997 | |
5998 ISP_SET_SENDMARKER(isp, chan, 1); 5999 isp_async(isp, ISPASYNC_LOOP_UP, chan); 6000#ifdef ISP_TARGET_MODE 6001 if (isp_target_async(isp, chan, mbox)) { 6002 acked = 1; 6003 } 6004#endif 6005 } 6006 break; 6007 6008 case ASYNC_LOOP_DOWN: 6009 /* 6010 * This is a broadcast event that has to be sent across 6011 * all active channels. 6012 */ 6013 for (chan = 0; chan < isp->isp_nchan; chan++) { | 5645 ISP_SET_SENDMARKER(isp, chan, 1); 5646 isp_async(isp, ISPASYNC_LOOP_UP, chan); 5647#ifdef ISP_TARGET_MODE 5648 if (isp_target_async(isp, chan, mbox)) { 5649 acked = 1; 5650 } 5651#endif 5652 } 5653 break; 5654 5655 case ASYNC_LOOP_DOWN: 5656 /* 5657 * This is a broadcast event that has to be sent across 5658 * all active channels. 5659 */ 5660 for (chan = 0; chan < isp->isp_nchan; chan++) { |
6014 fcparam *fcp = FCPARAM(isp, chan); 6015 6016 if (fcp->role == ISP_ROLE_NONE) { | 5661 fcp = FCPARAM(isp, chan); 5662 if (fcp->role == ISP_ROLE_NONE) |
6017 continue; | 5663 continue; |
6018 } 6019 | |
6020 ISP_SET_SENDMARKER(isp, chan, 1); 6021 fcp->isp_loopstate = LOOP_NIL; 6022 isp_async(isp, ISPASYNC_LOOP_DOWN, chan); | 5664 ISP_SET_SENDMARKER(isp, chan, 1); 5665 fcp->isp_loopstate = LOOP_NIL; 5666 isp_async(isp, ISPASYNC_LOOP_DOWN, chan); |
6023 | |
6024#ifdef ISP_TARGET_MODE 6025 if (isp_target_async(isp, chan, mbox)) { 6026 acked = 1; 6027 } 6028#endif 6029 } 6030 break; 6031 6032 case ASYNC_LOOP_RESET: 6033 /* 6034 * This is a broadcast event that has to be sent across 6035 * all active channels. 6036 */ 6037 for (chan = 0; chan < isp->isp_nchan; chan++) { | 5667#ifdef ISP_TARGET_MODE 5668 if (isp_target_async(isp, chan, mbox)) { 5669 acked = 1; 5670 } 5671#endif 5672 } 5673 break; 5674 5675 case ASYNC_LOOP_RESET: 5676 /* 5677 * This is a broadcast event that has to be sent across 5678 * all active channels. 5679 */ 5680 for (chan = 0; chan < isp->isp_nchan; chan++) { |
6038 fcparam *fcp = FCPARAM(isp, chan); 6039 6040 if (fcp->role == ISP_ROLE_NONE) { | 5681 fcp = FCPARAM(isp, chan); 5682 if (fcp->role == ISP_ROLE_NONE) |
6041 continue; | 5683 continue; |
6042 } 6043 | |
6044 ISP_SET_SENDMARKER(isp, chan, 1); 6045 fcp->isp_loopstate = LOOP_NIL; 6046 isp_async(isp, ISPASYNC_LOOP_RESET, chan); 6047#ifdef ISP_TARGET_MODE 6048 if (isp_target_async(isp, chan, mbox)) { 6049 acked = 1; 6050 } 6051#endif 6052 } 6053 break; 6054 6055 case ASYNC_PDB_CHANGED: 6056 { 6057 int echan, nphdl, nlstate, reason; 6058 | 5684 ISP_SET_SENDMARKER(isp, chan, 1); 5685 fcp->isp_loopstate = LOOP_NIL; 5686 isp_async(isp, ISPASYNC_LOOP_RESET, chan); 5687#ifdef ISP_TARGET_MODE 5688 if (isp_target_async(isp, chan, mbox)) { 5689 acked = 1; 5690 } 5691#endif 5692 } 5693 break; 5694 5695 case ASYNC_PDB_CHANGED: 5696 { 5697 int echan, nphdl, nlstate, reason; 5698 |
6059 if (IS_24XX(isp)) { 6060 nphdl = ISP_READ(isp, OUTMAILBOX1); 6061 nlstate = ISP_READ(isp, OUTMAILBOX2); | 5699 nphdl = ISP_READ(isp, OUTMAILBOX1); 5700 nlstate = ISP_READ(isp, OUTMAILBOX2); 5701 if (IS_24XX(isp)) |
6062 reason = ISP_READ(isp, OUTMAILBOX3) >> 8; | 5702 reason = ISP_READ(isp, OUTMAILBOX3) >> 8; |
6063 GET_24XX_BUS(isp, chan, "ASYNC_CHANGE_NOTIFY"); 6064 echan = (nphdl == NIL_HANDLE) ? 6065 isp->isp_nchan - 1 : chan; | 5703 else 5704 reason = 0xff; 5705 if (ISP_CAP_MULTI_ID(isp)) { 5706 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff; 5707 if (chan == 0xff || nphdl == NIL_HANDLE) { 5708 chan = 0; 5709 echan = isp->isp_nchan - 1; 5710 } else if (chan >= isp->isp_nchan) { 5711 break; 5712 } else { 5713 echan = chan; 5714 } |
6066 } else { | 5715 } else { |
6067 nphdl = NIL_HANDLE; 6068 nlstate = reason = 0; | |
6069 chan = echan = 0; 6070 } 6071 for (; chan <= echan; chan++) { | 5716 chan = echan = 0; 5717 } 5718 for (; chan <= echan; chan++) { |
6072 fcparam *fcp = FCPARAM(isp, chan); 6073 6074 if (fcp->role == ISP_ROLE_NONE) { | 5719 fcp = FCPARAM(isp, chan); 5720 if (fcp->role == ISP_ROLE_NONE) |
6075 continue; | 5721 continue; |
6076 } | |
6077 if (fcp->isp_loopstate > LOOP_LTEST_DONE) 6078 fcp->isp_loopstate = LOOP_LTEST_DONE; | 5722 if (fcp->isp_loopstate > LOOP_LTEST_DONE) 5723 fcp->isp_loopstate = LOOP_LTEST_DONE; |
6079 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason); | 5724 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, 5725 ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason); |
6080 } 6081 break; 6082 } 6083 case ASYNC_CHANGE_NOTIFY: 6084 { | 5726 } 5727 break; 5728 } 5729 case ASYNC_CHANGE_NOTIFY: 5730 { |
6085 int lochan, hichan; | 5731 int portid; |
6086 | 5732 |
6087 if (ISP_FW_NEWER_THAN(isp, 4, 0, 25) && ISP_CAP_MULTI_ID(isp)) { 6088 GET_24XX_BUS(isp, chan, "ASYNC_CHANGE_NOTIFY"); 6089 lochan = chan; 6090 hichan = chan + 1; | 5733 portid = ((ISP_READ(isp, OUTMAILBOX1) & 0xff) << 16) | 5734 ISP_READ(isp, OUTMAILBOX2); 5735 if (ISP_CAP_MULTI_ID(isp)) { 5736 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff; 5737 if (chan >= isp->isp_nchan) 5738 break; |
6091 } else { | 5739 } else { |
6092 lochan = 0; 6093 hichan = isp->isp_nchan; | 5740 chan = 0; |
6094 } | 5741 } |
6095 for (chan = lochan; chan < hichan; chan++) { 6096 fcparam *fcp = FCPARAM(isp, chan); 6097 6098 if (fcp->role == ISP_ROLE_NONE) { 6099 continue; 6100 } 6101 6102 if (fcp->isp_loopstate > LOOP_LSCAN_DONE) 6103 fcp->isp_loopstate = LOOP_LSCAN_DONE; 6104 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, ISPASYNC_CHANGE_SNS); 6105 } | 5742 fcp = FCPARAM(isp, chan); 5743 if (fcp->role == ISP_ROLE_NONE) 5744 break; 5745 if (fcp->isp_loopstate > LOOP_LSCAN_DONE) 5746 fcp->isp_loopstate = LOOP_LSCAN_DONE; 5747 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, 5748 ISPASYNC_CHANGE_SNS, portid); |
6106 break; 6107 } 6108 6109 case ASYNC_CONNMODE: 6110 /* 6111 * This only applies to 2100 amd 2200 cards 6112 */ 6113 if (!IS_2200(isp) && !IS_2100(isp)) { --- 1037 unchanged lines hidden (view full) --- 7151 ISP_FC_OPMAP(0x00, 0x00), /* 0x55: */ 7152 ISP_FC_OPMAP(0x00, 0x00), /* 0x56: */ 7153 ISP_FC_OPMAP(0x00, 0x00), /* 0x57: */ 7154 ISP_FC_OPMAP(0x00, 0x00), /* 0x58: */ 7155 ISP_FC_OPMAP(0x00, 0x00), /* 0x59: */ 7156 ISP_FC_OPMAP(0x00, 0x00), /* 0x5a: */ 7157 ISP_FC_OPMAP(0x03, 0x01), /* 0x5b: MBOX_DRIVER_HEARTBEAT */ 7158 ISP_FC_OPMAP(0xcf, 0x01), /* 0x5c: MBOX_FW_HEARTBEAT */ | 5749 break; 5750 } 5751 5752 case ASYNC_CONNMODE: 5753 /* 5754 * This only applies to 2100 amd 2200 cards 5755 */ 5756 if (!IS_2200(isp) && !IS_2100(isp)) { --- 1037 unchanged lines hidden (view full) --- 6794 ISP_FC_OPMAP(0x00, 0x00), /* 0x55: */ 6795 ISP_FC_OPMAP(0x00, 0x00), /* 0x56: */ 6796 ISP_FC_OPMAP(0x00, 0x00), /* 0x57: */ 6797 ISP_FC_OPMAP(0x00, 0x00), /* 0x58: */ 6798 ISP_FC_OPMAP(0x00, 0x00), /* 0x59: */ 6799 ISP_FC_OPMAP(0x00, 0x00), /* 0x5a: */ 6800 ISP_FC_OPMAP(0x03, 0x01), /* 0x5b: MBOX_DRIVER_HEARTBEAT */ 6801 ISP_FC_OPMAP(0xcf, 0x01), /* 0x5c: MBOX_FW_HEARTBEAT */ |
7159 ISP_FC_OPMAP(0x07, 0x03), /* 0x5d: MBOX_GET_SET_DATA_RATE */ | 6802 ISP_FC_OPMAP(0x07, 0x1f), /* 0x5d: MBOX_GET_SET_DATA_RATE */ |
7160 ISP_FC_OPMAP(0x00, 0x00), /* 0x5e: */ 7161 ISP_FC_OPMAP(0x00, 0x00), /* 0x5f: */ 7162 ISP_FC_OPMAP(0xcf, 0x0f), /* 0x60: MBOX_INIT_FIRMWARE */ 7163 ISP_FC_OPMAP(0x00, 0x00), /* 0x61: */ 7164 ISP_FC_OPMAP(0x01, 0x01), /* 0x62: MBOX_INIT_LIP */ 7165 ISP_FC_OPMAP(0xcd, 0x03), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */ 7166 ISP_FC_OPMAP(0xcf, 0x01), /* 0x64: MBOX_GET_PORT_DB */ 7167 ISP_FC_OPMAP(0x07, 0x01), /* 0x65: MBOX_CLEAR_ACA */ --- 761 unchanged lines hidden (view full) --- 7929 ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET); 7930 ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS); 7931 ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL); 7932 ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS); 7933 } 7934 } 7935 } 7936 | 6803 ISP_FC_OPMAP(0x00, 0x00), /* 0x5e: */ 6804 ISP_FC_OPMAP(0x00, 0x00), /* 0x5f: */ 6805 ISP_FC_OPMAP(0xcf, 0x0f), /* 0x60: MBOX_INIT_FIRMWARE */ 6806 ISP_FC_OPMAP(0x00, 0x00), /* 0x61: */ 6807 ISP_FC_OPMAP(0x01, 0x01), /* 0x62: MBOX_INIT_LIP */ 6808 ISP_FC_OPMAP(0xcd, 0x03), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */ 6809 ISP_FC_OPMAP(0xcf, 0x01), /* 0x64: MBOX_GET_PORT_DB */ 6810 ISP_FC_OPMAP(0x07, 0x01), /* 0x65: MBOX_CLEAR_ACA */ --- 761 unchanged lines hidden (view full) --- 7572 ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET); 7573 ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS); 7574 ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL); 7575 ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS); 7576 } 7577 } 7578 } 7579 |
7937 cleanup: | 7580cleanup: |
7938 isp->isp_nactive = 0; 7939 isp_clear_commands(isp); 7940 if (IS_FC(isp)) { 7941 for (i = 0; i < isp->isp_nchan; i++) | 7581 isp->isp_nactive = 0; 7582 isp_clear_commands(isp); 7583 if (IS_FC(isp)) { 7584 for (i = 0; i < isp->isp_nchan; i++) |
7942 isp_mark_portdb(isp, i, -1); | 7585 isp_clear_portdb(isp, i); |
7943 } 7944 return (res); 7945} 7946 7947/* 7948 * NVRAM Routines 7949 */ 7950static int --- 603 unchanged lines hidden --- | 7586 } 7587 return (res); 7588} 7589 7590/* 7591 * NVRAM Routines 7592 */ 7593static int --- 603 unchanged lines hidden --- |